리버티게임:언사이라이터

리버티게임, 모두가 만들어가는 자유로운 게임
imported>재미로봇님의 2020년 9월 9일 (수) 17:28 판 (change "백괴게임:" to "리버티게임:")

언사이라이터는 비슷비슷한 내용의 백괴게임 문서를 작성할때 도움을 줄 수 있는 특수문서 아닌 특수문서입니다. 기차, 지하철, 혹은 고속도로 게임과 같이 모든 문서들이 비슷비슷하게 생긴 게임을 클릭이랑 드래그 몇번만 하고 뿅하고 만들어낼 수 있습니다. 이 문서는 모바일을 지원하지 않습니다.

사용법

아래 인터페이스 창을 보시면 왼쪽에는 그림으로 되어있고 오른쪽엔 버튼이나 텍스트박스로 이루어져 있습니다. 왼쪽 파트를 캔버스라고 칭하고 오른쪽 파트를 명령팔레트라고 칭합니다. 각각 나누어서 기능을 설명하겠습니다.

캔버스

캔버스를 잘 보시면 네모와 화살표로 이루어져 있습니다. 네모(이하 노드라고 부르겠습니다)클릭하면 노란색으로 바뀝니다. 선택된 노드는 명령팔레트에서 지우는것이 가능합니다. 한 노드를 마우스로 드래그해서 다른 노드에 갖다 붙이는것으로 화살표(이하 브랜치라고 부르겠습니다)를 이을 수 있습니다. 또한 오른쪽 마우스로 갖다 붙이는 행위로 이어진 브랜치를 지우는것이 가능합니다.

명령 팔레트

새로운 노드 추가 탭, 기존 노드 수정탭, 노드 작성완료 탭. 명령팔레트는 이렇게 세 부분으로 나누어져있습니다. 아직 프로토타입만 만들었기 때문에 기능은 많지 않습니다. 새로운 노드 추가 탭의 텍스트박스에 생성할 노드 이름을 입력하고 추가 버튼을 누르는 것으로 새로운 노드를 추가할 수 있습니다. 또한 기존 노드 수정 탭에서는 캔버스에서 선택한 노드를 삭제가 가능합니다. 노드 작성 완료 및 생성 파트가 좀 복잡하고 제일 중요한 부분인데 설명이 쫌 딸릴 수 있지만 제 말빨 필력 다 동원해서 최대한 열심히 설명해 보도록 할게요.

노드 작성 완료 탭에서는 문서를 생성하는 양식, 즉 템플릿을 설정하고 그 탬플릿을 바탕으로 스크립트에게 문서 생성을 지시할 수 있습니다. 문서를 생성할때 각 문서는 노드 하나하나와 대응합니다. 캔버스에 노드를 5개 만들었으면 다섯개 문서가 생성이되고 노드 백개가 있으면 문서 백개가 만들어집니다. 백괴사전에서 PAGENAME이나 USERNAME같은 틀 쓸때 대괄호 두개 쓰는것처럼 여기선 대괄호와 꺽쇠괄호를 조합해 여러 변수들을 사용 가능합니다. 현재 총 다섯개의 변수를 사용할 수 있으며 아래 인터페이스에 사용법이 기재되어 있으니 참조 바랍니다.

사용할 수 있는 다섯개의 변수중 하나가 좀 사용법이 복잡한데요, 링크 변수가 그렇습니다. 이 변수만 사용법을 짚고 넘어가겠습니다. 링크는 다른 변수와달리 하나의 파라미터를 받을 수 있게 되어 있습니다. 파라미터 안에 내용을 적으면 그 내용이 문서에 해당되는 노드가 다른 노드에 링크된 갯수만큼 반복해서 작성됩니다. 무슨 소리냐 하면 아래 인터페이스를 보시면 부산노드는 서울과 대구 방향으로 총 두개의 브랜치가 이어져 있습니다. 이런 경우 링크 파라미터 내부의 내용이 두번씩 반복되어 출력됩니다. 서울노드는 다른노드의 브랜치가 이어지기만 했지 서울에서 뻗어나가는 브랜치는 없으므로 링크 내부의 내용은 출력되지 않습니다. 또한 이 함수 내부에서 링크노드네임이나 링크페이지네임 변수를 사용 가능한데, 이 링크함수가 반복될때 해당 노드에 대응되는 링크문서의 페이지명과 노드이름을 출력 할 수 있습니다.

