@riotjs/parser
Advanced tools
Comparing version 0.8.1 to 4.0.0-rc.1
# Changes for riot-parser | ||
### v4.0.0-rc.1 | ||
- Fix https://github.com/riot/riot/issues/2679 | ||
- Add support for `<a {href}>` expression attributes shortcuts | ||
### v0.8.1 | ||
@@ -4,0 +9,0 @@ - Add the `src` folder to the npm publishing files |
79
index.js
@@ -989,2 +989,26 @@ 'use strict'; | ||
/** | ||
* Memoization function | ||
* @param {Function} fn - function to memoize | ||
* @returns {*} return of the function to memoize | ||
*/ | ||
function memoize(fn) { | ||
const cache = new WeakMap(); | ||
return (...args) => { | ||
if (cache.has(args[0])) return cache.get(args[0]) | ||
const ret = fn(...args); | ||
cache.set(args[0], ret); | ||
return ret | ||
} | ||
} | ||
const expressionsContentRe = memoize(brackets => RegExp(`(${brackets[0]}[^${brackets[1]}]*?${brackets[1]})`)); | ||
const isSpreadAttribute = name => SPREAD_OPERATOR.test(name); | ||
const isAttributeExpression = (name, brackets) => name[0] === brackets[0]; | ||
const getAttributeEnd = (state, attr) => expr(state, attr, '[>/\\s]', attr.start); | ||
/** | ||
* The more complex parsing is for attributes as it can contain quoted or | ||
@@ -1042,9 +1066,12 @@ * unquoted values or expressions. | ||
const { data } = state; | ||
const expressionContent = expressionsContentRe(state.options.brackets); | ||
const re = ATTR_START; // (\S[^>/=\s]*)(?:\s*=\s*([^>/])?)? g | ||
const start = re.lastIndex = pos; // first non-whitespace | ||
const match = re.exec(data); | ||
const attrMatches = re.exec(data); | ||
const isExpressionName = isAttributeExpression(attrMatches[1], state.options.brackets); | ||
const match = isExpressionName ? [null, expressionContent.exec(data)[1], null] : attrMatches; | ||
if (match) { | ||
const end = re.lastIndex; | ||
const attr = parseAttribute(state, match, start, end); | ||
const attr = parseAttribute(state, match, start, end, isExpressionName); | ||
@@ -1090,12 +1117,19 @@ //assert(q && q.type === Mode.TAG, 'no previous tag for the attr!') | ||
function parseSpreadAttribute(state, attr, quote) { | ||
let end = expr(state, attr, quote || '[>/\\s]', attr.start); | ||
/** | ||
* Parse expression names <a {href}> | ||
* @param {ParserStore} state - Parser state | ||
* @param {Object} attr - attribute object parsed | ||
* @returns {Object} normalized attribute object | ||
*/ | ||
function parseSpreadAttribute(state, attr) { | ||
const end = getAttributeEnd(state, attr); | ||
return { | ||
[IS_SPREAD]: true, | ||
start: attr.start, | ||
expressions: attr.expressions.map(expr$$1 => Object.assign(expr$$1, { | ||
text: expr$$1.text.replace(SPREAD_OPERATOR, '') | ||
expressions: attr.expressions.map(expr => Object.assign(expr, { | ||
text: expr.text.replace(SPREAD_OPERATOR, '').trim() | ||
})), | ||
end: quote ? ++end : end | ||
end: end | ||
} | ||
@@ -1105,2 +1139,19 @@ } | ||
/** | ||
* Parse expression names <a {href}> | ||
* @param {ParserStore} state - Parser state | ||
* @param {Object} attr - attribute object parsed | ||
* @returns {Object} normalized attribute object | ||
*/ | ||
function parseExpressionNameAttribute(state, attr) { | ||
const end = getAttributeEnd(state, attr); | ||
return { | ||
start: attr.start, | ||
name: attr.expressions[0].text.trim(), | ||
expressions: attr.expressions, | ||
end: end | ||
} | ||
} | ||
/** | ||
* Parse the attribute values normalising the quotes | ||
@@ -1111,5 +1162,6 @@ * @param {ParserStore} state - Parser state | ||
* @param {number} end - attribute end position | ||
* @param {boolean} isExpressionName - true if the attribute name is an expression | ||
* @returns {Object} attribute object | ||
*/ | ||
function parseAttribute(state, match, start, end) { | ||
function parseAttribute(state, match, start, end, isExpressionName) { | ||
const attr = { | ||
@@ -1121,6 +1173,11 @@ name: match[1], | ||
}; | ||
const quote = match[2]; // first letter of value or nothing | ||
if (SPREAD_OPERATOR.test(attr.name)) { | ||
return parseSpreadAttribute(state, attr, quote) | ||
if (isExpressionName) { | ||
if (isSpreadAttribute(attr.name)) { | ||
return parseSpreadAttribute(state, attr) | ||
} | ||
return parseExpressionNameAttribute(state, attr) | ||
} | ||
@@ -1660,3 +1717,3 @@ | ||
exports.default = parser; | ||
exports.nodeTypes = nodeTypes; | ||
exports.default = parser; |
{ | ||
"name": "@riotjs/parser", | ||
"version": "0.8.1", | ||
"version": "4.0.0-rc.1", | ||
"description": "The parser for Riot tags", | ||
@@ -50,14 +50,14 @@ "main": "./index.js", | ||
"chai": "^4.2.0", | ||
"coveralls": "^3.0.2", | ||
"eslint": "^5.8.0", | ||
"coveralls": "^3.0.3", | ||
"eslint": "^5.16.0", | ||
"eslint-config-riot": "^2.0.0", | ||
"mocha": "^5.2.0", | ||
"nyc": "^13.1.0", | ||
"rollup": "^1.0.0", | ||
"rollup-plugin-node-resolve": "^3.4.0" | ||
"mocha": "^6.0.2", | ||
"nyc": "^13.3.0", | ||
"rollup": "^1.8.0", | ||
"rollup-plugin-node-resolve": "^4.0.1" | ||
}, | ||
"dependencies": { | ||
"curri": "^1.0.0", | ||
"curri": "^1.0.1", | ||
"dom-nodes": "^1.0.0" | ||
} | ||
} |
@@ -9,2 +9,9 @@ import {ATTR, TEXT} from '../node-types' | ||
import {isBoolAttribute} from 'dom-nodes' | ||
import memoize from '../utils/memoize' | ||
const expressionsContentRe = memoize(brackets => RegExp(`(${brackets[0]}[^${brackets[1]}]*?${brackets[1]})`)) | ||
const isSpreadAttribute = name => SPREAD_OPERATOR.test(name) | ||
const isAttributeExpression = (name, brackets) => name[0] === brackets[0] | ||
const getAttributeEnd = (state, attr) => expr(state, attr, '[>/\\s]', attr.start) | ||
/** | ||
@@ -63,9 +70,12 @@ * The more complex parsing is for attributes as it can contain quoted or | ||
const { data } = state | ||
const expressionContent = expressionsContentRe(state.options.brackets) | ||
const re = ATTR_START // (\S[^>/=\s]*)(?:\s*=\s*([^>/])?)? g | ||
const start = re.lastIndex = pos // first non-whitespace | ||
const match = re.exec(data) | ||
const attrMatches = re.exec(data) | ||
const isExpressionName = isAttributeExpression(attrMatches[1], state.options.brackets) | ||
const match = isExpressionName ? [null, expressionContent.exec(data)[1], null] : attrMatches | ||
if (match) { | ||
const end = re.lastIndex | ||
const attr = parseAttribute(state, match, start, end) | ||
const attr = parseAttribute(state, match, start, end, isExpressionName) | ||
@@ -111,5 +121,12 @@ //assert(q && q.type === Mode.TAG, 'no previous tag for the attr!') | ||
function parseSpreadAttribute(state, attr, quote) { | ||
let end = expr(state, attr, quote || '[>/\\s]', attr.start) | ||
/** | ||
* Parse expression names <a {href}> | ||
* @param {ParserStore} state - Parser state | ||
* @param {Object} attr - attribute object parsed | ||
* @returns {Object} normalized attribute object | ||
*/ | ||
function parseSpreadAttribute(state, attr) { | ||
const end = getAttributeEnd(state, attr) | ||
return { | ||
@@ -119,5 +136,5 @@ [IS_SPREAD]: true, | ||
expressions: attr.expressions.map(expr => Object.assign(expr, { | ||
text: expr.text.replace(SPREAD_OPERATOR, '') | ||
text: expr.text.replace(SPREAD_OPERATOR, '').trim() | ||
})), | ||
end: quote ? ++end : end | ||
end: end | ||
} | ||
@@ -127,2 +144,19 @@ } | ||
/** | ||
* Parse expression names <a {href}> | ||
* @param {ParserStore} state - Parser state | ||
* @param {Object} attr - attribute object parsed | ||
* @returns {Object} normalized attribute object | ||
*/ | ||
function parseExpressionNameAttribute(state, attr) { | ||
const end = getAttributeEnd(state, attr) | ||
return { | ||
start: attr.start, | ||
name: attr.expressions[0].text.trim(), | ||
expressions: attr.expressions, | ||
end: end | ||
} | ||
} | ||
/** | ||
* Parse the attribute values normalising the quotes | ||
@@ -133,5 +167,6 @@ * @param {ParserStore} state - Parser state | ||
* @param {number} end - attribute end position | ||
* @param {boolean} isExpressionName - true if the attribute name is an expression | ||
* @returns {Object} attribute object | ||
*/ | ||
function parseAttribute(state, match, start, end) { | ||
function parseAttribute(state, match, start, end, isExpressionName) { | ||
const attr = { | ||
@@ -143,6 +178,11 @@ name: match[1], | ||
} | ||
const quote = match[2] // first letter of value or nothing | ||
if (SPREAD_OPERATOR.test(attr.name)) { | ||
return parseSpreadAttribute(state, attr, quote) | ||
if (isExpressionName) { | ||
if (isSpreadAttribute(attr.name)) { | ||
return parseSpreadAttribute(state, attr) | ||
} | ||
return parseExpressionNameAttribute(state, attr) | ||
} | ||
@@ -149,0 +189,0 @@ |
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
97617
32
2748
Updatedcurri@^1.0.1