Add times syntax for SVG element

This commit is contained in:
yuanchuan 2022-07-20 14:00:21 +08:00
parent 0c6d520ff7
commit cfdc3a7f13
5 changed files with 127 additions and 14 deletions

View File

@ -0,0 +1,35 @@
function generate(token, indent = 0) {
let result = '';
if (token.type === 'block') {
if (token.times) {
result += '@M' + token.times + '(' + token.pureName + '{';
} else {
result += token.name + '{';
}
if (Array.isArray(token.value) && token.value.length) {
for (let t of token.value) {
result += generate(t, indent + 2);
}
}
if (token.times) {
result += '})';
} else {
result += '}';
}
} else if (token.type === 'statement') {
if (token.value && token.value.type) {
result += token.name + ':' + generate(token.value, indent);
} else {
result += token.name + ':' + token.value + ';';
}
}
return result;
}
function generate_svg_extended(token) {
return generate(token).trim();
}
export {
generate_svg_extended,
}

View File

@ -1,6 +1,8 @@
// I need to rewrite this
import parse_var from './parse-var.js';
import parse_svg from './parse-svg.js';
import { generate_svg_extended } from '../generator/svg-extended.js';
import { first, last, clone } from '../utils/list.js';
const Tokens = {
@ -260,8 +262,10 @@ function read_property(it) {
function read_arguments(it, composition, doodle) {
let args = [], group = [], stack = [], arg = '', c;
let raw = '';
while (!it.end()) {
c = it.curr();
let start = it.index();
if ((/[\('"`]/.test(c) && it.curr(-1) !== '\\')) {
if (stack.length) {
if (c != '(' && c === last(stack)) {
@ -291,7 +295,6 @@ function read_arguments(it, composition, doodle) {
}
arg += c;
}
else {
if (arg.length) {
if (!group.length) {
@ -328,10 +331,11 @@ function read_arguments(it, composition, doodle) {
break;
}
else {
raw += it.range(start, it.index() + 1);
it.next();
}
}
return skip_last_empty_args(args);
return [skip_last_empty_args(args), raw];
}
function skip_last_empty_args(args) {
@ -390,6 +394,11 @@ function seperate_func_name(name) {
return { fname, extra };
}
function has_times_syntax(token) {
let str = JSON.stringify(token);
return str.includes('pureName') && str.includes('times');
}
function read_func(it) {
let func = Tokens.func();
let name = '@', c;
@ -403,7 +412,18 @@ function read_func(it) {
if (c == '(' || composition) {
has_argument = true;
it.next();
func.arguments = read_arguments(it, composition, composible(name));
let [args, raw_args] = read_arguments(it, composition, composible(name));
if (name === '@svg') {
let parsed_svg = parse_svg(raw_args);
if (has_times_syntax(parsed_svg)) {
let svg = generate_svg_extended(parsed_svg);
// compatible with old iterator
svg += ')';
let extended = read_arguments(iterator(svg), composition, composible(name));
args = extended[0];
}
}
func.arguments = args;
break;
} else if (!has_argument && next !== '(' && !/[0-9a-zA-Z_\-.]/.test(next)) {
name += c;
@ -504,7 +524,7 @@ function read_cond_selector(it) {
while (!it.end()) {
if ((c = it.curr()) == '(') {
it.next();
selector.arguments = read_arguments(it);
selector.arguments = read_arguments(it)[0];
}
else if (/[){]/.test(c)) break;
else if (!is.white_space(c)) selector.name += c;

View File

@ -25,18 +25,19 @@ function readStatement(iter, token) {
}
let tokenName = selectors.pop();
let skip = isSkip(...selectors, tokenName);
inlineBlock = resolveId(walk(iter, {
inlineBlock = resolveId(walk(iter, splitTimes(tokenName, {
type: 'block',
name: tokenName,
inline: true,
value: []
}), skip);
name: tokenName,
value: [],
})), skip);
while (tokenName = selectors.pop()) {
inlineBlock = resolveId({
inlineBlock = resolveId(splitTimes(tokenName, {
type: 'block',
name: tokenName,
value: [inlineBlock]
}, skip);
}), skip);
}
break;
}
@ -94,17 +95,17 @@ function walk(iter, parentToken) {
}
let tokenName = selectors.pop();
let skip = isSkip(...selectors, parentToken.name, tokenName);
let block = resolveId(walk(iter, {
let block = resolveId(walk(iter, splitTimes(tokenName, {
type: 'block',
name: tokenName,
value: []
}), skip);
})), skip);
while (tokenName = selectors.pop()) {
block = resolveId({
block = resolveId(splitTimes(tokenName, {
type: 'block',
name: tokenName,
value: [block]
}, skip);
}), skip);
}
rules.push(block);
fragment = [];
@ -205,6 +206,18 @@ function getGroups(tokens, fn) {
return group;
}
function splitTimes(name, object) {
let target = Object.assign({}, object);
if (/\*[0-9]/.test(name)) {
let [tokenName, times] = name.split('*');
if (times) {
target.times = times;
target.pureName = tokenName;
}
}
return target;
}
function isSkip(...names) {
return names.some(n => n === 'style');
}

View File

@ -0,0 +1,28 @@
import test from 'ava';
import parseSvg from '../src/parser/parse-svg.js';
import { generate_svg_extended } from '../src/generator/svg-extended.js';
import compare from './_compare.js';
compare.use(input => {
return generate_svg_extended(parseSvg(input));
});
test('code transformation', t => {
compare(t,
`circle {}`,
`svg{circle{}}`
);
compare(t,
`circle*10 {}`,
`svg{@M10(circle{})}`
);
compare(t,
`g circle*10x10 {}`,
`svg{g{@M10x10(circle{})}}`
);
});

View File

@ -321,3 +321,20 @@ test('statement end on quotes', t => {
}]
});
});
test('times syntas', t => {
compare(t, `
circle*10 {}
`, {
type: 'block',
name: 'svg',
value: [{
type: 'block',
name: 'circle*10',
pureName: 'circle',
times: '10',
value: []
}]
});
});