어떻게든 열심히 설명해봤는데 내가봐도 뭔소린지 잘 모르겠네요 작성자가 필력이 딸려서 설명을 구성지게 못하겠습니다 죄송합니다. 대신 예시 몇개 남겨놓을테니 대충대충 끄적여보고 감 잡으시길 바랍니다 인터페이스도 이것저것 만져보고 테스트해보라고 노드 몇개랑 추가해놓고 템플릿 양식 적어놓은거구요 직접 사용할때 모든 노드 지워주시면 됩니다. 화이팅

업데이트

버전 업그레이드시 플러그인 업데이트 버튼이 제대로 동작하지 않는 버그가 있습니다. 플러그인 업데이트시 /업데이트문서에서 올바른 플러그인 업데이트가 가능합니다.

예시

 기본 예시

 CGI 예시

인터페이스



/**

* 시간에 따라 바뀌는 유동적인 값을 반환합니다. cos함수, 혹은 그의 절대값 형태를 띕니다.
* @param start 최소값
* @param height 진폭
* @param wavelength 파장
* @param isAbs 절대값인가 아닌가
*/

var getFluidValue = function (start, height, wavelength, isAbs) {

   if (isAbs === void 0) { isAbs = true; }
   var now = Date.now() / Math.PI / wavelength;
   var amplitude = Math.cos(now) * height;
   return start + (isAbs ? Math.abs(amplitude) : amplitude);

}; /**

* 뷰에 해당하는 클래스, 캔버스와 연동해 노드들의 관계를 보여줌
*/

