123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650 |
- // Generated by export.rb at Wed Oct 8 13:35:23 UTC 2014
- /*
- Copyright (c) 2014 Masafumi Oyamada
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- var Org = (function () {
- var exports = {};
- // ------------------------------------------------------------
- // Syntax
- // ------------------------------------------------------------
- var Syntax = {
- rules: {},
- define: function (name, syntax) {
- this.rules[name] = syntax;
- var methodName = "is" + name.substring(0, 1).toUpperCase() + name.substring(1);
- this[methodName] = function (line) {
- return this.rules[name].exec(line);
- };
- }
- };
- Syntax.define("header", /^(\*+)\s+(.*)$/); // m[1] => level, m[2] => content
- Syntax.define("preformatted", /^(\s*):(?: (.*)$|$)/); // m[1] => indentation, m[2] => content
- Syntax.define("unorderedListElement", /^(\s*)(?:-|\+|\s+\*)\s+(.*)$/); // m[1] => indentation, m[2] => content
- Syntax.define("orderedListElement", /^(\s*)(\d+)(?:\.|\))\s+(.*)$/); // m[1] => indentation, m[2] => number, m[3] => content
- Syntax.define("tableSeparator", /^(\s*)\|((?:\+|-)*?)\|?$/); // m[1] => indentation, m[2] => content
- Syntax.define("tableRow", /^(\s*)\|(.*?)\|?$/); // m[1] => indentation, m[2] => content
- Syntax.define("blank", /^$/);
- Syntax.define("horizontalRule", /^(\s*)-{5,}$/); //
- Syntax.define("directive", /^(\s*)#\+(?:(begin|end)_)?(.*)$/i); // m[1] => indentation, m[2] => type, m[3] => content
- Syntax.define("comment", /^(\s*)#(.*)$/);
- Syntax.define("line", /^(\s*)(.*)$/);
- // ------------------------------------------------------------
- // Token
- // ------------------------------------------------------------
- function Token() {
- }
- Token.prototype = {
- isListElement: function () {
- return this.type === Lexer.tokens.orderedListElement ||
- this.type === Lexer.tokens.unorderedListElement;
- },
- isTableElement: function () {
- return this.type === Lexer.tokens.tableSeparator ||
- this.type === Lexer.tokens.tableRow;
- }
- };
- // ------------------------------------------------------------
- // Lexer
- // ------------------------------------------------------------
- function Lexer(stream) {
- this.stream = stream;
- this.tokenStack = [];
- }
- Lexer.prototype = {
- tokenize: function (line) {
- var token = new Token();
- token.fromLineNumber = this.stream.lineNumber;
- if (Syntax.isHeader(line)) {
- token.type = Lexer.tokens.header;
- token.indentation = 0;
- token.content = RegExp.$2;
- // specific
- token.level = RegExp.$1.length;
- } else if (Syntax.isPreformatted(line)) {
- token.type = Lexer.tokens.preformatted;
- token.indentation = RegExp.$1.length;
- token.content = RegExp.$2;
- } else if (Syntax.isUnorderedListElement(line)) {
- token.type = Lexer.tokens.unorderedListElement;
- token.indentation = RegExp.$1.length;
- token.content = RegExp.$2;
- } else if (Syntax.isOrderedListElement(line)) {
- token.type = Lexer.tokens.orderedListElement;
- token.indentation = RegExp.$1.length;
- token.content = RegExp.$3;
- // specific
- token.number = RegExp.$2;
- } else if (Syntax.isTableSeparator(line)) {
- token.type = Lexer.tokens.tableSeparator;
- token.indentation = RegExp.$1.length;
- token.content = RegExp.$2;
- } else if (Syntax.isTableRow(line)) {
- token.type = Lexer.tokens.tableRow;
- token.indentation = RegExp.$1.length;
- token.content = RegExp.$2;
- } else if (Syntax.isBlank(line)) {
- token.type = Lexer.tokens.blank;
- token.indentation = 0;
- token.content = null;
- } else if (Syntax.isHorizontalRule(line)) {
- token.type = Lexer.tokens.horizontalRule;
- token.indentation = RegExp.$1.length;
- token.content = null;
- } else if (Syntax.isDirective(line)) {
- token.type = Lexer.tokens.directive;
- token.indentation = RegExp.$1.length;
- token.content = RegExp.$3;
- // decide directive type (begin, end or oneshot)
- var directiveTypeString = RegExp.$2;
- if (/^begin/i.test(directiveTypeString))
- token.beginDirective = true;
- else if (/^end/i.test(directiveTypeString))
- token.endDirective = true;
- else
- token.oneshotDirective = true;
- } else if (Syntax.isComment(line)) {
- token.type = Lexer.tokens.comment;
- token.indentation = RegExp.$1.length;
- token.content = RegExp.$2;
- } else if (Syntax.isLine(line)) {
- token.type = Lexer.tokens.line;
- token.indentation = RegExp.$1.length;
- token.content = RegExp.$2;
- } else {
- throw new Error("SyntaxError: Unknown line: " + line);
- }
- return token;
- },
- pushToken: function (token) {
- this.tokenStack.push(token);
- },
- pushDummyTokenByType: function (type) {
- var token = new Token();
- token.type = type;
- this.tokenStack.push(token);
- },
- peekStackedToken: function () {
- return this.tokenStack.length > 0 ?
- this.tokenStack[this.tokenStack.length - 1] : null;
- },
- getStackedToken: function () {
- return this.tokenStack.length > 0 ?
- this.tokenStack.pop() : null;
- },
- peekNextToken: function () {
- return this.peekStackedToken() ||
- this.tokenize(this.stream.peekNextLine());
- },
- getNextToken: function () {
- return this.getStackedToken() ||
- this.tokenize(this.stream.getNextLine());
- },
- hasNext: function () {
- return this.stream.hasNext();
- },
- getLineNumber: function () {
- return this.stream.lineNumber;
- }
- };
- Lexer.tokens = {};
- [
- "header",
- "orderedListElement",
- "unorderedListElement",
- "tableRow",
- "tableSeparator",
- "preformatted",
- "line",
- "horizontalRule",
- "blank",
- "directive",
- "comment"
- ].forEach(function (tokenName, i) {
- Lexer.tokens[tokenName] = i;
- });
- // ------------------------------------------------------------
- // Exports
- // ------------------------------------------------------------
- if (typeof exports !== "undefined")
- exports.Lexer = Lexer;
- function PrototypeNode(type, children) {
- this.type = type;
- this.children = [];
- if (children) {
- for (var i = 0, len = children.length; i < len; ++i) {
- this.appendChild(children[i]);
- }
- }
- }
- PrototypeNode.prototype = {
- previousSibling: null,
- parent: null,
- get firstChild() {
- return this.children.length < 1 ?
- null : this.children[0];
- },
- get lastChild() {
- return this.children.length < 1 ?
- null : this.children[this.children.length - 1];
- },
- appendChild: function (newChild) {
- var previousSibling = this.children.length < 1 ?
- null : this.lastChild;
- this.children.push(newChild);
- newChild.previousSibling = previousSibling;
- newChild.parent = this;
- },
- toString: function () {
- var string = "<" + this.type + ">";
- if (typeof this.value !== "undefined") {
- string += " " + this.value;
- } else if (this.children) {
- string += "\n" + this.children.map(function (child, idx) {
- return "#" + idx + " " + child.toString();
- }).join("\n").split("\n").map(function (line) {
- return " " + line;
- }).join("\n");
- }
- return string;
- }
- };
- var Node = {
- types: {},
- define: function (name, postProcess) {
- this.types[name] = name;
- var methodName = "create" + name.substring(0, 1).toUpperCase() + name.substring(1);
- var postProcessGiven = typeof postProcess === "function";
- this[methodName] = function (children, options) {
- var node = new PrototypeNode(name, children);
- if (postProcessGiven)
- postProcess(node, options || {});
- return node;
- };
- }
- };
- Node.define("text", function (node, options) {
- node.value = options.value;
- });
- Node.define("header", function (node, options) {
- node.level = options.level;
- });
- Node.define("orderedList");
- Node.define("unorderedList");
- Node.define("definitionList");
- Node.define("listElement");
- Node.define("paragraph");
- Node.define("preformatted");
- Node.define("table");
- Node.define("tableRow");
- Node.define("tableCell");
- Node.define("horizontalRule");
- Node.define("directive");
- // Inline
- Node.define("inlineContainer");
- Node.define("bold");
- Node.define("italic");
- Node.define("underline");
- Node.define("code");
- Node.define("verbatim");
- Node.define("dashed");
- Node.define("link", function (node, options) {
- node.src = options.src;
- });
- if (typeof exports !== "undefined")
- exports.Node = Node;
- function Stream(sequence) {
- this.sequences = sequence.split(/\r?\n/);
- this.totalLines = this.sequences.length;
- this.lineNumber = 0;
- }
- Stream.prototype.peekNextLine = function () {
- return this.hasNext() ? this.sequences[this.lineNumber] : null;
- };
- Stream.prototype.getNextLine = function () {
- return this.hasNext() ? this.sequences[this.lineNumber++] : null;
- };
- Stream.prototype.hasNext = function () {
- return this.lineNumber < this.totalLines;
- };
- if (typeof exports !== "undefined") {
- exports.Stream = Stream;
- }
- // var Stream = require("./stream.js").Stream;
- // var Lexer = require("./lexer.js").Lexer;
- // var Node = require("./node.js").Node;
- function Parser() {
- this.inlineParser = new InlineParser();
- }
- Parser.parseStream = function (stream, options) {
- var parser = new Parser();
- parser.initStatus(stream, options);
- parser.parseNodes();
- return parser.nodes;
- };
- Parser.prototype = {
- initStatus: function (stream, options) {
- if (typeof stream === "string")
- stream = new Stream(stream);
- this.lexer = new Lexer(stream);
- this.nodes = [];
- this.options = {
- toc: true,
- num: true,
- "^": "{}",
- multilineCell: false
- };
- // Override option values
- if (options && typeof options === "object") {
- for (var key in options) {
- this.options[key] = options[key];
- }
- }
- this.document = {
- options: this.options,
- convert: function (ConverterClass, exportOptions) {
- var converter = new ConverterClass(this, exportOptions);
- return converter.result;
- }
- };
- },
- parse: function (stream, options) {
- this.initStatus(stream, options);
- this.parseDocument();
- this.document.nodes = this.nodes;
- return this.document;
- },
- createErrorReport: function (message) {
- return new Error(message + " at line " + this.lexer.getLineNumber());
- },
- skipBlank: function () {
- var blankToken = null;
- while (this.lexer.peekNextToken().type === Lexer.tokens.blank)
- blankToken = this.lexer.getNextToken();
- return blankToken;
- },
- setNodeOriginFromToken: function (node, token) {
- node.fromLineNumber = token.fromLineNumber;
- return node;
- },
- appendNode: function (newNode) {
- var previousSibling = this.nodes.length > 0 ? this.nodes[this.nodes.length - 1] : null;
- this.nodes.push(newNode);
- newNode.previousSibling = previousSibling;
- },
- // ------------------------------------------------------------
- // <Document> ::= <Element>*
- // ------------------------------------------------------------
- parseDocument: function () {
- this.parseTitle();
- this.parseNodes();
- },
- parseNodes: function () {
- while (this.lexer.hasNext()) {
- var element = this.parseElement();
- if (element) this.appendNode(element);
- }
- },
- parseTitle: function () {
- this.skipBlank();
- if (this.lexer.hasNext() &&
- this.lexer.peekNextToken().type === Lexer.tokens.line)
- this.document.title = this.createTextNode(this.lexer.getNextToken().content);
- else
- this.document.title = null;
- this.lexer.pushDummyTokenByType(Lexer.tokens.blank);
- },
- // ------------------------------------------------------------
- // <Element> ::= (<Header> | <List>
- // | <Preformatted> | <Paragraph>
- // | <Table>)*
- // ------------------------------------------------------------
- parseElement: function () {
- var element = null;
- switch (this.lexer.peekNextToken().type) {
- case Lexer.tokens.header:
- element = this.parseHeader();
- break;
- case Lexer.tokens.preformatted:
- element = this.parsePreformatted();
- break;
- case Lexer.tokens.orderedListElement:
- case Lexer.tokens.unorderedListElement:
- element = this.parseList();
- break;
- case Lexer.tokens.line:
- element = this.parseText();
- break;
- case Lexer.tokens.tableRow:
- case Lexer.tokens.tableSeparator:
- element = this.parseTable();
- break;
- case Lexer.tokens.blank:
- this.skipBlank();
- if (this.lexer.hasNext()) {
- if (this.lexer.peekNextToken().type === Lexer.tokens.line)
- element = this.parseParagraph();
- else
- element = this.parseElement();
- }
- break;
- case Lexer.tokens.horizontalRule:
- this.lexer.getNextToken();
- element = Node.createHorizontalRule();
- break;
- case Lexer.tokens.directive:
- element = this.parseDirective();
- break;
- case Lexer.tokens.comment:
- // Skip
- this.lexer.getNextToken();
- break;
- default:
- throw this.createErrorReport("Unhandled token: " + this.lexer.peekNextToken().type);
- }
- return element;
- },
- parseElementBesidesDirectiveEnd: function () {
- try {
- // Temporary, override the definition of `parseElement`
- this.parseElement = this.parseElementBesidesDirectiveEndBody;
- return this.parseElement();
- } finally {
- this.parseElement = this.originalParseElement;
- }
- },
- parseElementBesidesDirectiveEndBody: function () {
- if (this.lexer.peekNextToken().type === Lexer.tokens.directive &&
- this.lexer.peekNextToken().endDirective) {
- return null;
- }
- return this.originalParseElement();
- },
- // ------------------------------------------------------------
- // <Header>
- //
- // : preformatted
- // : block
- // ------------------------------------------------------------
- parseHeader: function () {
- var headerToken = this.lexer.getNextToken();
- var header = Node.createHeader([
- this.createTextNode(headerToken.content) // TODO: Parse inline markups
- ], { level: headerToken.level });
- this.setNodeOriginFromToken(header, headerToken);
- return header;
- },
- // ------------------------------------------------------------
- // <Preformatted>
- //
- // : preformatted
- // : block
- // ------------------------------------------------------------
- parsePreformatted: function () {
- var preformattedFirstToken = this.lexer.peekNextToken();
- var preformatted = Node.createPreformatted([]);
- this.setNodeOriginFromToken(preformatted, preformattedFirstToken);
- var textContents = [];
- while (this.lexer.hasNext()) {
- var token = this.lexer.peekNextToken();
- if (token.type !== Lexer.tokens.preformatted ||
- token.indentation < preformattedFirstToken.indentation)
- break;
- this.lexer.getNextToken();
- textContents.push(token.content);
- }
- preformatted.appendChild(this.createTextNode(textContents.join("\n"), true /* no emphasis */));
- return preformatted;
- },
- // ------------------------------------------------------------
- // <List>
- //
- // - foo
- // 1. bar
- // 2. baz
- // ------------------------------------------------------------
- // XXX: not consider codes (e.g., =Foo::Bar=)
- definitionPattern: /^(.*?) :: *(.*)$/,
- parseList: function () {
- var rootToken = this.lexer.peekNextToken();
- var list;
- var isDefinitionList = false;
- if (this.definitionPattern.test(rootToken.content)) {
- list = Node.createDefinitionList([]);
- isDefinitionList = true;
- } else {
- list = rootToken.type === Lexer.tokens.unorderedListElement ?
- Node.createUnorderedList([]) : Node.createOrderedList([]);
- }
- this.setNodeOriginFromToken(list, rootToken);
- while (this.lexer.hasNext()) {
- var nextToken = this.lexer.peekNextToken();
- if (!nextToken.isListElement() || nextToken.indentation !== rootToken.indentation)
- break;
- list.appendChild(this.parseListElement(rootToken.indentation, isDefinitionList));
- }
- return list;
- },
- unknownDefinitionTerm: "???",
- parseListElement: function (rootIndentation, isDefinitionList) {
- var listElementToken = this.lexer.getNextToken();
- var listElement = Node.createListElement([]);
- this.setNodeOriginFromToken(listElement, listElementToken);
- listElement.isDefinitionList = isDefinitionList;
- if (isDefinitionList) {
- var match = this.definitionPattern.exec(listElementToken.content);
- listElement.term = [
- this.createTextNode(match && match[1] ? match[1] : this.unknownDefinitionTerm)
- ];
- listElement.appendChild(this.createTextNode(match ? match[2] : listElementToken.content));
- } else {
- listElement.appendChild(this.createTextNode(listElementToken.content));
- }
- while (this.lexer.hasNext()) {
- var blankToken = this.skipBlank();
- if (!this.lexer.hasNext())
- break;
- var notBlankNextToken = this.lexer.peekNextToken();
- if (blankToken && !notBlankNextToken.isListElement())
- this.lexer.pushToken(blankToken); // Recover blank token only when next line is not listElement.
- if (notBlankNextToken.indentation <= rootIndentation)
- break; // end of the list
- var element = this.parseElement(); // recursive
- if (element)
- listElement.appendChild(element);
- }
- return listElement;
- },
- // ------------------------------------------------------------
- // <Table> ::= <TableRow>+
- // ------------------------------------------------------------
- parseTable: function () {
- var nextToken = this.lexer.peekNextToken();
- var table = Node.createTable([]);
- this.setNodeOriginFromToken(table, nextToken);
- var sawSeparator = false;
- var allowMultilineCell = nextToken.type === Lexer.tokens.tableSeparator && this.options.multilineCell;
- while (this.lexer.hasNext() &&
- (nextToken = this.lexer.peekNextToken()).isTableElement()) {
- if (nextToken.type === Lexer.tokens.tableRow) {
- var tableRow = this.parseTableRow(allowMultilineCell);
- table.appendChild(tableRow);
- } else {
- // Lexer.tokens.tableSeparator
- sawSeparator = true;
- this.lexer.getNextToken();
- }
- }
- if (sawSeparator && table.children.length) {
- table.children[0].children.forEach(function (cell) {
- cell.isHeader = true;
- });
- }
- return table;
- },
- // ------------------------------------------------------------
- // <TableRow> ::= <TableCell>+
- // ------------------------------------------------------------
- parseTableRow: function (allowMultilineCell) {
- var tableRowTokens = [];
- while (this.lexer.peekNextToken().type === Lexer.tokens.tableRow) {
- tableRowTokens.push(this.lexer.getNextToken());
- if (!allowMultilineCell) {
- break;
- }
- }
- if (!tableRowTokens.length) {
- throw this.createErrorReport("Expected table row");
- }
- var firstTableRowToken = tableRowTokens.shift();
- var tableCellTexts = firstTableRowToken.content.split("|");
- tableRowTokens.forEach(function (rowToken) {
- rowToken.content.split("|").forEach(function (cellText, cellIdx) {
- tableCellTexts[cellIdx] = (tableCellTexts[cellIdx] || "") + "\n" + cellText;
- });
- });
- // TODO: Prepare two pathes: (1)
- var tableCells = tableCellTexts.map(
- // TODO: consider '|' escape?
- function (text) {
- return Node.createTableCell(Parser.parseStream(text));
- }, this);
- return this.setNodeOriginFromToken(Node.createTableRow(tableCells), firstTableRowToken);
- },
- // ------------------------------------------------------------
- // <Directive> ::= "#+.*"
- // ------------------------------------------------------------
- parseDirective: function () {
- var directiveToken = this.lexer.getNextToken();
- var directiveNode = this.createDirectiveNodeFromToken(directiveToken);
- if (directiveToken.endDirective)
- throw this.createErrorReport("Unmatched 'end' directive for " + directiveNode.directiveName);
- if (directiveToken.oneshotDirective) {
- this.interpretDirective(directiveNode);
- return directiveNode;
- }
- if (!directiveToken.beginDirective)
- throw this.createErrorReport("Invalid directive " + directiveNode.directiveName);
- // Parse begin ~ end
- directiveNode.children = [];
- if (this.isVerbatimDirective(directiveNode))
- return this.parseDirectiveBlockVerbatim(directiveNode);
- else
- return this.parseDirectiveBlock(directiveNode);
- },
- createDirectiveNodeFromToken: function (directiveToken) {
- var matched = /^[ ]*([^ ]*)[ ]*(.*)[ ]*$/.exec(directiveToken.content);
- var directiveNode = Node.createDirective(null);
- this.setNodeOriginFromToken(directiveNode, directiveToken);
- directiveNode.directiveName = matched[1].toLowerCase();
- directiveNode.directiveArguments = this.parseDirectiveArguments(matched[2]);
- directiveNode.directiveOptions = this.parseDirectiveOptions(matched[2]);
- directiveNode.directiveRawValue = matched[2];
- return directiveNode;
- },
- isVerbatimDirective: function (directiveNode) {
- var directiveName = directiveNode.directiveName;
- return directiveName === "src" || directiveName === "example";
- },
- parseDirectiveBlock: function (directiveNode, verbatim) {
- this.lexer.pushDummyTokenByType(Lexer.tokens.blank);
- while (this.lexer.hasNext()) {
- var nextToken = this.lexer.peekNextToken();
- if (nextToken.type === Lexer.tokens.directive &&
- nextToken.endDirective &&
- this.createDirectiveNodeFromToken(nextToken).directiveName === directiveNode.directiveName) {
- // Close directive
- this.lexer.getNextToken();
- return directiveNode;
- }
- var element = this.parseElementBesidesDirectiveEnd();
- if (element)
- directiveNode.appendChild(element);
- }
- throw this.createErrorReport("Unclosed directive " + directiveNode.directiveName);
- },
- parseDirectiveBlockVerbatim: function (directiveNode) {
- var textContent = [];
- while (this.lexer.hasNext()) {
- var nextToken = this.lexer.peekNextToken();
- if (nextToken.type === Lexer.tokens.directive &&
- nextToken.endDirective &&
- this.createDirectiveNodeFromToken(nextToken).directiveName === directiveNode.directiveName) {
- this.lexer.getNextToken();
- directiveNode.appendChild(this.createTextNode(textContent.join("\n"), true));
- return directiveNode;
- }
- textContent.push(this.lexer.stream.getNextLine());
- }
- throw this.createErrorReport("Unclosed directive " + directiveNode.directiveName);
- },
- parseDirectiveArguments: function (parameters) {
- return parameters.split(/[ ]+/).filter(function (param) {
- return param.length && param[0] !== "-";
- });
- },
- parseDirectiveOptions: function (parameters) {
- return parameters.split(/[ ]+/).filter(function (param) {
- return param.length && param[0] === "-";
- });
- },
- interpretDirective: function (directiveNode) {
- // http://orgmode.org/manual/Export-options.html
- switch (directiveNode.directiveName) {
- case "options:":
- this.interpretOptionDirective(directiveNode);
- break;
- case "title:":
- this.document.title = directiveNode.directiveRawValue;
- break;
- case "author:":
- this.document.author = directiveNode.directiveRawValue;
- break;
- case "email:":
- this.document.email = directiveNode.directiveRawValue;
- break;
- }
- },
- interpretOptionDirective: function (optionDirectiveNode) {
- optionDirectiveNode.directiveArguments.forEach(function (pairString) {
- var pair = pairString.split(":");
- this.options[pair[0]] = this.convertLispyValue(pair[1]);
- }, this);
- },
- convertLispyValue: function (lispyValue) {
- switch (lispyValue) {
- case "t":
- return true;
- case "nil":
- return false;
- default:
- if (/^[0-9]+$/.test(lispyValue))
- return parseInt(lispyValue);
- return lispyValue;
- }
- },
- // ------------------------------------------------------------
- // <Paragraph> ::= <Blank> <Line>*
- // ------------------------------------------------------------
- parseParagraph: function () {
- var paragraphFisrtToken = this.lexer.peekNextToken();
- var paragraph = Node.createParagraph([]);
- this.setNodeOriginFromToken(paragraph, paragraphFisrtToken);
- var textContents = [];
- while (this.lexer.hasNext()) {
- var nextToken = this.lexer.peekNextToken();
- if (nextToken.type !== Lexer.tokens.line
- || nextToken.indentation < paragraphFisrtToken.indentation)
- break;
- this.lexer.getNextToken();
- textContents.push(nextToken.content);
- }
- paragraph.appendChild(this.createTextNode(textContents.join("\n")));
- return paragraph;
- },
- parseText: function (noEmphasis) {
- var lineToken = this.lexer.getNextToken();
- return this.createTextNode(lineToken.content, noEmphasis);
- },
- // ------------------------------------------------------------
- // <Text> (DOM Like)
- // ------------------------------------------------------------
- createTextNode: function (text, noEmphasis) {
- return noEmphasis ? Node.createText(null, { value: text })
- : this.inlineParser.parseEmphasis(text);
- }
- };
- Parser.prototype.originalParseElement = Parser.prototype.parseElement;
- // ------------------------------------------------------------
- // Parser for Inline Elements
- //
- // @refs org-emphasis-regexp-components
- // ------------------------------------------------------------
- function InlineParser() {
- this.preEmphasis = " \t\\('\"";
- this.postEmphasis = "- \t.,:!?;'\"\\)";
- this.borderForbidden = " \t\r\n,\"'";
- this.bodyRegexp = "[\\s\\S]*?";
- this.markers = "*/_=~+";
- this.emphasisPattern = this.buildEmphasisPattern();
- this.linkPattern = /\[\[([^\]]*)\](?:\[([^\]]*)\])?\]/g; // \1 => link, \2 => text
- }
- InlineParser.prototype = {
- parseEmphasis: function (text) {
- var emphasisPattern = this.emphasisPattern;
- emphasisPattern.lastIndex = 0;
- var result = [],
- match,
- previousLast = 0,
- savedLastIndex;
- while ((match = emphasisPattern.exec(text))) {
- var whole = match[0];
- var pre = match[1];
- var marker = match[2];
- var body = match[3];
- var post = match[4];
- {
- // parse links
- var matchBegin = emphasisPattern.lastIndex - whole.length;
- var beforeContent = text.substring(previousLast, matchBegin + pre.length);
- savedLastIndex = emphasisPattern.lastIndex;
- result.push(this.parseLink(beforeContent));
- emphasisPattern.lastIndex = savedLastIndex;
- }
- var bodyNode = [Node.createText(null, { value: body })];
- var bodyContainer = this.emphasizeElementByMarker(bodyNode, marker);
- result.push(bodyContainer);
- previousLast = emphasisPattern.lastIndex - post.length;
- }
- if (emphasisPattern.lastIndex === 0 ||
- emphasisPattern.lastIndex !== text.length - 1)
- result.push(this.parseLink(text.substring(previousLast)));
- if (result.length === 1) {
- // Avoid duplicated inline container wrapping
- return result[0];
- } else {
- return Node.createInlineContainer(result);
- }
- },
- depth: 0,
- parseLink: function (text) {
- var linkPattern = this.linkPattern;
- linkPattern.lastIndex = 0;
- var match,
- result = [],
- previousLast = 0,
- savedLastIndex;
- while ((match = linkPattern.exec(text))) {
- var whole = match[0];
- var src = match[1];
- var title = match[2];
- // parse before content
- var matchBegin = linkPattern.lastIndex - whole.length;
- var beforeContent = text.substring(previousLast, matchBegin);
- result.push(Node.createText(null, { value: beforeContent }));
- // parse link
- var link = Node.createLink([]);
- link.src = src;
- if (title) {
- savedLastIndex = linkPattern.lastIndex;
- link.appendChild(this.parseEmphasis(title));
- linkPattern.lastIndex = savedLastIndex;
- } else {
- link.appendChild(Node.createText(null, { value: src }));
- }
- result.push(link);
- previousLast = linkPattern.lastIndex;
- }
- if (linkPattern.lastIndex === 0 ||
- linkPattern.lastIndex !== text.length - 1)
- result.push(Node.createText(null, { value: text.substring(previousLast) }));
- return Node.createInlineContainer(result);
- },
- emphasizeElementByMarker: function (element, marker) {
- switch (marker) {
- case "*":
- return Node.createBold(element);
- case "/":
- return Node.createItalic(element);
- case "_":
- return Node.createUnderline(element);
- case "=":
- case "~":
- return Node.createCode(element);
- case "+":
- return Node.createDashed(element);
- }
- },
- buildEmphasisPattern: function () {
- return new RegExp(
- "([" + this.preEmphasis + "]|^|\r?\n)" + // \1 => pre
- "([" + this.markers + "])" + // \2 => marker
- "([^" + this.borderForbidden + "]|" + // \3 => body
- "[^" + this.borderForbidden + "]" +
- this.bodyRegexp +
- "[^" + this.borderForbidden + "])" +
- "\\2" +
- "([" + this.postEmphasis +"]|$|\r?\n)", // \4 => post
- // flags
- "g"
- );
- }
- };
- if (typeof exports !== "undefined") {
- exports.Parser = Parser;
- exports.InlineParser = InlineParser;
- }
- // var Node = require("../node.js").Node;
- function Converter() {
- }
- Converter.prototype = {
- exportOptions: {
- headerOffset: 1,
- exportFromLineNumber: false,
- suppressSubScriptHandling: false,
- suppressAutoLink: false
- },
- untitled: "Untitled",
- result: null,
- // TODO: Manage TODO lists
- initialize: function (orgDocument, exportOptions) {
- this.orgDocument = orgDocument;
- this.documentOptions = orgDocument.options || {};
- this.exportOptions = exportOptions || {};
- this.headers = [];
- this.headerOffset =
- typeof this.exportOptions.headerOffset === "number" ? this.exportOptions.headerOffset : 1;
- this.sectionNumbers = [0];
- },
- createTocItem: function (headerNode, parentTocs) {
- var childTocs = [];
- childTocs.parent = parentTocs;
- var tocItem = { headerNode: headerNode, childTocs: childTocs };
- return tocItem;
- },
- computeToc: function (exportTocLevel) {
- if (typeof exportTocLevel !== "number")
- exportTocLevel = Infinity;
- var toc = [];
- toc.parent = null;
- var previousLevel = 1;
- var currentTocs = toc; // first
- for (var i = 0; i < this.headers.length; ++i) {
- var headerNode = this.headers[i];
- if (headerNode.level > exportTocLevel)
- continue;
- var levelDiff = headerNode.level - previousLevel;
- if (levelDiff > 0) {
- for (var j = 0; j < levelDiff; ++j) {
- if (currentTocs.length === 0) {
- // Create a dummy tocItem
- var dummyHeader = Node.createHeader([], {
- level: previousLevel + j
- });
- dummyHeader.sectionNumberText = "";
- currentTocs.push(this.createTocItem(dummyHeader, currentTocs));
- }
- currentTocs = currentTocs[currentTocs.length - 1].childTocs;
- }
- } else if (levelDiff < 0) {
- levelDiff = -levelDiff;
- for (var k = 0; k < levelDiff; ++k) {
- currentTocs = currentTocs.parent;
- }
- }
- currentTocs.push(this.createTocItem(headerNode, currentTocs));
- previousLevel = headerNode.level;
- }
- return toc;
- },
- convertNode: function (node, recordHeader, insideCodeElement) {
- if (!insideCodeElement) {
- if (node.type === Node.types.directive) {
- if (node.directiveName === "example" ||
- node.directiveName === "src") {
- insideCodeElement = true;
- }
- } else if (node.type === Node.types.preformatted) {
- insideCodeElement = true;
- }
- }
- if (typeof node === "string") {
- node = Node.createText(null, { value: node });
- }
- var childText = node.children ? this.convertNodes(node.children, recordHeader, insideCodeElement) : "";
- var text;
- var auxData = this.computeAuxDataForNode(node);
- switch (node.type) {
- case Node.types.header:
- // Parse task status
- var taskStatus = null;
- if (childText.indexOf("TODO ") === 0)
- taskStatus = "todo";
- else if (childText.indexOf("DONE ") === 0)
- taskStatus = "done";
- // Compute section number
- var sectionNumberText = null;
- if (recordHeader) {
- var thisHeaderLevel = node.level;
- var previousHeaderLevel = this.sectionNumbers.length;
- if (thisHeaderLevel > previousHeaderLevel) {
- // Fill missing section number
- var levelDiff = thisHeaderLevel - previousHeaderLevel;
- for (var j = 0; j < levelDiff; ++j) {
- this.sectionNumbers[thisHeaderLevel - 1 - j] = 0; // Extend
- }
- } else if (thisHeaderLevel < previousHeaderLevel) {
- this.sectionNumbers.length = thisHeaderLevel; // Collapse
- }
- this.sectionNumbers[thisHeaderLevel - 1]++;
- sectionNumberText = this.sectionNumbers.join(".");
- node.sectionNumberText = sectionNumberText; // Can be used in ToC
- }
- text = this.convertHeader(node, childText, auxData,
- taskStatus, sectionNumberText);
- if (recordHeader)
- this.headers.push(node);
- break;
- case Node.types.orderedList:
- text = this.convertOrderedList(node, childText, auxData);
- break;
- case Node.types.unorderedList:
- text = this.convertUnorderedList(node, childText, auxData);
- break;
- case Node.types.definitionList:
- text = this.convertDefinitionList(node, childText, auxData);
- break;
- case Node.types.listElement:
- if (node.isDefinitionList) {
- var termText = this.convertNodes(node.term, recordHeader, insideCodeElement);
- text = this.convertDefinitionItem(node, childText, auxData,
- termText, childText);
- } else {
- text = this.convertListItem(node, childText, auxData);
- }
- break;
- case Node.types.paragraph:
- text = this.convertParagraph(node, childText, auxData);
- break;
- case Node.types.preformatted:
- text = this.convertPreformatted(node, childText, auxData);
- break;
- case Node.types.table:
- text = this.convertTable(node, childText, auxData);
- break;
- case Node.types.tableRow:
- text = this.convertTableRow(node, childText, auxData);
- break;
- case Node.types.tableCell:
- if (node.isHeader)
- text = this.convertTableHeader(node, childText, auxData);
- else
- text = this.convertTableCell(node, childText, auxData);
- break;
- case Node.types.horizontalRule:
- text = this.convertHorizontalRule(node, childText, auxData);
- break;
- // ============================================================ //
- // Inline
- // ============================================================ //
- case Node.types.inlineContainer:
- text = this.convertInlineContainer(node, childText, auxData);
- break;
- case Node.types.bold:
- text = this.convertBold(node, childText, auxData);
- break;
- case Node.types.italic:
- text = this.convertItalic(node, childText, auxData);
- break;
- case Node.types.underline:
- text = this.convertUnderline(node, childText, auxData);
- break;
- case Node.types.code:
- text = this.convertCode(node, childText, auxData);
- break;
- case Node.types.dashed:
- text = this.convertDashed(node, childText, auxData);
- break;
- case Node.types.link:
- text = this.convertLink(node, childText, auxData);
- break;
- case Node.types.directive:
- switch (node.directiveName) {
- case "quote":
- text = this.convertQuote(node, childText, auxData);
- break;
- case "example":
- text = this.convertExample(node, childText, auxData);
- break;
- case "src":
- text = this.convertSrc(node, childText, auxData);
- break;
- default:
- text = childText;
- }
- break;
- case Node.types.text:
- text = this.convertText(node.value, insideCodeElement);
- break;
- default:
- throw "Unknown node type: " + node.type;
- }
- if (typeof this.postProcess === "function") {
- text = this.postProcess(node, text, insideCodeElement);
- }
- return text;
- },
- convertText: function (text, insideCodeElement) {
- var escapedText = this.escapeSpecialChars(text, insideCodeElement);
- if (!this.exportOptions.suppressSubScriptHandling && !insideCodeElement) {
- escapedText = this.makeSubscripts(escapedText, insideCodeElement);
- }
- if (!this.exportOptions.suppressAutoLink) {
- escapedText = this.linkURL(escapedText);
- }
- return escapedText;
- },
- convertNodes: function (nodes, recordHeader, insideCodeElement) {
- return nodes.map(function (node) {
- return this.convertNode(node, recordHeader, insideCodeElement);
- }, this).join("");
- },
- getNodeTextContent: function (node) {
- if (node.type === Node.types.text)
- return this.escapeSpecialChars(node.value);
- else
- return node.children ? node.children.map(this.getNodeTextContent, this).join("") : "";
- },
- // @Override
- escapeSpecialChars: function (text) {
- throw "Implement escapeSpecialChars";
- },
- // http://daringfireball.net/2010/07/improved_regex_for_matching_urls
- urlPattern: /\b(?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])/i,
- // @Override
- linkURL: function (text) {
- var self = this;
- return text.replace(this.urlPattern, function (matched) {
- if (matched.indexOf("://") < 0)
- matched = "http://" + matched;
- return self.makeLink(matched);
- });
- },
- makeLink: function (url) {
- throw "Implement makeLink";
- },
- makeSubscripts: function (text) {
- if (this.documentOptions["^"] === "{}")
- return text.replace(/\b([^_ \t]*)_{([^}]*)}/g,
- this.makeSubscript);
- else if (this.documentOptions["^"])
- return text.replace(/\b([^_ \t]*)_([^_]*)\b/g,
- this.makeSubscript);
- else
- return text;
- },
- makeSubscript: function (match, body, subscript) {
- throw "Implement makeSubscript";
- },
- imageExtensionPattern: new RegExp("(" + [
- "bmp", "png", "jpeg", "jpg", "gif", "tiff",
- "tif", "xbm", "xpm", "pbm", "pgm", "ppm"
- ].join("|") + ")$", "i")
- };
- if (typeof exports !== "undefined")
- exports.Converter = Converter;
- // var Converter = require("./converter.js").Converter;
- // var Node = require("../node.js").Node;
- function ConverterHTML(orgDocument, exportOptions) {
- this.initialize(orgDocument, exportOptions);
- this.result = this.convert();
- }
- ConverterHTML.prototype = {
- __proto__: Converter.prototype,
- convert: function () {
- var title = this.orgDocument.title ? this.convertNode(this.orgDocument.title) : this.untitled;
- var titleHTML = this.tag("h1", title);
- var contentHTML = this.convertNodes(this.orgDocument.nodes, true /* record headers */);
- var toc = this.computeToc(this.documentOptions["toc"]);
- var tocHTML = this.tocToHTML(toc);
- return {
- title: title,
- titleHTML: titleHTML,
- contentHTML: contentHTML,
- tocHTML: tocHTML,
- toc: toc,
- toString: function () {
- return titleHTML + tocHTML + "\n" + contentHTML;
- }
- };
- },
- tocToHTML: function (toc) {
- function tocToHTMLFunction(tocList) {
- var html = "";
- for (var i = 0; i < tocList.length; ++i) {
- var tocItem = tocList[i];
- var sectionNumberText = tocItem.headerNode.sectionNumberText;
- var sectionNumber = this.documentOptions.num ?
- this.inlineTag("span", sectionNumberText, {
- "class": "section-number"
- }) : "";
- var header = this.getNodeTextContent(tocItem.headerNode);
- var headerLink = this.inlineTag("a", sectionNumber + header, {
- href: "#header-" + sectionNumberText.replace(/\./g, "-")
- });
- var subList = tocItem.childTocs.length ? tocToHTMLFunction.call(this, tocItem.childTocs) : "";
- html += this.tag("li", headerLink + subList);
- }
- return this.tag("ul", html);
- }
- return tocToHTMLFunction.call(this, toc);
- },
- computeAuxDataForNode: function (node) {
- while (node.parent &&
- node.parent.type === Node.types.inlineContainer) {
- node = node.parent;
- }
- var attributesNode = node.previousSibling;
- var attributesText = "";
- while (attributesNode &&
- attributesNode.type === Node.types.directive &&
- attributesNode.directiveName === "attr_html:") {
- attributesText += attributesNode.directiveRawValue + " ";
- attributesNode = attributesNode.previousSibling;
- }
- return attributesText;
- },
- // ----------------------------------------------------
- // Node conversion
- // ----------------------------------------------------
- convertHeader: function (node, childText, auxData,
- taskStatus, sectionNumberText) {
- var headerAttributes = {};
- if (taskStatus) {
- childText = this.inlineTag("span", childText.substring(0, 4), {
- "class": "task-status " + taskStatus
- }) + childText.substring(5);
- }
- if (sectionNumberText) {
- childText = this.inlineTag("span", sectionNumberText, {
- "class": "section-number"
- }) + childText;
- headerAttributes["id"] = "header-" + sectionNumberText.replace(/\./g, "-");
- }
- if (taskStatus)
- headerAttributes["class"] = "task-status " + taskStatus;
- return this.tag("h" + (this.headerOffset + node.level),
- childText, headerAttributes, auxData);
- },
- convertOrderedList: function (node, childText, auxData) {
- return this.tag("ol", childText, null, auxData);
- },
- convertUnorderedList: function (node, childText, auxData) {
- return this.tag("ul", childText, null, auxData);
- },
- convertDefinitionList: function (node, childText, auxData) {
- return this.tag("dl", childText, null, auxData);
- },
- convertDefinitionItem: function (node, childText, auxData,
- term, definition) {
- return this.tag("dt", term) + this.tag("dd", definition);
- },
- convertListItem: function (node, childText, auxData) {
- if (this.exportOptions.suppressCheckboxHandling) {
- return this.tag("li", childText, null, auxData);
- } else {
- var listItemAttributes = {};
- var listItemText = childText;
- // Embed checkbox
- if (/^\s*\[(X| |-)\]([\s\S]*)/.exec(listItemText)) {
- listItemText = RegExp.$2 ;
- var checkboxIndicator = RegExp.$1;
- var checkboxAttributes = { type: "checkbox" };
- switch (checkboxIndicator) {
- case "X":
- checkboxAttributes["checked"] = "true";
- listItemAttributes["data-checkbox-status"] = "done";
- break;
- case "-":
- listItemAttributes["data-checkbox-status"] = "intermediate";
- break;
- default:
- listItemAttributes["data-checkbox-status"] = "undone";
- break;
- }
- listItemText = this.inlineTag("input", null, checkboxAttributes) + listItemText;
- }
- return this.tag("li", listItemText, listItemAttributes, auxData);
- }
- },
- convertParagraph: function (node, childText, auxData) {
- return this.tag("p", childText, null, auxData);
- },
- convertPreformatted: function (node, childText, auxData) {
- return this.tag("pre", childText, null, auxData);
- },
- convertTable: function (node, childText, auxData) {
- return this.tag("table", this.tag("tbody", childText), null, auxData);
- },
- convertTableRow: function (node, childText, auxData) {
- return this.tag("tr", childText);
- },
- convertTableHeader: function (node, childText, auxData) {
- return this.tag("th", childText);
- },
- convertTableCell: function (node, childText, auxData) {
- return this.tag("td", childText);
- },
- convertHorizontalRule: function (node, childText, auxData) {
- return this.tag("hr", null, null, auxData);
- },
- convertInlineContainer: function (node, childText, auxData) {
- return childText;
- },
- convertBold: function (node, childText, auxData) {
- return this.inlineTag("b", childText);
- },
- convertItalic: function (node, childText, auxData) {
- return this.inlineTag("i", childText);
- },
- convertUnderline: function (node, childText, auxData) {
- return this.inlineTag("span", childText, {
- style: "text-decoration:underline;"
- });
- },
- convertCode: function (node, childText, auxData) {
- return this.inlineTag("code", childText);
- },
- convertDashed: function (node, childText, auxData) {
- return this.inlineTag("del", childText);
- },
- convertLink: function (node, childText, auxData) {
- if (this.imageExtensionPattern.exec(node.src)) {
- var imgText = this.getNodeTextContent(node);
- return this.inlineTag("img", null, {
- src: node.src,
- alt: imgText,
- title: imgText
- }, auxData);
- } else {
- return this.inlineTag("a", childText, { href: node.src });
- }
- },
- convertQuote: function (node, childText, auxData) {
- return this.tag("blockquote", childText, null, auxData);
- },
- convertExample: function (node, childText, auxData) {
- return this.tag("pre", childText, null, auxData);
- },
- convertSrc: function (node, childText, auxData) {
- var codeLanguage = node.directiveArguments.length
- ? node.directiveArguments[0]
- : "unknown";
- childText = this.tag("code", childText, {
- "class": "language-" + codeLanguage
- }, auxData);
- return this.tag("pre", childText, {
- "class": "prettyprint"
- });
- },
- // ----------------------------------------------------
- // Supplemental methods
- // ----------------------------------------------------
- replaceMap: {
- // [replacing pattern, predicate]
- "&": ["&", null],
- "<": ["<", null],
- ">": [">", null],
- '"': [""", null],
- "'": ["'", null],
- "->": ["➔", function (text, insideCodeElement) {
- return this.exportOptions.translateSymbolArrow && !insideCodeElement;
- }]
- },
- replaceRegexp: null,
- // @implement @override
- escapeSpecialChars: function (text, insideCodeElement) {
- if (!this.replaceRegexp) {
- this.replaceRegexp = new RegExp(Object.keys(this.replaceMap).join("|"), "g");
- }
- var replaceMap = this.replaceMap;
- var self = this;
- return text.replace(this.replaceRegexp, function (matched) {
- if (!replaceMap[matched]) {
- throw "escapeSpecialChars: Invalid match";
- }
- var predicate = replaceMap[matched][1];
- if (typeof predicate === "function" &&
- !predicate.call(self, text, insideCodeElement)) {
- // Not fullfill the predicate
- return matched;
- }
- return replaceMap[matched][0];
- });
- },
- // @implement
- postProcess: function (node, currentText, insideCodeElement) {
- if (this.exportOptions.exportFromLineNumber &&
- typeof node.fromLineNumber === "number") {
- // Wrap with line number information
- currentText = this.inlineTag("div", currentText, {
- "data-line-number": node.fromLineNumber
- });
- }
- return currentText;
- },
- // @implement
- makeLink: function (url) {
- return "<a href=\"" + url + "\">" + decodeURIComponent(url) + "</a>";
- },
- // @implement
- makeSubscript: function (match, body, subscript) {
- return "<span class=\"org-subscript-parent\">" +
- body +
- "</span><span class=\"org-subscript-child\">" +
- subscript +
- "</span>";
- },
- // ----------------------------------------------------
- // Specific methods
- // ----------------------------------------------------
- attributesObjectToString: function (attributesObject) {
- var attributesString = "";
- for (var attributeName in attributesObject) {
- if (attributesObject.hasOwnProperty(attributeName)) {
- attributesString += " " + attributeName + "=\"" + attributesObject[attributeName] + "\"";
- }
- }
- return attributesString;
- },
- inlineTag: function (name, innerText, attributesObject, auxAttributesText) {
- attributesObject = attributesObject || {};
- var htmlString = "<" + name;
- // TODO: check duplicated attributes
- if (auxAttributesText)
- htmlString += " " + auxAttributesText;
- htmlString += this.attributesObjectToString(attributesObject);
- if (innerText === null)
- return htmlString + "/>";
- htmlString += ">" + innerText + "</" + name + ">";
- return htmlString;
- },
- tag: function (name, innerText, attributesObject, auxAttributesText) {
- return this.inlineTag(name, innerText, attributesObject, auxAttributesText) + "\n";
- }
- };
- if (typeof exports !== "undefined")
- exports.ConverterHTML = ConverterHTML;
- return exports;
- })();
|