ecmarkdown
Advanced tools
Comparing version 6.0.0 to 6.0.2
@@ -107,3 +107,3 @@ "use strict"; | ||
if (text !== null) { | ||
frag.push(text); | ||
pushOrJoin(frag, text); | ||
} | ||
@@ -125,3 +125,9 @@ } | ||
// valid format | ||
frag = frag.concat(this.parseFormat(tok.name, opts)); | ||
let f = this.parseFormat(tok.name, opts); | ||
if (f.length === 1 && f[0].name === 'text') { | ||
pushOrJoin(frag, f[0]); | ||
} | ||
else { | ||
frag = frag.concat(f); | ||
} | ||
} | ||
@@ -162,4 +168,6 @@ } | ||
let wsChunk = ''; | ||
let lastWsTok = null; | ||
while (isWhitespace(tok)) { | ||
wsChunk += tok.contents; | ||
lastWsTok = tok; | ||
this._t.next(); | ||
@@ -172,11 +180,15 @@ tok = this._t.peek(); | ||
contents += wsChunk; | ||
if (lastWsTok !== null) { | ||
lastRealTok = lastWsTok; | ||
} | ||
} | ||
break; | ||
} | ||
if (tok.name === 'opaqueTag') { | ||
contents += wsChunk; | ||
contents += wsChunk; | ||
if (lastWsTok !== null) { | ||
lastRealTok = lastWsTok; | ||
} | ||
if (tok.name === 'opaqueTag' || tok.name === 'comment' || tok.name === 'tag') { | ||
break; | ||
} | ||
lastRealTok = tok; | ||
contents += wsChunk; | ||
if (isFormatToken(tok)) { | ||
@@ -199,11 +211,3 @@ // check if format token is valid | ||
} | ||
// TODO why is this not with the earlier break? | ||
if (tok.name === 'tag') { | ||
break; | ||
} | ||
if (tok.name === 'text' || isWhitespace(tok)) { | ||
contents += tok.contents; | ||
this._t.next(); | ||
continue; | ||
} | ||
lastRealTok = tok; | ||
// By default just take the token's contents | ||
@@ -221,2 +225,3 @@ contents += tok.contents; | ||
parseFormat(format, opts) { | ||
var _a; | ||
const startTok = this._t.next(); | ||
@@ -232,39 +237,38 @@ let contents = []; | ||
} | ||
const endTok = this._t.peek(); | ||
const pos = this.getPos(startTok); | ||
const end = this.getPos(endTok); | ||
const nextTok = this._t.peek(); | ||
const start = this.getPos(startTok); | ||
// fragment ended but we don't have a close format. Convert this node into a text node. | ||
if (endTok.name !== format) { | ||
unshiftOrJoin(contents, this.finish({ name: 'text', contents: startTok.contents }, pos, end)); | ||
if (nextTok.name !== format) { | ||
const lastTok = (_a = contents[contents.length - 1]) !== null && _a !== void 0 ? _a : startTok; | ||
unshiftOrJoin(contents, this.finish({ name: 'text', contents: startTok.contents }, start, lastTok.location.end)); | ||
return contents; | ||
} | ||
else { | ||
this._t.next(); // consume end format. | ||
if (contents.length === 0) { | ||
// empty formats not allowed | ||
return [ | ||
this.finish({ name: 'text', contents: startTok.contents + endTok.contents }, pos, end), | ||
]; | ||
const end = nextTok.location.end; | ||
this._t.next(); // consume end format. | ||
if (contents.length === 0) { | ||
// empty formats not allowed | ||
return [ | ||
this.finish({ name: 'text', contents: startTok.contents + nextTok.contents }, start, end), | ||
]; | ||
} | ||
else if (format === 'tick') { | ||
contents = contents.map(child => child.name === 'tag' | ||
? { ...child, name: 'text', contents: escape_html_1.default(child.contents) } | ||
: child); | ||
} | ||
else if (format === 'pipe') { | ||
const ntNode = parseNonTerminal(contents[0].contents); | ||
if (ntNode === null) { | ||
// failed to parse a non-terminal, so convert to text. | ||
const firstPos = this.getPos(contents[0]); | ||
const lastEnd = this.getEnd(contents[contents.length - 1]); | ||
unshiftOrJoin(contents, this.finish({ name: 'text', contents: '|' }, start, firstPos)); | ||
pushOrJoin(contents, this.finish({ name: 'text', contents: '|' }, lastEnd, end)); | ||
return contents; | ||
} | ||
else if (format === 'tick') { | ||
contents = contents.map(child => child.name === 'tag' | ||
? { ...child, name: 'text', contents: escape_html_1.default(child.contents) } | ||
: child); | ||
else { | ||
return [this.finish(ntNode, start, end)]; | ||
} | ||
else if (format === 'pipe') { | ||
const ntNode = parseNonTerminal(contents[0].contents); | ||
if (ntNode === null) { | ||
// failed to parse a non-terminal, so convert to text. | ||
const firstPos = this.getPos(contents[0]); | ||
const lastEnd = this.getEnd(contents[contents.length - 1]); | ||
unshiftOrJoin(contents, this.finish({ name: 'text', contents: '|' }, pos, firstPos)); | ||
pushOrJoin(contents, this.finish({ name: 'text', contents: '|' }, lastEnd, end)); | ||
return contents; | ||
} | ||
else { | ||
return [this.finish(ntNode, pos, end)]; | ||
} | ||
} | ||
} | ||
return [this.finish({ name: format, contents }, pos, end)]; | ||
return [this.finish({ name: format, contents }, start, end)]; | ||
} | ||
@@ -334,2 +338,3 @@ pushPos() { | ||
last.contents += node.contents; | ||
last.location.end = node.location.end; | ||
} | ||
@@ -345,2 +350,3 @@ else { | ||
first.contents = node.contents + first.contents; | ||
first.location.start = node.location.start; | ||
} | ||
@@ -347,0 +353,0 @@ else { |
@@ -17,3 +17,2 @@ import type { Unlocated, Token, IdToken, Position } from './node-types'; | ||
scanChars(): string; | ||
scanToEOL(): string; | ||
scanToEndTag(endTag: string): string; | ||
@@ -25,3 +24,2 @@ tryScanTag(): RegExpMatchArray | undefined; | ||
getLocation(): Position; | ||
enqueueLookahead(tok: Unlocated<Token>, pos: Position): void; | ||
enqueue(tok: Unlocated<Token>, pos: Position): void; | ||
@@ -28,0 +26,0 @@ dequeue(): import("./node-types").EOFToken | import("./node-types").FormatToken | import("./node-types").ParabreakToken | import("./node-types").LinebreakToken | import("./node-types").WhitespaceToken | import("./node-types").TextToken | import("./node-types").CommentToken | import("./node-types").OpaqueTagToken | import("./node-types").TagToken | import("./node-types").UnorderedListToken | import("./node-types").OrderedListToken | undefined; |
@@ -53,3 +53,2 @@ "use strict"; | ||
while (this.pos < len) { | ||
const start = this.getLocation(); | ||
chr = this.str[this.pos]; | ||
@@ -64,18 +63,5 @@ if (chr === '\\') { | ||
else if (chr === '<') { | ||
const tag = this.tryScanTag(); | ||
if (tag) { | ||
if (opaqueTags.has(tag[1]) && tag[2] !== '/') { | ||
const rest = this.scanToEndTag(tag[1]); | ||
this.enqueueLookahead({ name: 'opaqueTag', contents: tag[0] + rest }, start); | ||
} | ||
else { | ||
this.enqueueLookahead({ name: 'tag', contents: tag[0] }, start); | ||
} | ||
if (this.tryScanComment() || this.tryScanTag()) { | ||
break; | ||
} | ||
const comment = this.tryScanComment(); | ||
if (comment) { | ||
this.enqueueLookahead({ name: 'comment', contents: comment }, start); | ||
break; | ||
} | ||
out += chr; | ||
@@ -90,13 +76,2 @@ this.pos++; | ||
} | ||
scanToEOL() { | ||
let start = this.pos; | ||
let len = this.str.length; | ||
while (this.pos < len && this.str[this.pos] !== '\n') { | ||
this.pos++; | ||
} | ||
if (this.str[this.pos] === '\n') { | ||
this.pos++; | ||
} | ||
return this.str.slice(start, this.pos); | ||
} | ||
scanToEndTag(endTag) { | ||
@@ -108,2 +83,3 @@ let start = this.pos; | ||
if (tag) { | ||
this.pos += tag[0].length; | ||
if (tag[1] === endTag && tag[0][1] === '/') { | ||
@@ -119,2 +95,4 @@ break; | ||
} | ||
// does not actually consume the tag | ||
// you should manually `this.pos += tag[0].length;` if you end up consuming it | ||
tryScanTag() { | ||
@@ -124,9 +102,2 @@ if (this.str[this.pos] !== '<') { | ||
} | ||
// TODO: handle directives like <! doctype...> | ||
if (this.pos + 1 < this.str.length && | ||
this.str[this.pos + 1] !== '/' && | ||
this.str[this.pos + 1] !== '!' && | ||
!this.str[this.pos + 1].match(/\w/)) { | ||
return; | ||
} | ||
const match = this.str.slice(this.pos).match(tagRegexp); | ||
@@ -136,5 +107,6 @@ if (!match) { | ||
} | ||
this.pos += match[0].length; | ||
return match; | ||
} | ||
// does not actually consume the comment | ||
// you should manually `this.pos += comment.length;` if you end up consuming it | ||
tryScanComment() { | ||
@@ -145,3 +117,2 @@ const match = this.str.slice(this.pos).match(commentRegexp); | ||
} | ||
this.pos += match[0].length; | ||
return match[0]; | ||
@@ -204,2 +175,3 @@ } | ||
if (opaqueTags.has(tag[1]) && tag[2] !== '/') { | ||
this.pos += tag[0].length; | ||
const rest = this.scanToEndTag(tag[1]); | ||
@@ -212,3 +184,5 @@ this.enqueue({ name: 'opaqueTag', contents: ws + tag[0] + rest }, start); | ||
} | ||
this.enqueue({ name: 'tag', contents: tag[0] }, start); | ||
const tagStart = this.getLocation(); | ||
this.pos += tag[0].length; | ||
this.enqueue({ name: 'tag', contents: tag[0] }, tagStart); | ||
} | ||
@@ -219,2 +193,3 @@ return; | ||
if (comment) { | ||
this.pos += comment.length; | ||
this.enqueue({ name: 'comment', contents: ws + comment }, start); | ||
@@ -285,2 +260,3 @@ // this._newline = true; | ||
if (comment) { | ||
this.pos += comment.length; | ||
this.enqueue({ name: 'comment', contents: comment }, start); | ||
@@ -293,2 +269,3 @@ return; | ||
if (tag) { | ||
this.pos += tag[0].length; | ||
if (opaqueTags.has(tag[1]) && tag[2] !== '/') { | ||
@@ -322,6 +299,2 @@ const rest = this.scanToEndTag(tag[1]); | ||
} | ||
enqueueLookahead(tok, pos) { | ||
this.locate(tok, pos); | ||
this._lookahead.push(tok); | ||
} | ||
enqueue(tok, pos) { | ||
@@ -328,0 +301,0 @@ this.locate(tok, pos); |
@@ -6,2 +6,2 @@ import type { Node } from './node-types'; | ||
}; | ||
export declare function visit(node: Node, observer: Observer): void; | ||
export declare function visit(node: Node | Node[], observer: Observer): void; |
@@ -21,2 +21,6 @@ "use strict"; | ||
var _a, _b; | ||
if (Array.isArray(node)) { | ||
node.forEach(n => visit(n, observer)); | ||
return; | ||
} | ||
(_a = observer.enter) === null || _a === void 0 ? void 0 : _a.call(observer, node); | ||
@@ -23,0 +27,0 @@ // @ts-ignore |
{ | ||
"name": "ecmarkdown", | ||
"version": "6.0.0", | ||
"version": "6.0.2", | ||
"description": "A compiler for \"Ecmarkdown\" algorithm shorthand into HTML.", | ||
@@ -39,3 +39,3 @@ "main": "dist/ecmarkdown.js", | ||
"inline-elements": "^1.0.0", | ||
"js-beautify": "1.5.5", | ||
"js-beautify": "1.13.0", | ||
"mocha": "^7.1.1", | ||
@@ -42,0 +42,0 @@ "prettier": "^2.0.4", |
@@ -80,3 +80,3 @@ # Ecmarkdown | ||
**Nonterminals** are written as `|x|`, `|x_opt|`, `|x[p]|`, or `|x[p]_opt|`. These are translated, respectively, into `<emu-nt>x</emu-nt>`, `<emu-nt optional>x</emu-nt>`, `<emu-nt params="p">x</emu-nt>`, or `<emu-nt params="p" optional>x</emu-nt>`. Nonterminal names can only be composed of letters and numbers. Params can be composed of anything except a closing square bracket. | ||
**Nonterminals** are written as `|x|`, `|x?|`, `|x[p]|`, or `|x[p]?|`. These are translated, respectively, into `<emu-nt>x</emu-nt>`, `<emu-nt optional>x</emu-nt>`, `<emu-nt params="p">x</emu-nt>`, or `<emu-nt params="p" optional>x</emu-nt>`. Nonterminal names can only be composed of letters and numbers. Params can be composed of anything except a closing square bracket. It's possible to write `_opt` instead of `?`, e.g.: `|x_opt|` instead of `|x?|` and `|x[p]_opt|` instead of `|x[p]?|`. | ||
@@ -83,0 +83,0 @@ All formats can be started following non-alphanumeric and non-whitespace characters and can be ended following any non-whitespace character. The one exception is code formats which can begin and end in any context. For example, `my_SIMD_constructor` does not contain any variables while `_SIMD_Constructor` does. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
50213
1204
1