var GUI = /** @class */ (function () {

   /**
    * 생성자, 컨텍스트를 가져오기 위한 용도인 getcdtx를 정의
    * @param canvas 그림판으로 사용할 캔버스 객체
    */
   function GUI(canvas) {
       if (canvas === void 0) { canvas = document.querySelector("#nodemap"); }
       var _this = this;
       this.canvas = canvas;
       this.nodeCache = [];
       this.selectedNode = null;
       this.isUnlinkNode = false;
       this.dragInfo = null;
       /**
        * 캔버스에서 사용할 각종 수치
        */
       this.elemUnit = {
           wrap: {
               marginX: 50,
               marginY: 20
           },
           node: {
               intervalY: 20,
               width: 100,
               height: 50,
               getctx: null,
               selectNodeColor: "yellow"
           },
           branch: {
               width: 100,
               weight: 3,
               getctx: null
           }
       };
       this.elemUnit.node.getctx = function () {
           var ctx = _this.canvas.getContext("2d");
           ctx.textAlign = "center";
           ctx.textBaseline = "middle";
           ctx.font = "30px sans-serif";
           ctx.lineWidth = 5;
           ctx.setLineDash([]);
           ctx.strokeStyle = "black";
           return ctx;
       };
       this.elemUnit.branch.getctx = function () {
           var ctx = _this.canvas.getContext("2d");
           ctx.strokeStyle = "black";
           ctx.setLineDash([]);
           return ctx;
       };
   }
   /**
    * 특정 노드의 위치 획득
    * @param nodeList 위치를 획득할 노드가 속하는 집단
    * @param node 위치를 획득할 노드
    */
   GUI.prototype.getPosition = function (nodeList, node) {
       var thisPosition;
       nodeList.every(function (currentNode, i) {
           thisPosition = i;
           if (currentNode === node)
               return false;
           return true;
       });
       return thisPosition;
   };
   /**
    * 수정 대상이 될 노드 지정
    * @param node 수정 대상이 될 노드
    */
   GUI.prototype.nodeSelect = function (node, isUnlinkNode) {
       this.isUnlinkNode = isUnlinkNode;
       this.selectedNode = node;
   };
   GUI.prototype.getNodeByAxis = function (axis) {
       var _a = this.elemUnit, wrap = _a.wrap, node = _a.node, branch = _a.branch;
       var nodeContainerSize = node.intervalY + node.height;
       var isSafeX = axis.x >= branch.width + wrap.marginX && axis.x <= branch.width + wrap.marginX + node.width;
       if (!isSafeX)
           return null;
       var p = parseInt((axis.y - wrap.marginY) / nodeContainerSize + "");
       if (p === -1)
           return null;
       return this.nodeCache[p];
   };
   GUI.prototype.setNodeList = function (nodeList) {
       this.nodeCache = nodeList;
   };
   GUI.prototype.setDragInfo = function (axis) {
       this.dragInfo = axis;
   };
   /**
    * 캔버스에 출력
    */
   GUI.prototype.draw = function () {
       var _this = this;
       var nodeList = this.nodeCache;
       this.initCanvasSize(nodeList.length);
       nodeList.forEach(function (node, i) {
           _this.drawNode(node, i);
           node.getLinked().forEach(function (linkednode) {
               var j = _this.getPosition(nodeList, linkednode);
               _this.drawbranch(i, j);
           });
       });
       this.drawbranch(this.selectedNode, this.dragInfo, function () {
           var ctx = _this.elemUnit.branch.getctx();
           ctx.setLineDash([7, 3]);
           ctx.lineDashOffset = Date.now() / 100 % 100;
           ctx.strokeStyle = _this.isUnlinkNode ? "red" : "blue";
           return ctx;
       });
   };
   GUI.prototype.initCanvasSize = function (nodeCount) {
       var _a = this.elemUnit, wrap = _a.wrap, node = _a.node, branch = _a.branch;
       var width = wrap.marginX * 2 + node.width + branch.width * 2;
       var height = wrap.marginY * 2
           + (node.height * nodeCount)
           + node.intervalY * (nodeCount - 1);
       this.canvas.width = width;
       this.canvas.height = height;
   };
   GUI.prototype.getNodePosition = function (position, hori, vert) {
       if (hori === void 0) { hori = "left"; }
       if (vert === void 0) { vert = "top"; }
       var _a = this.elemUnit, wrap = _a.wrap, node = _a.node, branch = _a.branch;
       var getBonusWidth = function (hori) {
           if (hori == "left")
               return 0;
           if (hori == "center")
               return node.width / 2;
           if (hori == "right")
               return node.width;
       };
       var getBonusHeight = function (vert) {
           if (vert === "top")
               return 0;
           if (vert === "middle")
               return node.height / 2;
           if (vert === "bottom")
               return node.height;
       };
       return [
           wrap.marginX + branch.width + getBonusWidth(hori),
           wrap.marginY
               + (node.intervalY + node.height) * position
               + getBonusHeight(vert)
       ];
   };
   GUI.prototype.drawNode = function (node, position) {
       var nodeSize = this.elemUnit.node;
       var ctx = nodeSize.getctx();
       var axis = this.getNodePosition(position);
       if (node === this.selectedNode) {
           ctx.fillStyle = nodeSize.selectNodeColor;
           ctx.fillRect.apply(ctx, this.getNodePosition(position).concat([nodeSize.width, nodeSize.height]));
           ctx.fillStyle = "black";
       }
       ctx.strokeRect.apply(ctx, this.getNodePosition(position).concat([nodeSize.width, nodeSize.height]));
       ctx.fillText.apply(ctx, [node.getName()].concat(this.getNodePosition(position, "center", "middle")));
   };
   GUI.prototype.getBranchAxis = function (startPosition, endPosition) {
       var _this = this;
       var getAxisY = function (axis) {
           if (axis instanceof DocNode)
               axis = _this.getPosition(_this.nodeCache, axis);
           if (typeof axis == "number")
               return _this.getNodePosition(axis, "center", "middle")[1];
           return axis.y;
       };
       var _a = [getAxisY(startPosition), getAxisY(endPosition)], startAxisY = _a[0], endAxisY = _a[1];
       var direction = startAxisY > endAxisY ? "left" : "right";
       var isDirectionLeft = direction === "left";
       var axisX = this.getNodePosition(0, direction, "middle")[0];
       var start = [axisX, startAxisY];
       var end = [axisX, endAxisY];
       return [start, end];
   };
   GUI.prototype.drawbranch = function (startPosition, endPosition, getctx) {
       if (getctx === void 0) { getctx = this.elemUnit.branch.getctx; }
       if (startPosition === null || endPosition === null)
           return;
       var _a = this.getBranchAxis(startPosition, endPosition), start = _a[0], end = _a[1];
       var max = start[1] > end[1] ? end : start;
       var isDirectionLeft = max === end;
       var radius = Math.abs((end[1] - start[1]) / 2);
       var arrowSize = (isDirectionLeft ? -1 : 1) * 15;
       var ctx = getctx();
       ctx.beginPath();
       ctx.arc(max[0], max[1] + radius, radius, isDirectionLeft ? Math.PI * 1 / 2 : Math.PI * 3 / 2, isDirectionLeft ? Math.PI * 3 / 2 : Math.PI * 1 / 2);
       ctx.moveTo.apply(ctx, end);
       ctx.lineTo(end[0] + arrowSize, end[1] + arrowSize);
       ctx.moveTo.apply(ctx, end);
       ctx.lineTo(end[0] + arrowSize, end[1] - arrowSize);
       ctx.stroke();
   };
   return GUI;

}()); var NodeInput = /** @class */ (function () {

   function NodeInput(gui, nodeList) {
       if (gui === void 0) { gui = new GUI(); }
       this.gui = gui;
       this.nodeList = nodeList;
       this.selectedNode = null;
       this.$$ = document.querySelector.bind(document);
       this.initEventListener();
       this.initCanvasEventListener();
   }
   NodeInput.prototype.initEventListener = function () {
       var _this = this;
       var $$ = this.$$;
       // addNode
       var addNodeListener = function (e) {
           var nodenameNode = $$(".inp_addnodename");
           var nodeName = nodenameNode.value;
           nodenameNode.value = "";
           _this.nodeList.addNode(nodeName);
       };
       $$(".btn_addnode").addEventListener("click", addNodeListener);
       $$(".inp_addnodename").addEventListener("keydown", function (e) {
           if (e.key === "Enter") {
               addNodeListener(e);
           }
       });
       $$(".btn_removenode").addEventListener("click", function (e) {
           if (_this.selectedNode === null)
               throw Error("삭제할 노드를 선택 해 주세요.");
           _this.nodeList.removeNode(_this.selectedNode.getName());
           var lastNode = _this.nodeList.getNodeList().slice(-1)[0];
           console.log(lastNode);
           _this.gui.nodeSelect(lastNode, false);
           _this.selectedNode = lastNode;
       });
       var createDocListener = function (e) {
           var sendMessage = function (message) { return $$(".btn_create_message").innerHTML = message; };
           $$(".btn_create_create").removeEventListener("click", createDocListener);
           sendMessage("문서 생성 요청을 보냈습니다. 준비할때까지 좀만 기다려주세요");
           var prefix = $$(".inp_create_target").value;
           var template = $$(".inp_create_form").value;
           if (prefix.slice(-1) !== "/")
               prefix += "/";
           DocFactory.create(_this.nodeList, template, prefix, sendMessage);
       };
       $$(".btn_create_create").addEventListener("click", createDocListener);
   };
   NodeInput.prototype.initCanvasEventListener = function () {
       var _this = this;
       var $$ = this.$$;
       var getAxis = function (e) { return ({ x: e.offsetX, y: e.offsetY }); };
       var setSelectedNode = function (node, isUnlinkMode) {
           _this.selectedNode = node;
           _this.setSelectedNode(node);
           _this.gui.nodeSelect(_this.selectedNode, isUnlinkMode);
       };
       var isMouseDown = false;
       // selectNode
       $$("#nodemap").addEventListener("mousedown", function (e) {
           var axis = getAxis(e);
           isMouseDown = true;
           setSelectedNode(_this.gui.getNodeByAxis(axis), e.button == 2);
       });
       // searchTarget
       $$("#nodemap").addEventListener("mousemove", function (e) {
           if (isMouseDown === false)
               return _this.gui.setDragInfo(null);
           ;
           var axis = getAxis(e);
           _this.gui.getNodeByAxis(axis);
           _this.gui.setDragInfo(axis);
       });
       // setTarget
       $$("#nodemap").addEventListener("mouseup", function (e) {
           var selectedNode = _this.selectedNode;
           isMouseDown = false;
           var axis = getAxis(e);
           var throwNode = _this.gui.getNodeByAxis(axis);
           if (selectedNode === null || throwNode === null)
               return;
           if (e.button == 0) {
               _this.nodeList.linkNode(throwNode.getName(), selectedNode.getName());
           }
           else if (e.button == 2) {
               _this.nodeList.unLinkNode(throwNode.getName(), selectedNode.getName());
           }
       });
       // removePreventEvent
       $$("#nodemap").addEventListener("contextmenu", function (e) {
           e.preventDefault();
       });
   };
   NodeInput.prototype.setSelectedNode = function (node) {
       var $$ = this.$$;
       this.selectedNode = node;
       $$(".spn_nodename").innerHTML = node.getName();
   };
   return NodeInput;

}()); var DocFactory = /** @class */ (function () {

   function DocFactory() {
   }
   DocFactory.setTemplateVariable = function (template, templateVariable) {
       var _a = templateVariable.shift(), searchValue = _a[0], replaceValue = _a[1];
       template = template.replace("{[" + searchValue + "]}", replaceValue);
       if (templateVariable.length != 0)
           return DocFactory.setTemplateVariable(template, templateVariable);
       return template;
   };
   DocFactory.setLinkNoding = function (node, template, prefix) {
       var nodeName = node.getName();
       return template.replace(/\{\[링크\|([^]+)\]\}/g, function (matchedStr) {
           matchedStr = matchedStr.replace(/\{\[링크\|\s*([^]+)\s*\]\}/g, "$1");
           return node.getLinked().map(function (linkedNode) {
               var templateVariable = [
                   ["링크노드네임", linkedNode.getName()],
                   ["링크페이지네임", prefix + linkedNode.getName()]
               ];
               return DocFactory.setTemplateVariable(matchedStr, templateVariable.slice());
           }).join("\n");
       });
   };
   DocFactory.setOtherVariable = function (node, template, prefix) {
       var nodeName = node.getName();
       var templateVariable = [
           ["노드네임", nodeName],
           ["페이지네임", prefix + nodeName]
       ];
       return DocFactory.setTemplateVariable(template, templateVariable);
   };
   DocFactory.create = function (docNodeList, template, prefix, messageCallback) {
       var nodeList = docNodeList.getNodeList();
       var docQueue = nodeList.map(function (node) {
           var docString = template;
           var nodeName = node.getName();
           docString = DocFactory.setLinkNoding(node, docString, prefix);
           docString = DocFactory.setOtherVariable(node, docString, prefix);
           return { title: prefix + nodeName, content: docString };
       });
       DocFactory.makeDoc(messageCallback, docQueue);
   };
   DocFactory.makeDoc = function (messageCallback, docQueue) {
       var api = MediaWikiAPI();
       var makeDocIntervar = setInterval(function () {
           if (docQueue.length === 0) {
               messageCallback("\uBAA8\uB4E0 \uBB38\uC11C\uB97C \uC791\uC131\uD588\uC2B5\uB2C8\uB2E4. \uCD5C\uADFC \uBC14\uB01C\uC744 \uD655\uC778 \uD574 \uC8FC\uC2ED\uC1FC");
               clearInterval(makeDocIntervar);
           }
           var nextDoc = docQueue.pop();
           api.changeDocument(nextDoc.title, "템플릿 문서작성 스크립트 실행중", nextDoc.content, true);
           messageCallback("\uBB38\uC11C\uB97C \uBAA8\uB450 \uC791\uC131\uD558\uAE30\uAE4C\uC9C0 \uC55E\uC73C\uB85C " + docQueue.length + "\uAC1C \uB0A8\uC558\uC2B5\uB2C8\uB2E4.");
       }, 3000);
   };
   return DocFactory;

}()); var DocNodeList = /** @class */ (function () {

   function DocNodeList(gui) {
       if (gui === void 0) { gui = new GUI(); }
       this.gui = gui;
       this.nodeList = {};
   }
   DocNodeList.prototype.sendDraw = function () {
       this.gui.setNodeList(Object.values(this.nodeList));
   };
   DocNodeList.prototype.hasNotNode = function (node) {
       return typeof node === "undefined";
   };
   DocNodeList.prototype.linkNode = function (forNodename, toNodename) {
       var _a = this, hasNotNode = _a.hasNotNode, nodeList = _a.nodeList;
       var forNode = nodeList[forNodename];
       var toNode = nodeList[toNodename];
       if (hasNotNode(forNode) || hasNotNode(toNode))
           throw Error("존재하지 않는 노드입니다.");
       toNode.link(forNode);
       this.sendDraw();
   };
   DocNodeList.prototype.unLinkNode = function (forNodename, toNodename) {
       if (toNodename === void 0) { toNodename = null; }
       var _a = this, hasNotNode = _a.hasNotNode, nodeList = _a.nodeList;
       var forNode = nodeList[forNodename];
       var toNode = nodeList[toNodename];
       if (hasNotNode(forNode))
           throw Error("존재하지 않는 노드입니다.");
       if (hasNotNode(toNodename)) {
           this.getNodeList().forEach(function (currentNode) {
               currentNode.unLink(forNode);
               forNode.unLink(currentNode);
           });
       }
       else {
           toNode.unLink(forNode);
       }
       this.sendDraw();
   };
   DocNodeList.prototype.addNode = function (nodename) {
       var nodeList = this.nodeList;
       if (nodeList[nodename] instanceof Node)
           throw Error("이미 존재하는 노드입니다");
       else {
           nodeList[nodename] = new DocNode(nodename);
           this.sendDraw();
       }
   };
   DocNodeList.prototype.removeNode = function (nodename) {
       var nodeList = this.nodeList;
       var targetNode = nodeList[nodename];
       if (this.hasNotNode(targetNode))
           throw Error("존재하지 않는 노드입니다.");
       delete nodeList[nodename];
       this.getNodeList().forEach(function (node) { return node.unLink(targetNode); });
       this.sendDraw();
   };
   DocNodeList.prototype.getNodeList = function () { return Object.values(this.nodeList); };
   return DocNodeList;

}()); var DocNode = /** @class */ (function () {

   function DocNode(name) {
       this.name = name;
       this.linkedNode = [];
   }
   DocNode.prototype.link = function (node) {
       if (node === this)
           return; //throw Error("연결하려는 노드가 자신입니다.");
       if (this.linkedNode.some(function (currentNode) { return currentNode === node; }))
           throw Error("이미 연결된 노드입니다.");
       this.linkedNode.push(node);
   };
   DocNode.prototype.unLink = function (node) {
       var _this = this;
       this.linkedNode.forEach(function (currentNode, i) {
           if (currentNode === node)
               _this.linkedNode.splice(i, 1);
       });
   };
   DocNode.prototype.getLinked = function () {
       return this.linkedNode;
   };
   DocNode.prototype.getName = function () { return this.name; };
   DocNode.prototype.setName = function (name) { return this.name = name; };
   return DocNode;

}()); var initHTML = function () {

$("#content").append(`

<section class="section_node">\n <canvas id="nodemap"></canvas>\n</section>\n<section class="section_node">\n

노드 스케치 조작법

\n
    \n
  • 노드 선택: 선택하고 싶은 노드 클릭
  • \n
  • 노드 링킹: 링크하고 싶은 노드 클릭 후 링크 대상이 되는 노드에 갖다 끌기
  • \n
  • 노드 링킹 해제: 해제하고 싶은 노드 클릭 후 링크 대상이 되는 노드에 갖다 끌기
  • \n
\n

새로운 노드 추가

\n 노드 이름 <input class="inp_addnodename"/> <button class="btn_addnode" placeholder="노드의 제목을 입력해주세요..." > 추가 </button>\n

기존 노드 수정

\n 현재 선택된 노드: 선택되지 않음 \n <button class="btn_removenode"> 노드 삭제 </button> \n\n

노드 작성 완료 및 문서 생성

\n
\n  아래 텍스트 에리어에 각 문서에 생성될 템플릿을 입력 해 주세요. 템플릿에서 사용 가능한 특수 문법은 다음과 같습니다.\n  {[노드네임]} : 노드 이름을 출력합니다.\n  {[페이지네임]} : 페이지 이름을 출력합니다.\n  {[링크| .... ]} : 다른 노드와 링크된 갯수만큼 파라미터 안의 내용을 반복합니다.\n  {[링크노드네임]} : 링크함수 내부에 쓰이는 변수입니다. 링크된 노드의 이름을 출력합니다.\n  {[링크페이지네임]} : 링크함수 내부에 쓰이는 변수입니다. 링크된 페이지의 이름을 출력합니다.\n  
\n 최상위 문서 제목<input class="inp_create_target" value="리버티게임:언사이라이터/테스트" size="40" />\n\n <textarea class="inp_create_form"> \n현재역은 {[노드네임]}입니다.\n== 선택지 ==\n{[링크|\n* [[{[링크페이지네임]}|{[링크노드네임]}역으로]]\n]}\n </textarea>\n <button class="btn_create_create"> 생성 </button>\n
문서를 생성할 준비가 다 되었으면 위 버튼 눌러주세요
\n</section>

`);

}; var test = (function () {

   initHTML();
   var gui = new GUI();
   var nodeList = new DocNodeList(gui);
   var nodeInput = new NodeInput(gui, nodeList);
   nodeList.addNode("서울");
   nodeList.addNode("부산");
   nodeList.addNode("인천");
   nodeList.addNode("대구");
   nodeList.linkNode("서울", "부산");
   nodeList.linkNode("서울", "인천");
   nodeList.linkNode("서울", "대구");
   nodeList.linkNode("대구", "부산");
   setInterval(function () { return gui.draw(); }, 50);
   //nodeList.removeNode("미남")

})();