UNPKG

css-doodle

Version:

A web component for drawing patterns with CSS

83 lines (76 loc) 1.96 kB
import { last } from './index.js'; import { by_charcode } from './transform.js'; import { memo } from '../cache.js'; function Type(type, value) { return { type, value }; } function range(start, stop, step) { let count = 0, old = start; let initial = n => (n > 0 && n < 1) ? .1 : 1; let length = arguments.length; if (length == 1) [start, stop] = [initial(start), start]; if (length < 3) step = initial(start); let range = []; while ((step >= 0 && start <= stop) || (step < 0 && start > stop)) { range.push(start); start += step; if (count++ >= 65535) break; } if (!range.length) range.push(old); return range; } function get_tokens(input) { let expr = String(input); let tokens = [], stack = []; if (!expr.startsWith('[') || !expr.endsWith(']')) { return tokens; } for (let i = 1; i < expr.length - 1; ++i) { let c = expr[i]; if (c == '-' && expr[i - 1] == '-') { continue; } if (c == '-') { stack.push(c); continue; } if (last(stack) == '-') { stack.pop(); let from = stack.pop(); tokens.push(from ? Type('range', [ from, c ]) : Type('char', c) ); continue; } if (stack.length) { tokens.push(Type('char', stack.pop())); } stack.push(c); } if (stack.length) { tokens.push(Type('char', stack.pop())); } return tokens; } const build_range = memo('build_range', (input) => { let tokens = get_tokens(input); return tokens.flatMap(({ type, value }) => { if (type == 'char') return value; let [ from, to ] = value; let reverse = false; if (from > to) { [from, to] = [ to, from ]; reverse = true; } let result = by_charcode(range)(from, to); if (reverse) result.reverse(); return result; }); }); export default function expand(fn) { return (...args) => fn(...(args.flatMap(n => String(n).startsWith('[') ? build_range(n) : n ))); }