New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

straylight

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

straylight - npm Package Compare versions

Comparing version
0.8.0
to
0.8.1
+86
src/builder.js
import * as dom from './dom.js';
import {
CommentUpdater,
AttributeUpdater,
AttributePartUpdater,
PropertyMapUpdater,
ChildUpdater } from './updaters.js';
class Builder {
constructor() {
this.updaters = null;
}
build(template, parent, next) {
this.updaters = [];
this.buildNode(template, parent, next);
return this.updaters;
}
addAttributePartUpdater(element, name, parts) {
let updaterParts = [parts[0]];
updaterParts.pending = [];
for (let i = 1; i < parts.length; ++i) {
let pos = updaterParts.length;
updaterParts.push('');
updaterParts.push(parts[i]);
let updater = new AttributePartUpdater(element, name, updaterParts, pos);
this.updaters.push(updater);
}
}
buildNode(node, parent, next) {
switch (node.kind) {
case 'root':
this.buildChildren(node, parent, next);
return;
case 'child-slot':
this.updaters.push(new ChildUpdater(parent, next));
return;
case 'null-slot':
this.updaters.push(new CommentUpdater());
return;
}
let elem = dom.createElement(node.tag, parent);
for (let attr of node.attributes) {
switch (attr.kind) {
case 'static':
dom.setAttr(elem, attr.name, attr.value);
break;
case 'value':
this.updaters.push(new AttributeUpdater(elem, attr.name));
break;
case 'map':
this.updaters.push(new PropertyMapUpdater(elem));
break;
case 'null':
this.updaters.push(new CommentUpdater());
break;
case 'parts':
this.addAttributePartUpdater(elem, attr.name, attr.value);
break;
}
}
this.buildChildren(node, elem, null);
dom.insertChild(elem, parent, next);
}
buildChildren(node, parent, next) {
for (let child of node.children) {
if (typeof child === 'string') {
let text = dom.createText(child, parent);
dom.insertChild(text, parent, next);
} else {
this.buildNode(child, parent, next);
}
}
}
}
export function buildTemplate(template, parent, next) {
return new Builder().build(template, parent, next);
}
+226
-291

