Comparing version 14.1.2 to 14.1.3
@@ -126,4 +126,9 @@ "use strict"; | ||
const match = tok.name === 'text' ? tok.contents.match(tokMatcher) : null; | ||
// the `tok.name !== 'text'` part in the test below is redundant but makes TS happier | ||
if (tok.name !== 'text' || match == null) { | ||
if (!(tok.name === 'text' && tok.contents.length === 0)) { | ||
const empty = (tok.name === 'text' && tok.contents.length === 0) || | ||
tok.name === 'tag' || | ||
tok.name === 'opaqueTag' || | ||
tok.name === 'comment'; | ||
if (!empty) { | ||
currentProse.push(tok); | ||
@@ -161,2 +166,27 @@ } | ||
} | ||
// returns true if this ate a newline | ||
eatWhitespace() { | ||
var _a; | ||
let next; | ||
let hadNewline = false; | ||
while (((_a = (next = this.peek())) === null || _a === void 0 ? void 0 : _a.type) === 'prose') { | ||
const firstNonWhitespaceIdx = next.parts.findIndex(part => part.name !== 'text' || /\S/.test(part.contents)); | ||
if (firstNonWhitespaceIdx === -1) { | ||
hadNewline || (hadNewline = next.parts.some(part => part.name === 'text' && part.contents.includes('\n'))); | ||
this.next.shift(); | ||
} | ||
else if (firstNonWhitespaceIdx === 0) { | ||
return hadNewline; | ||
} | ||
else { | ||
hadNewline || (hadNewline = next.parts.some((part, i) => i < firstNonWhitespaceIdx && part.name === 'text' && part.contents.includes('\n'))); | ||
this.next[0] = { | ||
type: 'prose', | ||
parts: next.parts.slice(firstNonWhitespaceIdx), | ||
}; | ||
return hadNewline; | ||
} | ||
} | ||
return hadNewline; | ||
} | ||
// guarantees the next token is an element of close | ||
@@ -329,3 +359,13 @@ parseSeq(close) { | ||
while (true) { | ||
const hadNewline = this.eatWhitespace(); | ||
const nextTok = this.peek(); | ||
if (nextTok.type === 'crec') { | ||
if (!hadNewline) { | ||
// ideally this would be a lint failure, or better yet a formatting thing, but whatever | ||
throw new ParseFailure(members.length > 0 | ||
? 'trailing commas are only allowed when followed by a newline' | ||
: 'records cannot be empty', nextTok.offset); | ||
} | ||
break; | ||
} | ||
if (nextTok.type !== 'prose') { | ||
@@ -340,10 +380,2 @@ throw new ParseFailure('expected to find record field name', nextTok.offset); | ||
if (nameMatch == null) { | ||
if (members.length > 0 && /^\s*$/.test(contents) && contents.includes('\n')) { | ||
// allow trailing commas when followed by a newline | ||
this.next.shift(); // eat the whitespace | ||
if (this.peek().type === 'crec') { | ||
this.next.shift(); | ||
break; | ||
} | ||
} | ||
throw new ParseFailure('expected to find record field', nextTok.parts[0].location.start.offset + contents.match(/^\s*/)[0].length); | ||
@@ -478,2 +510,4 @@ } | ||
} | ||
// Note: this does not necessarily represent the entire input | ||
// in particular it may omit some whitespace, tags, and comments | ||
function parse(src, opNames) { | ||
@@ -480,0 +514,0 @@ const parser = new ExprParser(src, opNames); |
{ | ||
"name": "ecmarkup", | ||
"version": "14.1.2", | ||
"version": "14.1.3", | ||
"description": "Custom element definitions and core utilities for markup that specifies ECMAScript and related technologies.", | ||
@@ -5,0 +5,0 @@ "main": "lib/ecmarkup.js", |
456239
12041