@markuplint/parser-utils
Advanced tools
Comparing version 4.4.0 to 4.5.0
@@ -1,2 +0,2 @@ | ||
import type { QuoteSet } from './types.js'; | ||
import type { QuoteSet, ValueType } from './types.js'; | ||
import { AttrState } from './enums.js'; | ||
@@ -8,3 +8,3 @@ /** | ||
*/ | ||
export declare function attrTokenizer(raw: string, quoteSet?: readonly QuoteSet[], startState?: AttrState, quoteInValueChars?: ReadonlyArray<QuoteSet>, endOfUnquotedValueChars?: ReadonlyArray<string>): { | ||
export declare function attrTokenizer(raw: string, quoteSet?: readonly QuoteSet[], startState?: AttrState, noQuoteValueType?: ValueType, endOfUnquotedValueChars?: ReadonlyArray<string>): { | ||
spacesBeforeAttrName: string; | ||
@@ -11,0 +11,0 @@ attrName: string; |
import { defaultSpaces } from './const.js'; | ||
import { AttrState } from './enums.js'; | ||
import { safeScriptParser } from './script-parser.js'; | ||
const defaultQuoteSet = [ | ||
{ start: '"', end: '"' }, | ||
{ start: "'", end: "'" }, | ||
{ start: '"', end: '"', type: 'string' }, | ||
{ start: "'", end: "'", type: 'string' }, | ||
]; | ||
const defaultQuoteInValueChars = []; | ||
const spaces = defaultSpaces; | ||
@@ -15,3 +15,3 @@ const EQUAL = '='; | ||
*/ | ||
export function attrTokenizer(raw, quoteSet = defaultQuoteSet, startState = AttrState.BeforeName, quoteInValueChars = defaultQuoteInValueChars, endOfUnquotedValueChars = [...defaultSpaces, '/', '>']) { | ||
export function attrTokenizer(raw, quoteSet = defaultQuoteSet, startState = AttrState.BeforeName, noQuoteValueType = 'string', endOfUnquotedValueChars = [...defaultSpaces, '/', '>']) { | ||
let state = startState; | ||
@@ -26,5 +26,5 @@ let spacesBeforeAttrName = ''; | ||
let attrValue = ''; | ||
let valueType = noQuoteValueType; | ||
let quoteEnd = ''; | ||
const isBeforeValueStarted = startState === AttrState.BeforeValue; | ||
const quoteModeStack = []; | ||
const chars = [...raw]; | ||
@@ -109,14 +109,6 @@ while (chars.length > 0) { | ||
quoteStart = quote.start; | ||
valueType = quote.type; | ||
state = AttrState.Value; | ||
break; | ||
} | ||
const raw = char + chars.join(''); | ||
const inQuote = quoteInValueChars.find(quote => raw.startsWith(quote.start)); | ||
if (inQuote) { | ||
quoteModeStack.push(inQuote); | ||
attrValue += inQuote.start; | ||
chars.splice(0, inQuote.start.length - 1); | ||
state = AttrState.Value; | ||
break; | ||
} | ||
chars.unshift(char); | ||
@@ -132,3 +124,3 @@ state = AttrState.Value; | ||
} | ||
if (quoteModeStack.length === 0 && char === quoteSet[quoteTypeIndex]?.end) { | ||
if (char === quoteSet[quoteTypeIndex]?.end) { | ||
quoteEnd = char; | ||
@@ -138,17 +130,9 @@ state = AttrState.AfterValue; | ||
} | ||
const raw = char + chars.join(''); | ||
const inQuoteEnd = quoteModeStack.at(-1); | ||
if (inQuoteEnd && raw.startsWith(inQuoteEnd.end)) { | ||
quoteModeStack.pop(); | ||
attrValue += inQuoteEnd.end; | ||
chars.splice(0, inQuoteEnd.end.length - 1); | ||
if (valueType === 'script') { | ||
const raw = char + chars.join(''); | ||
const { validScript } = safeScriptParser(raw); | ||
attrValue += validScript; | ||
chars.splice(0, validScript.length - 1); | ||
break; | ||
} | ||
const inQuoteStart = quoteInValueChars.find(quote => raw.startsWith(quote.start)); | ||
if (inQuoteStart) { | ||
quoteModeStack.push(inQuoteStart); | ||
attrValue += inQuoteStart.start; | ||
chars.splice(0, inQuoteStart.start.length - 1); | ||
break; | ||
} | ||
attrValue += char; | ||
@@ -155,0 +139,0 @@ break; |
@@ -1,2 +0,2 @@ | ||
import type { Token, ChildToken, QuoteSet, ParseOptions, ParserOptions, Tokenized } from './types.js'; | ||
import type { Token, ChildToken, QuoteSet, ParseOptions, ParserOptions, Tokenized, ValueType } from './types.js'; | ||
import type { EndTagType, MLASTDocument, MLASTParentNode, MLParser, ParserAuthoredElementNameDistinguishing, MLASTElement, MLASTElementCloseTag, MLASTToken, MLASTNodeTreeItem, MLASTTag, MLASTText, MLASTAttr, MLASTChildNode, MLASTSpreadAttr, ElementType, Walker, MLASTHTMLAttr } from '@markuplint/ml-ast'; | ||
@@ -79,3 +79,3 @@ import { AttrState } from './enums.js'; | ||
readonly quoteSet?: readonly QuoteSet[]; | ||
readonly quoteInValueChars?: readonly QuoteSet[]; | ||
readonly noQuoteValueType?: ValueType; | ||
readonly endOfUnquotedValueChars?: readonly string[]; | ||
@@ -82,0 +82,0 @@ readonly startState?: AttrState; |
@@ -358,3 +358,3 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
const startState = options?.startState ?? AttrState.BeforeName; | ||
const quoteInValueChars = options?.quoteInValueChars; | ||
const noQuoteValueType = options?.noQuoteValueType; | ||
const endOfUnquotedValueChars = options?.endOfUnquotedValueChars; | ||
@@ -366,3 +366,3 @@ let startOffset = token.startOffset; | ||
try { | ||
tokens = attrTokenizer(raw, quoteSet, startState, quoteInValueChars, endOfUnquotedValueChars); | ||
tokens = attrTokenizer(raw, quoteSet, startState, noQuoteValueType, endOfUnquotedValueChars); | ||
} | ||
@@ -786,3 +786,3 @@ catch (error) { | ||
const endTagUUID = node.uuid; | ||
const openTag = newNodeList.findLast((n) => n.type === 'starttag' ? n.pairNode?.uuid === endTagUUID : false); | ||
const openTag = newNodeList.findLast((n) => n.type === 'starttag' && !n.isGhost ? n.pairNode?.uuid === endTagUUID : false); | ||
if (!openTag) { | ||
@@ -789,0 +789,0 @@ node = __classPrivateFieldGet(this, _Parser_instances, "m", _Parser_convertIntoInvalidNode).call(this, node); |
export declare function scriptParser(script: string): ScriptTokenType[]; | ||
export declare function safeScriptParser(script: string): { | ||
validScript: string; | ||
leftover: string; | ||
}; | ||
export type ScriptTokenType = { | ||
@@ -3,0 +7,0 @@ type: 'Identifier' | 'Boolean' | 'Numeric' | 'String' | 'Template' | 'Punctuator'; |
// @ts-ignore | ||
import { tokenize } from 'espree'; | ||
import { tokenize, parse } from 'espree'; | ||
export function scriptParser(script) { | ||
@@ -13,1 +13,58 @@ const tokens = tokenize(script, { | ||
} | ||
export function safeScriptParser(script) { | ||
let { validScript, leftover } = safeParse(script); | ||
// Support for object literal | ||
if (leftover.trim()) { | ||
const assignment = '$='; | ||
({ validScript } = safeParse(`${assignment}${script}`)); | ||
validScript = validScript.length > assignment.length ? validScript.slice(assignment.length) : ''; | ||
} | ||
// Support for spread operator | ||
if (validScript.trim() === '') { | ||
const coverStart = '$={'; | ||
const coverEnd = '}'; | ||
({ validScript } = safeParse(`${coverStart}${script}${coverEnd}`)); | ||
const coverEndLastIndex = validScript.lastIndexOf(coverEnd); | ||
validScript = | ||
validScript.length > coverStart.length + coverEnd.length | ||
? validScript.slice(coverStart.length, coverEndLastIndex) | ||
: ''; | ||
} | ||
leftover = script.slice(validScript.length); | ||
return { | ||
validScript, | ||
leftover, | ||
}; | ||
} | ||
function safeParse(script) { | ||
let validScript; | ||
let leftover; | ||
try { | ||
parse(script, { | ||
ecmaVersion: 'latest', | ||
ecmaFeatures: { | ||
jsx: true, | ||
}, | ||
}); | ||
validScript = script; | ||
leftover = ''; | ||
} | ||
catch (error) { | ||
if (error instanceof SyntaxError && 'index' in error && typeof error.index === 'number') { | ||
let index = error.index; | ||
const unexpectedToken = script.slice(index); | ||
if (unexpectedToken.trim() === '') { | ||
index = script.search(/\S\s*$/); | ||
} | ||
validScript = script.slice(0, index); | ||
leftover = script.slice(index); | ||
} | ||
else { | ||
throw error; | ||
} | ||
} | ||
return { | ||
validScript, | ||
leftover, | ||
}; | ||
} |
@@ -56,2 +56,4 @@ import type { EndTagType, MLASTParentNode, ParserOptions as ConfigParserOptions } from '@markuplint/ml-ast'; | ||
readonly end: string; | ||
readonly type: ValueType; | ||
}; | ||
export type ValueType = 'string' | 'script'; |
{ | ||
"name": "@markuplint/parser-utils", | ||
"version": "4.4.0", | ||
"version": "4.5.0", | ||
"description": "Utility module for markuplint parser plugin", | ||
@@ -31,11 +31,11 @@ "repository": "git@github.com:markuplint/markuplint.git", | ||
"@markuplint/ml-ast": "4.2.0", | ||
"@markuplint/ml-spec": "4.3.0", | ||
"@markuplint/types": "4.2.0", | ||
"@markuplint/ml-spec": "4.4.0", | ||
"@markuplint/types": "4.3.0", | ||
"@types/uuid": "9.0.8", | ||
"debug": "4.3.4", | ||
"espree": "10.0.1", | ||
"type-fest": "4.14.0", | ||
"type-fest": "4.15.0", | ||
"uuid": "9.0.1" | ||
}, | ||
"gitHead": "ad3db077e96bea0666c9105b250f895263907a87" | ||
"gitHead": "d5c8786b0dbbd82cdd89018dd57941d62bbe8d06" | ||
} |
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
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
102432
2658
+ Added@markuplint/ml-spec@4.4.0(transitive)
+ Added@markuplint/types@4.3.0(transitive)
+ Addedtype-fest@4.15.0(transitive)
- Removed@markuplint/ml-spec@4.3.0(transitive)
- Removed@markuplint/types@4.2.0(transitive)
- Removedtype-fest@4.14.0(transitive)
Updated@markuplint/ml-spec@4.4.0
Updated@markuplint/types@4.3.0
Updatedtype-fest@4.15.0