@@ -6,14 +6,2 @@ function makeEnum(i = 0) {

const {
T_NONE,
T_COMMENT,
T_TEXT,
T_ATTR_PART,
T_ATTR_MAP,
T_ATTR_VALUE,
T_TAG_START,
T_ATTR_KEY,
T_TAG_END,
} = makeEnum();
const {
S_TEXT,

@@ -23,2 +11,3 @@ S_RAW,

S_ATTR,
S_ATTR_CLOSE,
S_ATTR_KEY,

@@ -33,9 +22,8 @@ S_ATTR_KEY_WS,

const $tokens = Symbol('tokens');
const ESC_RE = /&(?:(lt|gt|amp|quot)|#([0-9]+)|#x([0-9a-f]+));?/ig;
const ESC_RE = /&(?:(lt|gt|amp|quot)|#([0-9]+)|#x([0-9a-f]+));?/ig;
const NAMED_REFS = { lt: '<', gt: '>', amp: '&', quot: '"' };
function wsToken(t) {
return t.type === T_TEXT && !t.mutable && (!t.value || !t.value.trim());
function notReached(msg) {
throw new Error(msg);
}

@@ -74,22 +62,47 @@

class Token {
constructor(type, value, hasEscape) {
this.type = type;
this.value = hasEscape ? escape(value) : value;
this.mutable = false;
function maybeEscape(hasEscape, text) {
return hasEscape ? escape(text) : text;
}
class ParseNode {
constructor(kind) {
this.kind = kind;
this.tag = '';
this.attributes = [];
this.children = [];
}
}
class Attribute {
constructor(kind, name, value) {
this.kind = kind;
this.name = name;
this.value = value;
}
}
class Parser {
constructor() {
this.tokens = [];
this.node = new ParseNode('root');
this.stack = [this.node];
this.state = S_TEXT;
this.attrName = '';
this.attrParts = [];
this.tag = '';
this.closing = false;
}
addAttr(value) {
this.node.attributes.push(new Attribute('static', this.attrName, value));
}
addAttrParts() {
let attr = new Attribute('parts', this.attrName, this.attrParts);
this.node.attributes.push(attr);
this.attrParts = [];
}
parseChunk(chunk) {
let state = this.state;
let tokens = this.tokens;
let attrPart = (state === S_ATTR_VALUE_DQ || state === S_ATTR_VALUE_SQ);
let attrPart = state === S_ATTR_VALUE_DQ || state === S_ATTR_VALUE_SQ;
let hasEscape = false;

@@ -108,5 +121,3 @@ let a = 0;

if (c === '>' && rmatch(chunk, b, '--')) {
if (b - 2 > a) {
tokens.push(new Token(T_COMMENT, chunk.slice(a, b - 2), false));
}
// Comments are ignored
state = S_TEXT;

@@ -121,6 +132,8 @@ hasEscape = false;

if (b > a) {
tokens.push(new Token(T_TEXT, chunk.slice(a, b), hasEscape));
let text = maybeEscape(hasEscape, chunk.slice(a, b));
this.node.children.push(text);
}
state = S_OPEN;
hasEscape = false;
this.closing = false;
a = b + 1;

@@ -130,7 +143,13 @@ }

if (c === "'") {
let type = attrPart ? T_ATTR_PART : T_ATTR_VALUE;
tokens.push(new Token(type, chunk.slice(a, b), hasEscape));
let value = maybeEscape(hasEscape, chunk.slice(a, b));
if (attrPart) {
this.attrParts.push(value);
this.addAttrParts();
attrPart = false;
} else {
this.addAttr(value);
}
state = S_ATTR;
hasEscape = false;
attrPart = false;
this.attrName = '';
a = b + 1;

@@ -140,7 +159,13 @@ }

if (c === '"') {
let type = attrPart ? T_ATTR_PART : T_ATTR_VALUE;
tokens.push(new Token(type, chunk.slice(a, b), hasEscape));
let value = maybeEscape(hasEscape, chunk.slice(a, b));
if (attrPart) {
this.attrParts.push(value);
this.addAttrParts();
attrPart = false;
} else {
this.addAttr(value);
}
state = S_ATTR;
hasEscape = false;
attrPart = false;
this.attrName = '';
a = b + 1;

@@ -150,27 +175,25 @@ }

if (state === S_OPEN) {
let value = chunk.slice(a, b);
tokens.push(new Token(T_TAG_START, value, hasEscape));
hasEscape = false;
a = b;
this.tag = value;
this.tag = maybeEscape(hasEscape, chunk.slice(a, b));
if (!this.closing) {
this.pushNode();
}
} else if (state === S_ATTR_KEY) {
tokens.push(new Token(T_ATTR_KEY, chunk.slice(a, b), hasEscape));
hasEscape = false;
a = b;
this.attrName = maybeEscape(hasEscape, chunk.slice(a, b));
this.addAttr(true);
} else if (state === S_ATTR_KEY_WS) {
this.addAttr(true);
} else if (state === S_ATTR_VALUE) {
tokens.push(new Token(T_ATTR_VALUE, chunk.slice(a, b), hasEscape));
hasEscape = false;
a = b;
this.addAttr(maybeEscape(hasEscape, chunk.slice(a, b)));
} else if (state === S_ATTR_VALUE_WS) {
this.addAttr(true);
}
if (rmatch(chunk, b, '/') && this.tag[0] !== '/') {
tokens.push(new Token(T_TAG_END, '/', false));
if (this.closing || rmatch(chunk, b, '/')) {
// Closing or self-closing tag
this.popNode();
state = S_TEXT;
hasEscape = false;
a = b + 1;
} else {
tokens.push(new Token(T_TAG_END, '', false));
hasEscape = false;
state = rawTag(this.tag) ? S_RAW : S_TEXT;
a = b + 1;
}
hasEscape = false;
a = b + 1;
} else if (state === S_OPEN) {

@@ -180,11 +203,16 @@ if (c === '-' && chunk.slice(a, b) === '!-') {

a = b + 1;
} else if (c === '/' && b === a) ; else if (!attrChar(c)) {
let value = chunk.slice(a, b);
tokens.push(new Token(T_TAG_START, value, hasEscape));
this.tag = value;
} else if (c === '/' && b === a) {
this.closing = true;
} else if (!attrChar(c)) {
this.tag = maybeEscape(hasEscape, chunk.slice(a, b));
if (this.closing) {
state = S_ATTR_CLOSE;
} else {
this.pushNode();
state = S_ATTR;
}
hasEscape = false;
state = S_ATTR;
a = b + 1;
}
} else if (state === S_ATTR) {
} else if (state === S_ATTR_CLOSE) ; else if (state === S_ATTR) {
if (attrChar(c)) {

@@ -196,3 +224,3 @@ state = S_ATTR_KEY;

if (c === '=') {
tokens.push(new Token(T_ATTR_KEY, chunk.slice(a, b), hasEscape));
this.attrName = maybeEscape(hasEscape, chunk.slice(a, b));
hasEscape = false;

@@ -202,3 +230,3 @@ state = S_ATTR_VALUE_WS;

} else if (!attrChar(c)) {
tokens.push(new Token(T_ATTR_KEY, chunk.slice(a, b), hasEscape));
this.attrName = maybeEscape(hasEscape, chunk.slice(a, b));
hasEscape = false;

@@ -213,2 +241,3 @@ state = S_ATTR_KEY_WS;

} else if (attrChar(c)) {
this.addAttr(true);
state = S_ATTR_KEY;

@@ -230,3 +259,3 @@ a = b;

if (!attrChar(c)) {
tokens.push(new Token(T_ATTR_VALUE, chunk.slice(a, b), hasEscape));
this.addAttr(maybeEscape(hasEscape, chunk.slice(a, b)));
hasEscape = false;

@@ -241,17 +270,15 @@ state = S_ATTR;

if (a < b) {
tokens.push(new Token(T_TEXT, chunk.slice(a, b), hasEscape));
let text = maybeEscape(hasEscape, chunk.slice(a, b));
this.node.children.push(text);
}
} else if (state === S_COMMENT) {
if (a < b) {
tokens.push(new Token(T_COMMENT, chunk.slice(a, b), hasEscape));
}
} else if (state === S_OPEN) {
if (a < b) {
let value = chunk.slice(a, b);
tokens.push(new Token(T_TAG_START, value, hasEscape));
this.tag = value;
} else if (state === S_COMMENT) ; else if (state === S_OPEN) {
this.tag = maybeEscape(hasEscape, chunk.slice(a, b));
if (this.closing) {
state = S_ATTR_CLOSE;
} else {
this.pushNode();
state = S_ATTR;
}
} else if (state === S_ATTR_KEY) {
tokens.push(new Token(T_ATTR_KEY, chunk.slice(a, b), hasEscape));
this.attrName = maybeEscape(hasEscape, chunk.slice(a, b));
state = S_ATTR;

@@ -261,8 +288,7 @@ } else if (state === S_ATTR_KEY_WS) {

} else if (state === S_ATTR_VALUE) {
tokens.push(new Token(T_ATTR_VALUE, chunk.slice(a, b), hasEscape));
this.addAttr(maybeEscape(hasEscape, chunk.slice(a, b)));
state = S_ATTR;
} else if (state === S_ATTR_VALUE_SQ || state === S_ATTR_VALUE_DQ) {
if (a < b) {
tokens.push(new Token(T_ATTR_PART, chunk.slice(a, b), hasEscape));
}
let value = maybeEscape(hasEscape, chunk.slice(a, b));
this.attrParts.push(value);
}

@@ -273,23 +299,34 @@

pushValue(value) {
let type = T_NONE;
pushNode() {
let node = new ParseNode('element');
node.tag = this.tag;
this.node.children.push(node);
this.node = node;
this.stack.push(node);
}
popNode() {
if (this.stack.length > 1) {
this.stack.pop();
this.node = this.stack[this.stack.length - 1];
}
}
addSlot() {
switch (this.state) {
case S_TEXT:
case S_RAW:
type = T_TEXT;
this.node.children.push(new ParseNode('child-slot'));
break;
case S_COMMENT:
type = T_COMMENT;
this.node.children.push(new ParseNode('null-slot'));
break;
case S_OPEN:
type = T_TAG_START;
this.tag = value;
this.state = S_ATTR;
break;
case S_ATTR:
type = T_ATTR_MAP;
this.node.attributes.push(new Attribute('map', '', ''));
break;
case S_ATTR_CLOSE:
this.node.attributes.push(new Attribute('null', '', ''));
break;
case S_ATTR_VALUE_WS:
type = T_ATTR_VALUE;
this.node.attributes.push(new Attribute('value', this.attrName, ''));
this.state = S_ATTR;

@@ -299,39 +336,25 @@ break;

case S_ATTR_VALUE_DQ:
type = T_ATTR_PART;
// Slots will be added when the next chunk is parsed
break;
default:
notReached('Unexpected parser state');
break;
}
if (type !== T_NONE) {
let token = new Token(type, value);
token.mutable = true;
this.tokens.push(token);
}
}
end() {
let tokens = this.tokens;
let a = 0;
let b = tokens.length;
if (b === 0) {
return tokens;
}
if (wsToken(tokens[0])) { a++; }
if (wsToken(tokens[b - 1])) { b--; }
return a === 0 && b === tokens.length ? tokens : tokens.slice(a, b);
if (this.attrParts.length > 0) { this.addAttrParts(); }
while (this.stack.length > 1) { this.popNode(); }
return this.node;
}
}
function tokenize(chunks) {
if (chunks.length === 0) {
return [];
}
function parse(chunks) {
let parser = new Parser();
parser.parseChunk(chunks[0]);
for (let i = 1; i < chunks.length; i++) {
parser.pushValue('');
parser.parseChunk(chunks[i]);
if (chunks.length > 0) {
parser.parseChunk(chunks[0]);
for (let i = 1; i < chunks.length; i++) {
parser.addSlot();
parser.parseChunk(chunks[i]);
}
}

@@ -341,88 +364,7 @@ return parser.end();

function walk(i, node, tokens, vals, actions) {
for (; i < tokens.length; ++i) {
let t = tokens[i];
switch (t.type) {
case T_TAG_START: {
let tag = vals.read(t);
if (typeof tag === 'string' && tag[0] === '/') { // Closing tag
while (i < tokens.length && tokens[++i].type !== T_TAG_END); // Skip attributes
return i;
}
let child = actions.createElement(tag, node);
i = walk(i + 1, child, tokens, vals, actions);
actions.appendChild(node, actions.finishElement(child));
break;
}
case T_TAG_END:
if (t.value === '/') { return i; }
break;
case T_TEXT:
actions.appendChild(node, vals.read(t));
break;
case T_COMMENT:
actions.appendChild(node, actions.createComment(vals.read(t), node));
break;
case T_ATTR_MAP:
actions.setAttributes(node, vals.read(t));
break;
case T_ATTR_KEY: {
let name = vals.read(t);
switch (i + 1 < tokens.length ? tokens[i + 1].type : T_NONE) {
case T_ATTR_VALUE:
actions.setAttribute(node, name, vals.read(tokens[++i]));
break;
case T_ATTR_PART: {
let parts = [vals.read(tokens[++i])];
while (i + 1 < tokens.length && tokens[i + 1].type === T_ATTR_PART) {
parts.push(vals.read(tokens[++i]));
}
actions.setAttributeParts(node, name, parts);
break;
}
default:
actions.setAttribute(node, name, true);
break;
}
}
}
}
}
class Vals {
constructor(values, actions) {
this.index = 0;
this.values = values;
this.actions = actions;
}
read(t) {
return t.mutable
? this.actions.mapValue(this.values[this.index++])
: t.value;
}
}
class TemplateResult {
constructor(callsite, values) {
let tokens = TemplateResult.cache.get(callsite);
if (!tokens) {
tokens = tokenize(callsite.raw);
tokens.source = {};
TemplateResult.cache.set(callsite, tokens);
}
this[$tokens] = tokens;
this.source = tokens.source;
constructor(template, values) {
this.template = template;
this.values = values;
}
evaluate(actions) {
let root = actions.createRoot();
walk(0, root, this[$tokens], new Vals(this.values, actions), actions);
return actions.finishRoot(root);
}
}

@@ -432,11 +374,9 @@

// IE11's WeakMap implementation is incorrect
try {
new WeakMap().set({}, 1).get({});
} catch (e) {
TemplateResult.cache = new Map();
}
function html(callsite, ...values) {
return new TemplateResult(callsite, values);
let template = TemplateResult.cache.get(callsite);
if (!template) {
template = parse(callsite.raw);
TemplateResult.cache.set(callsite, template);
}
return new TemplateResult(template, values);
}

@@ -619,4 +559,4 @@

class ChildUpdater {
constructor(context, parent, next) {
this.slot = createSlot(context, parent, next, null);
constructor(parent, next) {
this.slot = createSlot(parent, next, null);
}

@@ -629,77 +569,71 @@

class Dynamic {
constructor(value) { this.value = value; }
}
class Builder {
constructor() {
this.updaters = null;
}
function isDynamic(x) {
return x instanceof Dynamic;
}
class Actions {
constructor(context, root, next) {
this.context = context;
this.root = root;
this.next = next;
build(template, parent, next) {
this.updaters = [];
}
createRoot() {
return this.root;
}
finishRoot() {
this.buildNode(template, parent, next);
return this.updaters;
}
createElement(tag, parent) {
if (typeof tag !== 'string') {
throw new TypeError('Tag name must be a string');
addAttributePartUpdater(element, name, parts) {
let updaterParts = [parts[0]];
updaterParts.pending = [];
for (let i = 1; i < parts.length; ++i) {
let pos = updaterParts.length;
updaterParts.push('');
updaterParts.push(parts[i]);
let updater = new AttributePartUpdater(element, name, updaterParts, pos);
this.updaters.push(updater);
}
return createElement(tag, parent);
}
createComment(value) {
if (isDynamic(value)) {
this.updaters.push(new CommentUpdater());
buildNode(node, parent, next) {
switch (node.kind) {
case 'root':
this.buildChildren(node, parent, next);
return;
case 'child-slot':
this.updaters.push(new ChildUpdater(parent, next));
return;
case 'null-slot':
this.updaters.push(new CommentUpdater());
return;
}
return null;
}
finishElement(node) {
return node;
}
let elem = createElement(node.tag, parent);
appendChild(node, child) {
let next = node === this.root ? this.next : null;
if (isDynamic(child)) {
this.updaters.push(new ChildUpdater(this.context, node, next));
} else if (child !== null) {
if (typeof child === 'string') {
child = createText(child, node);
for (let attr of node.attributes) {
switch (attr.kind) {
case 'static':
setAttr(elem, attr.name, attr.value);
break;
case 'value':
this.updaters.push(new AttributeUpdater(elem, attr.name));
break;
case 'map':
this.updaters.push(new PropertyMapUpdater(elem));
break;
case 'null':
this.updaters.push(new CommentUpdater());
break;
case 'parts':
this.addAttributePartUpdater(elem, attr.name, attr.value);
break;
}
insertChild(child, node, next);
}
}
mapValue(v) {
return new Dynamic(v);
this.buildChildren(node, elem, null);
insertChild(elem, parent, next);
}
setAttribute(node, name, value) {
if (isDynamic(value)) {
this.updaters.push(new AttributeUpdater(node, name));
} else {
setAttr(node, name, value);
}
}
setAttributes(node) {
this.updaters.push(new PropertyMapUpdater(node));
}
setAttributeParts(node, name, parts) {
parts.pending = [];
for (let i = 0; i < parts.length; ++i) {
if (isDynamic(parts[i])) {
this.updaters.push(new AttributePartUpdater(node, name, parts, i));
buildChildren(node, parent, next) {
for (let child of node.children) {
if (typeof child === 'string') {
let text = createText(child, parent);
insertChild(text, parent, next);
} else {
this.buildNode(child, parent, next);
}

@@ -710,19 +644,23 @@ }

function buildTemplate(template, parent, next) {
return new Builder().build(template, parent, next);
}
const createSlotSymbol = Symbol('createSlot');
function createSlot(context, parent, next, value) {
function createSlot(parent, next, value) {
if (isTextLike(value)) {
return new TextSlot(context, parent, next, value);
return new TextSlot(parent, next, value);
}
if (value instanceof TemplateResult) {
return new TemplateSlot(context, parent, next, value);
return new TemplateSlot(parent, next, value);
}
if (typeof value[createSlotSymbol] === 'function') {
return value[createSlotSymbol](context, parent, next);
return value[createSlotSymbol](parent, next);
}
if (isIterable(value)) {
return new MapSlot(context, parent, next, value);
return new MapSlot(parent, next, value);
}

@@ -739,3 +677,3 @@

let next = slot.start;
let newSlot = createSlot(slot.context, parent(next), next, value);
let newSlot = createSlot(parent(next), next, value);
removeSlot(slot);

@@ -769,6 +707,5 @@ return newSlot;

class TextSlot {
constructor(context, parent, next, value) {
constructor(parent, next, value) {
let node = createText(value, parent);
insertChild(node, parent, next);
this.context = context;
this.start = node;

@@ -850,7 +787,6 @@ this.end = node;

class MapSlot {
constructor(context, parent, next, value) {
this.context = context;
constructor(parent, next, value) {
this.parent = parent;
this.map = new Map();
this.list = new MapSlotList(createSlot(this.context, parent, next), null);
this.list = new MapSlotList(createSlot(parent, next), null);
this.update(value);

@@ -902,3 +838,3 @@ }

} else {
let slot = createSlot(this.context, this.parent, next.slot.start, value);
let slot = createSlot(this.parent, next.slot.start, value);
item = new MapSlotList(slot, key);

@@ -921,4 +857,3 @@ item.insertBefore(next);

class TemplateSlot {
constructor(context, parent, next, template) {
this.context = context;
constructor(parent, next, value) {
// The first and last nodes of the template could be dynamic,

@@ -928,6 +863,6 @@ // so create stable marker nodes before and after the content.

this.end = insertMarker(parent, next);
this.source = template.source;
this.updaters = template.evaluate(new Actions(context, parent, this.end));
this.template = value.template;
this.updaters = buildTemplate(this.template, parent, this.end);
this.pending = Array(this.updaters.length);
this.update(template);
this.update(value);
}

@@ -948,9 +883,9 @@

value instanceof TemplateResult &&
value.source === this.source
value.template === this.template
);
}
update(template) {
// Assert: template.source === this.updater.source
let { values } = template;
update(value) {
// Assert: value.template === this.template
let { values } = value;
for (let i = 0; i < this.updaters.length; ++i) {

@@ -1047,3 +982,3 @@ let value = values[i];

let next = firstChild(target);
slot = createSlot(null, target, next, template);
slot = createSlot(target, next, template);
if (next) {

@@ -1056,2 +991,2 @@ removeSiblings(next, null);

export { applyTemplate, createSlot, createSlotSymbol, html, removeSlot, updateSlot, withKey };
export { TemplateResult, applyTemplate, createSlot, createSlotSymbol, html, removeSlot, updateSlot, withKey };

@@ -1,1 +0,1 @@

function makeEnum(t=0){return new Proxy({},{get:()=>t++})}const{T_NONE:T_NONE,T_COMMENT:T_COMMENT,T_TEXT:T_TEXT,T_ATTR_PART:T_ATTR_PART,T_ATTR_MAP:T_ATTR_MAP,T_ATTR_VALUE:T_ATTR_VALUE,T_TAG_START:T_TAG_START,T_ATTR_KEY:T_ATTR_KEY,T_TAG_END:T_TAG_END}=makeEnum(),{S_TEXT:S_TEXT,S_RAW:S_RAW,S_OPEN:S_OPEN,S_ATTR:S_ATTR,S_ATTR_KEY:S_ATTR_KEY,S_ATTR_KEY_WS:S_ATTR_KEY_WS,S_ATTR_VALUE_WS:S_ATTR_VALUE_WS,S_ATTR_VALUE:S_ATTR_VALUE,S_ATTR_VALUE_SQ:S_ATTR_VALUE_SQ,S_ATTR_VALUE_DQ:S_ATTR_VALUE_DQ,S_COMMENT:S_COMMENT}=makeEnum(),$tokens=Symbol("tokens"),ESC_RE=/&(?:(lt|gt|amp|quot)|#([0-9]+)|#x([0-9a-f]+));?/gi,NAMED_REFS={lt:"<",gt:">",amp:"&",quot:'"'};function wsToken(t){return!(t.type!==T_TEXT||t.mutable||t.value&&t.value.trim())}function rmatch(t,e,s){return e>=s.length&&t.slice(e-s.length,e)===s}function wsChar(t){switch(t){case" ":case"\n":case"\r":case"\t":case"\f":case"\v":return!0}return t.charCodeAt(0)>128&&/\s/.test(t)}function attrChar(t){return!wsChar(t)&&'"'!==t&&"'"!==t&&"="!==t&&"/"!==t}function rawTag(t){return"script"===t||"style"===t}function escape(t){return t.replace(ESC_RE,((t,e,s,n)=>e?NAMED_REFS[e.toLowerCase()]:String.fromCharCode(parseInt(s||n,n?16:10))))}class Token{constructor(t,e,s){this.type=t,this.value=s?escape(e):e,this.mutable=!1}}class Parser{constructor(){this.tokens=[],this.state=S_TEXT,this.tag=""}parseChunk(t){let e=this.state,s=this.tokens,n=e===S_ATTR_VALUE_DQ||e===S_ATTR_VALUE_SQ,r=!1,i=0,a=0;for(;a<t.length;++a){let o=t[a];if(e===S_RAW)">"===o&&rmatch(t,a,"</"+this.tag)&&(a-=this.tag.length+3,e=S_TEXT);else if(e===S_COMMENT)">"===o&&rmatch(t,a,"--")&&(a-2>i&&s.push(new Token(T_COMMENT,t.slice(i,a-2),!1)),e=S_TEXT,r=!1,i=a+1);else if("&"===o)r=!0;else if(e===S_TEXT)"<"===o&&(a>i&&s.push(new Token(T_TEXT,t.slice(i,a),r)),e=S_OPEN,r=!1,i=a+1);else if(e===S_ATTR_VALUE_SQ){if("'"===o){let o=n?T_ATTR_PART:T_ATTR_VALUE;s.push(new Token(o,t.slice(i,a),r)),e=S_ATTR,r=!1,n=!1,i=a+1}}else if(e===S_ATTR_VALUE_DQ){if('"'===o){let o=n?T_ATTR_PART:T_ATTR_VALUE;s.push(new Token(o,t.slice(i,a),r)),e=S_ATTR,r=!1,n=!1,i=a+1}}else if(">"===o){if(e===S_OPEN){let e=t.slice(i,a);s.push(new Token(T_TAG_START,e,r)),r=!1,i=a,this.tag=e}else e===S_ATTR_KEY?(s.push(new Token(T_ATTR_KEY,t.slice(i,a),r)),r=!1,i=a):e===S_ATTR_VALUE&&(s.push(new Token(T_ATTR_VALUE,t.slice(i,a),r)),r=!1,i=a);rmatch(t,a,"/")&&"/"!==this.tag[0]?(s.push(new Token(T_TAG_END,"/",!1)),e=S_TEXT,r=!1,i=a+1):(s.push(new Token(T_TAG_END,"",!1)),r=!1,e=rawTag(this.tag)?S_RAW:S_TEXT,i=a+1)}else if(e===S_OPEN){if("-"===o&&"!-"===t.slice(i,a))e=S_COMMENT,i=a+1;else if("/"===o&&a===i);else if(!attrChar(o)){let n=t.slice(i,a);s.push(new Token(T_TAG_START,n,r)),this.tag=n,r=!1,e=S_ATTR,i=a+1}}else e===S_ATTR?attrChar(o)&&(e=S_ATTR_KEY,i=a):e===S_ATTR_KEY?"="===o?(s.push(new Token(T_ATTR_KEY,t.slice(i,a),r)),r=!1,e=S_ATTR_VALUE_WS,i=a+1):attrChar(o)||(s.push(new Token(T_ATTR_KEY,t.slice(i,a),r)),r=!1,e=S_ATTR_KEY_WS,i=a+1):e===S_ATTR_KEY_WS?"="===o?(e=S_ATTR_VALUE_WS,i=a+1):attrChar(o)&&(e=S_ATTR_KEY,i=a):e===S_ATTR_VALUE_WS?'"'===o?(e=S_ATTR_VALUE_DQ,i=a+1):"'"===o?(e=S_ATTR_VALUE_SQ,i=a+1):attrChar(o)&&(e=S_ATTR_VALUE,i=a):e===S_ATTR_VALUE&&(attrChar(o)||(s.push(new Token(T_ATTR_VALUE,t.slice(i,a),r)),r=!1,e=S_ATTR,i=a+1))}if(e===S_TEXT||e===S_RAW)i<a&&s.push(new Token(T_TEXT,t.slice(i,a),r));else if(e===S_COMMENT)i<a&&s.push(new Token(T_COMMENT,t.slice(i,a),r));else if(e===S_OPEN){if(i<a){let n=t.slice(i,a);s.push(new Token(T_TAG_START,n,r)),this.tag=n,e=S_ATTR}}else e===S_ATTR_KEY?(s.push(new Token(T_ATTR_KEY,t.slice(i,a),r)),e=S_ATTR):e===S_ATTR_KEY_WS?e=S_ATTR:e===S_ATTR_VALUE?(s.push(new Token(T_ATTR_VALUE,t.slice(i,a),r)),e=S_ATTR):e!==S_ATTR_VALUE_SQ&&e!==S_ATTR_VALUE_DQ||i<a&&s.push(new Token(T_ATTR_PART,t.slice(i,a),r));this.state=e}pushValue(t){let e=T_NONE;switch(this.state){case S_TEXT:case S_RAW:e=T_TEXT;break;case S_COMMENT:e=T_COMMENT;break;case S_OPEN:e=T_TAG_START,this.tag=t,this.state=S_ATTR;break;case S_ATTR:e=T_ATTR_MAP;break;case S_ATTR_VALUE_WS:e=T_ATTR_VALUE,this.state=S_ATTR;break;case S_ATTR_VALUE_SQ:case S_ATTR_VALUE_DQ:e=T_ATTR_PART}if(e!==T_NONE){let s=new Token(e,t);s.mutable=!0,this.tokens.push(s)}}end(){let t=this.tokens,e=0,s=t.length;return 0===s?t:(wsToken(t[0])&&e++,wsToken(t[s-1])&&s--,0===e&&s===t.length?t:t.slice(e,s))}}function tokenize(t){if(0===t.length)return[];let e=new Parser;e.parseChunk(t[0]);for(let s=1;s<t.length;s++)e.pushValue(""),e.parseChunk(t[s]);return e.end()}function walk(t,e,s,n,r){for(;t<s.length;++t){let i=s[t];switch(i.type){case T_TAG_START:{let a=n.read(i);if("string"==typeof a&&"/"===a[0]){for(;t<s.length&&s[++t].type!==T_TAG_END;);return t}let o=r.createElement(a,e);t=walk(t+1,o,s,n,r),r.appendChild(e,r.finishElement(o));break}case T_TAG_END:if("/"===i.value)return t;break;case T_TEXT:r.appendChild(e,n.read(i));break;case T_COMMENT:r.appendChild(e,r.createComment(n.read(i),e));break;case T_ATTR_MAP:r.setAttributes(e,n.read(i));break;case T_ATTR_KEY:{let a=n.read(i);switch(t+1<s.length?s[t+1].type:T_NONE){case T_ATTR_VALUE:r.setAttribute(e,a,n.read(s[++t]));break;case T_ATTR_PART:{let i=[n.read(s[++t])];for(;t+1<s.length&&s[t+1].type===T_ATTR_PART;)i.push(n.read(s[++t]));r.setAttributeParts(e,a,i);break}default:r.setAttribute(e,a,!0)}}}}}class Vals{constructor(t,e){this.index=0,this.values=t,this.actions=e}read(t){return t.mutable?this.actions.mapValue(this.values[this.index++]):t.value}}class TemplateResult{constructor(t,e){let s=TemplateResult.cache.get(t);s||(s=tokenize(t.raw),s.source={},TemplateResult.cache.set(t,s)),this[$tokens]=s,this.source=s.source,this.values=e}evaluate(t){let e=t.createRoot();return walk(0,e,this[$tokens],new Vals(this.values,t),t),t.finishRoot(e)}}TemplateResult.cache=new WeakMap;try{(new WeakMap).set({},1).get({})}catch(t){TemplateResult.cache=new Map}function html(t,...e){return new TemplateResult(t,e)}const HTML_NS="http://www.w3.org/1999/xhtml",SVG_NS="http://www.w3.org/2000/svg";function doc(t){return t.ownerDocument}function convertToString(t){return null==t?"":"string"==typeof t?t:String(t)}function setAttr(t,e,s){null==s||!1===s?t.removeAttribute(e):t.setAttribute(e,!0===s?e:s)}function setTextValue(t,e){t.nodeValue=convertToString(e)}function createText(t,e){return doc(e).createTextNode(convertToString(t))}function insertMarker(t,e){let s=doc(t).createTextNode("");return t.insertBefore(s,e),s}function createElement(t,e){let s=getNamespace(t,e);return s===HTML_NS?doc(e).createElement(t):doc(e).createElementNS(s,t)}function firstChild(t){return t.firstChild}function parent(t){return t?t.parentNode:null}function insertChild(t,e,s=null){e.insertBefore(t,s)}function insertSiblings(t,e,s){let n=s.parentNode;for(let r;t&&(r=t.nextSibling,n.insertBefore(t,s),t!==e);t=r);}function removeSiblings(t,e){let s=t.parentNode;for(let n;t&&(n=t.nextSibling,s.removeChild(t),t!==e);t=n);}function getNamespace(t,e){return"svg"===t?SVG_NS:e.namespaceURI||HTML_NS}function isObjectLike(t){return t&&("function"==typeof t||"object"==typeof t)}function toAttributeValue(t){if(!isObjectLike(t))return t;if(Array.isArray(t))return t.join(" ");if(t[Symbol.iterator])return Array.from(t).join(" ");throw new TypeError("Invalid attribute value")}class CommentUpdater{update(){}}class AttributeUpdater{constructor(t,e){this.node=t,this.name=e,this.last=void 0}update(t){let e=toAttributeValue(t);e!==this.last&&(this.last=e,setAttr(this.node,this.name,e))}}class AttributePartUpdater{constructor(t,e,s,n){this.node=t,this.name=e,this.parts=s,this.pos=n,s.pending[n]=!0}isReady(){let t=this.parts.pending;return!t||(t[this.pos]=!1,!!t.every((t=>!t))&&(this.parts.pending=null,!0))}update(t){this.parts[this.pos]=toAttributeValue(t),this.isReady()&&setAttr(this.node,this.name,this.parts.join(""))}}class PropertyMapUpdater{constructor(t){this.node=t}update(t){if("function"==typeof t&&(t=t(this.node)),null!=t){if("object"!=typeof t)throw new Error("Invalid property map value");Object.assign(this.node,t)}}}class ChildUpdater{constructor(t,e,s){this.slot=createSlot(t,e,s,null)}update(t){this.slot=updateSlot(this.slot,t)}}class Dynamic{constructor(t){this.value=t}}function isDynamic(t){return t instanceof Dynamic}class Actions{constructor(t,e,s){this.context=t,this.root=e,this.next=s,this.updaters=[]}createRoot(){return this.root}finishRoot(){return this.updaters}createElement(t,e){if("string"!=typeof t)throw new TypeError("Tag name must be a string");return createElement(t,e)}createComment(t){return isDynamic(t)&&this.updaters.push(new CommentUpdater),null}finishElement(t){return t}appendChild(t,e){let s=t===this.root?this.next:null;isDynamic(e)?this.updaters.push(new ChildUpdater(this.context,t,s)):null!==e&&("string"==typeof e&&(e=createText(e,t)),insertChild(e,t,s))}mapValue(t){return new Dynamic(t)}setAttribute(t,e,s){isDynamic(s)?this.updaters.push(new AttributeUpdater(t,e)):setAttr(t,e,s)}setAttributes(t){this.updaters.push(new PropertyMapUpdater(t))}setAttributeParts(t,e,s){s.pending=[];for(let n=0;n<s.length;++n)isDynamic(s[n])&&this.updaters.push(new AttributePartUpdater(t,e,s,n))}}const createSlotSymbol=Symbol("createSlot");function createSlot(t,e,s,n){if(isTextLike(n))return new TextSlot(t,e,s,n);if(n instanceof TemplateResult)return new TemplateSlot(t,e,s,n);if("function"==typeof n[createSlotSymbol])return n[createSlotSymbol](t,e,s);if(isIterable(n))return new MapSlot(t,e,s,n);throw new TypeError("Invalid child slot value")}function updateSlot(t,e){if(t.matches(e))return t.update(e),t;let s=t.start,n=createSlot(t.context,parent(s),s,e);return removeSlot(t),n}function removeSlot(t){t.cancelUpdates(),removeSiblings(t.start,t.end)}function withKey(t,e){return new KeyedValue(t,e)}function isTextLike(t){return null===t||"function"!=typeof t&&"object"!=typeof t}function isIterable(t){return Array.isArray(t)||t&&"string"!=typeof t&&t[Symbol.iterator]}class TextSlot{constructor(t,e,s,n){let r=createText(n,e);insertChild(r,e,s),this.context=t,this.start=r,this.end=r,this.last=n}cancelUpdates(){}matches(t){return isTextLike(t)}update(t){t!==this.last&&(this.last=t,setTextValue(this.start,t))}}class KeyedValue{constructor(t,e){this.key=t,this.value=e}}const positionKeyPrefix="wyxOoLpzQhihTM6QZ83HVA0";function convertValueToMap(t){if(t instanceof Map)return t;let e=new Map,s=0;for(let n of t)n instanceof KeyedValue?e.set(n.key,n.value):e.set(`${positionKeyPrefix}:${s}`,n),s++;return e}class MapSlotList{constructor(t,e){this.slot=t,this.key=e,this.next=this,this.previous=this,this.end=!0}insertBefore(t){this.remove();let e=t.previous;e.next=this,t.previous=this,this.previous=e,this.next=t,this.end=!1}remove(){this.next.previous=this.previous,this.previous.next=this.next,this.next=this,this.previous=this,this.end=!0}}class MapSlot{constructor(t,e,s,n){this.context=t,this.parent=e,this.map=new Map,this.list=new MapSlotList(createSlot(this.context,e,s),null),this.update(n)}get start(){return this.list.next.slot.start}get end(){return this.list.slot.end}cancelUpdates(){for(let t=this.list.next;!t.end;t=t.next)t.slot.cancelUpdates()}matches(t){return isIterable(t)}update(t){let e=convertValueToMap(t),s=this.list.next;for(e.forEach(((t,n)=>{for(;!s.end&&!e.has(s.key);)s=this.removeItem(s);s=this.updateItem(n,t,s)}));!s.end;)s=this.removeItem(s)}updateItem(t,e,s){let n=this.map.get(t);if(n&&n.slot.matches(e))n.slot.update(e),n===s?s=s.next:(insertSiblings(n.slot.start,n.slot.end,s.slot.start),n.insertBefore(s));else{let r=createSlot(this.context,this.parent,s.slot.start,e);n=new MapSlotList(r,t),n.insertBefore(s),this.map.set(t,n)}return s}removeItem(t){let e=t.next;return t.remove(),this.map.delete(t.key),removeSlot(t.slot),e}}class TemplateSlot{constructor(t,e,s,n){this.context=t,this.start=insertMarker(e,s),this.end=insertMarker(e,s),this.source=n.source,this.updaters=n.evaluate(new Actions(t,e,this.end)),this.pending=Array(this.updaters.length),this.update(n)}cancelUpdates(){for(let t=0;t<this.updaters.length;++t){this.cancelPending(t);let e=this.updaters[t];e.slot&&e.slot.cancelUpdates()}}matches(t){return t instanceof TemplateResult&&t.source===this.source}update(t){let{values:e}=t;for(let t=0;t<this.updaters.length;++t){let s=e[t];s&&s[Symbol.asyncIterator]?this.awaitAsyncIterator(s,t):(this.cancelPending(t),this.updaters[t].update(s))}}pendingSource(t){return this.pending[t]&&this.pending[t].source}cancelPending(t){let e=this.pending[t];e&&(this.pending[t]=null,e.cancel())}setPending(t,e){this.cancelPending(e),this.pending[e]=t}awaitAsyncIterator(t,e){if(this.pendingSource(e)===t)return;let s=t[Symbol.asyncIterator](),n=()=>{s.next().then((t=>{if(!r.cancelled)if(t.done)this.pending[e]=null;else{try{this.updaters[e].update(t.value)}catch(t){throw this.cancelPending(e),t}n()}}),(t=>{throw r.cancelled||(this.pending[e]=null),t}))},r={source:t,cancelled:!1,cancel(){this.cancelled=!0,"function"==typeof s.return&&s.return()}};n(),this.setPending(r,e)}}const slotMap=new WeakMap;function applyTemplate(t,e){if("string"==typeof t&&"object"==typeof document&&(t=document.querySelector(t)),!t||"function"!=typeof t.appendChild)throw new TypeError(`${t} is not a valid DOM target`);if(!(e instanceof TemplateResult))throw new TypeError(`${e} is not a TemplateResult object`);let s=slotMap.get(t);if(s)s=updateSlot(s,e);else{let n=firstChild(t);s=createSlot(null,t,n,e),n&&removeSiblings(n,null)}slotMap.set(t,s)}export{applyTemplate,createSlot,createSlotSymbol,html,removeSlot,updateSlot,withKey};
function makeEnum(t=0){return new Proxy({},{get:()=>t++})}const{S_TEXT:S_TEXT,S_RAW:S_RAW,S_OPEN:S_OPEN,S_ATTR:S_ATTR,S_ATTR_CLOSE:S_ATTR_CLOSE,S_ATTR_KEY:S_ATTR_KEY,S_ATTR_KEY_WS:S_ATTR_KEY_WS,S_ATTR_VALUE_WS:S_ATTR_VALUE_WS,S_ATTR_VALUE:S_ATTR_VALUE,S_ATTR_VALUE_SQ:S_ATTR_VALUE_SQ,S_ATTR_VALUE_DQ:S_ATTR_VALUE_DQ,S_COMMENT:S_COMMENT}=makeEnum(),ESC_RE=/&(?:(lt|gt|amp|quot)|#([0-9]+)|#x([0-9a-f]+));?/gi,NAMED_REFS={lt:"<",gt:">",amp:"&",quot:'"'};function notReached(t){throw new Error(t)}function rmatch(t,e,s){return e>=s.length&&t.slice(e-s.length,e)===s}function wsChar(t){switch(t){case" ":case"\n":case"\r":case"\t":case"\f":case"\v":return!0}return t.charCodeAt(0)>128&&/\s/.test(t)}function attrChar(t){return!wsChar(t)&&'"'!==t&&"'"!==t&&"="!==t&&"/"!==t}function rawTag(t){return"script"===t||"style"===t}function escape(t){return t.replace(ESC_RE,((t,e,s,r)=>e?NAMED_REFS[e.toLowerCase()]:String.fromCharCode(parseInt(s||r,r?16:10))))}function maybeEscape(t,e){return t?escape(e):e}class ParseNode{constructor(t){this.kind=t,this.tag="",this.attributes=[],this.children=[]}}class Attribute{constructor(t,e,s){this.kind=t,this.name=e,this.value=s}}class Parser{constructor(){this.node=new ParseNode("root"),this.stack=[this.node],this.state=S_TEXT,this.attrName="",this.attrParts=[],this.tag="",this.closing=!1}addAttr(t){this.node.attributes.push(new Attribute("static",this.attrName,t))}addAttrParts(){let t=new Attribute("parts",this.attrName,this.attrParts);this.node.attributes.push(t),this.attrParts=[]}parseChunk(t){let e=this.state,s=e===S_ATTR_VALUE_DQ||e===S_ATTR_VALUE_SQ,r=!1,i=0,a=0;for(;a<t.length;++a){let n=t[a];if(e===S_RAW)">"===n&&rmatch(t,a,"</"+this.tag)&&(a-=this.tag.length+3,e=S_TEXT);else if(e===S_COMMENT)">"===n&&rmatch(t,a,"--")&&(e=S_TEXT,r=!1,i=a+1);else if("&"===n)r=!0;else if(e===S_TEXT){if("<"===n){if(a>i){let e=maybeEscape(r,t.slice(i,a));this.node.children.push(e)}e=S_OPEN,r=!1,this.closing=!1,i=a+1}}else if(e===S_ATTR_VALUE_SQ){if("'"===n){let n=maybeEscape(r,t.slice(i,a));s?(this.attrParts.push(n),this.addAttrParts(),s=!1):this.addAttr(n),e=S_ATTR,r=!1,this.attrName="",i=a+1}}else if(e===S_ATTR_VALUE_DQ){if('"'===n){let n=maybeEscape(r,t.slice(i,a));s?(this.attrParts.push(n),this.addAttrParts(),s=!1):this.addAttr(n),e=S_ATTR,r=!1,this.attrName="",i=a+1}}else">"===n?(e===S_OPEN?(this.tag=maybeEscape(r,t.slice(i,a)),this.closing||this.pushNode()):e===S_ATTR_KEY?(this.attrName=maybeEscape(r,t.slice(i,a)),this.addAttr(!0)):e===S_ATTR_KEY_WS?this.addAttr(!0):e===S_ATTR_VALUE?this.addAttr(maybeEscape(r,t.slice(i,a))):e===S_ATTR_VALUE_WS&&this.addAttr(!0),this.closing||rmatch(t,a,"/")?(this.popNode(),e=S_TEXT):e=rawTag(this.tag)?S_RAW:S_TEXT,r=!1,i=a+1):e===S_OPEN?"-"===n&&"!-"===t.slice(i,a)?(e=S_COMMENT,i=a+1):"/"===n&&a===i?this.closing=!0:attrChar(n)||(this.tag=maybeEscape(r,t.slice(i,a)),this.closing?e=S_ATTR_CLOSE:(this.pushNode(),e=S_ATTR),r=!1,i=a+1):e===S_ATTR_CLOSE||(e===S_ATTR?attrChar(n)&&(e=S_ATTR_KEY,i=a):e===S_ATTR_KEY?"="===n?(this.attrName=maybeEscape(r,t.slice(i,a)),r=!1,e=S_ATTR_VALUE_WS,i=a+1):attrChar(n)||(this.attrName=maybeEscape(r,t.slice(i,a)),r=!1,e=S_ATTR_KEY_WS,i=a+1):e===S_ATTR_KEY_WS?"="===n?(e=S_ATTR_VALUE_WS,i=a+1):attrChar(n)&&(this.addAttr(!0),e=S_ATTR_KEY,i=a):e===S_ATTR_VALUE_WS?'"'===n?(e=S_ATTR_VALUE_DQ,i=a+1):"'"===n?(e=S_ATTR_VALUE_SQ,i=a+1):attrChar(n)&&(e=S_ATTR_VALUE,i=a):e===S_ATTR_VALUE&&(attrChar(n)||(this.addAttr(maybeEscape(r,t.slice(i,a))),r=!1,e=S_ATTR,i=a+1)))}if(e===S_TEXT||e===S_RAW){if(i<a){let e=maybeEscape(r,t.slice(i,a));this.node.children.push(e)}}else if(e===S_COMMENT);else if(e===S_OPEN)this.tag=maybeEscape(r,t.slice(i,a)),this.closing?e=S_ATTR_CLOSE:(this.pushNode(),e=S_ATTR);else if(e===S_ATTR_KEY)this.attrName=maybeEscape(r,t.slice(i,a)),e=S_ATTR;else if(e===S_ATTR_KEY_WS)e=S_ATTR;else if(e===S_ATTR_VALUE)this.addAttr(maybeEscape(r,t.slice(i,a))),e=S_ATTR;else if(e===S_ATTR_VALUE_SQ||e===S_ATTR_VALUE_DQ){let e=maybeEscape(r,t.slice(i,a));this.attrParts.push(e)}this.state=e}pushNode(){let t=new ParseNode("element");t.tag=this.tag,this.node.children.push(t),this.node=t,this.stack.push(t)}popNode(){this.stack.length>1&&(this.stack.pop(),this.node=this.stack[this.stack.length-1])}addSlot(){switch(this.state){case S_TEXT:case S_RAW:this.node.children.push(new ParseNode("child-slot"));break;case S_COMMENT:this.node.children.push(new ParseNode("null-slot"));break;case S_ATTR:this.node.attributes.push(new Attribute("map","",""));break;case S_ATTR_CLOSE:this.node.attributes.push(new Attribute("null","",""));break;case S_ATTR_VALUE_WS:this.node.attributes.push(new Attribute("value",this.attrName,"")),this.state=S_ATTR;break;case S_ATTR_VALUE_SQ:case S_ATTR_VALUE_DQ:break;default:notReached("Unexpected parser state")}}end(){for(this.attrParts.length>0&&this.addAttrParts();this.stack.length>1;)this.popNode();return this.node}}function parse(t){let e=new Parser;if(t.length>0){e.parseChunk(t[0]);for(let s=1;s<t.length;s++)e.addSlot(),e.parseChunk(t[s])}return e.end()}class TemplateResult{constructor(t,e){this.template=t,this.values=e}}function html(t,...e){let s=TemplateResult.cache.get(t);return s||(s=parse(t.raw),TemplateResult.cache.set(t,s)),new TemplateResult(s,e)}TemplateResult.cache=new WeakMap;const HTML_NS="http://www.w3.org/1999/xhtml",SVG_NS="http://www.w3.org/2000/svg";function doc(t){return t.ownerDocument}function convertToString(t){return null==t?"":"string"==typeof t?t:String(t)}function setAttr(t,e,s){null==s||!1===s?t.removeAttribute(e):t.setAttribute(e,!0===s?e:s)}function setTextValue(t,e){t.nodeValue=convertToString(e)}function createText(t,e){return doc(e).createTextNode(convertToString(t))}function insertMarker(t,e){let s=doc(t).createTextNode("");return t.insertBefore(s,e),s}function createElement(t,e){let s=getNamespace(t,e);return s===HTML_NS?doc(e).createElement(t):doc(e).createElementNS(s,t)}function firstChild(t){return t.firstChild}function parent(t){return t?t.parentNode:null}function insertChild(t,e,s=null){e.insertBefore(t,s)}function insertSiblings(t,e,s){let r=s.parentNode;for(let i;t&&(i=t.nextSibling,r.insertBefore(t,s),t!==e);t=i);}function removeSiblings(t,e){let s=t.parentNode;for(let r;t&&(r=t.nextSibling,s.removeChild(t),t!==e);t=r);}function getNamespace(t,e){return"svg"===t?SVG_NS:e.namespaceURI||HTML_NS}function isObjectLike(t){return t&&("function"==typeof t||"object"==typeof t)}function toAttributeValue(t){if(!isObjectLike(t))return t;if(Array.isArray(t))return t.join(" ");if(t[Symbol.iterator])return Array.from(t).join(" ");throw new TypeError("Invalid attribute value")}class CommentUpdater{update(){}}class AttributeUpdater{constructor(t,e){this.node=t,this.name=e,this.last=void 0}update(t){let e=toAttributeValue(t);e!==this.last&&(this.last=e,setAttr(this.node,this.name,e))}}class AttributePartUpdater{constructor(t,e,s,r){this.node=t,this.name=e,this.parts=s,this.pos=r,s.pending[r]=!0}isReady(){let t=this.parts.pending;return!t||(t[this.pos]=!1,!!t.every((t=>!t))&&(this.parts.pending=null,!0))}update(t){this.parts[this.pos]=toAttributeValue(t),this.isReady()&&setAttr(this.node,this.name,this.parts.join(""))}}class PropertyMapUpdater{constructor(t){this.node=t}update(t){if("function"==typeof t&&(t=t(this.node)),null!=t){if("object"!=typeof t)throw new Error("Invalid property map value");Object.assign(this.node,t)}}}class ChildUpdater{constructor(t,e){this.slot=createSlot(t,e,null)}update(t){this.slot=updateSlot(this.slot,t)}}class Builder{constructor(){this.updaters=null}build(t,e,s){return this.updaters=[],this.buildNode(t,e,s),this.updaters}addAttributePartUpdater(t,e,s){let r=[s[0]];r.pending=[];for(let i=1;i<s.length;++i){let a=r.length;r.push(""),r.push(s[i]);let n=new AttributePartUpdater(t,e,r,a);this.updaters.push(n)}}buildNode(t,e,s){switch(t.kind){case"root":return void this.buildChildren(t,e,s);case"child-slot":return void this.updaters.push(new ChildUpdater(e,s));case"null-slot":return void this.updaters.push(new CommentUpdater)}let r=createElement(t.tag,e);for(let e of t.attributes)switch(e.kind){case"static":setAttr(r,e.name,e.value);break;case"value":this.updaters.push(new AttributeUpdater(r,e.name));break;case"map":this.updaters.push(new PropertyMapUpdater(r));break;case"null":this.updaters.push(new CommentUpdater);break;case"parts":this.addAttributePartUpdater(r,e.name,e.value)}this.buildChildren(t,r,null),insertChild(r,e,s)}buildChildren(t,e,s){for(let r of t.children)if("string"==typeof r){insertChild(createText(r,e),e,s)}else this.buildNode(r,e,s)}}function buildTemplate(t,e,s){return(new Builder).build(t,e,s)}const createSlotSymbol=Symbol("createSlot");function createSlot(t,e,s){if(isTextLike(s))return new TextSlot(t,e,s);if(s instanceof TemplateResult)return new TemplateSlot(t,e,s);if("function"==typeof s[createSlotSymbol])return s[createSlotSymbol](t,e);if(isIterable(s))return new MapSlot(t,e,s);throw new TypeError("Invalid child slot value")}function updateSlot(t,e){if(t.matches(e))return t.update(e),t;let s=t.start,r=createSlot(parent(s),s,e);return removeSlot(t),r}function removeSlot(t){t.cancelUpdates(),removeSiblings(t.start,t.end)}function withKey(t,e){return new KeyedValue(t,e)}function isTextLike(t){return null===t||"function"!=typeof t&&"object"!=typeof t}function isIterable(t){return Array.isArray(t)||t&&"string"!=typeof t&&t[Symbol.iterator]}class TextSlot{constructor(t,e,s){let r=createText(s,t);insertChild(r,t,e),this.start=r,this.end=r,this.last=s}cancelUpdates(){}matches(t){return isTextLike(t)}update(t){t!==this.last&&(this.last=t,setTextValue(this.start,t))}}class KeyedValue{constructor(t,e){this.key=t,this.value=e}}const positionKeyPrefix="wyxOoLpzQhihTM6QZ83HVA0";function convertValueToMap(t){if(t instanceof Map)return t;let e=new Map,s=0;for(let r of t)r instanceof KeyedValue?e.set(r.key,r.value):e.set(`${positionKeyPrefix}:${s}`,r),s++;return e}class MapSlotList{constructor(t,e){this.slot=t,this.key=e,this.next=this,this.previous=this,this.end=!0}insertBefore(t){this.remove();let e=t.previous;e.next=this,t.previous=this,this.previous=e,this.next=t,this.end=!1}remove(){this.next.previous=this.previous,this.previous.next=this.next,this.next=this,this.previous=this,this.end=!0}}class MapSlot{constructor(t,e,s){this.parent=t,this.map=new Map,this.list=new MapSlotList(createSlot(t,e),null),this.update(s)}get start(){return this.list.next.slot.start}get end(){return this.list.slot.end}cancelUpdates(){for(let t=this.list.next;!t.end;t=t.next)t.slot.cancelUpdates()}matches(t){return isIterable(t)}update(t){let e=convertValueToMap(t),s=this.list.next;for(e.forEach(((t,r)=>{for(;!s.end&&!e.has(s.key);)s=this.removeItem(s);s=this.updateItem(r,t,s)}));!s.end;)s=this.removeItem(s)}updateItem(t,e,s){let r=this.map.get(t);if(r&&r.slot.matches(e))r.slot.update(e),r===s?s=s.next:(insertSiblings(r.slot.start,r.slot.end,s.slot.start),r.insertBefore(s));else{let i=createSlot(this.parent,s.slot.start,e);r=new MapSlotList(i,t),r.insertBefore(s),this.map.set(t,r)}return s}removeItem(t){let e=t.next;return t.remove(),this.map.delete(t.key),removeSlot(t.slot),e}}class TemplateSlot{constructor(t,e,s){this.start=insertMarker(t,e),this.end=insertMarker(t,e),this.template=s.template,this.updaters=buildTemplate(this.template,t,this.end),this.pending=Array(this.updaters.length),this.update(s)}cancelUpdates(){for(let t=0;t<this.updaters.length;++t){this.cancelPending(t);let e=this.updaters[t];e.slot&&e.slot.cancelUpdates()}}matches(t){return t instanceof TemplateResult&&t.template===this.template}update(t){let{values:e}=t;for(let t=0;t<this.updaters.length;++t){let s=e[t];s&&s[Symbol.asyncIterator]?this.awaitAsyncIterator(s,t):(this.cancelPending(t),this.updaters[t].update(s))}}pendingSource(t){return this.pending[t]&&this.pending[t].source}cancelPending(t){let e=this.pending[t];e&&(this.pending[t]=null,e.cancel())}setPending(t,e){this.cancelPending(e),this.pending[e]=t}awaitAsyncIterator(t,e){if(this.pendingSource(e)===t)return;let s=t[Symbol.asyncIterator](),r=()=>{s.next().then((t=>{if(!i.cancelled)if(t.done)this.pending[e]=null;else{try{this.updaters[e].update(t.value)}catch(t){throw this.cancelPending(e),t}r()}}),(t=>{throw i.cancelled||(this.pending[e]=null),t}))},i={source:t,cancelled:!1,cancel(){this.cancelled=!0,"function"==typeof s.return&&s.return()}};r(),this.setPending(i,e)}}const slotMap=new WeakMap;function applyTemplate(t,e){if("string"==typeof t&&"object"==typeof document&&(t=document.querySelector(t)),!t||"function"!=typeof t.appendChild)throw new TypeError(`${t} is not a valid DOM target`);if(!(e instanceof TemplateResult))throw new TypeError(`${e} is not a TemplateResult object`);let s=slotMap.get(t);if(s)s=updateSlot(s,e);else{let r=firstChild(t);s=createSlot(t,r,e),r&&removeSiblings(r,null)}slotMap.set(t,s)}export{TemplateResult,applyTemplate,createSlot,createSlotSymbol,html,removeSlot,updateSlot,withKey};
{
"name": "straylight",
"version": "0.8.0",
"version": "0.8.1",
"description": "HTML templating and update engine",

@@ -12,13 +12,13 @@ "license": "MIT",

"dependencies": {
"htmltag": "^0.6.5"
"htmltag": "^0.7.0"
},
"devDependencies": {
"async-iteration-buffer": "^0.2.1",
"eslint": "^8.34.0",
"eslint": "^8.46.0",
"express": "^4.18.2",
"gzip-size-cli": "^5.1.0",
"moon-unit": "^0.3.2",
"rollup": "^3.17.2",
"rollup": "^3.28.0",
"rollup-plugin-node-resolve": "^5.2.0",
"terser": "^5.16.4"
"terser": "^5.19.2"
},

@@ -25,0 +25,0 @@ "main": "src/index.js",

@@ -29,3 +29,3 @@ import { html, TemplateResult } from 'htmltag';

let next = dom.firstChild(target);
slot = createSlot(null, target, next, template);
slot = createSlot(target, next, template);
if (next) {

@@ -40,2 +40,3 @@ dom.removeSiblings(next, null);

html,
TemplateResult,
applyTemplate,

@@ -42,0 +43,0 @@ createSlotSymbol,

import { TemplateResult } from 'htmltag';
import { Actions } from './actions.js';
import { buildTemplate } from './builder.js';

@@ -8,17 +8,17 @@ import * as dom from './dom.js';

export function createSlot(context, parent, next, value) {
export function createSlot(parent, next, value) {
if (isTextLike(value)) {
return new TextSlot(context, parent, next, value);
return new TextSlot(parent, next, value);
}
if (value instanceof TemplateResult) {
return new TemplateSlot(context, parent, next, value);
return new TemplateSlot(parent, next, value);
}
if (typeof value[createSlotSymbol] === 'function') {
return value[createSlotSymbol](context, parent, next);
return value[createSlotSymbol](parent, next);
}
if (isIterable(value)) {
return new MapSlot(context, parent, next, value);
return new MapSlot(parent, next, value);
}

@@ -35,3 +35,3 @@

let next = slot.start;
let newSlot = createSlot(slot.context, dom.parent(next), next, value);
let newSlot = createSlot(dom.parent(next), next, value);
removeSlot(slot);

@@ -65,6 +65,5 @@ return newSlot;

class TextSlot {
constructor(context, parent, next, value) {
constructor(parent, next, value) {
let node = dom.createText(value, parent);
dom.insertChild(node, parent, next);
this.context = context;
this.start = node;

@@ -146,7 +145,6 @@ this.end = node;

class MapSlot {
constructor(context, parent, next, value) {
this.context = context;
constructor(parent, next, value) {
this.parent = parent;
this.map = new Map();
this.list = new MapSlotList(createSlot(this.context, parent, next), null);
this.list = new MapSlotList(createSlot(parent, next), null);
this.update(value);

@@ -198,3 +196,3 @@ }

} else {
let slot = createSlot(this.context, this.parent, next.slot.start, value);
let slot = createSlot(this.parent, next.slot.start, value);
item = new MapSlotList(slot, key);

@@ -217,4 +215,3 @@ item.insertBefore(next);

class TemplateSlot {
constructor(context, parent, next, template) {
this.context = context;
constructor(parent, next, value) {
// The first and last nodes of the template could be dynamic,

@@ -224,6 +221,6 @@ // so create stable marker nodes before and after the content.

this.end = dom.insertMarker(parent, next);
this.source = template.source;
this.updaters = template.evaluate(new Actions(context, parent, this.end));
this.template = value.template;
this.updaters = buildTemplate(this.template, parent, this.end);
this.pending = Array(this.updaters.length);
this.update(template);
this.update(value);
}

@@ -244,9 +241,9 @@

value instanceof TemplateResult &&
value.source === this.source
value.template === this.template
);
}
update(template) {
// Assert: template.source === this.updater.source
let { values } = template;
update(value) {
// Assert: value.template === this.template
let { values } = value;
for (let i = 0; i < this.updaters.length; ++i) {

@@ -253,0 +250,0 @@ let value = values[i];

@@ -94,4 +94,4 @@ import { createSlot, updateSlot } from './slots.js';

export class ChildUpdater {
constructor(context, parent, next) {
this.slot = createSlot(context, parent, next, null);
constructor(parent, next) {
this.slot = createSlot(parent, next, null);
}

@@ -98,0 +98,0 @@

@@ -87,3 +87,5 @@ const htmlEscapes = {

get innerHTML() {
return rawTags.test(this.parentNode.nodeName) ? this.nodeValue : esc(this.nodeValue);
return rawTags.test(this.parentNode.nodeName)
? this.nodeValue
: esc(this.nodeValue);
}

@@ -90,0 +92,0 @@

import * as dom from './dom.js';
import {
CommentUpdater,
AttributeUpdater,
AttributePartUpdater,
PropertyMapUpdater,
ChildUpdater } from './updaters.js';
class Dynamic {
constructor(value) { this.value = value; }
}
function isDynamic(x) {
return x instanceof Dynamic;
}
export class Actions {
constructor(context, root, next) {
this.context = context;
this.root = root;
this.next = next;
this.updaters = [];
}
createRoot() {
return this.root;
}
finishRoot() {
return this.updaters;
}
createElement(tag, parent) {
if (typeof tag !== 'string') {
throw new TypeError('Tag name must be a string');
}
return dom.createElement(tag, parent);
}
createComment(value) {
if (isDynamic(value)) {
this.updaters.push(new CommentUpdater());
}
return null;
}
finishElement(node) {
return node;
}
appendChild(node, child) {
let next = node === this.root ? this.next : null;
if (isDynamic(child)) {
this.updaters.push(new ChildUpdater(this.context, node, next));
} else if (child !== null) {
if (typeof child === 'string') {
child = dom.createText(child, node);
}
dom.insertChild(child, node, next);
}
}
mapValue(v) {
return new Dynamic(v);
}
setAttribute(node, name, value) {
if (isDynamic(value)) {
this.updaters.push(new AttributeUpdater(node, name));
} else {
dom.setAttr(node, name, value);
}
}
setAttributes(node) {
this.updaters.push(new PropertyMapUpdater(node));
}
setAttributeParts(node, name, parts) {
parts.pending = [];
for (let i = 0; i < parts.length; ++i) {
if (isDynamic(parts[i])) {
this.updaters.push(new AttributePartUpdater(node, name, parts, i));
}
}
}
}