diff --git a/CHANGELOG.md b/CHANGELOG.md
index aa1315e..ef7c4bd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,47 @@
+## 0.24.0
+
+### Changes
+
+* Removed `@min-size`, `@max-size`, `@path()`, `nrand()`, and `@reflect()` since I never used them.
+* Removed the feature of registering typed custom properties automatically, which was used for animation.
+* Renamed `place-cell` to `offset` in favor of shorter name.
+
+### Features
+
+* Added Perlin noise function `@rn()` and `@noise()`.
+ ```css
+ /* similar to @r() function */
+ scale: @rn(0, 1);
+ rotate: @rn(360deg);
+ ```
+
+* Added support for `direction` inside `@plot()` function.
+ Each element will rotate towards the curve direction or with custom angles.
+ ```csss
+ @offset: @plot(
+ /* the syntax is similar to offset-rotate */
+ direction: auto 90deg;
+ );
+ ```
+
+* Added support for `unit` inside `@plot()` function.
+ Now the `box-shadow` value can be plotted.
+ ```css
+ box-shadow: @m10(
+ @plot(r: 10, unit: em) 0 0 #000
+ );
+ ```
+ Or simply put the unit at the end of `r`.
+ ```css
+ box-shadow: @m10(
+ @plot(r: 10em) 0 0 #000
+ );
+ ```
+
+
+
+
+
## 0.23.1
* Fixed `index` calculation in `@pattern`.
diff --git a/css-doodle.js b/css-doodle.js
index 8658519..a2f93ab 100644
--- a/css-doodle.js
+++ b/css-doodle.js
@@ -1,4 +1,4 @@
-/*! css-doodle@0.23.1 */
+/*! css-doodle@0.24.0 */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
@@ -191,7 +191,8 @@
else if (is$2.symbol(curr) && !is$2.selfClosedTag(curr, next)) {
let lastToken = last$3(tokens);
// negative
- if (curr === '-' && is$2.digit(next) && (!lastToken || !lastToken.isNumber())) {
+ let isNextDigit = is$2.digit(next) || (is$2.dot(next) && is$2.digit(next2));
+ if (curr === '-' && isNextDigit && (!lastToken || !lastToken.isNumber())) {
let num = readNumber(iter);
tokens.push(new Token({
type: 'Number', value: num, pos
@@ -264,7 +265,7 @@
return tokens;
}
- function parse$7(input) {
+ function parse$9(input) {
let iter = iterator$1(scan(input));
return walk$2(iter);
}
@@ -347,7 +348,7 @@
}
function shuffle(arr) {
- let ret = Array.from ? Array.from(arr) : arr.slice();
+ let ret = [...arr];
let m = arr.length;
while (m) {
let i = ~~(random() * m--);
@@ -358,6 +359,10 @@
return ret;
}
+ function duplicate(arr) {
+ return [].concat(arr, arr);
+ }
+
function flat_map(arr, fn) {
if (Array.prototype.flatMap) return arr.flatMap(fn);
return arr.reduce((acc, x) => acc.concat(fn(x)), []);
@@ -379,6 +384,7 @@
clone,
shuffle,
flat_map,
+ duplicate,
remove_empty_values
}
}
@@ -968,7 +974,7 @@
function evaluate_value(values, extra) {
values.forEach && values.forEach(v => {
if (v.type == 'text' && v.value) {
- let vars = parse$7(v.value);
+ let vars = parse$9(v.value);
v.value = vars.reduce((ret, p) => {
let rule = '', other = '', parsed;
rule = read_variable(extra, p.name);
@@ -982,7 +988,7 @@
});
}
try {
- parsed = parse$6(rule, extra);
+ parsed = parse$8(rule, extra);
} catch (e) { }
if (parsed) {
ret.push.apply(ret, parsed);
@@ -1011,7 +1017,7 @@
}, []);
}
- function parse$6(input, extra) {
+ function parse$8(input, extra) {
const it = iterator(input);
const Tokens = [];
while (!it.end()) {
@@ -1114,7 +1120,7 @@
let index = 1;
for (let i = 1; i <= y; ++i) {
for (let j = 1; j <= x; ++j) {
- ret.push(fn(index++, j, i, max));
+ ret.push(fn(index++, j, i, max, x, y));
}
}
return ret;
@@ -1210,7 +1216,7 @@
});
}
- function parse$5(input) {
+ function parse$7(input) {
let iter = iterator$1(removeParens(scan(input)));
let stack = [];
let tokens = [];
@@ -1396,31 +1402,20 @@
return element;
}
- function random_func(random) {
+ function Random(random) {
- function lerp(start, end, t) {
- return start * (1 - t) + end * t;
+ function lerp(t, a, b) {
+ return a + t * (b - a);
}
function rand(start = 0, end) {
if (arguments.length == 1) {
[start, end] = [0, start];
}
- return lerp(start, end, random());
+ return lerp(random(), start, end);
}
- function nrand(mean = 0, scale = 1) {
- let u1 = 0, u2 = 0;
- //Convert [0,1) to (0,1)
- while (u1 === 0) u1 = random();
- while (u2 === 0) u2 = random();
- const R = Math.sqrt(-2.0 * Math.log(u1));
- const t = 2.0 * Math.PI * u2;
- const u0 = R * Math.cos(t);
- return mean + scale * u0;
- }
-
- function pick( ...items) {
+ function pick(...items) {
let args = items.reduce((acc, n) => acc.concat(n), []);
return args[~~(random() * args.length)];
}
@@ -1432,7 +1427,6 @@
return {
lerp,
rand,
- nrand,
pick,
unique_id
};
@@ -1899,7 +1893,65 @@
}
}
- function parse$4(input) {
+ /**
+ * Improved noise by Ken Perlin
+ * Translated from: https://mrl.nyu.edu/~perlin/noise/
+ */
+
+ class Perlin {
+ constructor(random) {
+ let { lerp } = Random(random);
+ let { shuffle, duplicate } = List(random);
+ this.lerp = lerp;
+ this.p = duplicate(shuffle([
+ 151,160,137,91,90,15,
+ 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
+ 190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
+ 88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,
+ 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
+ 102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,196,
+ 135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,
+ 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
+ 223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,
+ 129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228,
+ 251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239,107,
+ 49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,
+ 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
+ ]));
+ }
+
+ // Convert LO 4 bits of hash code into 12 gradient directions.
+ grad(hash, x, y, z) {
+ let h = hash & 15,
+ u = h < 8 ? x : y,
+ v = h < 4 ? y : h == 12 || h == 14 ? x : z;
+ return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
+ }
+
+ noise(x, y, z) {
+ let { p, grad, lerp } = this;
+ // Find unit cube that contains point.
+ let [X, Y, Z] = [x, y, z].map(n => Math.floor(n) & 255);
+ // Find relative x, y, z of point in cube.
+ [x, y, z] = [x, y, z].map(n => n - Math.floor(n));
+ // Compute fade curves for each of x, y, z.
+ let [u, v, w] = [x, y, z].map(n => n * n * n * (n * (n * 6 - 15) + 10));
+ // hash coordinates of the 8 cube corners.
+ let A = p[X ]+Y, AA = p[A]+Z, AB = p[A+1]+Z,
+ B = p[X+1]+Y, BA = p[B]+Z, BB = p[B+1]+Z;
+ // And add blended results from 8 corners of cube.
+ return lerp(w, lerp(v, lerp(u, grad(p[AA ], x , y , z ),
+ grad(p[BA ], x-1, y , z )),
+ lerp(u, grad(p[AB ], x , y-1, z ),
+ grad(p[BB ], x-1, y-1, z ))),
+ lerp(v, lerp(u, grad(p[AA+1], x , y , z-1 ),
+ grad(p[BA+1], x-1, y , z-1 )),
+ lerp(u, grad(p[AB+1], x , y-1, z-1 ),
+ grad(p[BB+1], x-1, y-1, z-1 ))));
+ }
+ }
+
+ function parse$6(input) {
let iter = iterator$1(scan(input));
let commands = {};
let tokens = [];
@@ -1930,16 +1982,15 @@
}
}
}
-
if (tokens.length && name) {
commands[name] = transformNegative(name, joinTokens$1(tokens), negative);
}
-
return commands;
}
function transformNegative(name, value, negative) {
- if (name === 'fill-rule') {
+ let excludes = ['fill-rule', 'fill'];
+ if (excludes.includes(name)) {
return value;
}
return negative ? `-1 * (${ value })` : value;
@@ -1949,11 +2000,133 @@
return tokens.map(n => n.value).join('');
}
- const { cos, sin, atan2, PI } = Math;
+ function parse$5(input, noSpace) {
+ let group = [];
+ let tokens = [];
+ let parenStack = [];
+ let quoteStack = [];
+
+ if (is_empty(input)) {
+ return group;
+ }
+
+ let iter = iterator$1(scan(input));
+
+ function isSeperator(token) {
+ if (noSpace) {
+ return token.isSymbol(',');
+ }
+ return token.isSymbol(',') || token.isSpace();
+ }
+
+ while (iter.next()) {
+ let { prev, curr, next } = iter.get();
+ if (curr.isSymbol('(')) {
+ parenStack.push(curr.value);
+ }
+ if (curr.isSymbol(')')) {
+ parenStack.pop();
+ }
+ if (curr.status === 'open') {
+ quoteStack.push(curr.value);
+ }
+ if (curr.status === 'close') {
+ quoteStack.pop();
+ }
+ if (isSeperator(curr) && !parenStack.length && !quoteStack.length) {
+ group.push(joinTokens(tokens));
+ tokens = [];
+ } else {
+ tokens.push(curr);
+ }
+ }
+
+ if (tokens.length) {
+ group.push(joinTokens(tokens));
+ }
+
+ return group;
+ }
+
+ function joinTokens(tokens) {
+ return tokens.map(n => n.value).join('');
+ }
+
+ const keywords = ['auto', 'reverse'];
+ const units = ['deg', 'rad', 'grad', 'turn'];
+
+ function parse$4(input) {
+ let iter = iterator$1(scan(input));
+ let matched = false;
+ let unit = '';
+ let ret = {
+ direction: '',
+ angle: '',
+ };
+ while (iter.next()) {
+ let { prev, curr, next } = iter.get();
+ if (curr.isWord() && keywords.includes(curr.value)) {
+ ret.direction = curr.value;
+ matched = true;
+ }
+ else if (curr.isNumber()) {
+ ret.angle = Number(curr.value);
+ matched = true;
+ }
+ else if (curr.isWord() && prev && prev.isNumber() && units.includes(curr.value)) {
+ unit = curr.value;
+ }
+ else if (curr.isSpace() && ret.direction !== '' && ret.angle !== '') {
+ break;
+ }
+ }
+ if (!matched) {
+ ret.direction = 'auto';
+ }
+ return normalizeAngle(ret, unit);
+ }
+
+ function normalizeAngle(input, unit) {
+ let { angle } = input;
+ if (angle === '') {
+ angle = 0;
+ }
+ if (unit === 'rad') {
+ angle /= (Math.PI / 180);
+ }
+ if (unit === 'grad') {
+ angle *= .9;
+ }
+ if (unit === 'turn') {
+ angle *= 360;
+ }
+ return Object.assign({}, input, { angle });
+ }
+
+ function parse$3(input) {
+ let iter = iterator$1(scan(input));
+ let ret = {};
+ let matched = false;
+ while (iter.next()) {
+ let { prev, curr } = iter.get();
+ if (curr.isNumber()) {
+ ret.value = Number(curr.value);
+ matched = true;
+ }
+ else if (matched && curr.isWord() && prev && prev.isNumber()) {
+ ret.unit = curr.value;
+ } else {
+ break;
+ }
+ }
+ return ret;
+ }
+
+ const { cos, sin, abs, atan2, PI } = Math;
const _ = make_tag_function(c => {
return create_shape_points(
- parse$4(c), {min: 3, max: 3600}
+ parse$6(c), {min: 3, max: 3600}
);
});
@@ -2090,6 +2263,20 @@
},
};
+ class Point {
+ constructor(x, y, angle) {
+ this.x = x;
+ this.y = y;
+ this.extra = angle;
+ }
+ valueOf() {
+ return this.x + ' ' + this.y;
+ }
+ toString() {
+ return this.valueOf();
+ }
+ }
+
function create_polygon_points(option, fn) {
if (typeof arguments[0] == 'function') {
fn = option;
@@ -2104,25 +2291,37 @@
let turn = option.turn || 1;
let frame = option.frame;
let fill = option['fill'] || option['fill-rule'];
+ let direction = parse$4(option['direction'] || option['dir'] || '');
+ let unit = option.unit;
let rad = (PI * 2) * turn / split;
let points = [];
let first_point, first_point2;
- if (fill == 'nonzero' || fill == 'evenodd') {
- points.push(fill);
- }
-
let factor = (option.scale === undefined) ? 1 : option.scale;
- let add = ([x1, y1]) => {
+ let add = ([x1, y1, dx = 0, dy = 0]) => {
+ if (x1 == 'evenodd' || x1 == 'nonzero') {
+ return points.push(new Point(x1, '', ''));
+ }
let [x, y] = scale(x1, -y1, factor);
- if (!option.absolute) {
+ let [dx1, dy2] = scale(dx, -dy, factor);
+ let angle = calc_angle(x, y, dx1, dy2, direction);
+ if (unit !== undefined && unit !== '%') {
+ if (unit !== 'none') {
+ x += unit;
+ y += unit;
+ }
+ } else {
x = (x + 1) * 50 + '%';
y = (y + 1) * 50 + '%';
}
- points.push(x + ' ' + y);
+ points.push(new Point(x, y, angle));
};
+ if (fill == 'nonzero' || fill == 'evenodd') {
+ add([fill, '', '']);
+ }
+
for (let i = 0; i < split; ++i) {
let t = rad * i;
let point = fn(t, i);
@@ -2153,6 +2352,20 @@
return points;
}
+ function calc_angle(x, y, dx, dy, option) {
+ let base = atan2(y + dy, x - dx) * 180 / PI;
+ if (option.direction === 'reverse') {
+ base -= 180;
+ }
+ if (!option.direction) {
+ base = 90;
+ }
+ if (option.angle) {
+ base += option.angle;
+ }
+ return base;
+ }
+
function rotate(x, y, deg) {
let rad = -PI / 180 * deg;
return [
@@ -2162,7 +2375,7 @@
}
function translate(x, y, offset) {
- let [dx, dy = dx] = String(offset).split(/[,\s]+/).map(Number);
+ let [dx, dy = dx] = parse$5(offset).map(Number);
return [
x + (dx || 0),
y - (dy || 0),
@@ -2172,7 +2385,7 @@
}
function scale(x, y, factor) {
- let [fx, fy = fx] = String(factor).split(/[,\s]+/).map(Number);
+ let [fx, fy = fx] = parse$5(factor).map(Number);
return [
x * fx,
y * fy
@@ -2181,11 +2394,18 @@
function create_shape_points(props, {min, max}) {
let split = clamp(parseInt(props.vertices || props.points || props.split) || 0, min, max);
- let option = Object.assign({}, props, { split });
let px = is_empty(props.x) ? 'cos(t)' : props.x;
let py = is_empty(props.y) ? 'sin(t)' : props.y;
let pr = is_empty(props.r) ? '' : props.r;
+ let { unit, value } = parse$3(pr);
+ if (unit && !props[unit] && unit !== 't') {
+ if (is_empty(props.unit)) {
+ props.unit = unit;
+ }
+ pr = props.r = value;
+ }
+
if (props.degree) {
props.rotate = props.degree;
}
@@ -2194,6 +2414,8 @@
props.move = props.origin;
}
+ let option = Object.assign({}, props, { split });
+
return create_polygon_points(option, (t, i) => {
let context = Object.assign({}, props, {
't': t,
@@ -2206,7 +2428,7 @@
a = Number(a) || 0;
b = Number(b) || 0;
if (a > b) [a, b] = [b, a];
- let step = Math.abs(b - a) / (split - 1);
+ let step = abs(b - a) / (split - 1);
return a + step * i;
}
});
@@ -2216,8 +2438,8 @@
let dy = 0;
if (pr) {
let r = calc(pr, context);
- x = r * Math.cos(t);
- y = r * Math.sin(t);
+ x = r * cos(t);
+ y = r * sin(t);
}
if (props.rotate) {
[x, y] = rotate(x, y, Number(props.rotate) || 0);
@@ -2229,58 +2451,6 @@
});
}
- function parse$3(input, noSpace) {
- let group = [];
- let tokens = [];
- let parenStack = [];
- let quoteStack = [];
-
- if (is_empty(input)) {
- return group;
- }
-
- let iter = iterator$1(scan(input));
-
- function isSeperator(token) {
- if (noSpace) {
- return token.isSymbol(',');
- }
- return token.isSymbol(',') || token.isSpace();
- }
-
- while (iter.next()) {
- let { prev, curr, next } = iter.get();
- if (curr.isSymbol('(')) {
- parenStack.push(curr.value);
- }
- if (curr.isSymbol(')')) {
- parenStack.pop();
- }
- if (curr.status === 'open') {
- quoteStack.push(curr.value);
- }
- if (curr.status === 'close') {
- quoteStack.pop();
- }
- if (isSeperator(curr) && !parenStack.length && !quoteStack.length) {
- group.push(joinTokens(tokens));
- tokens = [];
- } else {
- tokens.push(curr);
- }
- }
-
- if (tokens.length) {
- group.push(joinTokens(tokens));
- }
-
- return group;
- }
-
- function joinTokens(tokens) {
- return tokens.map(n => n.value).join('');
- }
-
function readStatement$1(iter, token) {
let fragment = [];
while (iter.next()) {
@@ -2499,39 +2669,39 @@
function get_exposed(random) {
const { shuffle } = List(random);
- const { pick, rand, nrand, unique_id } = random_func(random);
+ const { pick, rand, lerp, unique_id } = Random(random);
const Expose = {
- index({ count }) {
+ i({ count }) {
return _ => count;
},
- row({ y }) {
+ y({ y }) {
return _ => y;
},
- col({ x }) {
+ x({ x }) {
return _ => x;
},
- depth({ z }) {
+ z({ z }) {
return _ => z;
},
- size({ grid }) {
+ I({ grid }) {
return _ => grid.count;
},
- ['size-row']({ grid }) {
+ Y({ grid }) {
return _ => grid.y;
},
- ['size-col']({ grid }) {
+ X({ grid }) {
return _ => grid.x;
},
- ['size-depth']({ grid }) {
+ Z({ grid }) {
return _ => grid.z;
},
@@ -2555,25 +2725,25 @@
return n => extra ? (extra[3] + (Number(n) || 0)) : '@N';
},
- repeat: (
+ µ: (
make_sequence('')
),
- multiple: (
+ m: (
make_sequence(',')
),
- ['multiple-with-space']: (
+ M: (
make_sequence(' ')
),
- pick({ context }) {
+ p({ context }) {
return expand((...args) => {
return push_stack(context, 'last_pick', pick(args));
});
},
- ['pick-n']({ context, extra, position }) {
+ pn({ context, extra, position }) {
let counter = 'pn-counter' + position;
return expand((...args) => {
if (!context[counter]) context[counter] = 0;
@@ -2586,14 +2756,14 @@
});
},
- ['pick-d']({ context, extra, position }) {
+ pd({ context, extra, position }) {
let counter = 'pd-counter' + position;
let values = 'pd-values' + position;
return expand((...args) => {
if (!context[counter]) context[counter] = 0;
context[counter] += 1;
if (!context[values]) {
- context[values] = shuffle(args);
+ context[values] = shuffle(args || []);
}
let max = args.length;
let [idx = context[counter]] = extra || [];
@@ -2603,14 +2773,14 @@
});
},
- ['last-pick']({ context }) {
+ lp({ context }) {
return (n = 1) => {
let stack = context.last_pick;
return stack ? stack.last(n) : '';
};
},
- rand({ context }) {
+ r({ context }) {
return (...args) => {
let transform_type = args.every(is_letter)
? by_charcode
@@ -2620,17 +2790,7 @@
};
},
- nrand({ context }) {
- return (...args) => {
- let transform_type = args.every(is_letter)
- ? by_charcode
- : by_unit;
- let value = transform_type(nrand).apply(null, args);
- return push_stack(context, 'last_rand', value);
- };
- },
-
- ['rand-int']({ context }) {
+ ri({ context }) {
return (...args) => {
let transform_type = args.every(is_letter)
? by_charcode
@@ -2641,24 +2801,57 @@
}
},
- ['nrand-int']({ context }) {
+ rn({ x, y, context, position, grid, extra }) {
+ let counter = 'noise-2d' + position;
+ let [ni, nx, ny, nm, NX, NY] = extra || [];
+ let isSeqContext = (ni && nm);
return (...args) => {
- let transform_type = args.every(is_letter)
- ? by_charcode
- : by_unit;
- let nrand_int = (...args) => Math.round(nrand(...args));
- let value = transform_type(nrand_int).apply(null, args);
+ let [start, end = start, freq = 1, amp = 1] = args;
+ if (args.length == 1) {
+ [start, end] = [0, start];
+ }
+ if (!context[counter]) {
+ context[counter] = new Perlin(random);
+ }
+ freq = normalize(freq);
+ amp = normalize(amp);
+ let transform = [start, end].every(is_letter) ? by_charcode : by_unit;
+ let t = isSeqContext
+ ? context[counter].noise((nx - 1)/NX * freq, (ny - 1)/NY * freq, 0)
+ : context[counter].noise((x - 1)/grid.x * freq, (y - 1)/grid.y * freq, 0);
+ let fn = transform((start, end) => map2d(t * amp, start, end, amp));
+ let value = fn(start, end);
return push_stack(context, 'last_rand', value);
- }
+ };
},
- ['last-rand']({ context }) {
+ lr({ context }) {
return (n = 1) => {
let stack = context.last_rand;
return stack ? stack.last(n) : '';
};
},
+ noise({ context, grid, position, ...rest }) {
+ let vars = {
+ i: rest.count, I: grid.count,
+ x: rest.x, X: grid.x,
+ y: rest.y, Y: grid.y,
+ z: rest.z, Z: grid.z,
+ };
+ return (x, y, z = 0) => {
+ let counter = 'raw-noise-2d' + position;
+ if (!context[counter]) {
+ context[counter] = new Perlin(random);
+ }
+ return context[counter].noise(
+ calc(x, vars),
+ calc(y, vars),
+ calc(z, vars)
+ );
+ };
+ },
+
stripe() {
return (...input) => {
let colors = input.map(get_value);
@@ -2670,7 +2863,7 @@
return '';
}
colors.forEach(step => {
- let [_, size] = parse$3(step);
+ let [_, size] = parse$5(step);
if (size !== undefined) custom_sizes.push(size);
else default_count += 1;
});
@@ -2679,7 +2872,7 @@
: `100% / ${max}`;
return colors.map((step, i) => {
if (custom_sizes.length) {
- let [color, size] = parse$3(step);
+ let [color, size] = parse$5(step);
let prefix = prev ? (prev + ' + ') : '';
prev = prefix + (size !== undefined ? size : default_size);
return `${color} 0 calc(${ prev })`
@@ -2690,15 +2883,6 @@
}
},
- reflect() {
- return (...input) => {
- return [
- ...input,
- ...input.slice(0, -1).reverse()
- ].join(',');
- }
- },
-
calc() {
return value => calc(get_value(value));
},
@@ -2717,7 +2901,7 @@
return create_svg_url(svg);
}),
- ['svg-filter']: lazy((...args) => {
+ filter: lazy((...args) => {
let value = args.map(input => get_value(input()).trim()).join(',');
let id = unique_id('filter-');
if (!value.startsWith('<')) {
@@ -2747,7 +2931,10 @@
return commands => {
let [idx = count, _, __, max = grid.count] = extra || [];
if (!context[key]) {
- let config = parse$4(commands);
+ let config = parse$6(commands);
+ delete config['fill'];
+ delete config['fill-rule'];
+ delete config['frame'];
config.points = max;
context[key] = create_shape_points(config, {min: 1, max: 65536});
}
@@ -2755,20 +2942,6 @@
};
},
- Plot({ count, context, extra, position, grid }) {
- let key = 'offset-points' + position;
- return commands => {
- let [idx = count, _, __, max = grid.count] = extra || [];
- if (!context[key]) {
- let config = parse$4(commands);
- config.points = max;
- config.absolute = true;
- context[key] = create_shape_points(config, {min: 1, max: 65536});
- }
- return context[key][idx - 1];
- };
- },
-
shape() {
return memo('shape-function', (type = '', ...args) => {
type = String(type).trim();
@@ -2782,7 +2955,7 @@
if (rest.length) {
commands = type + ',' + rest;
}
- let config = parse$4(commands);
+ let config = parse$6(commands);
points = create_shape_points(config, {min: 3, max: 3600});
}
}
@@ -2806,10 +2979,6 @@
return value => value;
},
- path() {
- return value => value;
- },
-
invert() {
return commands => {
let parsed = parse$1(commands);
@@ -2903,61 +3072,61 @@
return -1 * num;
}
+ function map2d(value, min, max, amp = 1) {
+ let dimention = 2;
+ let v = Math.sqrt(dimention / 4) * amp;
+ let [ma, mb] = [-v, v];
+ return lerp((value - ma) / (mb - ma), min * amp, max * amp);
+ }
+
+ function normalize(value) {
+ value = Number(value) || 0;
+ return value < 0 ? 0 : value;
+ }
+
return alias_for(Expose, {
- 'm': 'multiple',
- 'M': 'multiple-with-space',
-
- 'r': 'rand',
- 'rn': 'nrand',
- 'ri': 'rand-int',
- 'rni': 'nrand-int',
- 'lr': 'last-rand',
-
- 'p': 'pick',
- 'pn': 'pick-n',
- 'pd': 'pick-d',
- 'lp': 'last-pick',
-
- 'rep': 'repeat',
-
- 'i': 'index',
- 'x': 'col',
- 'y': 'row',
- 'z': 'depth',
-
- 'I': 'size',
- 'X': 'size-col',
- 'Y': 'size-row',
- 'Z': 'size-depth',
-
- 'flipv': 'flipV',
- 'fliph': 'flipH',
-
- // legacy names, keep them before 1.0
- 'nr': 'rn',
- 'nri': 'nri',
- 'ms': 'multiple-with-space',
- 's': 'size',
- 'sx': 'size-col',
- 'sy': 'size-row',
- 'sz': 'size-depth',
- 'size-x': 'size-col',
- 'size-y': 'size-row',
- 'size-z': 'size-depth',
- 'multi': 'multiple',
- 'pick-by-turn': 'pick-n',
- 'max-row': 'size-row',
- 'max-col': 'size-col',
- 'offset': 'plot',
- 'Offset': 'Plot',
- 'point': 'plot',
- 'Point': 'Plot',
- 'paint': 'canvas',
+ 'index': 'i',
+ 'col': 'x',
+ 'row': 'y',
+ 'depth': 'z',
+ 'rand': 'r',
+ 'pick': 'p',
// error prone
'stripes': 'stripe',
'strip': 'stripe',
'patern': 'pattern',
+ 'flipv': 'flipV',
+ 'fliph': 'flipH',
+
+ // legacy names, keep them before 1.0
+ 'svg-filter': 'filter',
+ 'last-rand': 'lr',
+ 'last-pick': 'lp',
+ 'multiple': 'm',
+ 'multi': 'm',
+ 'rep': 'µ',
+ 'repeat': 'µ',
+ 'ms': 'M',
+ 's': 'I',
+ 'size': 'I',
+ 'sx': 'X',
+ 'size-x': 'X',
+ 'size-col': 'X',
+ 'max-col': 'X',
+ 'sy': 'Y',
+ 'size-y': 'Y',
+ 'size-row': 'Y',
+ 'max-row': 'Y',
+ 'sz': 'Z',
+ 'size-z': 'Z',
+ 'size-depth': 'Z',
+ 'pick-by-turn': 'pn',
+ 'offset': 'plot',
+ 'Offset': 'Plot',
+ 'point': 'plot',
+ 'Point': 'Plot',
+ 'paint': 'canvas',
});
}
@@ -3087,10 +3256,10 @@
return !!presets[name];
}
- var Property = {
+ const Expose = {
['@size'](value, { is_special_selector, grid }) {
- let [w, h = w] = parse$3(value);
+ let [w, h = w] = parse$5(value);
if (is_preset(w)) {
[w, h] = get_preset(w, h);
}
@@ -3111,17 +3280,7 @@
return styles;
},
- ['@min-size'](value) {
- let [w, h = w] = parse$3(value);
- return `min-width: ${ w }; min-height: ${ h };`;
- },
-
- ['@max-size'](value) {
- let [w, h = w] = parse$3(value);
- return `max-width: ${ w }; max-height: ${ h };`;
- },
-
- ['@place-cell']: (() => {
+ ['@offset']: (() => {
let map_left_right = {
'center': '50%',
'left': '0%', 'right': '100%',
@@ -3133,8 +3292,8 @@
'left': '50%', 'right': '50%',
};
- return value => {
- let [left, top = '50%'] = parse$3(value);
+ return (value, { extra }) => {
+ let [left, top = '50%'] = parse$5(value);
left = map_left_right[left] || left;
top = map_top_bottom[top] || top;
const cw = 'var(--internal-cell-width, 25%)';
@@ -3148,6 +3307,8 @@
margin-left: calc(${ cw } / -2);
margin-top: calc(${ ch } / -2);
grid-area: unset;
+ --plot-angle: ${ extra || 0 };
+ transform: rotate(${ extra || 0 }deg);
`;
}
})(),
@@ -3162,7 +3323,7 @@
},
['@shape']: memo('shape-property', value => {
- let [type, ...args] = parse$3(value);
+ let [type, ...args] = parse$5(value);
let prop = 'clip-path';
if (typeof shapes[type] !== 'function') return '';
let points = shapes[type](...args);
@@ -3178,6 +3339,13 @@
};
+ var Property = alias_for(Expose, {
+
+ // legacy names.
+ '@place-cell': '@offset',
+
+ });
+
function nth(input, curr, max) {
for (let i = 0; i <= max; ++i) {
if (calc(input, { n: i }) == curr) return true;
@@ -3280,35 +3448,6 @@
return expose;
}, {});
- const initial = {
- length: '0px',
- number: 0,
- color: 'black',
- url: 'url()',
- image: 'url()',
- integer: 0,
- angle: '0deg',
- time: '0ms',
- resolution: '0dpi',
- percentage: '0%',
- 'length-percentage': '0%',
- 'transform-function': 'translate(0)',
- 'transform-list': 'translate(0)',
- 'custom-ident': '_'
- };
-
- function get_definition(name) {
- let type = String(name).substr(2).split('-')[0];
- if (initial[type] !== undefined) {
- return {
- name: name,
- syntax: `<${type}> | <${type}>+ | <${type}>#`,
- initialValue: initial[type],
- inherits: false
- }
- }
- }
-
let { join, make_array, remove_empty_values } = List();
function is_host_selector(s) {
@@ -3337,13 +3476,12 @@
this.canvas = {};
this.pattern = {};
this.shaders = {};
- this.paths = {};
this.reset();
this.Func = get_exposed(random);
this.Selector = Selector(random);
this.custom_properties = {};
this.uniforms = {};
- this.unique_id = random_func(random).unique_id;
+ this.unique_id = Random(random).unique_id;
}
reset() {
@@ -3383,9 +3521,8 @@
args.forEach(arg => {
let type = typeof arg.value;
let is_string_or_number = (type === 'number' || type === 'string');
-
if (!arg.cluster && (is_string_or_number)) {
- input.push(...parse$3(arg.value, true));
+ input.push(...parse$5(arg.value, true));
}
else {
if (typeof arg === 'function') {
@@ -3450,9 +3587,6 @@
: this.compose_argument(n, coords, extra);
});
let value = this.apply_func(fn, coords, args);
- if (fname == 'path') {
- return this.compose_path(value);
- }
return value;
}
}
@@ -3499,20 +3633,15 @@
return '${' + id + '}';
}
- compose_path(commands) {
- let id = this.unique_id('path');
- this.paths[id] = {
- id,
- commands
- };
- return '${' + id + '}';
- }
-
compose_value(value, coords) {
if (!Array.isArray(value)) {
- return '';
+ return {
+ value: '',
+ extra: '',
+ }
}
- return value.reduce((result, val) => {
+ let extra = '';
+ let output = value.reduce((result, val) => {
switch (val.type) {
case 'text': {
result += val.value;
@@ -3549,11 +3678,10 @@
let output = this.apply_func(fn, coords, args);
if (!is_nil(output)) {
- if (fname == 'path') {
- result += this.compose_path(output);
- } else {
- result += output;
- }
+ result += output;
+ }
+ if (output.extra) {
+ extra = output.extra;
}
}
}
@@ -3561,14 +3689,27 @@
}
return result;
}, '');
+
+ return {
+ value: output,
+ extra: extra,
+ }
}
compose_rule(token, _coords, selector) {
let coords = Object.assign({}, _coords);
let prop = token.property;
+ let extra;
let value_group = token.value.reduce((ret, v) => {
let composed = this.compose_value(v, coords);
- if (composed) ret.push(composed);
+ if (composed) {
+ if (composed.value) {
+ ret.push(composed.value);
+ }
+ if (composed.extra) {
+ extra = composed.extra;
+ }
+ }
return ret;
}, []);
@@ -3607,7 +3748,7 @@
}
if (prop === 'content') {
- if (!/["']|^none$|^(var|counter|counters|attr)\(/.test(value)) {
+ if (!/["']|^none$|^(var|counter|counters|attr|url)\(/.test(value)) {
value = `'${ value }'`;
}
}
@@ -3641,7 +3782,8 @@
if (Property[prop]) {
let transformed = Property[prop](value, {
is_special_selector: is_special_selector(selector),
- grid: coords.grid
+ grid: coords.grid,
+ extra
});
switch (prop) {
case '@grid': {
@@ -3691,7 +3833,7 @@
case '@grid': {
let value_group = token.value.reduce((ret, v) => {
let composed = this.compose_value(v, coords);
- if (composed) ret.push(composed);
+ if (composed && composed.value) ret.push(composed.value);
return ret;
}, []);
let value = value_group.join(', ');
@@ -3842,24 +3984,14 @@
});
});
- let definitions = [];
- Object.keys(this.custom_properties).forEach(name => {
- let def = get_definition(name);
- if (def) {
- definitions.push(def);
- }
- });
-
return {
props: this.props,
styles: this.styles,
grid: this.grid,
doodles: this.doodles,
shaders: this.shaders,
- paths: this.paths,
canvas: this.canvas,
pattern: this.pattern,
- definitions: definitions,
uniforms: this.uniforms
}
}
@@ -4617,7 +4749,7 @@
let { x: gx, y: gy, z: gz } = this.grid_size;
const compiled = this.generate(
- parse$6(use + styles, this.extra)
+ parse$8(use + styles, this.extra)
);
if (!this.shadowRoot.innerHTML) {
@@ -4639,20 +4771,12 @@
if (gx !== x || gy !== y || gz !== z) {
Object.assign(this.grid_size, grid);
return this.build_grid(
- this.generate(parse$6(use + styles, this.extra)),
+ this.generate(parse$8(use + styles, this.extra)),
grid
);
}
}
- let svg_paths = this.build_svg_paths(compiled.paths);
- if (svg_paths) {
- let defs = this.shadowRoot.querySelector('.svg-defs');
- if (defs) {
- defs.innerHTML = svg_paths;
- }
- }
-
if (compiled.uniforms.time) {
this.register_uniform_time();
}
@@ -4758,12 +4882,11 @@
fn = options;
options = null;
}
- let parsed = parse$6(code, this.extra);
+ let parsed = parse$8(code, this.extra);
let _grid = parse_grid({});
let compiled = generator(parsed, _grid, this.random);
let grid = compiled.grid ? compiled.grid : _grid;
const { keyframes, host, container, cells } = compiled.styles;
- let svg_defs = this.build_svg_paths(compiled.paths);
let replace = this.replace(compiled);
let grid_container = create_grid(grid);
@@ -4784,9 +4907,7 @@
${ cells }
${ keyframes }
-
+
${ grid_container }
@@ -4810,7 +4931,7 @@
}
shader_to_image({ shader, cell }, fn) {
- let parsed = parse$5(shader);
+ let parsed = parse$7(shader);
let element = this.doodle.getElementById(cell);
let { width, height } = element && element.getBoundingClientRect() || {
width: 0, height: 0
@@ -4847,7 +4968,7 @@
}
}
let use = this.get_use();
- let parsed = parse$6(use + un_entity(this.innerHTML), this.extra);
+ let parsed = parse$8(use + un_entity(this.innerHTML), this.extra);
let compiled = this.generate(parsed);
this.grid_size = compiled.grid
@@ -4857,13 +4978,12 @@
this.build_grid(compiled, this.grid_size);
}
- replace({ doodles, shaders, paths, canvas, pattern }) {
+ replace({ doodles, shaders, canvas, pattern }) {
let doodle_ids = Object.keys(doodles);
let shader_ids = Object.keys(shaders);
- let path_ids = Object.keys(paths);
let canvas_ids = Object.keys(canvas);
let pattern_ids = Object.keys(pattern);
- let length = doodle_ids.length + canvas_ids.length + shader_ids.length + path_ids.length + pattern_ids.length;
+ let length = doodle_ids.length + canvas_ids.length + shader_ids.length + pattern_ids.length;
return input => {
if (!length) {
return Promise.resolve(input);
@@ -4905,13 +5025,6 @@
return Promise.resolve('');
}
}),
- path_ids.map(id => {
- if (input.includes(id)) {
- return Promise.resolve({ id, value: '#' + id });
- } else {
- return Promise.resolve('');
- }
- })
);
return Promise.all(mappings).then(mapping => {
@@ -4942,7 +5055,6 @@
const { keyframes, host, container, cells } = compiled.styles;
let style_container = get_grid_styles(grid) + host + container;
let style_cells = has_delay ? '' : cells;
- let svg_defs = this.build_svg_paths(compiled.paths);
const { uniforms } = compiled;
@@ -4953,9 +5065,7 @@
-
+
${ create_grid(grid) }
`;
@@ -4970,26 +5080,15 @@
}
// might be removed in the future
- const definitions = compiled.definitions;
if (window.CSS && window.CSS.registerProperty) {
try {
if (uniforms.time) {
this.register_uniform_time();
}
- definitions.forEach(CSS.registerProperty);
} catch (e) { }
}
}
- build_svg_paths(paths) {
- let names = Object.keys(paths || {});
- return names.map(name => `
-
-
-
- `).join('');
- }
-
register_uniform_time() {
if (!this.is_uniform_time_registered) {
try {
diff --git a/css-doodle.min.js b/css-doodle.min.js
index b597d6f..b294a31 100644
--- a/css-doodle.min.js
+++ b/css-doodle.min.js
@@ -1 +1 @@
-/*! css-doodle@0.23.1 */!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).CSSDoodle=t()}(this,(function(){"use strict";const e=[":",";",",","(",")","[","]","{","}","\u03c0","\xb1","+","-","*","/","%",'"',"'","`","@"],t={escape:e=>"\\"==e,space:e=>/[\r\n\t\s]/.test(e),digit:e=>/^[0-9]$/.test(e),sign:e=>/^[+-]$/.test(e),dot:e=>"."==e,quote:e=>/^["'`]$/.test(e),symbol:t=>e.includes(t),hexNum:e=>/^[0-9a-f]$/i.test(e),hex:(e,n,r)=>"0"==e&&t.letter(n,"x")&&t.hexNum(r),expWithSign:(e,n,r)=>t.letter(e,"e")&&t.sign(n)&&t.digit(r),exp:(e,n)=>t.letter(e,"e")&&t.digit(n),dots:(e,n)=>t.dot(e)&&t.dot(n),letter:(e,t)=>String(e).toLowerCase()==String(t).toLowerCase(),comment:(e,t)=>"/"==e&&"*"==t,selfClosedTag:(e,t)=>"/"==e&&">"==t,closedTag:(e,t)=>"<"==e&&"/"==t};class n{constructor({type:e,value:t,pos:n,status:r}){this.type=e,this.value=t,this.pos=n,r&&(this.status=r)}isSymbol(...e){let t="Symbol"==this.type;return e.length?e.some((e=>e===this.value)):t}isSpace(){return"Space"==this.type}isNumber(){return"Number"==this.type}isWord(){return"Word"==this.type}}function r(e){let t=-1,n=e.length,r=-1,i=0;return{curr:(n=0)=>e[t+n],next(n=1){let s=e[t+=n];return"\n"==s?(i++,r=0):r+=n,s},end:()=>t>=n,get:()=>({prev:e[t-1],curr:e[t+0],next:e[t+1],next2:e[t+2],next3:e[t+3],pos:[r,i]})}}function i(e){for(;e.next();){let{curr:n,prev:r}=e.get();if(t.comment(n,r))break}}function s(e){return[":",";",",","{","}","(",")","[","]"].includes(e)}function l(e){let n="";for(;!e.end();){let{curr:r,next:i}=e.get();n+=r;let s=t.symbol(i)||t.space(i)||t.digit(i);if(n.length&&s&&!t.closedTag(r,i))break;e.next()}return n.trim()}function o(e){let n="";for(;!e.end();){let{curr:r,next:i}=e.get();if(n+=r,!t.space(i))break;e.next()}return n}function a(e){let n="",r=!1;for(;!e.end();){let{curr:i,next:s,next2:l,next3:o}=e.get();if(n+=i,r&&t.dot(s))break;if(t.dot(i)&&(r=!0),t.dots(s,l))break;if(t.expWithSign(s,l,o))n+=e.next()+e.next();else if(t.exp(s,l))n+=e.next();else if(!t.digit(s)&&!t.dot(s))break;e.next()}return n}function u(e){let n="0x";for(e.next(2);!e.end();){let{curr:r,next:i}=e.get();if(n+=r,!t.hexNum(i))break;e.next()}return n}function c(e){return e[e.length-1]}function h(e){let h=r(String(e).trim()),p=[],f=[];for(;h.next();){let{prev:e,curr:r,next:d,next2:m,pos:g}=h.get();if(t.comment(r,d))i(h);else if(t.hex(r,d,m)){let e=u(h);p.push(new n({type:"Number",value:e,pos:g}))}else if(t.digit(r)||t.digit(d)&&t.dot(r)&&!t.dots(e,r)){let e=a(h);p.push(new n({type:"Number",value:e,pos:g}))}else if(t.symbol(r)&&!t.selfClosedTag(r,d)){let e=c(p);if("-"===r&&t.digit(d)&&(!e||!e.isNumber())){let e=a(h);p.push(new n({type:"Number",value:e,pos:g}));continue}let i={type:"Symbol",value:r,pos:g};if(f.length&&t.escape(e.value)){p.pop();let e=l(h);e.length&&p.push(new n({type:"Word",value:e,pos:g}))}else{if(t.quote(r)){c(f)==r?(f.pop(),i.status="close"):(f.push(r),i.status="open")}p.push(new n(i))}}else if(t.space(r)){let e=o(h),t=c(p),{next:r}=h.get();if(!f.length&&t){if(s(t.value)||s(r))continue;e=" "}p.length&&r&&r.trim()&&p.push(new n({type:"Space",value:e,pos:g}))}else{let e=l(h);e.length&&p.push(new n({type:"Word",value:e,pos:g}))}}let d=c(p);return d&&d.isSpace()&&(p.length=p.length-1),p}function p(e){let t=[];for(;e.next();){let{curr:n,next:r}=e.get();if("var"===n.value){if(r&&r.isSymbol("(")){e.next();let n=f(e);m(n.name)&&t.push(n)}}else if(t.length&&!n.isSymbol(","))break}return t}function f(e){let t={},n=[];for(;e.next();){let{curr:r,next:i}=e.get();if(r.isSymbol(")",";")&&!t.name){t.name=d(n);break}r.isSymbol(",")?(void 0===t.name&&(t.name=d(n),n=[]),t.name&&(t.fallback=p(e))):n.push(r)}return t}function d(e){return e.map((e=>e.value)).join("")}function m(e){return void 0!==e&&(!(e.length<=2)&&(!e.substr(2).startsWith("-")&&!!e.startsWith("--")))}function g(e){return{make_array:function(e){return Array.isArray(e)?e:[e]},join:function(e,t="\n"){return(e||[]).join(t)},last:function(e,t=1){return e[e.length-t]},first:function(e){return e[0]},clone:function(e){return JSON.parse(JSON.stringify(e))},shuffle:function(t){let n=Array.from?Array.from(t):t.slice(),r=t.length;for(;r;){let t=~~(e()*r--),i=n[r];n[r]=n[t],n[t]=i}return n},flat_map:function(e,t){return Array.prototype.flatMap?e.flatMap(t):e.reduce(((e,n)=>e.concat(t(n))),[])},remove_empty_values:function(e){return e.filter((e=>null!=e&&String(e).trim().length))}}}let{first:y,last:v,clone:x}=g();const b={func:(e="")=>({type:"func",name:e,arguments:[]}),argument:()=>({type:"argument",value:[]}),text:(e="")=>({type:"text",value:e}),pseudo:(e="")=>({type:"pseudo",selector:e,styles:[]}),cond:(e="")=>({type:"cond",name:e,styles:[],arguments:[]}),rule:(e="")=>({type:"rule",property:e,value:[]}),keyframes:(e="")=>({type:"keyframes",name:e,steps:[]}),step:(e="")=>({type:"step",name:e,styles:[]})},_={white_space:e=>/[\s\n\t]/.test(e),line_break:e=>/\n/.test(e),number:e=>!isNaN(e),pair:e=>['"',"(",")","'"].includes(e),pair_of:(e,t)=>({'"':'"',"'":"'","(":")"}[e]==t)},w={\u03c0:Math.PI,"\u220f":Math.PI};function $(e){return["@canvas","@shaders","@doodle"].includes(e)}function k(e,{col:t,line:n}){console.warn(`(at line ${n}, column ${t}) ${e}`)}function S(e){return function(t,n){let r=t.index(),i="";for(;!t.end();){let n=t.next();if(e(n))break;i+=n}return n&&t.index(r),i}}function j(e,t){return S((e=>/[^\w@]/.test(e)))(e,t)}function E(e){return S((e=>/[\s\{]/.test(e)))(e)}function z(e,t){return S((e=>_.line_break(e)||"{"==e))(e,t)}function T(e,t){let n,r=b.step();for(;!e.end()&&"}"!=(n=e.curr());)if(_.white_space(n))e.next();else{if(r.name.length){if(r.styles.push(q(e,t)),"}"==e.curr())break}else r.name=W(e);e.next()}return r}function P(e,t){const n=[];let r;for(;!e.end()&&"}"!=(r=e.curr());)_.white_space(r)||n.push(T(e,t)),e.next();return n}function A(e,t){let n,r=b.keyframes();for(;!e.end()&&"}"!=(n=e.curr());)if(r.name.length){if("{"==n){e.next(),r.steps=P(e,t);break}e.next()}else if(j(e),r.name=E(e),!r.name.length){k("missing keyframes name",e.info());break}return r}function R(e,t={}){for(e.next();!e.end();){let n=e.curr();if(t.inline){if("\n"==n)break}else if("*"==(n=e.curr())&&"/"==e.curr(1))break;e.next()}t.inline||(e.next(),e.next())}function C(e){for(e.next();!e.end();){if(">"==e.curr())break;e.next()}}function M(e){let t,n="";for(;!e.end()&&":"!=(t=e.curr());)_.white_space(t)||(n+=t),e.next();return n}function N(e,t,n){let r,i=[],s=[],l=[],o="";for(;!e.end();){if(r=e.curr(),/[\('"`]/.test(r)&&"\\"!==e.curr(-1))l.length&&"("!=r&&r===v(l)?l.pop():l.push(r),o+=r;else if("@"!=r||n)if(n&&/[)]/.test(r)||!n&&/[,)]/.test(r))if(l.length)")"==r&&l.pop(),o+=r;else{if(o.length&&(s.length?s.push(b.text(o)):s.push(b.text((a=o).trim().length?_.number(+a)?+a:a.trim():a)),o.startsWith("\xb1")&&!n)){let e=o.substr(1),t=x(s);v(t).value="-"+e,i.push(L(t)),v(s).value=e}if(i.push(L(s)),[s,o]=[[],""],")"==r)break}else w[r]&&!/[0-9]/.test(e.curr(-1))&&(r=w[r]),o+=r;else s.length||(o=o.trimLeft()),o.length&&(s.push(b.text(o)),o=""),s.push(O(e));if(!(!t||")"!=e.curr(1)&&/[0-9a-zA-Z_\-.]/.test(e.curr())||l.length)){s.length&&i.push(L(s));break}e.next()}var a;return i}function L(e){let t=e.map((e=>{if("text"==e.type&&"string"==typeof e.value){let t=String(e.value);t.includes("`")&&(e.value=t=t.replace(/`/g,'"')),e.value=t}return e})),n=y(t)||{},r=v(t)||{};if("text"==n.type&&"text"==r.type){let e=y(n.value),i=v(r.value);"string"==typeof n.value&&"string"==typeof r.value&&_.pair_of(e,i)&&(n.value=n.value.slice(1),r.value=r.value.slice(0,r.value.length-1),t.cluster=!0)}return t}function O(e){let t,n=b.func(),r="@",i=!1;for(e.next();!e.end();){t=e.curr();let s="."==t&&"@"==e.curr(1),l=e.curr(1);if("("==t||s){i=!0,e.next(),n.arguments=N(e,s,$(r));break}if(!i&&"("!==l&&!/[0-9a-zA-Z_\-.]/.test(l)){r+=t;break}r+=t,e.next()}let{fname:s,extra:l}=function(e){let t="",n="";if(/\D$/.test(e)&&!/\d+x\d+/.test(e)||Math[e.substr(1)])return{fname:e,extra:n};for(let r=e.length-1;r>=0;r--){let i=e[r],s=e[r-1],l=e[r+1];if(!(/[\d.]/.test(i)||"x"==i&&/\d/.test(s)&&/\d/.test(l))){t=e.substring(0,r+1);break}n=i+n}return{fname:t,extra:n}}(r);return n.name=s,l.length&&n.arguments.unshift([{type:"text",value:l}]),n.position=e.info().index,n}function I(e){let t,n=b.text(),r=0,i=!0;const s=[],l=[];for(s[r]=[];!e.end();)if(t=e.curr(),i&&_.white_space(t))e.next();else{if(i=!1,"\n"!=t||_.white_space(e.curr(-1)))if(","!=t||l.length){if(/[;}<]/.test(t)){n.value.length&&(s[r].push(n),n=b.text());break}"@"==t?(n.value.length&&(s[r].push(n),n=b.text()),s[r].push(O(e))):_.white_space(t)&&_.white_space(e.curr(-1))||("("==t&&l.push(t),")"==t&&l.pop(),w[t]&&!/[0-9]/.test(e.curr(-1))&&(t=w[t]),n.value+=t)}else n.value.length&&(s[r].push(n),n=b.text()),s[++r]=[],i=!0;else n.value+=" ";e.next()}return n.value.length&&s[r].push(n),s}function W(e){let t,n="";for(;!e.end()&&"{"!=(t=e.curr());)_.white_space(t)||(n+=t),e.next();return n}function U(e){let t,n={name:"",arguments:[]};for(;!e.end();){if("("==(t=e.curr()))e.next(),n.arguments=N(e);else{if(/[){]/.test(t))break;_.white_space(t)||(n.name+=t)}e.next()}return n}function D(e,t){let n,r=b.pseudo();for(;!e.end()&&"}"!=(n=e.curr());)if(_.white_space(n))e.next();else{if(r.selector){let n=q(e,t);if("@use"==n.property?r.styles=r.styles.concat(n.value):r.styles.push(n),"}"==e.curr())break}else r.selector=W(e);e.next()}return r}function q(e,t){let n=b.rule();for(;!e.end()&&";"!=e.curr();){if(n.property.length){n.value=I(e);break}if(n.property=M(e),"@use"==n.property){n.value=X(e,t);break}e.next()}return n}function H(e,t){let n,r=b.cond();for(;!e.end()&&"}"!=(n=e.curr());){if(r.name.length)if(":"==n){let t=D(e);t.selector&&r.styles.push(t)}else if("@"!=n||z(e,!0).includes(":")){if(!_.white_space(n)){let n=q(e,t);if(n.property&&r.styles.push(n),"}"==e.curr())break}}else r.styles.push(H(e));else Object.assign(r,U(e));e.next()}return r}function B(e,t){let n="";return e&&e.get_variable&&(n=e.get_variable(t)),n}function F(e,t){e.forEach&&e.forEach((e=>{if("text"==e.type&&e.value){let n=p(r(h(e.value)));e.value=n.reduce(((e,n)=>{let r,i="",s="";i=B(t,n.name),!i&&n.fallback&&n.fallback.every((e=>{if(s=B(t,e.name),s)return i=s,!1}));try{r=V(i,t)}catch(e){}return r&&e.push.apply(e,r),e}),[])}"func"==e.type&&e.arguments&&e.arguments.forEach((e=>{F(e,t)}))}))}function X(e,t){return e.next(),(I(e)||[]).reduce(((e,n)=>{F(n,t);let[r]=n;return r.value&&r.value.length&&e.push(...r.value),e}),[])}function V(e,t){const n=function(e=""){let t=0,n=1,r=1;return{curr:(n=0)=>e[t+n],end:()=>e.length<=t,info:()=>({index:t,col:n,line:r}),index:e=>void 0===e?t:t=e,next(){let i=e[t++];return"\n"==i?(r++,n=0):n++,i}}}(e),r=[];for(;!n.end();){let e=n.curr();if(_.white_space(e))n.next();else{if("/"==e&&"*"==n.curr(1))R(n);else if("/"==e&&"/"==n.curr(1))R(n,{inline:!0});else if(":"==e){let e=D(n,t);e.selector&&r.push(e)}else if("@"==e&&"@keyframes"===j(n,!0)){let e=A(n,t);r.push(e)}else if("@"!=e||z(n,!0).includes(":")){if("<"==e)C(n);else if(!_.white_space(e)){let e=q(n,t);e.property&&r.push(e)}}else{let e=H(n,t);e.name.length&&r.push(e)}n.next()}}return r}function G(e,t,n){return Math.max(t,Math.min(n,e))}function Y(e,t,n){let r=0,i=e,s=e=>e>0&&e<1?.1:1,l=arguments.length;1==l&&([e,t]=[s(e),e]),l<3&&(n=s(e));let o=[];for(;(n>=0&&e<=t||n<0&&e>t)&&(o.push(e),e+=n,!(r++>=1e3)););return o.length||o.push(i),o}function Z(e){return/^[a-zA-Z]$/.test(e)}function K(e){return null==e}function J(e){return K(e)||Number.isNaN(e)}function Q(e){return K(e)||""===e}function ee(e){let t=()=>e;return t.lazy=!0,t}function te(e,t,n){return"c-"+e+"-"+t+"-"+n}function ne(e){for(;e&&e.value;)return ne(e.value);return K(e)?"":e}function re(e,t,n=0){let r=new Image;r.crossOrigin="anonymous",r.src=e,r.onload=function(){setTimeout(t,n)}}function ie(){return/^((?!chrome|android).)*safari/i.test(navigator.userAgent)}function se(e){let t=document.createElement("textarea");return t.innerHTML=e,t.value}function le(e,t=0){let n=3735928559^t,r=1103547991^t;for(let t,i=0;i>>16,2246822507)^Math.imul(r^r>>>13,3266489909),r=Math.imul(r^r>>>16,2246822507)^Math.imul(n^n>>>13,3266489909),4294967296*(2097151&r)+(n>>>0)}function oe(e){return(t,...n)=>{let r=t.reduce(((e,t,r)=>{return e+t+(K(i=n[r])?"":i);var i}),"");return e(r)}}const[ae,ue,ce]=[1,32,1024];function he(e){let[t,n,r]=(e+"").replace(/\s+/g,"").replace(/[,\uff0cxX]+/g,"x").split("x").map((e=>parseInt(e)));const i=1==t||1==n?ce:ue,s=1==t&&1==n?ce:ae,l={x:G(t||ae,1,i),y:G(n||t||ae,1,i),z:G(r||ae,1,s)};return Object.assign({},l,{count:l.x*l.y*l.z,ratio:l.x/l.y})}function pe(e){return/^texture\w*$|^(fragment|vertex)$/.test(e)}function fe(){return new n({type:"LineBreak",value:"\n"})}function de(e){let t=e[0],n=e[e.length-1];for(;t&&t.isSymbol("(")&&n&&n.isSymbol(")");)t=(e=e.slice(1,e.length-1))[0],n=e[e.length-1];return e}function me(e){return de(e).map((e=>e.value)).join("")}const ge="http://www.w3.org/2000/svg",ye="http://www.w3.org/1999/xlink";function ve(e,t){return`url("data:image/svg+xml;utf8,${encodeURIComponent(e)+(t?`#${t}`:"")}")`}function xe(e){const t=`xmlns="${ge}"`,n=`xmlns:xlink="${ye}"`;return e.includes("`),e.includes("xmlns")||(e=e.replace(/