diff --git a/www/docs.md b/www/docs.md
index 6e9c7537..94734452 100644
--- a/www/docs.md
+++ b/www/docs.md
@@ -112,6 +112,8 @@ For added security, you can load the script using [Subresource Integrity (SRI)](
```
+If you are migrating to htmx from intercooler.js, please see the [migration guide here](/migration-guide).
+
## [AJAX](#ajax)
The core of htmx is a set of attributes that allow you to issue AJAX requests directly from HTML:
diff --git a/www/examples.md b/www/examples.md
index 09c86364..596baae4 100644
--- a/www/examples.md
+++ b/www/examples.md
@@ -20,6 +20,7 @@ You can copy and paste them and then adjust them for your needs.
| [Bulk Update](/examples/bulk-update) | Demonstrates bulk updating of multiple rows of data
| [Click To Load](/examples/click-to-load) | Demonstrates clicking to load more rows in a table
| [Delete Row](/examples/delete-row) | Demonstrates row deletion in a table
+| [Edit Row](/examples/edit-row) | Demonstrates how to edit rows in a table
| [Lazy Loading](/examples/lazy-load) | Demonstrates how to lazy load content
| [Inline Validation](/examples/inline-validation) | Demonstrates how to do inline field validation
| [Infinite Scroll](/examples/infinite-scroll) | Demonstrates infinite scrolling of a page
diff --git a/www/examples/edit-row.md b/www/examples/edit-row.md
new file mode 100644
index 00000000..43ee541c
--- /dev/null
+++ b/www/examples/edit-row.md
@@ -0,0 +1,215 @@
+---
+layout: demo_layout.njk
+---
+
+## Edit Row
+
+This example shows how to implement editable rows. First let's look at the table body:
+
+```html
+
+
+
+
Name
+
Email
+
+
+
+
+ ...
+
+
+```
+
+This will tell the requests from within the table to target the closest enclosing row that the request is triggered
+on and to replace the entire row.
+
+Here is the HTML for a row:
+
+```html
+
+
${contact.name}
+
${contact.email}
+
+
+
+
+```
+
+Here we are getting a bit fancy and only allowing one row at a time to be edited, using [hyperscript](http://hyperscript.org).
+We check to see if there is a row with the `.editing` class on it and confirm that the user wants to edit this row
+and dismiss the other one. If so, we send a cancel event to the other row so it will issue a request to go back to
+its initial state.
+
+We then trigger the `edit` event on the current element, which triggers the htmx request to get the editable version
+of the row.
+
+Note that if you didn't care if a user was editing multiple rows, you could omit the hyperscript and custom `hx-trigger`,
+and just let the normal click handling work with htmx. You could also implement mutual exclusivity by simply targeting the
+entire table when the Edit button was clicked. Here we wanted to show how to integrate htmx and hyperscript to solve
+the problem and narrow down the server interactions a bit, plus we get to use a nice SweetAlert confirm dialog.
+
+Finally, here is what the row looks like when the data is being edited:
+
+```html
+
+
+
+
+
+
+
+
+```
+
+Here we have a few things going on: First off the row itself can respond to the `cancel` event, which will bring
+back the read-only version of the row. This is used by the hyperscript above. There is a cancel button that allows
+cancelling the current edit. Finally, there is a save button that issues a `PUT` to update the contact. Note that
+there is an [`hx-include`](attributes/hx-include) that includes all the inputs in the closest row. Tables rows are
+notoriously difficult to use with forms due to HTML constraints (you can't put a `form` directly inside a `tr`) so
+this makes things a bit nicer to deal with.
+
+{% include demo_ui.html.liquid %}
+
+
+
\ No newline at end of file
diff --git a/www/js/_hyperscript.js b/www/js/_hyperscript.js
index ccc64d5e..bbeb7e2d 100644
--- a/www/js/_hyperscript.js
+++ b/www/js/_hyperscript.js
@@ -1,3956 +1,2 @@
-///=========================================================================
-/// This module provides the core runtime and grammar for hyperscript
-///=========================================================================
-//AMD insanity
-(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define([], factory);
- } else {
- // Browser globals
- root._hyperscript = factory();
- }
-}(typeof self !== 'undefined' ? self : this, function () {
- return (function () {
- 'use strict';
-
-
- //====================================================================
- // Utilities
- //====================================================================
-
- function mergeObjects(obj1, obj2) {
- for (var key in obj2) {
- if (obj2.hasOwnProperty(key)) {
- obj1[key] = obj2[key];
- }
- }
- return obj1;
- }
-
- function parseJSON(jString) {
- try {
- return JSON.parse(jString);
- } catch(error) {
- logError(error);
- return null;
- }
- }
-
- function logError(msg) {
- if(console.error) {
- console.error(msg);
- } else if (console.log) {
- console.log("ERROR: ", msg);
- }
- }
-
- // https://stackoverflow.com/a/8843181
- function varargConstructor(Cls, args) {
- return new (Cls.bind.apply(Cls, [Cls].concat(args)));
- }
-
- var globalScope = typeof self !== 'undefined' ? self : typeof global !== 'undefined' ? global : this;
-
- //====================================================================
- // Lexer
- //====================================================================
- var _lexer = function () {
- var OP_TABLE = {
- '+': 'PLUS',
- '-': 'MINUS',
- '*': 'MULTIPLY',
- '/': 'DIVIDE',
- '.': 'PERIOD',
- '\\': 'BACKSLASH',
- ':': 'COLON',
- '%': 'PERCENT',
- '|': 'PIPE',
- '!': 'EXCLAMATION',
- '?': 'QUESTION',
- '#': 'POUND',
- '&': 'AMPERSAND',
- '$': 'DOLLAR',
- ';': 'SEMI',
- ',': 'COMMA',
- '(': 'L_PAREN',
- ')': 'R_PAREN',
- '<': 'L_ANG',
- '>': 'R_ANG',
- '<=': 'LTE_ANG',
- '>=': 'GTE_ANG',
- '==': 'EQ',
- '===': 'EQQ',
- '!=': 'NEQ',
- '!==': 'NEQQ',
- '{': 'L_BRACE',
- '}': 'R_BRACE',
- '[': 'L_BRACKET',
- ']': 'R_BRACKET',
- '=': 'EQUALS'
- };
-
- function isValidCSSClassChar(c) {
- return isAlpha(c) || isNumeric(c) || c === "-" || c === "_";
- }
-
- function isValidCSSIDChar(c) {
- return isAlpha(c) || isNumeric(c) || c === "-" || c === "_" || c === ":";
- }
-
- function isWhitespace(c) {
- return c === " " || c === "\t" || isNewline(c);
- }
-
- function positionString(token) {
- return "[Line: " + token.line + ", Column: " + token.col + "]"
- }
-
- function isNewline(c) {
- return c === '\r' || c === '\n';
- }
-
- function isNumeric(c) {
- return c >= '0' && c <= '9';
- }
-
- function isAlpha(c) {
- return (c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z');
- }
-
- function isIdentifierChar(c, dollarIsOp) {
- return (c === "_" || (!dollarIsOp && c === "$"));
- }
-
- function isReservedChar(c) {
- return (c === "`" || c === "^");
- }
-
-
- function makeTokensObject(tokens, consumed, source) {
-
- consumeWhitespace(); // consume initial whitespace
-
- function consumeWhitespace(){
- while(token(0, true).type === "WHITESPACE") {
- consumed.push(tokens.shift());
- }
- }
-
- function raiseError(tokens, error) {
- _parser.raiseParseError(tokens, error);
- }
-
- function requireOpToken(value) {
- var token = matchOpToken(value);
- if (token) {
- return token;
- } else {
- raiseError(this, "Expected '" + value + "' but found '" + currentToken().value + "'");
- }
- }
-
- function matchAnyOpToken(op1, op2, op3) {
- for (var i = 0; i < arguments.length; i++) {
- var opToken = arguments[i];
- var match = matchOpToken(opToken);
- if (match) {
- return match;
- }
- }
- }
-
- function matchOpToken(value) {
- if (currentToken() && currentToken().op && currentToken().value === value) {
- return consumeToken();
- }
- }
-
- function requireTokenType(type1, type2, type3, type4) {
- var token = matchTokenType(type1, type2, type3, type4);
- if (token) {
- return token;
- } else {
- raiseError(this, "Expected one of " + JSON.stringify([type1, type2, type3]));
- }
- }
-
- function matchTokenType(type1, type2, type3, type4) {
- if (currentToken() && currentToken().type && [type1, type2, type3, type4].indexOf(currentToken().type) >= 0) {
- return consumeToken();
- }
- }
-
- function requireToken(value, type) {
- var token = matchToken(value, type);
- if (token) {
- return token;
- } else {
- raiseError(this, "Expected '" + value + "' but found '" + currentToken().value + "'");
- }
- }
-
- function matchToken(value, type) {
- var type = type || "IDENTIFIER";
- if (currentToken() && currentToken().value === value && currentToken().type === type) {
- return consumeToken();
- }
- }
-
- function consumeToken() {
- var match = tokens.shift();
- consumed.push(match);
- consumeWhitespace(); // consume any whitespace
- return match;
- }
-
- function consumeUntil(value, type) {
- var tokenList = [];
- var currentToken = token(0, true);
- while ((type == null || currentToken.type !== type) &&
- (value == null || currentToken.value !== value) &&
- currentToken.type !== "EOF") {
- var match = tokens.shift();
- consumed.push(match);
- tokenList.push(currentToken);
- currentToken = token(0, true);
- }
- consumeWhitespace(); // consume any whitespace
- return tokenList;
- }
-
- function lastWhitespace() {
- if (consumed[consumed.length - 1] && consumed[consumed.length - 1].type === "WHITESPACE") {
- return consumed[consumed.length - 1].value;
- } else {
- return "";
- }
- }
-
- function consumeUntilWhitespace() {
- return consumeUntil(null, "WHITESPACE");
- }
-
- function hasMore() {
- return tokens.length > 0;
- }
-
- function token(n, dontIgnoreWhitespace) {
- var token;
- var i = 0;
- do {
- if (!dontIgnoreWhitespace) {
- while (tokens[i] && tokens[i].type === "WHITESPACE") {
- i++;
- }
- }
- token = tokens[i];
- n--;
- i++;
- } while (n > -1)
- if (token) {
- return token;
- } else {
- return {
- type:"EOF",
- value:"<<>>"
- }
- }
- }
-
- function currentToken() {
- return token(0);
- }
-
- return {
- matchAnyOpToken: matchAnyOpToken,
- matchOpToken: matchOpToken,
- requireOpToken: requireOpToken,
- matchTokenType: matchTokenType,
- requireTokenType: requireTokenType,
- consumeToken: consumeToken,
- matchToken: matchToken,
- requireToken: requireToken,
- list: tokens,
- consumed: consumed,
- source: source,
- hasMore: hasMore,
- currentToken: currentToken,
- token: token,
- consumeUntil: consumeUntil,
- consumeUntilWhitespace: consumeUntilWhitespace,
- lastWhitespace: lastWhitespace
- }
- }
-
- function tokenize(string, noDollarStart) {
- var source = string;
- var tokens = [];
- var position = 0;
- var column = 0;
- var line = 1;
- var lastToken = "";
-
- while (position < source.length) {
- if (currentChar() === "-" && nextChar() === "-") {
- consumeComment();
- } else {
- if (isWhitespace(currentChar())) {
- tokens.push(consumeWhitespace());
- } else if (!possiblePrecedingSymbol() && currentChar() === "." && isAlpha(nextChar())) {
- tokens.push(consumeClassReference());
- } else if (!possiblePrecedingSymbol() && currentChar() === "#" && isAlpha(nextChar())) {
- tokens.push(consumeIdReference());
- } else if (isAlpha(currentChar()) || isIdentifierChar(currentChar(), noDollarStart)) {
- tokens.push(consumeIdentifier());
- } else if (isNumeric(currentChar())) {
- tokens.push(consumeNumber());
- } else if (currentChar() === '"' || currentChar() === "'" || currentChar() === "`") {
- tokens.push(consumeString());
- } else if (OP_TABLE[currentChar()]) {
- tokens.push(consumeOp());
- } else if (isReservedChar(currentChar())) {
- tokens.push(makeToken('RESERVED', currentChar()))
- } else {
- if (position < source.length) {
- throw Error("Unknown token: " + currentChar() + " ");
- }
- }
- }
- }
-
- return makeTokensObject(tokens, [], source);
-
- function makeOpToken(type, value) {
- var token = makeToken(type, value);
- token.op = true;
- return token;
- }
-
- function makeToken(type, value) {
- return {
- type: type,
- value: value,
- start: position,
- end: position + 1,
- column: column,
- line: line
- };
- }
-
- function consumeComment() {
- while (currentChar() && !isNewline(currentChar())) {
- consumeChar();
- }
- consumeChar();
- }
-
- function consumeClassReference() {
- var classRef = makeToken("CLASS_REF");
- var value = consumeChar();
- while (isValidCSSClassChar(currentChar())) {
- value += consumeChar();
- }
- classRef.value = value;
- classRef.end = position;
- return classRef;
- }
-
-
- function consumeIdReference() {
- var idRef = makeToken("ID_REF");
- var value = consumeChar();
- while (isValidCSSIDChar(currentChar())) {
- value += consumeChar();
- }
- idRef.value = value;
- idRef.end = position;
- return idRef;
- }
-
- function consumeIdentifier() {
- var identifier = makeToken("IDENTIFIER");
- var value = consumeChar();
- while (isAlpha(currentChar()) || isIdentifierChar(currentChar())) {
- value += consumeChar();
- }
- identifier.value = value;
- identifier.end = position;
- return identifier;
- }
-
- function consumeNumber() {
- var number = makeToken("NUMBER");
- var value = consumeChar();
- while (isNumeric(currentChar())) {
- value += consumeChar();
- }
- if (currentChar() === ".") {
- value += consumeChar();
- }
- while (isNumeric(currentChar())) {
- value += consumeChar();
- }
- number.value = value;
- number.end = position;
- return number;
- }
-
- function consumeOp() {
- var value = consumeChar(); // consume leading char
- while (currentChar() && OP_TABLE[value + currentChar()]) {
- value += consumeChar();
- }
- var op = makeOpToken(OP_TABLE[value], value);
- op.value = value;
- op.end = position;
- return op;
- }
-
- function consumeString() {
- var string = makeToken("STRING");
- var startChar = consumeChar(); // consume leading quote
- var value = "";
- while (currentChar() && currentChar() !== startChar) {
- if (currentChar() === "\\") {
- consumeChar(); // consume escape char and move on
- }
- value += consumeChar();
- }
- if (currentChar() !== startChar) {
- throw Error("Unterminated string at " + positionString(string));
- } else {
- consumeChar(); // consume final quote
- }
- string.value = value;
- string.end = position;
- string.template = startChar === "`";
- return string;
- }
-
- function currentChar() {
- return source.charAt(position);
- }
-
- function nextChar() {
- return source.charAt(position + 1);
- }
-
- function consumeChar() {
- lastToken = currentChar();
- position++;
- column++;
- return lastToken;
- }
-
- function possiblePrecedingSymbol() {
- return isAlpha(lastToken) || isNumeric(lastToken) || lastToken === ")" || lastToken === "}" || lastToken === "]"
- }
-
- function consumeWhitespace() {
- var whitespace = makeToken("WHITESPACE");
- var value = "";
- while (currentChar() && isWhitespace(currentChar())) {
- if (isNewline(currentChar())) {
- column = 0;
- line++;
- }
- value += consumeChar();
- }
- whitespace.value = value;
- whitespace.end = position;
- return whitespace;
- }
- }
-
- return {
- tokenize: tokenize,
- makeTokensObject: makeTokensObject
- }
- }();
-
- //====================================================================
- // Parser
- //====================================================================
- var _parser = function () {
-
- var GRAMMAR = {}
- var COMMANDS = {}
- var FEATURES = {}
- var LEAF_EXPRESSIONS = [];
- var INDIRECT_EXPRESSIONS = [];
-
- function parseElement(type, tokens, root) {
- var elementDefinition = GRAMMAR[type];
- if (elementDefinition) return elementDefinition(_parser, _runtime, tokens, root);
- }
-
- function requireElement(type, tokens, message, root) {
- var result = parseElement(type, tokens, root);
- return result || raiseParseError(tokens, message || "Expected " + type);
- }
-
- function parseAnyOf(types, tokens) {
- for (var i = 0; i < types.length; i++) {
- var type = types[i];
- var expression = parseElement(type, tokens);
- if (expression) {
- return expression;
- }
- }
- }
-
- function addGrammarElement(name, definition) {
- GRAMMAR[name] = definition;
- }
-
- function addCommand(keyword, definition) {
- var commandGrammarType = keyword + "Command";
- var commandDefinitionWrapper = function (parser, runtime, tokens) {
- var commandElement = definition(parser, runtime, tokens);
- if (commandElement) {
- commandElement.type = commandGrammarType;
- commandElement.execute = function (context) {
- return runtime.unifiedExec(this, context);
- }
- return commandElement;
- }
- };
- GRAMMAR[commandGrammarType] = commandDefinitionWrapper;
- COMMANDS[keyword] = commandDefinitionWrapper;
- }
-
- function addFeature(keyword, definition) {
- var featureGrammarType = keyword + "Feature";
- var featureDefinitionWrapper = function (parser, runtime, tokens) {
- var featureElement = definition(parser, runtime, tokens);
- if (featureElement) {
- featureElement.keyword = keyword;
- featureElement.type = featureGrammarType;
- return featureElement;
- }
- };
- GRAMMAR[featureGrammarType] = featureDefinitionWrapper;
- FEATURES[keyword] = featureDefinitionWrapper;
- }
-
- function addLeafExpression(name, definition) {
- LEAF_EXPRESSIONS.push(name);
- addGrammarElement(name, definition);
- }
-
- function addIndirectExpression(name, definition) {
- INDIRECT_EXPRESSIONS.push(name);
- addGrammarElement(name, definition);
- }
-
- /* ============================================================================================ */
- /* Core hyperscript Grammar Elements */
- /* ============================================================================================ */
- addGrammarElement("feature", function(parser, runtime, tokens) {
- if (tokens.matchOpToken("(")) {
- var featureDefinition = parser.requireElement("feature", tokens);
- tokens.requireOpToken(")");
- return featureDefinition;
- } else {
- var featureDefinition = FEATURES[tokens.currentToken().value];
- if (featureDefinition) {
- return featureDefinition(parser, runtime, tokens);
- }
- }
- })
-
- addGrammarElement("command", function(parser, runtime, tokens) {
- if (tokens.matchOpToken("(")) {
- var commandDefinition = parser.requireElement("command", tokens);
- tokens.requireOpToken(")");
- return commandDefinition;
- } else {
- var commandDefinition = COMMANDS[tokens.currentToken().value];
- if (commandDefinition) {
- return commandDefinition(parser, runtime, tokens);
- } else if (tokens.currentToken().type === "IDENTIFIER" && tokens.token(1).value === "(") {
- return parser.requireElement("pseudoCommand", tokens);
- }
- }
- })
-
- addGrammarElement("commandList", function(parser, runtime, tokens) {
- var cmd = parser.parseElement("command", tokens);
- if (cmd) {
- tokens.matchToken("then");
- cmd.next = parser.parseElement("commandList", tokens);
- return cmd;
- }
- })
-
- addGrammarElement("leaf", function(parser, runtime, tokens) {
- var result = parseAnyOf(LEAF_EXPRESSIONS, tokens);
- // symbol is last so it doesn't consume any constants
- if (result == null) {
- return parseElement('symbol', tokens);
- } else {
- return result;
- }
- })
-
- addGrammarElement("indirectExpression", function(parser, runtime, tokens, root) {
- for (var i = 0; i < INDIRECT_EXPRESSIONS.length; i++) {
- var indirect = INDIRECT_EXPRESSIONS[i];
- var result = parser.parseElement(indirect, tokens, root);
- if(result){
- return result;
- }
- }
- return root;
- });
-
- addGrammarElement("primaryExpression", function(parser, runtime, tokens) {
- var leaf = parser.parseElement("leaf", tokens);
- if (leaf) {
- return parser.parseElement("indirectExpression", tokens, leaf);
- }
- parser.raiseParseError(tokens, "Unexpected value: " + tokens.currentToken().value);
- });
- /* ============================================================================================ */
- /* END Core hyperscript Grammar Elements */
- /* ============================================================================================ */
-
-
- function createParserContext(tokens) {
- var currentToken = tokens.currentToken();
- var source = tokens.source;
- var lines = source.split("\n");
- var line = currentToken ? currentToken.line - 1 : lines.length - 1;
- var contextLine = lines[line];
- var offset = currentToken ? currentToken.column : contextLine.length - 1;
- return contextLine + "\n" + " ".repeat(offset) + "^^\n\n";
- }
-
- function raiseParseError(tokens, message) {
- message = (message || "Unexpected Token : " + tokens.currentToken().value) + "\n\n" +
- createParserContext(tokens);
- var error = new Error(message);
- error.tokens = tokens;
- throw error
- }
-
- function parseHyperScript(tokens) {
- return parseElement("hyperscript", tokens)
- }
-
- function setParent(elt, parent) {
- if (elt) {
- elt.parent = parent;
- setParent(elt.next, parent);
- }
- }
-
- function commandStart(token){
- return COMMANDS[token.value];
- }
-
- function featureStart(token){
- return FEATURES[token.value];
- }
-
- function commandBoundary(token) {
- if (token.value == "end" ||
- token.value == "then" ||
- token.value == "else" ||
- token.value == ")" ||
- commandStart(token) ||
- featureStart(token) ||
- token.type == "EOF") {
- return true;
- }
- }
-
- function parseStringTemplate(tokens) {
- var returnArr = [""];
- do {
- returnArr.push(tokens.lastWhitespace());
- if (tokens.currentToken().value === "$") {
- tokens.consumeToken();
- var startingBrace = tokens.matchOpToken('{');
- returnArr.push(requireElement("expression", tokens));
- if(startingBrace){
- tokens.requireOpToken("}");
- }
- returnArr.push("");
- } else if (tokens.currentToken().value === "\\") {
- tokens.consumeToken(); // skip next
- tokens.consumeToken()
- } else {
- var token = tokens.consumeToken();
- returnArr[returnArr.length - 1] += token.value;
- }
- } while (tokens.hasMore())
- returnArr.push(tokens.lastWhitespace());
- return returnArr;
- }
-
- return {
- // parser API
- setParent: setParent,
- requireElement: requireElement,
- parseElement: parseElement,
- featureStart: featureStart,
- commandStart: commandStart,
- commandBoundary: commandBoundary,
- parseAnyOf: parseAnyOf,
- parseHyperScript: parseHyperScript,
- raiseParseError: raiseParseError,
- addGrammarElement: addGrammarElement,
- addCommand: addCommand,
- addFeature: addFeature,
- addLeafExpression: addLeafExpression,
- addIndirectExpression: addIndirectExpression,
- parseStringTemplate: parseStringTemplate,
- }
- }();
-
- //====================================================================
- // Runtime
- //====================================================================
- var CONVERSIONS = {
- dynamicResolvers : [],
- "String" : function(val){
- if(val.toString){
- return val.toString();
- } else {
- return "" + val;
- }
- },
- "Int" : function(val){
- return parseInt(val);
- },
- "Float" : function(val){
- return parseFloat(val);
- },
- "Number" : function(val){
- return Number(val);
- },
- "Date" : function(val){
- return Date(val);
- },
- "Array" : function(val){
- return Array.from(val);
- },
- "JSON" : function(val){
- return JSON.stringify(val);
- },
- "Object" : function(val){
- if (typeof val === 'string' || val instanceof String) {
- return JSON.parse(val);
- } else {
- return mergeObjects({}, val);
- }
- }
- }
- var _runtime = function () {
-
- function matchesSelector(elt, selector) {
- // noinspection JSUnresolvedVariable
- var matchesFunction = elt.matches ||
- elt.matchesSelector || elt.msMatchesSelector || elt.mozMatchesSelector
- || elt.webkitMatchesSelector || elt.oMatchesSelector;
- return matchesFunction && matchesFunction.call(elt, selector);
- }
-
- function makeEvent(eventName, detail) {
- var evt;
- if (window.CustomEvent && typeof window.CustomEvent === 'function') {
- evt = new CustomEvent(eventName, {bubbles: true, cancelable: true, detail: detail});
- } else {
- evt = document.createEvent('CustomEvent');
- evt.initCustomEvent(eventName, true, true, detail);
- }
- return evt;
- }
-
- function triggerEvent(elt, eventName, detail) {
- var detail = detail || {};
- detail["sentBy"] = elt;
- var event = makeEvent(eventName, detail);
- var eventResult = elt.dispatchEvent(event);
- return eventResult;
- }
-
- function isArrayLike(value) {
- return Array.isArray(value) || value instanceof NodeList;
- }
-
- function forEach(value, func) {
- if (value == null) {
- // do nothing
- } else if (isArrayLike(value)) {
- for (var i = 0; i < value.length; i++) {
- func(value[i]);
- }
- } else {
- func(value);
- }
- }
-
- var ARRAY_SENTINEL = {array_sentinel:true}
- function linearize(args) {
- var arr = [];
- for (var i = 0; i < args.length; i++) {
- var arg = args[i];
- if (Array.isArray(arg)) {
- arr.push(ARRAY_SENTINEL);
- for (var j = 0; j < arg.length; j++) {
- arr.push(arg[j]);
- }
- arr.push(ARRAY_SENTINEL);
- } else {
- arr.push(arg);
- }
- }
- return arr;
- }
-
- function delinearize(values){
- var arr = [];
- for (var i = 0; i < values.length; i++) {
- var value = values[i];
- if (value === ARRAY_SENTINEL) {
- value = values[++i];
- var valueArray = [];
- arr.push(valueArray);
- while (value !== ARRAY_SENTINEL) {
- valueArray.push(value);
- value = values[++i];
- }
- } else {
- arr.push(value);
- }
- }
- return arr;
-
- }
-
- function unwrapAsyncs(values) {
- for (var i = 0; i < values.length; i++) {
- var value = values[i];
- if (value.asyncWrapper) {
- values[i] = value.value;
- }
- if (Array.isArray(value)) {
- for (var j = 0; j < value.length; j++) {
- var valueElement = value[j];
- if (valueElement.asyncWrapper) {
- value[j] = valueElement.value;
- }
- }
- }
- }
- }
-
- var HALT = {halt_flag:true};
- function unifiedExec(command, ctx) {
- while(true) {
- try {
- var next = unifiedEval(command, ctx);
- } catch(e) {
- _runtime.registerHyperTrace(ctx, e);
- if (ctx.meta.errorHandler && !ctx.meta.handlingError) {
- ctx.meta.handlingError = true;
- ctx[ctx.meta.errorSymmbol] = e;
- command = ctx.meta.errorHandler;
- continue;
- } else if (ctx.meta.reject) {
- ctx.meta.reject(e);
- next = HALT;
- } else {
- throw e;
- }
- }
- if (next == null) {
- console.error(command, " did not return a next element to execute! context: " , ctx)
- return;
- } else if (next.then) {
- next.then(function (resolvedNext) {
- unifiedExec(resolvedNext, ctx);
- }).catch(function(reason){
- _runtime.registerHyperTrace(ctx, reason);
- if (ctx.meta.errorHandler && !ctx.meta.handlingError) {
- ctx.meta.handlingError = true;
- ctx[ctx.meta.errorSymmbol] = reason;
- unifiedExec(ctx.meta.errorHandler, ctx);
- } else if(ctx.meta.reject) {
- ctx.meta.reject(reason);
- } else {
- throw reason;
- }
- });
- return;
- } else if (next === HALT) {
- // done
- return;
- } else {
- command = next; // move to the next command
- }
- }
- }
-
- function unifiedEval(parseElement, ctx) {
- var async = false;
- var wrappedAsyncs = false;
- var args = [ctx];
- if (parseElement.args) {
- for (var i = 0; i < parseElement.args.length; i++) {
- var argument = parseElement.args[i];
- if (argument == null) {
- args.push(null);
- } else if (Array.isArray(argument)) {
- var arr = [];
- for (var j = 0; j < argument.length; j++) {
- var element = argument[j];
- var value = element ? element.evaluate(ctx) : null; // OK
- if (value) {
- if (value.then) {
- async = true;
- } else if (value.asyncWrapper) {
- wrappedAsyncs = true;
- }
- }
- arr.push(value);
- }
- args.push(arr);
- } else if (argument.evaluate) {
- var value = argument.evaluate(ctx); // OK
- if (value) {
- if (value.then) {
- async = true;
- } else if (value.asyncWrapper) {
- wrappedAsyncs = true;
- }
- }
- args.push(value);
- } else {
- args.push(argument);
- }
- }
- }
- if (async) {
- return new Promise(function(resolve, reject){
- var linearized = linearize(args);
- Promise.all(linearized).then(function(values){
- values = delinearize(values);
- if (wrappedAsyncs) {
- unwrapAsyncs(values);
- }
- try{
- var apply = parseElement.op.apply(parseElement, values);
- resolve(apply);
- } catch(e) {
- reject(e);
- }
- }).catch(function(reason){
- if (ctx.meta.errorHandler && !ctx.meta.handlingError) {
- ctx.meta.handlingError = true;
- ctx[ctx.meta.errorSymmbol] = reason;
- unifiedExec(ctx.meta.errorHandler, ctx);
- } else if(ctx.meta.reject) {
- ctx.meta.reject(reason);
- } else {
- // TODO: no meta context to reject with, trigger event?
- }
- })
- })
- } else {
- if (wrappedAsyncs) {
- unwrapAsyncs(args);
- }
- return parseElement.op.apply(parseElement, args);
- }
- }
-
- var _scriptAttrs = null;
- function getScriptAttributes() {
- if (_scriptAttrs == null) {
- _scriptAttrs = _hyperscript.config.attributes.replace(/ /g,'').split(",")
- }
- return _scriptAttrs;
- }
-
- function getScript(elt) {
- for (var i = 0; i < getScriptAttributes().length; i++) {
- var scriptAttribute = getScriptAttributes()[i];
- if (elt.hasAttribute && elt.hasAttribute(scriptAttribute)) {
- return elt.getAttribute(scriptAttribute)
- }
- }
- if (elt.type === "text/hyperscript") {
- return elt.innerText;
- }
- return null;
- }
-
- function makeContext(owner, feature, hyperscriptTarget, event) {
- var ctx = {
- meta: {
- parser: _parser,
- lexer: _lexer,
- runtime: _runtime,
- owner: owner,
- feature: feature,
- iterators: {}
- },
- me: hyperscriptTarget,
- event: event,
- target: event ? event.target : null,
- detail: event ? event.detail : null,
- body: 'document' in globalScope ? document.body : null
- }
- ctx.meta.ctx = ctx;
- return ctx;
- }
-
- function getScriptSelector() {
- return getScriptAttributes().map(function (attribute) {
- return "[" + attribute + "]";
- }).join(", ");
- }
-
- function convertValue(value, type) {
-
- var dynamicResolvers = CONVERSIONS.dynamicResolvers;
- for (var i = 0; i < dynamicResolvers.length; i++) {
- var dynamicResolver = dynamicResolvers[i];
- var converted = dynamicResolver(type, value);
- if (converted !== undefined) {
- return converted;
- }
- }
-
- if (value == null) {
- return null;
- }
- var converter = CONVERSIONS[type];
- if (converter) {
- return converter(value);
- }
-
- throw "Unknown conversion : " + type;
- }
-
-
- function isType(o, type) {
- return Object.prototype.toString.call(o) === "[object " + type + "]";
- }
-
- function evaluate(src, ctx) {
- ctx = ctx || {};
- var tokens = _lexer.tokenize(src);
- if (_parser.commandStart(tokens.currentToken())) {
- var commandList = _parser.parseElement("commandList", tokens);
- var last = commandList;
- while (last.next) {
- last = last.next;
- }
- last.next = {
- op : function() {
- return HALT;
- }
- }
- commandList.execute(ctx);
- } else if (_parser.featureStart(tokens.currentToken())) {
- var hyperscript = _parser.parseElement("hyperscript", tokens);
- hyperscript.apply(document.body, null);
- return null;
- } else {
- var expression = _parser.parseElement("expression", tokens);
- return expression.evaluate(ctx);
- }
- }
-
- function processNode(elt) {
- var selector = _runtime.getScriptSelector();
- if (matchesSelector(elt, selector)) {
- initElement(elt);
- }
- if (elt.querySelectorAll) {
- forEach(elt.querySelectorAll(selector), function (elt) {
- initElement(elt);
- });
- }
- if (elt.type === "text/hyperscript") {
- initElement(elt, document.body);
- }
- if (elt.querySelectorAll) {
- forEach(elt.querySelectorAll("[type=\'text/hyperscript\']"), function (elt) {
- initElement(elt, document.body);
- });
- }
- }
-
- function initElement(elt, target) {
- var internalData = getInternalData(elt);
- if (!internalData.initialized) {
- var src = getScript(elt);
- if (src) {
- try {
- internalData.initialized = true;
- internalData.script = src;
- var tokens = _lexer.tokenize(src);
- var hyperScript = _parser.parseHyperScript(tokens);
- hyperScript.apply(target || elt, elt);
- setTimeout(function () {
- triggerEvent(target || elt, 'load');
- }, 1);
- } catch(e) {
- console.error("hyperscript errors were found on the following element:", elt, "\n\n", e.message, e.stack);
- }
- }
- }
- }
-
- function getInternalData(elt) {
- var dataProp = 'hyperscript-internal-data';
- var data = elt[dataProp];
- if (!data) {
- data = elt[dataProp] = {};
- }
- return data;
- }
-
- function typeCheck(value, typeString, nullOk) {
- if (value == null && nullOk) {
- return value;
- }
- var typeName = Object.prototype.toString.call(value).slice(8, -1);
- var typeCheckValue = value && typeName === typeString;
- if (typeCheckValue) {
- return value;
- } else {
- throw new Error("Typecheck failed! Expected: " + typeString + ", Found: " + typeName);
- }
- }
-
- function resolveSymbol(str, context) {
- if (str === "me" || str === "my" || str === "I") {
- return context["me"];
- } if (str === "it" || str === "its") {
- return context["result"];
- } else {
- if (context.meta && context.meta.context) {
- var fromMetaContext = context.meta.context[str];
- if (typeof fromMetaContext !== "undefined") {
- return fromMetaContext;
- }
- }
- var fromContext = context[str];
- if (typeof fromContext !== "undefined") {
- return fromContext;
- } else {
- return globalScope[str];
- }
- }
- }
-
- function findNext(command, context) {
- if (command) {
- if (command.resolveNext) {
- return command.resolveNext(context);
- } else if (command.next) {
- return command.next;
- } else {
- return findNext(command.parent, context)
- }
- }
- }
-
- function resolveProperty(root, property) {
- if (root != null) {
- var val = root[property];
- if (typeof val !== 'undefined') {
- return val;
- } else {
- if (isArrayLike(root)) {
- if (property === "first") {
- return root[0];
- } else if (property === "last") {
- return root[root.length - 1];
- } else if (property === "random") {
- return root[Math.floor(root.length * Math.random())]
- } else {
- // flat map
- var result = [];
- for (var i = 0; i < root.length; i++) {
- var component = root[i];
- var componentValue = component[property];
- if (componentValue) {
- result.push(componentValue);
- }
- }
- return result;
- }
- }
- }
- }
- }
-
- function assignToNamespace(nameSpace, name, value) {
- var root = globalScope;
- while (nameSpace.length > 0) {
- var propertyName = nameSpace.shift();
- var newRoot = root[propertyName];
- if (newRoot == null) {
- newRoot = {};
- root[propertyName] = newRoot;
- }
- root = newRoot;
- }
-
- root[name] = value;
- }
-
- function getHyperTrace(ctx, thrown) {
- var trace = [];
- var root = ctx;
- while(root.meta.caller) {
- root = root.meta.caller;
- }
- if (root.meta.traceMap) {
- return root.meta.traceMap.get(thrown, trace);
- }
- }
-
- function registerHyperTrace(ctx, thrown) {
- var trace = [];
- var root = null;
- while(ctx != null) {
- trace.push(ctx);
- root = ctx;
- ctx = ctx.meta.caller;
- }
- if (root.meta.traceMap == null) {
- root.meta.traceMap = new Map(); // TODO - WeakMap?
- }
- if (!root.meta.traceMap.get(thrown)) {
- var traceEntry = {
- trace: trace,
- print : function(logger) {
- logger = logger || console.error;
- logger("hypertrace /// ")
- var maxLen = 0;
- for (var i = 0; i < trace.length; i++) {
- maxLen = Math.max(maxLen, trace[i].meta.feature.displayName.length);
- }
- for (var i = 0; i < trace.length; i++) {
- var traceElt = trace[i];
- logger(" ->", traceElt.meta.feature.displayName.padEnd(maxLen + 2), "-", traceElt.meta.owner)
- }
- }
- };
- root.meta.traceMap.set(thrown, traceEntry);
- }
- }
-
- var hyperscriptUrl = 'document' in globalScope ? document.currentScript.src : null
-
- return {
- typeCheck: typeCheck,
- forEach: forEach,
- triggerEvent: triggerEvent,
- matchesSelector: matchesSelector,
- getScript: getScript,
- processNode: processNode,
- evaluate: evaluate,
- getScriptSelector: getScriptSelector,
- resolveSymbol: resolveSymbol,
- makeContext: makeContext,
- findNext: findNext,
- unifiedEval: unifiedEval,
- convertValue: convertValue,
- unifiedExec: unifiedExec,
- resolveProperty: resolveProperty,
- assignToNamespace: assignToNamespace,
- registerHyperTrace: registerHyperTrace,
- getHyperTrace: getHyperTrace,
- getInternalData: getInternalData,
- hyperscriptUrl: hyperscriptUrl,
- HALT: HALT
- }
- }();
-
- //====================================================================
- // Grammar
- //====================================================================
- {
- _parser.addLeafExpression("parenthesized", function(parser, runtime, tokens) {
- if (tokens.matchOpToken('(')) {
- var expr = parser.requireElement("expression", tokens);
- tokens.requireOpToken(")");
- return {
- type: "parenthesized",
- expr: expr,
- evaluate: function (context) {
- return expr.evaluate(context); //OK
- }
- }
- }
- })
-
- _parser.addLeafExpression("string", function(parser, runtime, tokens) {
- var stringToken = tokens.matchTokenType('STRING');
- if (stringToken) {
- var rawValue = stringToken.value;
- if (stringToken.template) {
- var innerTokens = _lexer.tokenize(rawValue, true);
- var args = parser.parseStringTemplate(innerTokens);
- } else {
- var args = [];
- }
- return {
- type: "string",
- token: stringToken,
- args: args,
- op: function (context) {
- var returnStr = "";
- for (var i = 1; i < arguments.length; i++) {
- var val = arguments[i];
- if (val) {
- returnStr += val;
- }
- }
- return returnStr;
- },
- evaluate: function (context) {
- if (args.length === 0) {
- return rawValue;
- } else {
- return runtime.unifiedEval(this, context);
- }
- }
- };
- }
- })
-
- _parser.addGrammarElement("nakedString", function(parser, runtime, tokens) {
- if (tokens.hasMore()) {
- var tokenArr = tokens.consumeUntilWhitespace();
- tokens.matchTokenType("WHITESPACE");
- return {
- type: "nakedString",
- tokens: tokenArr,
- evaluate: function (context) {
- return tokenArr.map(function (t) {return t.value}).join("");
- }
- }
- }
- })
-
- _parser.addLeafExpression("number", function(parser, runtime, tokens) {
- var number = tokens.matchTokenType('NUMBER');
- if (number) {
- var numberToken = number;
- var value = parseFloat(number.value)
- return {
- type: "number",
- value: value,
- numberToken: numberToken,
- evaluate: function () {
- return value;
- }
- }
- }
- })
-
- _parser.addLeafExpression("idRef", function(parser, runtime, tokens) {
- var elementId = tokens.matchTokenType('ID_REF');
- if (elementId) {
- return {
- type: "idRef",
- css: elementId.value,
- value: elementId.value.substr(1),
- evaluate: function (context) {
- return document.getElementById(this.value);
- }
- };
- }
- })
-
- _parser.addLeafExpression("classRef", function(parser, runtime, tokens) {
- var classRef = tokens.matchTokenType('CLASS_REF');
- if (classRef) {
- return {
- type: "classRef",
- css: classRef.value,
- className: function () {
- return this.css.substr(1);
- },
- evaluate: function () {
- return document.querySelectorAll(this.css);
- }
- };
- }
- })
-
- _parser.addLeafExpression("queryRef", function(parser, runtime, tokens) {
- var queryStart = tokens.matchOpToken('<');
- if (queryStart) {
- var queryTokens = tokens.consumeUntil("/");
- tokens.requireOpToken("/");
- tokens.requireOpToken(">");
- var queryValue = queryTokens.map(function(t){return t.value}).join("");
- return {
- type: "queryRef",
- css: queryValue,
- evaluate: function () {
- return document.querySelectorAll(this.css);
- }
- };
- }
- })
-
- _parser.addGrammarElement("attributeRef", function(parser, runtime, tokens) {
- if (tokens.matchOpToken("[")) {
- var content = tokens.consumeUntil("]");
- var contentStr = content.map(function (t) {
- return t.value
- }).join("");
- var values = contentStr.split("=");
- var name = values[0];
- var value = values[1];
- tokens.requireOpToken("]");
-
- return {
- type: "attribute_expression",
- name: name,
- value: value,
- args: [value],
- op:function(context, value){
- if (this.value) {
- return {name:this.name, value:value}
- } else {
- return {name:this.name};
- }
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- }
- }
- })
-
- _parser.addLeafExpression("objectLiteral", function(parser, runtime, tokens) {
- if (tokens.matchOpToken("{")) {
- var fields = []
- var valueExpressions = []
- if (!tokens.matchOpToken("}")) {
- do {
- var name = tokens.requireTokenType("IDENTIFIER", "STRING");
- tokens.requireOpToken(":");
- var value = parser.requireElement("expression", tokens);
- valueExpressions.push(value);
- fields.push({name: name, value: value});
- } while (tokens.matchOpToken(","))
- tokens.requireOpToken("}");
- }
- return {
- type: "objectLiteral",
- fields: fields,
- args: [valueExpressions],
- op:function(context, values){
- var returnVal = {};
- for (var i = 0; i < values.length; i++) {
- var field = fields[i];
- returnVal[field.name.value] = values[i];
- }
- return returnVal;
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- }
- }
- })
-
- _parser.addGrammarElement("namedArgumentList", function(parser, runtime, tokens) {
- if (tokens.matchOpToken("(")) {
- var fields = []
- var valueExpressions = []
- if (!tokens.matchOpToken(")")) {
- do {
- var name = tokens.requireTokenType("IDENTIFIER");
- tokens.requireOpToken(":");
- var value = parser.requireElement("expression", tokens);
- valueExpressions.push(value);
- fields.push({name: name, value: value});
- } while (tokens.matchOpToken(","))
- tokens.requireOpToken(")");
- }
- return {
- type: "namedArgumentList",
- fields: fields,
- args:[valueExpressions],
- op:function(context, values){
- var returnVal = {_namedArgList_:true};
- for (var i = 0; i < values.length; i++) {
- var field = fields[i];
- returnVal[field.name.value] = values[i];
- }
- return returnVal;
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- }
- }
-
-
- })
-
- _parser.addGrammarElement("symbol", function(parser, runtime, tokens) {
- var identifier = tokens.matchTokenType('IDENTIFIER');
- if (identifier) {
- return {
- type: "symbol",
- token: identifier,
- name: identifier.value,
- evaluate: function (context) {
- return runtime.resolveSymbol(identifier.value, context);
- }
- };
- }
- });
-
- _parser.addGrammarElement("implicitMeTarget", function(parser, runtime, tokens) {
- return {
- type: "implicitMeTarget",
- evaluate: function (context) {
- return context.me
- }
- };
- });
-
- _parser.addGrammarElement("implicitAllTarget", function(parser, runtime, tokens) {
- return {
- type: "implicitAllTarget",
- evaluate: function (context) {
- return document.querySelectorAll("*");
- }
- };
- });
-
- _parser.addLeafExpression("boolean", function(parser, runtime, tokens) {
- var booleanLiteral = tokens.matchToken("true") || tokens.matchToken("false");
- if (booleanLiteral) {
- return {
- type: "boolean",
- evaluate: function (context) {
- return booleanLiteral.value === "true";
- }
- }
- }
- });
-
- _parser.addLeafExpression("null", function(parser, runtime, tokens) {
- if (tokens.matchToken('null')) {
- return {
- type: "null",
- evaluate: function (context) {
- return null;
- }
- }
- }
- });
-
- _parser.addLeafExpression("arrayLiteral", function(parser, runtime, tokens) {
- if (tokens.matchOpToken('[')) {
- var values = [];
- if (!tokens.matchOpToken(']')) {
- do {
- var expr = parser.requireElement("expression", tokens);
- values.push(expr);
- } while (tokens.matchOpToken(","))
- tokens.requireOpToken("]");
- }
- return {
- type: "arrayLiteral",
- values: values,
- args: [values],
- op:function(context, values){
- return values;
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- }
- }
- });
-
- _parser.addLeafExpression("blockLiteral", function(parser, runtime, tokens) {
- if (tokens.matchOpToken('\\')) {
- var args = []
- var arg1 = tokens.matchTokenType("IDENTIFIER");
- if (arg1) {
- args.push(arg1);
- while (tokens.matchOpToken(",")) {
- args.push(tokens.requireTokenType("IDENTIFIER"));
- }
- }
- // TODO compound op token
- tokens.requireOpToken("-");
- tokens.requireOpToken(">");
- var expr = parser.requireElement("expression", tokens);
- return {
- type: "blockLiteral",
- args: args,
- expr: expr,
- evaluate: function (ctx) {
- var returnFunc = function(){
- //TODO - push scope
- for (var i = 0; i < args.length; i++) {
- ctx[args[i].value] = arguments[i];
- }
- return expr.evaluate(ctx) //OK
- }
- return returnFunc;
- }
- }
- }
- });
-
- _parser.addGrammarElement("timeExpression", function(parser, runtime, tokens){
- var time = parser.requireElement("expression", tokens);
- var factor = 1;
- if (tokens.matchToken("s") || tokens.matchToken("seconds")) {
- factor = 1000;
- } else if (tokens.matchToken("ms") || tokens.matchToken("milliseconds")) {
- // do nothing
- }
- return {
- type:"timeExpression",
- time: time,
- factor: factor,
- args: [time],
- op: function (context, val) {
- return val * this.factor
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- }
- })
-
- _parser.addIndirectExpression("propertyAccess", function(parser, runtime, tokens, root) {
- if (tokens.matchOpToken(".")) {
- var prop = tokens.requireTokenType("IDENTIFIER");
- var propertyAccess = {
- type: "propertyAccess",
- root: root,
- prop: prop,
- args: [root],
- op:function(context, rootVal){
- var value = runtime.resolveProperty(rootVal, prop.value);
- return value;
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- };
- return parser.parseElement("indirectExpression", tokens, propertyAccess);
- }
- });
-
- _parser.addIndirectExpression("of", function(parser, runtime, tokens, root) {
- if (tokens.matchToken("of")) {
- var newRoot = parser.requireElement('expression', tokens);
- // find the urroot
- var childOfUrRoot = null;
- var urRoot = root;
- while (urRoot.root) {
- childOfUrRoot = urRoot;
- urRoot = urRoot.root;
- }
- if (urRoot.type !== 'symbol') {
- parser.raiseParseError(tokens, "Cannot take a property of a non-symbol");
- }
- var prop = urRoot.name;
- var propertyAccess = {
- type: "ofExpression",
- prop: urRoot.token,
- root: newRoot,
- expression: root,
- args: [newRoot],
- op:function(context, rootVal){
- return runtime.resolveProperty(rootVal, prop);
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- };
-
- if (childOfUrRoot) {
- childOfUrRoot.root = propertyAccess;
- childOfUrRoot.args = [propertyAccess];
- } else {
- root = propertyAccess;
- }
-
- return parser.parseElement("indirectExpression", tokens, root);
- }
- });
-
- _parser.addIndirectExpression("inExpression", function(parser, runtime, tokens, root) {
- if (tokens.matchToken("in")) {
- if (root.type !== "idRef" && root.type === "queryRef" || root.type === "classRef") {
- var query = true;
- }
- var target = parser.requireElement("expression", tokens);
- var propertyAccess = {
- type: "inExpression",
- root: root,
- args: [query ? null : root, target],
- op:function(context, rootVal, target){
- var returnArr = [];
- if(query){
- runtime.forEach(target, function (targetElt) {
- var results = targetElt.querySelectorAll(root.css);
- for (var i = 0; i < results.length; i++) {
- returnArr.push(results[i]);
- }
- })
- } else {
- runtime.forEach(rootVal, function(rootElt){
- runtime.forEach(target, function(targetElt){
- if (rootElt === targetElt) {
- returnArr.push(rootElt);
- }
- })
- })
- }
- if (returnArr.length > 0) {
- return returnArr;
- } else {
- return null;
- }
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- };
- return parser.parseElement("indirectExpression", tokens, propertyAccess);
- }
- });
-
- _parser.addIndirectExpression("asExpression", function(parser, runtime, tokens, root) {
- if (tokens.matchToken("as")) {
- var conversion = parser.requireElement('dotOrColonPath', tokens).evaluate(); // OK No promise
- var propertyAccess = {
- type: "asExpression",
- root: root,
- args: [root],
- op:function(context, rootVal){
- return runtime.convertValue(rootVal, conversion);
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- };
- return parser.parseElement("indirectExpression", tokens, propertyAccess);
- }
- });
-
- _parser.addIndirectExpression("functionCall", function(parser, runtime, tokens, root) {
- if (tokens.matchOpToken("(")) {
- var args = [];
- if (!tokens.matchOpToken(')')) {
- do {
- args.push(parser.requireElement("expression", tokens));
- } while (tokens.matchOpToken(","))
- tokens.requireOpToken(")");
- }
-
- if (root.root) {
- var functionCall = {
- type: "functionCall",
- root: root,
- argExressions: args,
- args: [root.root, args],
- op: function (context, rootRoot, args) {
- var func = rootRoot[root.prop.value];
- if (func.hyperfunc) {
- args.push(context);
- }
- return func.apply(rootRoot, args);
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- }
- } else {
- var functionCall = {
- type: "functionCall",
- root: root,
- argExressions: args,
- args: [root, args],
- op: function(context, func, argVals){
- if (func.hyperfunc) {
- argVals.push(context);
- }
- var apply = func.apply(null, argVals);
- return apply;
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- }
- }
- return parser.parseElement("indirectExpression", tokens, functionCall);
- }
- });
-
- _parser.addIndirectExpression("arrayIndex", function (parser, runtime, tokens, root) {
- if (tokens.matchOpToken("[")) {
- var index = parser.requireElement("expression", tokens);
- tokens.requireOpToken("]")
-
- var arrayIndex = {
- type: "arrayIndex",
- root: root,
- index: index,
- args: [root, index],
- op: function(ctx, root, index) {
- return root[index]
- },
- evaluate: function(context){
- return _runtime.unifiedEval(this, context);
- }
- };
-
- return _parser.parseElement("indirectExpression", tokens, arrayIndex);
- }
- });
-
- _parser.addGrammarElement("postfixExpression", function(parser, runtime, tokens) {
- var root = parser.parseElement("primaryExpression", tokens);
- if (tokens.matchOpToken(":")) {
- var typeName = tokens.requireTokenType("IDENTIFIER");
- var nullOk = !tokens.matchOpToken("!");
- return {
- type: "typeCheck",
- typeName: typeName,
- root: root,
- nullOk: nullOk,
- args: [root],
- op: function (context, val) {
- return runtime.typeCheck(val, this.typeName.value, this.nullOk);
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- }
- } else {
- return root;
- }
- });
-
- _parser.addGrammarElement("logicalNot", function(parser, runtime, tokens) {
- if (tokens.matchToken("not")) {
- var root = parser.requireElement("unaryExpression", tokens);
- return {
- type: "logicalNot",
- root: root,
- args: [root],
- op: function (context, val) {
- return !val;
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- };
- }
- });
-
- _parser.addGrammarElement("noExpression", function(parser, runtime, tokens) {
- if (tokens.matchToken("no")) {
- var root = parser.requireElement("unaryExpression", tokens);
- return {
- type: "noExpression",
- root: root,
- args: [root],
- op: function (context, val) {
- return val == null || val.length === 0;
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- };
- }
- });
-
- _parser.addGrammarElement("negativeNumber", function(parser, runtime, tokens) {
- if (tokens.matchOpToken("-")) {
- var root = parser.requireElement("unaryExpression", tokens);
- return {
- type: "negativeNumber",
- root: root,
- args: [root],
- op:function(context, value){
- return -1 * value;
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- };
- }
- });
-
- _parser.addGrammarElement("unaryExpression", function(parser, runtime, tokens) {
- return parser.parseAnyOf(["logicalNot", "noExpression", "negativeNumber", "postfixExpression"], tokens);
- });
-
- _parser.addGrammarElement("mathOperator", function(parser, runtime, tokens) {
- var expr = parser.parseElement("unaryExpression", tokens);
- var mathOp, initialMathOp = null;
- mathOp = tokens.matchAnyOpToken("+", "-", "*", "/", "%")
- while (mathOp) {
- initialMathOp = initialMathOp || mathOp;
- var operator = mathOp.value;
- if (initialMathOp.value !== operator) {
- parser.raiseParseError(tokens, "You must parenthesize math operations with different operators")
- }
- var rhs = parser.parseElement("unaryExpression", tokens);
- expr = {
- type: "mathOperator",
- lhs: expr,
- rhs: rhs,
- operator: operator,
- args: [expr, rhs],
- op:function (context, lhsVal, rhsVal) {
- if (this.operator === "+") {
- return lhsVal + rhsVal;
- } else if (this.operator === "-") {
- return lhsVal - rhsVal;
- } else if (this.operator === "*") {
- return lhsVal * rhsVal;
- } else if (this.operator === "/") {
- return lhsVal / rhsVal;
- } else if (this.operator === "%") {
- return lhsVal % rhsVal;
- }
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- }
- mathOp = tokens.matchAnyOpToken("+", "-", "*", "/", "%")
- }
- return expr;
- });
-
- _parser.addGrammarElement("mathExpression", function(parser, runtime, tokens) {
- return parser.parseAnyOf(["mathOperator", "unaryExpression"], tokens);
- });
-
- _parser.addGrammarElement("comparisonOperator", function(parser, runtime, tokens) {
- var expr = parser.parseElement("mathExpression", tokens);
- var comparisonToken = tokens.matchAnyOpToken("<", ">", "<=", ">=", "==", "===", "!=", "!==")
- var comparisonStr = comparisonToken ? comparisonToken.value : null;
- if (comparisonStr == null) {
- if (tokens.matchToken("is") || tokens.matchToken("am")) {
- if (tokens.matchToken("not")) {
- if (tokens.matchToken("in")) {
- comparisonStr = "not in";
- } else {
- comparisonStr = "!=";
- }
- } else {
- if (tokens.matchToken("in")) {
- comparisonStr = "in";
- } else {
- comparisonStr = "==";
- }
- }
- } else if (tokens.matchToken("matches") || tokens.matchToken("match")) {
- comparisonStr = "match";
- } else if (tokens.matchToken("contains") || tokens.matchToken("contain")) {
- comparisonStr = "contain";
- } else if (tokens.matchToken("do") || tokens.matchToken("does")) {
- tokens.requireToken('not');
- if (tokens.matchToken("matches") || tokens.matchToken("match")) {
- comparisonStr = "not match";
- } else if (tokens.matchToken("contains") || tokens.matchToken("contain")) {
- comparisonStr = "not contain";
- } else {
- parser.raiseParseError(tokens, "Expected matches or contains");
- }
- }
- }
-
- if (comparisonStr) { // Do not allow chained comparisons, which is dumb
- var rhs = parser.requireElement("mathExpression", tokens);
- if (comparisonStr === "match" || comparisonStr === "not match") {
- rhs = rhs.css ? rhs.css : rhs;
- }
- expr = {
- type: "comparisonOperator",
- operator: comparisonStr,
- lhs: expr,
- rhs: rhs,
- args: [expr, rhs],
- op:function (context, lhsVal, rhsVal) {
- if (this.operator === "==") {
- return lhsVal == rhsVal;
- } else if (this.operator === "!=") {
- return lhsVal != rhsVal;
- } if (this.operator === "in") {
- return (rhsVal != null) && Array.from(rhsVal).indexOf(lhsVal) >= 0;
- } if (this.operator === "not in") {
- return (rhsVal == null) || Array.from(rhsVal).indexOf(lhsVal) < 0;
- } if (this.operator === "match") {
- return (lhsVal != null) && lhsVal.matches(rhsVal);
- } if (this.operator === "not match") {
- return (lhsVal == null) || !lhsVal.matches(rhsVal);
- } if (this.operator === "contain") {
- return (lhsVal != null) && lhsVal.contains(rhsVal);
- } if (this.operator === "not contain") {
- return (lhsVal == null) || !lhsVal.contains(rhsVal);
- } if (this.operator === "===") {
- return lhsVal === rhsVal;
- } else if (this.operator === "!==") {
- return lhsVal !== rhsVal;
- } else if (this.operator === "<") {
- return lhsVal < rhsVal;
- } else if (this.operator === ">") {
- return lhsVal > rhsVal;
- } else if (this.operator === "<=") {
- return lhsVal <= rhsVal;
- } else if (this.operator === ">=") {
- return lhsVal >= rhsVal;
- }
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- };
- }
- return expr;
- });
-
- _parser.addGrammarElement("comparisonExpression", function(parser, runtime, tokens) {
- return parser.parseAnyOf(["comparisonOperator", "mathExpression"], tokens);
- });
-
- _parser.addGrammarElement("logicalOperator", function(parser, runtime, tokens) {
- var expr = parser.parseElement("comparisonExpression", tokens);
- var logicalOp, initialLogicalOp = null;
- logicalOp = tokens.matchToken("and") || tokens.matchToken("or");
- while (logicalOp) {
- initialLogicalOp = initialLogicalOp || logicalOp;
- if (initialLogicalOp.value !== logicalOp.value) {
- parser.raiseParseError(tokens, "You must parenthesize logical operations with different operators")
- }
- var rhs = parser.requireElement("comparisonExpression", tokens);
- expr = {
- type: "logicalOperator",
- operator: logicalOp.value,
- lhs: expr,
- rhs: rhs,
- args: [expr, rhs],
- op: function (context, lhsVal, rhsVal) {
- if (this.operator === "and") {
- return lhsVal && rhsVal;
- } else {
- return lhsVal || rhsVal;
- }
- },
- evaluate: function (context) {
- return runtime.unifiedEval(this, context);
- }
- }
- logicalOp = tokens.matchToken("and") || tokens.matchToken("or");
- }
- return expr;
- });
-
- _parser.addGrammarElement("logicalExpression", function(parser, runtime, tokens) {
- return parser.parseAnyOf(["logicalOperator", "mathExpression"], tokens);
- });
-
- _parser.addGrammarElement("asyncExpression", function(parser, runtime, tokens) {
- if (tokens.matchToken('async')) {
- var value = parser.requireElement("logicalExpression", tokens);
- var expr = {
- type: "asyncExpression",
- value: value,
- evaluate: function (context) {
- return {
- asyncWrapper: true,
- value: this.value.evaluate(context) //OK
- }
- }
- }
- return expr;
- } else {
- return parser.parseElement("logicalExpression", tokens);
- }
- });
-
- _parser.addGrammarElement("expression", function(parser, runtime, tokens) {
- tokens.matchToken("the"); // optional the
- return parser.parseElement("asyncExpression", tokens);
- });
-
- _parser.addGrammarElement("target", function(parser, runtime, tokens) {
- var expr = _parser.parseElement("expression", tokens);
- if (expr.type === "symbol" || expr.type === "idRef" || expr.type === "inExpression" ||
- expr.type === "queryRef" || expr.type === "classRef" || expr.type === "ofExpression" ||
- expr.type === "propertyAccess") {
- return expr;
- } else {
- _parser.raiseParseError(tokens, "A target expression must be writable");
- }
- return expr;
- });
-
- _parser.addGrammarElement("hyperscript", function(parser, runtime, tokens) {
-
- var features = [];
-
- if (tokens.hasMore()) {
- do {
- var feature = parser.requireElement("feature", tokens);
- features.push(feature);
- tokens.matchToken("end"); // optional end
- } while (parser.featureStart(tokens.currentToken()) || tokens.currentToken().value === "(")
- if (tokens.hasMore()) {
- parser.raiseParseError(tokens);
- }
- }
- return {
- type: "hyperscript",
- features: features,
- apply: function (target, source) {
- // no op
- _runtime.forEach(features, function(feature){
- feature.install(target, source);
- })
- }
- };
- })
-
- _parser.addFeature("on", function(parser, runtime, tokens) {
- if (tokens.matchToken('on')) {
- var every = false;
- if (tokens.matchToken("every")) {
- every = true;
- }
- var events = [];
- var displayName = null;
- do {
-
- var on = parser.requireElement("dotOrColonPath", tokens, "Expected event name");
-
- var eventName = on.evaluate(); // OK No Promise
- if (displayName) {
- displayName = displayName + " or " + eventName;
- } else {
- displayName = "on " + eventName;
- }
- var args = [];
- // handle argument list (look ahead 3)
- if (tokens.token(0).value === "(" &&
- (tokens.token(1).value === ")" ||
- tokens.token(2).value === "," ||
- tokens.token(2).value === ")")) {
- tokens.matchOpToken("(");
- do {
- args.push(tokens.requireTokenType('IDENTIFIER'));
- } while (tokens.matchOpToken(","))
- tokens.requireOpToken(')')
- }
-
- var filter = null;
- if (tokens.matchOpToken('[')) {
- filter = parser.requireElement("expression", tokens);
- tokens.requireOpToken(']');
- }
-
- if (tokens.currentToken().type === "NUMBER") {
- var startCountToken = tokens.consumeToken();
- var startCount = parseInt(startCountToken.value);
- if (tokens.matchToken("to")) {
- var endCountToken = tokens.consumeToken();
- var endCount = parseInt(endCountToken.value);
- } else if (tokens.matchToken("and")) {
- var unbounded = true;
- tokens.requireToken("on");
- }
- }
-
- var from = null;
- var elsewhere = false;
- if (tokens.matchToken("from")) {
- if (tokens.matchToken('elsewhere')) {
- elsewhere = true;
- } else {
- from = parser.parseElement("target", tokens)
- if (!from) {
- parser.raiseParseError('Expected either target value or "elsewhere".', tokens);
- }
- }
- }
- // support both "elsewhere" and "from elsewhere"
- if (from === null && elsewhere === false && tokens.matchToken("elsewhere")) {
- elsewhere = true;
- }
-
- if (tokens.matchToken('in')) {
- var inExpr = parser.parseAnyOf(["idRef", "queryRef", "classRef"], tokens);
- }
-
- if (tokens.matchToken('debounced')) {
- tokens.requireToken("at");
- var timeExpr = parser.requireElement("timeExpression", tokens);
- var debounceTime = timeExpr.evaluate({}); // OK No promise TODO make a literal time expr
- } else if (tokens.matchToken('throttled')) {
- tokens.requireToken("at");
- var timeExpr = parser.requireElement("timeExpression", tokens);
- var throttleTime = timeExpr.evaluate({}); // OK No promise TODO make a literal time expr
- }
-
- events.push({
- execCount: 0,
- every: every,
- on: eventName,
- args: args,
- filter: filter,
- from:from,
- inExpr:inExpr,
- elsewhere:elsewhere,
- startCount : startCount,
- endCount : endCount,
- unbounded : unbounded,
- debounceTime : debounceTime,
- throttleTime : throttleTime,
- })
- } while (tokens.matchToken("or"))
-
-
- var queue = [];
- var queueLast = true;
- if (!every) {
- if (tokens.matchToken("queue")) {
- if (tokens.matchToken("all")) {
- var queueAll = true;
- var queueLast = false;
- } else if(tokens.matchToken("first")) {
- var queueFirst = true;
- } else if(tokens.matchToken("none")) {
- var queueNone = true;
- } else {
- tokens.requireToken("last");
- }
- }
- }
-
- var start = parser.requireElement("commandList", tokens);
-
- var implicitReturn = {
- type: "implicitReturn",
- op: function (context) {
- // automatically resolve at the end of an event handler if nothing else does
- context.meta.resolve();
- return runtime.HALT;
- },
- execute: function (ctx) {
- // do nothing
- }
- };
- if (start) {
- var end = start;
- while (end.next) {
- end = end.next;
- }
- end.next = implicitReturn
- } else {
- start = implicitReturn
- }
-
- var onFeature = {
- displayName: displayName,
- events:events,
- start: start,
- every: every,
- executing: false,
- execCount: 0,
- queue: queue,
- execute: function (ctx) {
- if (this.executing && this.every === false) {
- if (queueNone || (queueFirst && queue.length > 0)) {
- return;
- }
- if (queueLast) {
- onFeature.queue.length = 0;
- }
- onFeature.queue.push(ctx);
- return;
- }
- this.execCount++;
- this.executing = true;
- ctx.meta.resolve = function () {
- onFeature.executing = false;
- var queued = onFeature.queue.shift();
- if (queued) {
- setTimeout(function () {
- onFeature.execute(queued);
- }, 1);
- }
- }
- ctx.meta.reject = function (err) {
- console.error(err.message ? err.message : err);
- var hypertrace = runtime.getHyperTrace(ctx, err);
- if (hypertrace) {
- hypertrace.print();
- }
- runtime.triggerEvent(ctx.me, 'exception', {error: err})
- onFeature.executing = false;
- var queued = onFeature.queue.shift();
- if (queued) {
- setTimeout(function () {
- onFeature.execute(queued);
- }, 1);
- }
- }
- start.execute(ctx);
- },
- install: function (elt, source) {
- runtime.forEach(onFeature.events, function(eventSpec) {
- var targets;
- if (eventSpec.elsewhere) {
- targets = [document];
- } else if (eventSpec.from) {
- targets = eventSpec.from.evaluate({});
- } else {
- targets = [elt];
- }
- runtime.forEach(targets, function (target) { // OK NO PROMISE
- target.addEventListener(eventSpec.on, function (evt) { // OK NO PROMISE
- var ctx = runtime.makeContext(elt, onFeature, elt, evt);
- if (eventSpec.elsewhere && elt.contains(evt.target)) {
- return
- }
-
- // establish context
- runtime.forEach(eventSpec.args, function (arg) {
- ctx[arg.value] = ctx.event[arg.value] || (ctx.event.detail ? ctx.event.detail[arg.value] : null);
- });
-
- // apply filter
- if (eventSpec.filter) {
- var initialCtx = ctx.meta.context;
- ctx.meta.context = ctx.event;
- try {
- var value = eventSpec.filter.evaluate(ctx); //OK NO PROMISE
- if (value) {
- // match the javascript semantics for if statements
- } else {
- return;
- }
- } finally {
- ctx.meta.context = initialCtx;
- }
- }
-
- if (eventSpec.inExpr) {
- var inElement = evt.target;
- while(true) {
- if (inElement.matches && inElement.matches(eventSpec.inExpr.css)) {
- ctx.result = inElement;
- break;
- } else {
- inElement = inElement.parentElement;
- if (inElement == null) {
- return; // no match found
- }
- }
- }
- }
-
- // verify counts
- eventSpec.execCount++;
- if (eventSpec.startCount) {
- if (eventSpec.endCount) {
- if (eventSpec.execCount < eventSpec.startCount ||
- eventSpec.execCount > eventSpec.endCount) {
- return;
- }
- } else if (eventSpec.unbounded) {
- if (eventSpec.execCount < eventSpec.startCount) {
- return;
- }
- } else if (eventSpec.execCount !== eventSpec.startCount) {
- return;
- }
- }
-
- //debounce
- if (eventSpec.debounceTime) {
- if (eventSpec.debounced) {
- clearTimeout(eventSpec.debounced);
- }
- eventSpec.debounced = setTimeout(function () {
- onFeature.execute(ctx);
- }, eventSpec.debounceTime);
- return;
- }
-
- // throttle
- if (eventSpec.throttleTime) {
- if (eventSpec.lastExec && Date.now() < eventSpec.lastExec + eventSpec.throttleTime) {
- return;
- } else {
- eventSpec.lastExec = Date.now();
- }
- }
-
- // apply execute
- onFeature.execute(ctx);
- });
- })
- });
- }
- };
- parser.setParent(start, onFeature);
- return onFeature;
- }
- });
-
- _parser.addFeature("def", function(parser, runtime, tokens) {
- if (tokens.matchToken('def')) {
- var functionName = parser.requireElement("dotOrColonPath", tokens);
- var nameVal = functionName.evaluate(); // OK
- var nameSpace = nameVal.split(".");
- var funcName = nameSpace.pop();
-
- var args = [];
- if (tokens.matchOpToken("(")) {
- if (tokens.matchOpToken(")")) {
- // emtpy args list
- } else {
- do {
- args.push(tokens.requireTokenType('IDENTIFIER'));
- } while (tokens.matchOpToken(","))
- tokens.requireOpToken(')')
- }
- }
-
- var start = parser.parseElement("commandList", tokens);
- if (tokens.matchToken('catch')) {
- var errorSymbol = tokens.requireTokenType('IDENTIFIER').value;
- var errorHandler = parser.parseElement("commandList", tokens);
- }
- var functionFeature = {
- displayName: funcName + "(" + args.map(function(arg){ return arg.value }).join(", ") + ")",
- name: funcName,
- args: args,
- start: start,
- errorHandler: errorHandler,
- errorSymbol: errorSymbol,
- install: function (target, source) {
- var func = function () {
- // null, worker
- var elt = 'document' in globalScope ? document.body : globalScope
- var ctx = runtime.makeContext(source, functionFeature, elt, null);
-
- // install error handler if any
- ctx.meta.errorHandler = errorHandler;
- ctx.meta.errorSymmbol = errorSymbol;
-
- for (var i = 0; i < args.length; i++) {
- var name = args[i];
- var argumentVal = arguments[i];
- if (name) {
- ctx[name.value] = argumentVal;
- }
- }
- ctx.meta.caller = arguments[args.length];
- var resolve, reject = null;
- var promise = new Promise(function (theResolve, theReject) {
- resolve = theResolve;
- reject = theReject;
- });
- start.execute(ctx);
- if (ctx.meta.returned) {
- return ctx.meta.returnValue;
- } else {
- ctx.meta.resolve = resolve;
- ctx.meta.reject = reject;
- return promise
- }
- };
- func.hyperfunc = true;
- runtime.assignToNamespace(nameSpace, funcName, func);
- }
- };
-
- var implicitReturn = {
- type: "implicitReturn",
- op: function (context) {
- // automatically return at the end of the function if nothing else does
- context.meta.returned = true;
- if (context.meta.resolve) {
- context.meta.resolve();
- }
- return runtime.HALT;
- },
- execute: function (context) {
- // do nothing
- }
- }
- // terminate body
- if (start) {
- var end = start;
- while (end.next) {
- end = end.next;
- }
- end.next = implicitReturn
- } else {
- functionFeature.start = implicitReturn
- }
-
- // terminate error handler
- if (errorHandler) {
- var end = errorHandler;
- while (end.next) {
- end = end.next;
- }
- end.next = implicitReturn
- }
-
- parser.setParent(start, functionFeature);
- return functionFeature;
- }
- });
-
- _parser.addFeature("init", function(parser, runtime, tokens) {
- if (tokens.matchToken('init')) {
- var start = parser.parseElement("commandList", tokens);
- var initFeature = {
- start: start,
- install: function (target, source) {
- setTimeout(function () {
- start.execute(runtime.makeContext(target, this, target));
- }, 0);
- }
- };
-
- var implicitReturn = {
- type: "implicitReturn",
- op: function (context) {
- return runtime.HALT;
- },
- execute: function (context) {
- // do nothing
- }
- }
- // terminate body
- if (start) {
- var end = start;
- while (end.next) {
- end = end.next;
- }
- end.next = implicitReturn
- } else {
- initFeature.start = implicitReturn
- }
- parser.setParent(start, initFeature);
- return initFeature;
- }
- });
-
- _parser.addFeature("worker", function (parser, runtime, tokens) {
- if (tokens.matchToken("worker")) {
- parser.raiseParseError(tokens,
- "In order to use the 'worker' feature, include " +
- "the _hyperscript worker plugin. See " +
- "https://hyperscript.org/features/worker/ for " +
- "more info.")
- }
- })
-
- _parser.addGrammarElement("jsBody", function(parser, runtime, tokens) {
- var jsSourceStart = tokens.currentToken().start;
- var jsLastToken = tokens.currentToken();
-
- var funcNames = [];
- var funcName = "";
- var expectFunctionDeclaration = false;
- while (tokens.hasMore()) {
- jsLastToken = tokens.consumeToken();
- var peek = tokens.currentToken(true);
- if (peek.type === "IDENTIFIER"
- && peek.value === "end") {
- break;
- }
- if (expectFunctionDeclaration) {
- if (jsLastToken.type === "IDENTIFIER"
- || jsLastToken.type === "NUMBER") {
- funcName += jsLastToken.value;
- } else {
- if (funcName !== "") funcNames.push(funcName);
- funcName = "";
- expectFunctionDeclaration = false;
- }
- } else if (jsLastToken.type === "IDENTIFIER"
- && jsLastToken.value === "function") {
- expectFunctionDeclaration = true;
- }
- }
- var jsSourceEnd = jsLastToken.end + 1;
-
- return {
- type: 'jsBody',
- exposedFunctionNames: funcNames,
- jsSource: tokens.source.substring(jsSourceStart, jsSourceEnd),
- }
- })
-
- _parser.addFeature("js", function(parser, runtime, tokens) {
- if (tokens.matchToken('js')) {
-
- var jsBody = parser.parseElement('jsBody', tokens);
-
- var jsSource = jsBody.jsSource +
- "\nreturn { " +
- jsBody.exposedFunctionNames.map(function (name) {
- return name+":"+name;
- }).join(",") +
- " } ";
- var func = new Function(jsSource);
-
- return {
- jsSource: jsSource,
- function: func,
- exposedFunctionNames: jsBody.exposedFunctionNames,
- install: function() {
- mergeObjects(globalScope, func())
- }
- }
- }
- })
-
- _parser.addCommand("js", function (parser, runtime, tokens) {
- if (tokens.matchToken("js")) {
- // Parse inputs
- var inputs = [];
- if (tokens.matchOpToken("(")) {
- if (tokens.matchOpToken(")")) {
- // empty input list
- } else {
- do {
- var inp = tokens.requireTokenType('IDENTIFIER');
- inputs.push(inp.value);
- } while (tokens.matchOpToken(","));
- tokens.requireOpToken(')');
- }
- }
-
- var jsBody = parser.parseElement('jsBody', tokens);
- tokens.matchToken('end');
-
- var func = varargConstructor(Function, inputs.concat([jsBody.jsSource]));
-
- return {
- jsSource: jsBody.jsSource,
- function: func,
- inputs: inputs,
- op: function (context) {
- var args = [];
- inputs.forEach(function (input) {
- args.push(runtime.resolveSymbol(input, context))
- });
- var result = func.apply(globalScope, args)
- if (result && typeof result.then === 'function') {
- return Promise(function (resolve) {
- result.then(function (actualResult) {
- context.result = actualResult
- resolve(runtime.findNext(this, context));
- })
- })
- } else {
- context.result = result
- return runtime.findNext(this, context);
- }
- }
- };
- }
- })
-
- _parser.addCommand("async", function (parser, runtime, tokens) {
- if (tokens.matchToken("async")) {
- if (tokens.matchToken("do")) {
- var body = parser.requireElement('commandList', tokens)
- tokens.requireToken("end")
- } else {
- var body = parser.requireElement('command', tokens)
- }
- return {
- body: body,
- op: function (context) {
- setTimeout(function(){
- body.execute(context);
- })
- return runtime.findNext(this, context);
- }
- };
- }
- })
-
- _parser.addCommand("with", function (parser, runtime, tokens) {
- var startToken = tokens.currentToken();
- if (tokens.matchToken("with")) {
- var value = parser.requireElement("expression", tokens);
- var body = parser.requireElement('commandList', tokens)
- if (tokens.hasMore()) {
- tokens.requireToken("end");
- }
- var slot = "with_" + startToken.start;
- var withCmd = {
- value: value,
- body: body,
- args: [value],
- resolveNext: function (context) {
- var iterator = context.meta.iterators[slot];
- if (iterator.index < iterator.value.length) {
- context.me = iterator.value[iterator.index++];
- return body;
- } else {
- // restore original me
- context.me = iterator.originalMe;
- if (this.next) {
- return this.next;
- } else {
- return runtime.findNext(this.parent, context);
- }
- }
- },
- op: function (context, value) {
- if (value == null) {
- value = [];
- } else if (!(Array.isArray(value) || value instanceof NodeList)) {
- value = [value];
- }
- context.meta.iterators[slot] = {
- originalMe: context.me,
- index: 0,
- value: value
- };
- return this.resolveNext(context);
- }
- };
- parser.setParent(body, withCmd);
- return withCmd;
- }
- })
-
- _parser.addCommand("wait", function(parser, runtime, tokens) {
- if (tokens.matchToken("wait")) {
- // wait on event
- if (tokens.matchToken("for")) {
- tokens.matchToken("a"); // optional "a"
- var evt = _parser.requireElement("dotOrColonPath", tokens, "Expected event name");
- if (tokens.matchToken("from")) {
- var on = parser.requireElement("expression", tokens);
- }
- // wait on event
- var waitCmd = {
- event: evt,
- on: on,
- args: [evt, on],
- op: function (context, eventName, on) {
- var target = on ? on : context.me;
- return new Promise(function (resolve) {
- var listener = function () {
- resolve(runtime.findNext(waitCmd, context));
- };
- target.addEventListener(eventName, listener, {once: true});
- });
- }
- };
- } else {
- var time = _parser.requireElement("timeExpression", tokens);
- var waitCmd = {
- type: "waitCmd",
- time: time,
- args: [time],
- op: function (context, timeValue) {
- return new Promise(function (resolve) {
- setTimeout(function () {
- resolve(runtime.findNext(waitCmd, context));
- }, timeValue);
- });
- },
- execute: function (context) {
- return runtime.unifiedExec(this, context);
- }
- };
- }
- return waitCmd
- }
- })
-
- // TODO - colon path needs to eventually become part of ruby-style symbols
- _parser.addGrammarElement("dotOrColonPath", function(parser, runtime, tokens) {
- var root = tokens.matchTokenType("IDENTIFIER");
- if (root) {
- var path = [root.value];
-
- var separator = tokens.matchOpToken(".") || tokens.matchOpToken(":");
- if (separator) {
- do {
- path.push(tokens.requireTokenType("IDENTIFIER").value);
- } while (tokens.matchOpToken(separator.value))
- }
-
- return {
- type: "dotOrColonPath",
- path: path,
- evaluate: function () {
- return path.join(separator ? separator.value : "");
- }
- }
- }
- });
-
- _parser.addCommand("send", function(parser, runtime, tokens) {
- if (tokens.matchToken('send')) {
- var eventName = parser.requireElement("dotOrColonPath", tokens);
-
- var details = parser.parseElement("namedArgumentList", tokens);
- if (tokens.matchToken("to")) {
- var to = parser.requireElement("target", tokens);
- } else {
- var to = parser.requireElement("implicitMeTarget");
- }
-
-
- var sendCmd = {
- eventName: eventName,
- details: details,
- to: to,
- args: [to, eventName, details],
- op: function (context, to, eventName, details) {
- runtime.forEach(to, function (target) {
- runtime.triggerEvent(target, eventName, details ? details : {});
- });
- return runtime.findNext(sendCmd, context);
- }
- };
- return sendCmd
- }
- })
-
- _parser.addCommand("return", function(parser, runtime, tokens) {
- if (tokens.matchToken('return')) {
- var value = parser.requireElement("expression", tokens);
-
- var returnCmd = {
- value: value,
- args: [value],
- op: function (context, value) {
- var resolve = context.meta.resolve;
- context.meta.returned = true;
- if (resolve) {
- if (value) {
- resolve(value);
- } else {
- resolve()
- }
- } else {
- context.meta.returned = true;
- context.meta.returnValue = value;
- }
- return runtime.HALT;
- }
- };
- return returnCmd
- }
- })
-
- _parser.addCommand("log", function(parser, runtime, tokens) {
- if (tokens.matchToken('log')) {
- var exprs = [parser.parseElement("expression", tokens)];
- while (tokens.matchOpToken(",")) {
- exprs.push(parser.requireElement("expression", tokens));
- }
- if (tokens.matchToken("with")) {
- var withExpr = parser.requireElement("expression", tokens);
- }
- var logCmd = {
- exprs: exprs,
- withExpr: withExpr,
- args: [withExpr, exprs],
- op: function (ctx, withExpr, values) {
- if (withExpr) {
- withExpr.apply(null, values);
- } else {
- console.log.apply(null, values);
- }
- return runtime.findNext(this, ctx);
- }
- };
- return logCmd;
- }
- })
-
- _parser.addCommand("throw", function(parser, runtime, tokens) {
- if (tokens.matchToken('throw')) {
- var expr = parser.requireElement("expression", tokens);
- var throwCmd = {
- expr: expr,
- args: [expr],
- op: function (ctx, expr) {
- runtime.registerHyperTrace(ctx, expr);
- var reject = ctx.meta && ctx.meta.reject;
- if (reject) {
- reject(expr);
- return runtime.HALT;
- } else {
- throw expr;
- }
- }
- };
- return throwCmd;
- }
- })
-
- var parseCallOrGet = function(parser, runtime, tokens) {
- var expr = parser.requireElement("expression", tokens);
- var callCmd = {
- expr: expr,
- args: [expr],
- op: function (context, result) {
- context.result = result;
- return runtime.findNext(callCmd, context);
- }
- };
- return callCmd
- }
- _parser.addCommand("call", function(parser, runtime, tokens) {
- if (tokens.matchToken('call')) {
- var call = parseCallOrGet(parser, runtime, tokens);
- if (call.expr && call.expr.type !== "functionCall") {
- parser.raiseParseError(tokens, "Must be a function invocation");
- }
- return call;
- }
- })
- _parser.addCommand("get", function(parser, runtime, tokens) {
- if (tokens.matchToken('get')) {
- return parseCallOrGet(parser, runtime, tokens);
- }
- })
-
- _parser.addGrammarElement("pseudoCommand", function(parser, runtime, tokens) {
- var expr = parser.requireElement("primaryExpression", tokens);
- if (expr.type !== 'functionCall' && expr.root.type !== "symbol") {
- parser.raiseParseError("Implicit function calls must start with a simple function", tokens);
- }
- // optional "with"
- if (!tokens.matchToken("with") && parser.commandBoundary(tokens.currentToken())) {
- var target = parser.requireElement("implicitMeTarget", tokens);
- } else {
- var target = parser.requireElement("expression", tokens);
- }
- var functionName = expr.root.name;
- var functionArgs = expr.argExressions;
-
- var pseudoCommand = {
- type: "pseudoCommand",
- expr: expr,
- args: [target, functionArgs],
- op: function (context, target, args) {
- var func = target[functionName];
- if (func.hyperfunc) {
- args.push(context);
- }
- var result = func.apply(target, args);
- context.result = result;
- return runtime.findNext(pseudoCommand, context);
- },
- execute : function (context) {
- return runtime.unifiedExec(this, context);
- }
- };
-
- return pseudoCommand;
- })
-
- _parser.addCommand("set", function(parser, runtime, tokens) {
- if (tokens.matchToken('set')) {
- var target = parser.requireElement("target", tokens);
-
- tokens.requireToken("to");
-
- var value = parser.requireElement("expression", tokens);
-
- var symbolWrite = target.type === "symbol";
- if (target.type !== "symbol" && target.root == null) {
- parser.raiseParseError(tokens, "Can only put directly into symbols, not references")
- }
-
- var root = null;
- var prop = null;
- if (symbolWrite) {
- // root is null
- } else {
- prop = target.prop.value;
- root = target.root;
- }
-
- var setCmd = {
- target: target,
- symbolWrite: symbolWrite,
- value: value,
- args: [root, value],
- op: function (context, root, valueToSet) {
- if (symbolWrite) {
- context[target.name] = valueToSet;
- } else {
- runtime.forEach(root, function (elt) {
- elt[prop] = valueToSet;
- })
- }
- return runtime.findNext(this, context);
- }
- };
- return setCmd
- }
- })
-
- _parser.addCommand("if", function(parser, runtime, tokens) {
- if (tokens.matchToken('if')) {
- var expr = parser.requireElement("expression", tokens);
- tokens.matchToken("then"); // optional 'then'
- var trueBranch = parser.parseElement("commandList", tokens);
- if (tokens.matchToken("else")) {
- var falseBranch = parser.parseElement("commandList", tokens);
- }
- if (tokens.hasMore()) {
- tokens.requireToken("end");
- }
- var ifCmd = {
- expr: expr,
- trueBranch: trueBranch,
- falseBranch: falseBranch,
- args: [expr],
- op: function (context, expr) {
- if (expr) {
- return trueBranch;
- } else if (falseBranch) {
- return falseBranch;
- } else {
- return runtime.findNext(this, context);
- }
- }
- };
- parser.setParent(trueBranch, ifCmd);
- parser.setParent(falseBranch, ifCmd);
- return ifCmd
- }
- })
-
- var parseRepeatExpression = function(parser, tokens, runtime, startedWithForToken) {
- var innerStartToken = tokens.currentToken();
- if (tokens.matchToken("for") || startedWithForToken) {
- var identifierToken = tokens.requireTokenType('IDENTIFIER');
- var identifier = identifierToken.value;
- tokens.requireToken("in");
- var expression = parser.requireElement("expression", tokens);
- } else if (tokens.matchToken("in")) {
- var identifier = "it";
- var expression = parser.requireElement("expression", tokens);
- } else if (tokens.matchToken("while")) {
- var whileExpr = parser.requireElement("expression", tokens);
- } else if (tokens.matchToken("until")) {
- var isUntil = true;
- if (tokens.matchToken("event")) {
- var evt = _parser.requireElement("dotOrColonPath", tokens, "Expected event name");
- if (tokens.matchToken("from")) {
- var on = parser.requireElement("expression", tokens);
- }
- } else {
- var whileExpr = parser.requireElement("expression", tokens);
- }
- } else if (tokens.matchTokenType('NUMBER')) {
- var times = parseFloat(innerStartToken.value);
- tokens.requireToken('times');
- } else {
- tokens.matchToken("forever"); // consume optional forever
- var forever = true;
- }
-
- if (tokens.matchToken("index")) {
- var identifierToken = tokens.requireTokenType('IDENTIFIER');
- var indexIdentifier = identifierToken.value
- }
-
- var loop = parser.parseElement("commandList", tokens);
- if (tokens.hasMore()) {
- tokens.requireToken("end");
- }
-
- if (identifier == null) {
- identifier = "_implicit_repeat_" + innerStartToken.start;
- var slot = identifier;
- } else {
- var slot = identifier + "_" + innerStartToken.start;
- }
-
- var repeatCmd = {
- identifier: identifier,
- indexIdentifier: indexIdentifier,
- slot: slot,
- expression: expression,
- forever: forever,
- times: times,
- until: isUntil,
- event: evt,
- on: on,
- whileExpr: whileExpr,
- resolveNext: function () {
- return this;
- },
- loop: loop,
- args: [whileExpr],
- op: function (context, whileValue) {
- var iterator = context.meta.iterators[slot];
- var keepLooping = false;
- if (this.forever) {
- keepLooping = true;
- } else if (this.until) {
- if (evt) {
- keepLooping = context.meta.iterators[slot].eventFired === false;
- } else {
- keepLooping = whileValue !== true;
- }
- } else if (whileValue) {
- keepLooping = true;
- } else if (times) {
- keepLooping = iterator.index < this.times;
- } else {
- keepLooping = iterator.value !== null && iterator.index < iterator.value.length
- }
-
- if (keepLooping) {
- if (iterator.value) {
- context[identifier] = iterator.value[iterator.index];
- context.result = iterator.value[iterator.index];
- } else {
- context.result = iterator.index;
- }
- if (indexIdentifier) {
- context[indexIdentifier] = iterator.index;
- }
- iterator.index++;
- return loop;
- } else {
- context.meta.iterators[slot] = null;
- return runtime.findNext(this.parent, context);
- }
- }
- };
- parser.setParent(loop, repeatCmd);
- var repeatInit = {
- name: "repeatInit",
- args: [expression, evt, on],
- op: function (context, value, event, on) {
- context.meta.iterators[slot] = {
- index: 0,
- value: value,
- eventFired: false
- };
- if (evt) {
- var target = on || context.me;
- target.addEventListener(event, function (e) {
- context.meta.iterators[slot].eventFired = true;
- }, {once: true});
- }
- return repeatCmd; // continue to loop
- },
- execute: function (context) {
- return runtime.unifiedExec(this, context);
- }
- }
- parser.setParent(repeatCmd, repeatInit);
- return repeatInit
- }
-
- _parser.addCommand("repeat", function(parser, runtime, tokens) {
- if (tokens.matchToken('repeat')) {
- return parseRepeatExpression(parser, tokens, runtime,false);
- }
- })
-
- _parser.addCommand("for", function(parser, runtime, tokens) {
- if (tokens.matchToken('for')) {
- return parseRepeatExpression(parser, tokens, runtime, true);
- }
- })
-
-
- _parser.addGrammarElement("stringLike", function(parser, runtime, tokens) {
- return _parser.parseAnyOf(["string", "nakedString"], tokens);
- });
-
- _parser.addCommand("fetch", function(parser, runtime, tokens) {
- if (tokens.matchToken('fetch')) {
-
-
- var url = parser.requireElement("stringLike", tokens);
- var args = parser.parseElement("objectLiteral", tokens);
-
- var type = "text";
- if (tokens.matchToken("as")) {
- if (tokens.matchToken("json")) {
- type = "json";
- } else if (tokens.matchToken("response")) {
- type = "response";
- } else if (tokens.matchToken("text")) {
- } else {
- parser.raiseParseError(tokens, "Unknown response type: " + tokens.currentToken());
- }
- }
-
- var fetchCmd = {
- url:url,
- argExrepssions:args,
- args: [url, args],
- op: function (context, url, args) {
- return new Promise(function (resolve, reject) {
- fetch(url, args)
- .then(function (value) {
- if (type === "response") {
- context.result = value;
- resolve(runtime.findNext(fetchCmd, context));
- } else if (type === "json") {
- value.json().then(function (result) {
- context.result = result;
- resolve(runtime.findNext(fetchCmd, context));
- })
- } else {
- value.text().then(function (result) {
- context.result = result;
- resolve(runtime.findNext(fetchCmd, context));
- })
- }
- })
- .catch(function (reason) {
- runtime.triggerEvent(context.me, "fetch:error", {
- reason: reason
- })
- reject(reason);
- })
- })
- }
- };
- return fetchCmd;
- }
- })
- }
-
- //====================================================================
- // Initialization
- //====================================================================
- function ready(fn) {
- if (document.readyState !== 'loading') {
- fn();
- } else {
- document.addEventListener('DOMContentLoaded', fn);
- }
- }
-
- function getMetaConfig() {
- var element = document.querySelector('meta[name="htmx-config"]');
- if (element) {
- return parseJSON(element.content);
- } else {
- return null;
- }
- }
-
- function mergeMetaConfig() {
- var metaConfig = getMetaConfig();
- if (metaConfig) {
- _hyperscript.config = mergeObjects(_hyperscript.config , metaConfig)
- }
- }
-
- if ('document' in globalScope) {
- ready(function () {
- mergeMetaConfig();
- _runtime.processNode(document.body);
- document.addEventListener("htmx:load", function(evt){
- _runtime.processNode(evt.detail.elt);
- })
- })
- }
-
- //====================================================================
- // API
- //====================================================================
- return mergeObjects(function (str, ctx) {
- return _runtime.evaluate(str, ctx); //OK
- }, {
- internals: {
- lexer: _lexer,
- parser: _parser,
- runtime: _runtime,
- },
- addFeature: function (keyword, definition) {
- _parser.addFeature(keyword, definition)
- },
- addCommand: function (keyword, definition) {
- _parser.addCommand(keyword, definition)
- },
- addLeafExpression: function (keyword, definition) {
- _parser.addLeafExpression(definition)
- },
- addIndirectExpression: function (keyword, definition) {
- _parser.addIndirectExpression(definition)
- },
- evaluate: function (str, ctx) { //OK
- return _runtime.evaluate(str, ctx); //OK
- },
- processNode: function (elt) {
- _runtime.processNode(elt);
- },
- config: {
- attributes: "_, script, data-script",
- defaultTransition: "all 500ms ease-in",
- conversions: CONVERSIONS
- }
- }
- )
- }
- )()
-}));
-///=========================================================================
-/// This module provides the core web functionality for hyperscript
-///=========================================================================
-(function(){
-
- function mergeObjects(obj1, obj2) {
- for (var key in obj2) {
- if (obj2.hasOwnProperty(key)) {
- obj1[key] = obj2[key];
- }
- }
- return obj1;
- }
-
- _hyperscript.addCommand("settle", function(parser, runtime, tokens) {
- if (tokens.matchToken("settle")) {
-
- if (!parser.commandBoundary(tokens.currentToken())) {
- var on = parser.requireElement("expression", tokens);
- } else {
- var on = parser.requireElement("implicitMeTarget");
- }
-
- var settleCommand = {
- type: "settleCmd",
- args: [on],
- op: function (context, on) {
- var resolve = null;
- var resolved = false;
- var transitionStarted = false;
-
- var promise = new Promise(function (r) {
- resolve = r;
- });
-
- // listen for a transition begin
- on.addEventListener('transitionstart', function () {
- transitionStarted = true;
- }, {once: true});
-
- // if no transition begins in 500ms, cancel
- setTimeout(function () {
- if (!transitionStarted && !resolved) {
- resolve(runtime.findNext(settleCommand, context));
- }
- }, 500);
-
- // continue on a transition emd
- on.addEventListener('transitionend', function () {
- if (!resolved) {
- resolve(runtime.findNext(settleCommand, context));
- }
- }, {once: true});
- return promise;
-
- },
- execute: function (context) {
- return runtime.unifiedExec(this, context);
- }
- };
- return settleCommand
- }
- })
-
- _hyperscript.addCommand("add", function(parser, runtime, tokens) {
- if (tokens.matchToken("add")) {
- var classRef = parser.parseElement("classRef", tokens);
- var attributeRef = null;
- if (classRef == null) {
- attributeRef = parser.parseElement("attributeRef", tokens);
- if (attributeRef == null) {
- parser.raiseParseError(tokens, "Expected either a class reference or attribute expression")
- }
- }
-
- if (tokens.matchToken("to")) {
- var to = parser.requireElement("target", tokens);
- } else {
- var to = parser.parseElement("implicitMeTarget");
- }
-
- if (classRef) {
- var addCmd = {
- classRef: classRef,
- attributeRef: attributeRef,
- to: to,
- args: [to],
- op: function (context, to) {
- runtime.forEach(to, function (target) {
- target.classList.add(classRef.className());
- })
- return runtime.findNext(this, context);
- }
- }
- } else {
- var addCmd = {
- type: "addCmd",
- classRef: classRef,
- attributeRef: attributeRef,
- to: to,
- args: [to, attributeRef],
- op: function (context, to, attrRef) {
- runtime.forEach(to, function (target) {
- target.setAttribute(attrRef.name, attrRef.value);
- })
- return runtime.findNext(addCmd, context);
- },
- execute: function (ctx) {
- return runtime.unifiedExec(this, ctx);
- }
- };
- }
- return addCmd
- }
- });
-
- _hyperscript.addCommand("remove", function(parser, runtime, tokens) {
- if (tokens.matchToken('remove')) {
- var classRef = parser.parseElement("classRef", tokens);
- var attributeRef = null;
- var elementExpr = null;
- if (classRef == null) {
- attributeRef = parser.parseElement("attributeRef", tokens);
- if (attributeRef == null) {
- elementExpr = parser.parseElement("expression", tokens)
- if (elementExpr == null) {
- parser.raiseParseError(tokens, "Expected either a class reference, attribute expression or value expression");
- }
- }
- }
- if (tokens.matchToken("from")) {
- var from = parser.requireElement("target", tokens);
- } else {
- var from = parser.requireElement("implicitMeTarget");
- }
-
- if (elementExpr) {
- var removeCmd = {
- classRef: classRef,
- attributeRef: attributeRef,
- elementExpr: elementExpr,
- from: from,
- args: [elementExpr],
- op: function (context, element) {
- runtime.forEach(element, function (target) {
- target.parentElement.removeChild(target);
- })
- return runtime.findNext(this, context);
- }
- };
- } else {
- var removeCmd = {
- classRef: classRef,
- attributeRef: attributeRef,
- elementExpr: elementExpr,
- from: from,
- args: [from],
- op: function (context, from) {
- if (this.classRef) {
- runtime.forEach(from, function (target) {
- target.classList.remove(classRef.className());
- })
- } else {
- runtime.forEach(from, function (target) {
- target.removeAttribute(attributeRef.name);
- })
- }
- return runtime.findNext(this, context);
- }
- };
-
- }
- return removeCmd
- }
- });
-
- _hyperscript.addCommand("toggle", function(parser, runtime, tokens) {
- if (tokens.matchToken('toggle')) {
-
- if (tokens.matchToken('between')) {
- var between = true;
- var classRef = parser.parseElement("classRef", tokens);
- tokens.requireToken("and");
- var classRef2 = parser.requireElement("classRef", tokens);
- } else {
- var classRef = parser.parseElement("classRef", tokens);
- var attributeRef = null;
- if (classRef == null) {
- attributeRef = parser.parseElement("attributeRef", tokens);
- if (attributeRef == null) {
- parser.raiseParseError(tokens, "Expected either a class reference or attribute expression")
- }
- }
- }
-
- if (tokens.matchToken("on")) {
- var on = parser.requireElement("target", tokens);
- } else {
- var on = parser.requireElement("implicitMeTarget");
- }
-
- if (tokens.matchToken("for")) {
- var time = parser.requireElement("timeExpression", tokens);
- } else if (tokens.matchToken("until")) {
- var evt = parser.requireElement("dotOrColonPath", tokens, "Expected event name");
- if (tokens.matchToken("from")) {
- var from = parser.requireElement("expression", tokens);
- }
- }
-
- var toggleCmd = {
- classRef: classRef,
- classRef2: classRef2,
- attributeRef: attributeRef,
- on: on,
- time: time,
- evt: evt,
- from: from,
- toggle: function (on, value) {
- if (this.classRef) {
- if (between) {
- runtime.forEach(on, function (target) {
- if (target.classList.contains(classRef.className())) {
- target.classList.remove(classRef.className());
- target.classList.add(classRef2.className());
- } else {
- target.classList.add(classRef.className());
- target.classList.remove(classRef2.className());
- }
- });
- } else {
- runtime.forEach(on, function (target) {
- target.classList.toggle(classRef.className())
- });
- }
- } else {
- runtime.forEach(on, function (target) {
- if (target.hasAttribute(attributeRef.name)) {
- target.removeAttribute(attributeRef.name);
- } else {
- target.setAttribute(attributeRef.name, value)
- }
- });
- }
- },
- args: [on, attributeRef ? attributeRef.value : null, time, evt, from],
- op: function (context, on, value, time, evt, from) {
- if (time) {
- return new Promise(function (resolve) {
- toggleCmd.toggle(on, value);
- setTimeout(function () {
- toggleCmd.toggle(on, value);
- resolve(runtime.findNext(toggleCmd, context));
- }, time);
- });
- } else if (evt) {
- return new Promise(function (resolve) {
- var target = from || context.me;
- target.addEventListener(evt, function () {
- toggleCmd.toggle(on, value);
- resolve(runtime.findNext(toggleCmd, context));
- }, {once: true})
- toggleCmd.toggle(on, value);
- });
- } else {
- this.toggle(on, value);
- return runtime.findNext(toggleCmd, context);
- }
- }
- };
- return toggleCmd
- }
- })
-
- var HIDE_SHOW_STRATEGIES = {
- "display": function (op, element, arg) {
- if(arg){
- element.style.display = arg;
- } else if (op === 'hide') {
- element.style.display = 'none';
- } else {
- element.style.display = 'block';
- }
- },
- "visibility": function (op, element, arg) {
- if(arg){
- element.style.visibility = arg;
- } else if (op === 'hide') {
- element.style.visibility = 'hidden';
- } else {
- element.style.visibility = 'visible';
- }
- },
- "opacity": function (op, element, arg) {
- if(arg){
- element.style.opacity = arg;
- } else if (op === 'hide') {
- element.style.opacity = '0';
- } else {
- element.style.opacity = '1';
- }
- }
- }
-
- var parseShowHideTarget = function (parser, runtime, tokens) {
- var target;
- var currentTokenValue = tokens.currentToken();
- if (currentTokenValue.value === "with" || parser.commandBoundary(currentTokenValue)) {
- target = parser.parseElement("implicitMeTarget", tokens);
- } else {
- target = parser.parseElement("target", tokens);
- }
- return target;
- }
-
- var resolveStrategy = function (parser, tokens, name) {
- var configDefault = _hyperscript.config.defaultHideShowStrategy;
- var strategies = HIDE_SHOW_STRATEGIES;
- if (_hyperscript.config.hideShowStrategies) {
- strategies = mergeObjects(strategies, _hyperscript.config.hideShowStrategies); // merge in user provided strategies
- }
- name = name || configDefault || "display";
- var value = strategies[name];
- if (value == null) {
- parser.raiseParseError(tokens, 'Unknown show/hide strategy : ' + name);
- }
- return value;
- }
-
- _hyperscript.addCommand("hide", function (parser, runtime, tokens) {
- if (tokens.matchToken("hide")) {
- var target = parseShowHideTarget(parser, runtime, tokens);
-
- var name = null;
- if (tokens.matchToken("with")) {
- name = tokens.requireTokenType("IDENTIFIER").value;
- }
- var hideShowStrategy = resolveStrategy(parser, tokens, name);
-
- return {
- target: target,
- args: [target],
- op: function (ctx, target) {
- runtime.forEach(target, function (elt) {
- hideShowStrategy('hide', elt);
- });
- return runtime.findNext(this, ctx);
- }
- }
- }
- });
-
- _hyperscript.addCommand("show", function (parser, runtime, tokens) {
- if (tokens.matchToken("show")) {
- var target = parseShowHideTarget(parser, runtime, tokens);
-
- var name = null;
- if (tokens.matchToken("with")) {
- name = tokens.requireTokenType("IDENTIFIER").value;
- }
- var arg = null;
- if (tokens.matchOpToken(":")) {
- var tokenArr = tokens.consumeUntilWhitespace();
- tokens.matchTokenType("WHITESPACE");
- arg = tokenArr.map(function (t) {
- return t.value
- }).join("");
- }
- var hideShowStrategy = resolveStrategy(parser, tokens, name);
-
- return {
- target: target,
- args: [target],
- op: function (ctx, target) {
- runtime.forEach(target, function (elt) {
- hideShowStrategy('show', elt, arg);
- });
- return runtime.findNext(this, ctx);
- }
- }
- }
- });
-
- _hyperscript.addCommand("trigger", function(parser, runtime, tokens) {
- if (tokens.matchToken('trigger')) {
- var eventName = parser.requireElement("dotOrColonPath", tokens);
- var details = parser.parseElement("namedArgumentList", tokens);
-
- var triggerCmd = {
- eventName: eventName,
- details: details,
- args: [eventName, details],
- op: function (context, eventNameStr, details) {
- runtime.triggerEvent(context.me, eventNameStr, details ? details : {});
- return runtime.findNext(triggerCmd, context);
- }
- };
- return triggerCmd
- }
- })
-
- _hyperscript.addCommand("take", function(parser, runtime, tokens) {
- if (tokens.matchToken('take')) {
- var classRef = tokens.requireTokenType(tokens, "CLASS_REF");
-
- if (tokens.matchToken("from")) {
- var from = parser.requireElement("target", tokens);
- } else {
- var from = parser.requireElement("implicitAllTarget")
- }
-
- if (tokens.matchToken("for")) {
- var forElt = parser.requireElement("target", tokens);
- } else {
- var forElt = parser.requireElement("implicitMeTarget")
- }
-
- var takeCmd = {
- classRef: classRef,
- from: from,
- forElt: forElt,
- args: [from, forElt],
- op: function (context, from, forElt) {
- var clazz = this.classRef.value.substr(1)
- runtime.forEach(from, function (target) {
- target.classList.remove(clazz);
- })
- runtime.forEach(forElt, function (target) {
- target.classList.add(clazz);
- });
- return runtime.findNext(this, context);
- }
- };
- return takeCmd
- }
- })
-
- function putInto(context, prop, valueToPut){
- if (prop) {
- var value = context[prop];
- } else {
- var value = context;
- }
- if (value instanceof Element || value instanceof HTMLDocument) {
- value.innerHTML = valueToPut;
- } else {
- if (prop) {
- context[prop] = valueToPut;
- } else {
- throw "Don't know how to put a value into " + typeof context;
- }
- }
- }
-
- _hyperscript.addCommand("put", function(parser, runtime, tokens) {
- if (tokens.matchToken('put')) {
- var value = parser.requireElement("expression", tokens);
-
- var operationToken = tokens.matchToken("into") ||
- tokens.matchToken("before") ||
- tokens.matchToken("after");
-
- if (operationToken == null && tokens.matchToken("at")) {
- operationToken = tokens.matchToken("start") ||
- tokens.matchToken("end");
- tokens.requireToken("of");
- }
-
- if (operationToken == null) {
- parser.raiseParseError(tokens, "Expected one of 'into', 'before', 'at start of', 'at end of', 'after'");
- }
- var target = parser.requireElement("target", tokens);
-
- var operation = operationToken.value;
-
- var symbolWrite = false;
- var root = null;
- var prop = null;
- if (target.type === "propertyAccess" && operation === "into") {
- prop = target.prop.value;
- root = target.root;
- } else if(target.type === "symbol" && operation === "into") {
- symbolWrite = true;
- prop = target.name;
- } else {
- root = target;
- }
-
- var putCmd = {
- target: target,
- operation: operation,
- symbolWrite: symbolWrite,
- value: value,
- args: [root, value],
- op: function (context, root, valueToPut) {
- if (symbolWrite) {
- putInto(context, prop, valueToPut);
- context[target.name] = valueToPut;
- } else {
- if (operation === "into") {
- runtime.forEach(root, function (elt) {
- putInto(elt, prop, valueToPut);
- })
- } else if (operation === "before") {
- runtime.forEach(root, function (elt) {
- elt.insertAdjacentHTML('beforebegin', valueToPut);
- })
- } else if (operation === "start") {
- runtime.forEach(root, function (elt) {
- elt.insertAdjacentHTML('afterbegin', valueToPut);
- })
- } else if (operation === "end") {
- runtime.forEach(root, function (elt) {
- elt.insertAdjacentHTML('beforeend', valueToPut);
- })
- } else if (operation === "after") {
- runtime.forEach(root, function (elt) {
- elt.insertAdjacentHTML('afterend', valueToPut);
- })
- }
- }
- return runtime.findNext(this, context);
- }
- };
- return putCmd
- }
- })
-
- _hyperscript.addCommand("transition", function(parser, runtime, tokens) {
- if (tokens.matchToken("transition")) {
- if (tokens.matchToken('element') || tokens.matchToken('elements')) {
- var targets = parser.parseElement("expression", tokens);
- } else {
- var targets = parser.parseElement("implicitMeTarget");
- }
- var properties = [];
- var from = [];
- var to = [];
- var currentToken = tokens.currentToken();
- while (!parser.commandBoundary(currentToken) && currentToken.value !== "using") {
- properties.push(tokens.requireTokenType("IDENTIFIER").value);
- if (tokens.matchToken("from")) {
- from.push(parser.requireElement("stringLike", tokens));
- } else {
- from.push(null);
- }
- tokens.requireToken("to");
- to.push(parser.requireElement("stringLike", tokens));
- currentToken = tokens.currentToken();
- }
- if (tokens.matchToken("using")) {
- var using = parser.requireElement("expression", tokens);
- }
-
- var transition = {
- to: to,
- args: [targets, from, to, using],
- op: function (context, targets, from, to, using) {
- var promises = [];
- runtime.forEach(targets, function(target){
- var promise = new Promise(function (resolve, reject) {
- var initialTransition = target.style.transition;
- target.style.transition = using || _hyperscript.config.defaultTransition;
- var internalData = runtime.getInternalData(target);
- var computedStyles = getComputedStyle(target);
-
- var initialStyles = {};
- for (var i = 0; i < computedStyles.length; i++) {
- var name = computedStyles[i];
- var initialValue = computedStyles[name];
- initialStyles[name] = initialValue;
- }
-
- // store intitial values
- if (!internalData.initalStyles) {
- internalData.initalStyles = initialStyles;
- }
-
- for (var i = 0; i < properties.length; i++) {
- var property = properties[i];
- var fromVal = from[i];
- if (fromVal == 'computed' || fromVal == null) {
- target.style[property] = initialStyles[property];
- } else {
- target.style[property] = fromVal;
- }
- }
- // console.log("transition started", transition);
- setTimeout(function () {
- var autoProps = [];
- for (var i = 0; i < properties.length; i++) {
- var property = properties[i];
- var toVal = to[i];
- if (toVal == 'initial') {
- var propertyValue = internalData.initalStyles[property];
- target.style[property] = propertyValue;
- } else {
- target.style[property] = toVal;
- }
- // console.log("set", property, "to", target.style[property], "on", target, "value passed in : ", toVal);
- }
- target.addEventListener('transitionend', function () {
- // console.log("transition ended", transition);
- target.style.transition = initialTransition;
- resolve();
- }, {once:true})
- }, 5);
- });
- promises.push(promise);
- })
- return Promise.all(promises).then(function(){
- return runtime.findNext(transition, context);
- })
- }
- };
- return transition
- }
- });
-
-})()
\ No newline at end of file
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e||self)._hyperscript=t()}(this,function(){function e(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function c(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}function f(e,t){var n=e[t];if(n)return n;var r={};return e[t]=r,r}function m(e,t){return new(e.bind.apply(e,[e].concat(t)))}var p,d=globalThis,h=function(e){function n(e,t,n){this._css=e,this.relativeToElement=t,this.escape=n}var r=n.prototype;return r.contains=function(e){for(var t,n=l(this);!(t=n()).done;)if(t.value.contains(e))return!0;return!1},r[e]=function(){return this.selectMatches()[Symbol.iterator]()},r.selectMatches=function(){return T.getRootNode(this.relativeToElement).querySelectorAll(this.css)},t(n,[{key:"css",get:function(){return this.escape?T.escapeSelector(this._css):this._css}},{key:"className",get:function(){return this._css.substr(1)}},{key:"id",get:function(){return this.className()}},{key:"length",get:function(){return this.selectMatches().length}}]),n}(Symbol.iterator),v=function(){var e={"+":"PLUS","-":"MINUS","*":"MULTIPLY","/":"DIVIDE",".":"PERIOD","..":"ELLIPSIS","\\":"BACKSLASH",":":"COLON","%":"PERCENT","|":"PIPE","!":"EXCLAMATION","?":"QUESTION","#":"POUND","&":"AMPERSAND",$:"DOLLAR",";":"SEMI",",":"COMMA","(":"L_PAREN",")":"R_PAREN","<":"L_ANG",">":"R_ANG","<=":"LTE_ANG",">=":"GTE_ANG","==":"EQ","===":"EQQ","!=":"NEQ","!==":"NEQQ","{":"L_BRACE","}":"R_BRACE","[":"L_BRACKET","]":"R_BRACKET","=":"EQUALS"};function t(e){return a(e)||i(e)||"-"===e||"_"===e||":"===e}function n(e){return a(e)||i(e)||"-"===e||"_"===e||":"===e}function r(e){return" "===e||"\t"===e||o(e)}function o(e){return"\r"===e||"\n"===e}function i(e){return e>="0"&&e<="9"}function a(e){return e>="a"&&e<="z"||e>="A"&&e<="Z"}function u(e,t){return"_"===e||"$"===e}function s(e,t,n){o();var r=null;function o(){for(;"WHITESPACE"===f(0,!0).type;)t.push(e.shift())}function i(e,t){y.raiseParseError(e,t)}function a(e){if(m()&&m().op&&m().value===e)return l()}function u(e,t,n,r){if(m()&&m().type&&[e,t,n,r].indexOf(m().type)>=0)return l()}function s(e,t){if(-1===p.indexOf(e))return t=t||"IDENTIFIER",m()&&m().value===e&&m().type===t?l():void 0}function l(){var n=e.shift();return t.push(n),r=n,o(),n}function c(n,r){for(var i=[],a=f(0,!0);!(null!=r&&a.type===r||null!=n&&a.value===n||"EOF"===a.type);){var u=e.shift();t.push(u),i.push(a),a=f(0,!0)}return o(),i}function f(t,n){var r,o=0;do{if(!n)for(;e[o]&&"WHITESPACE"===e[o].type;)o++;r=e[o],t--,o++}while(t>-1);return r||{type:"EOF",value:"<<>>"}}function m(){return f(0)}var p=[];return{pushFollow:function(e){p.push(e)},popFollow:function(){p.pop()},clearFollow:function(){var e=p;return p=[],e},restoreFollow:function(e){p=e},matchAnyToken:function(e,t,n){for(var r=0;r0},currentToken:m,lastMatch:function(){return r},token:f,consumeUntil:c,consumeUntilWhitespace:function(){return c(null,"WHITESPACE")},lastWhitespace:function(){return t[t.length-1]&&"WHITESPACE"===t[t.length-1].type?t[t.length-1].value:""},sourceFor:function(){return n.substring(this.startToken.start,this.endToken.end)},lineFor:function(){return n.split("\n")[this.startToken.line-1]}}}function l(e){if(e.length>0){var t=e[e.length-1];if("IDENTIFIER"===t.type||"CLASS_REF"===t.type||"ID_REF"===t.type)return!1;if(t.op&&(">"===t.value||")"===t.value))return!1}return!0}return{tokenize:function(c,f){var m,p=[],d=c,h=0,v=0,y=1,E="",T=0;function k(){return f&&0===T}for(;h0;){var i=t.shift(),a=o[i];null==a&&(o[i]=a={}),o=a}o[n]=r},registerHyperTrace:function(e,t){for(var n=[],r=null;null!=e;)n.push(e),r=e,e=e.meta.caller;null==r.meta.traceMap&&(r.meta.traceMap=new Map),r.meta.traceMap.get(t)||r.meta.traceMap.set(t,{trace:n,print:function(e){(e=e||console.error)("hypertrace /// ");for(var t=0,r=0;r",o.meta.feature.displayName.padEnd(t+2),"-",o.meta.owner)}}})},getHyperTrace:function(e,t){for(var n=e;n.meta.caller;)n=n.meta.caller;if(n.meta.traceMap)return n.meta.traceMap.get(t,[])},getInternalData:O,getHyperscriptFeatures:w,escapeSelector:function(e){return e.replace(/:/g,function(e){return"\\"+e})},nullCheck:function(e,t){if(null==e)throw new Error("'"+t.sourceFor()+"' is null")},isEmpty:function(e){return null==e||0===e.length},doesExist:function(e){if(null==e)return!1;if(o(e))for(var t=l(e);!t().done;)return!0;return!1},getRootNode:function(e){if(e&&e instanceof Node){var t=e.getRootNode();if(t instanceof Document||t instanceof ShadowRoot)return t}return document},getEventQueueFor:function(e,t){var n=O(e),r=n.eventQueues;null==r&&(r=new Map,n.eventQueues=r);var o=r.get(t);return null==o&&r.set(t,o={queue:[],executing:!1}),o},hyperscriptUrl:"document"in d?"undefined"==typeof document&&"undefined"==typeof location?new(require("url").URL)("file:"+__filename).href:"undefined"==typeof document?location.href:document.currentScript&&document.currentScript.src||new URL("_hyperscript_w9y.min.js",document.baseURI).href:null,HALT:s}}(),k=function(e,t,n){if(t.contains)return t.contains(n);if(t.includes)return t.includes(n);throw Error("The value of "+e.sourceFor()+" does not have a contains or includes method on it")},g=function(e,t,n){if(t.match)return!!t.match(n);if(t.matches)return t.matches(n);throw Error("The value of "+e.sourceFor()+" does not have a match or matches method on it")},x=function(e,t,n,r){var o=t.requireElement("eventName",r),i=t.parseElement("namedArgumentList",r);if("send"===e&&r.matchToken("to")||"trigger"===e&&r.matchToken("on"))var a=t.requireElement("expression",r);else a=t.requireElement("implicitMeTarget",r);var u={eventName:o,details:i,to:a,args:[a,o,i],op:function(e,t,r,o){return n.nullCheck(t,a),n.forEach(t,function(t){n.triggerEvent(t,r,o,e.me)}),n.findNext(u,e)}};return u},b=function(e,t){var n,r="text";return e.matchToken("a")||e.matchToken("an"),e.matchToken("json")||e.matchToken("Object")?r="json":e.matchToken("response")?r="response":e.matchToken("html")?r="html":e.matchToken("text")||(n=t.requireElement("dotOrColonPath",e).evaluate()),{type:r,conversion:n}};y.addLeafExpression("parenthesized",function(e,t,n){if(n.matchOpToken("(")){var r=n.clearFollow();try{var o=e.requireElement("expression",n)}finally{n.restoreFollow(r)}return n.requireOpToken(")"),o}}),y.addLeafExpression("string",function(e,t,n){var r=n.matchTokenType("STRING");if(r){var o,i=r.value;if(r.template){var a=v.tokenize(i,!0);o=e.parseStringTemplate(a)}else o=[];return{type:"string",token:r,args:o,op:function(e){for(var t="",n=1;n");var o=r.map(function(e){return"STRING"===e.type?'"'+e.value+'"':e.value}).join("");if(o.indexOf("$")>=0)var i=!0,a=v.tokenize(o,!0),u=e.parseStringTemplate(a);return{type:"queryRef",css:o,args:u,op:function(e){return i?new w(o,e.me,[].slice.call(arguments,1)):new h(o,e.me)},evaluate:function(e){return t.unifiedEval(this,e)}}}}),y.addLeafExpression("attributeRef",function(e,t,n){var r=n.matchTokenType("ATTRIBUTE_REF");if(r){var o=r.value;if(0===o.indexOf("["))var i=o.substring(2,o.length-1);else i=o.substring(1);var a="["+i+"]",u=i.split("="),s=u[0],l=u[1];return l&&0===l.indexOf('"')&&(l=l.substring(1,l.length-1)),{type:"attributeRef",name:s,css:a,value:l,op:function(e){var t=e.beingTold||e.me;if(t)return t.getAttribute(s)},evaluate:function(e){return t.unifiedEval(this,e)}}}}),y.addLeafExpression("styleRef",function(e,t,n){var r=n.matchTokenType("STYLE_REF");if(r){var o=r.value.substr(1);return o.startsWith("computed-")?{type:"computedStyleRef",name:o=o.substr("computed-".length),op:function(e){var n=e.beingTold||e.me;if(n)return t.resolveComputedStyle(n,o)},evaluate:function(e){return t.unifiedEval(this,e)}}:{type:"styleRef",name:o,op:function(e){var n=e.beingTold||e.me;if(n)return t.resolveStyle(n,o)},evaluate:function(e){return t.unifiedEval(this,e)}}}}),y.addGrammarElement("objectKey",function(e,t,n){var r;if(r=n.matchTokenType("STRING"))return{type:"objectKey",key:r.value,evaluate:function(){return r.value}};if(n.matchOpToken("[")){var o=e.parseElement("expression",n);return n.requireOpToken("]"),{type:"objectKey",expr:o,args:[o],op:function(e,t){return t},evaluate:function(e){return t.unifiedEval(this,e)}}}var i="";do{(r=n.matchTokenType("IDENTIFIER")||n.matchOpToken("-"))&&(i+=r.value)}while(r);return{type:"objectKey",key:i,evaluate:function(){return i}}}),y.addLeafExpression("objectLiteral",function(e,t,n){if(n.matchOpToken("{")){var r=[],o=[];if(!n.matchOpToken("}")){do{var i=e.requireElement("objectKey",n);n.requireOpToken(":");var a=e.requireElement("expression",n);o.push(a),r.push(i)}while(n.matchOpToken(","));n.requireOpToken("}")}return{type:"objectLiteral",args:[r,o],op:function(e,t,n){for(var r={},o=0;o");var i=e.requireElement("expression",n);return{type:"blockLiteral",args:r,expr:i,evaluate:function(e){return function(){for(var t=0;t0?o:null},evaluate:function(e){return t.unifiedEval(this,e)}};return e.parseElement("indirectExpression",n,o)}}),y.addIndirectExpression("asExpression",function(e,t,n,r){if(n.matchToken("as")){n.matchToken("a")||n.matchToken("an");var o=e.requireElement("dotOrColonPath",n).evaluate();return e.parseElement("indirectExpression",n,{type:"asExpression",root:r,args:[r],op:function(e,n){return t.convertValue(n,o)},evaluate:function(e){return t.unifiedEval(this,e)}})}}),y.addIndirectExpression("functionCall",function(e,t,n,r){if(n.matchOpToken("(")){var o=[];if(!n.matchOpToken(")")){do{o.push(e.requireElement("expression",n))}while(n.matchOpToken(","));n.requireOpToken(")")}if(r.root)var i={type:"functionCall",root:r,argExressions:o,args:[r.root,o],op:function(e,n,o){t.nullCheck(n,r.root);var i=n[r.prop.value];return t.nullCheck(i,r),i.hyperfunc&&o.push(e),i.apply(n,o)},evaluate:function(e){return t.unifiedEval(this,e)}};else i={type:"functionCall",root:r,argExressions:o,args:[r,o],op:function(e,n,o){return t.nullCheck(n,r),n.hyperfunc&&o.push(e),n.apply(null,o)},evaluate:function(e){return t.unifiedEval(this,e)}};return e.parseElement("indirectExpression",n,i)}}),y.addIndirectExpression("attributeRefAccess",function(e,t,n,r){var o=e.parseElement("attributeRef",n);if(o)return{type:"attributeRefAccess",root:r,attribute:o,args:[r],op:function(e,n){return t.resolveAttribute(n,o.name)},evaluate:function(e){return T.unifiedEval(this,e)}}}),y.addIndirectExpression("arrayIndex",function(e,t,n,r){if(n.matchOpToken("[")){var o=!1,i=!1,a=null,u=null;n.matchOpToken("..")?(o=!0,a=e.requireElement("expression",n)):(a=e.requireElement("expression",n),n.matchOpToken("..")&&(i=!0,"R_BRACKET"!==n.currentToken().type&&(u=e.parseElement("expression",n)))),n.requireOpToken("]");var s={type:"arrayIndex",root:r,firstIndex:a,secondIndex:u,args:[r,a,u],op:function(e,t,n,r){return o?t.slice(0,n+1):i?null!=r?t.slice(n,r+1):t.slice(n):t[n]},evaluate:function(e){return T.unifiedEval(this,e)}};return y.parseElement("indirectExpression",n,s)}});var q=["em","ex","cap","ch","ic","rem","lh","rlh","vw","vh","vi","vb","vmin","vmax","cm","mm","Q","pc","pt","px"];y.addGrammarElement("postfixExpression",function(e,t,n){var r=e.parseElement("primaryExpression",n),o=n.matchAnyToken.apply(n,q)||n.matchOpToken("%");if(o)return{type:"stringPostfix",postfix:o.value,args:[r],op:function(e,t){return""+t+o.value},evaluate:function(e){return t.unifiedEval(this,e)}};var i=null;if(n.matchToken("s")||n.matchToken("seconds")?i=1e3:(n.matchToken("ms")||n.matchToken("milliseconds"))&&(i=1),i)return{type:"timeExpression",time:r,factor:i,args:[r],op:function(e,t){return t*i},evaluate:function(e){return t.unifiedEval(this,e)}};if(n.matchOpToken(":")){var a=n.requireTokenType("IDENTIFIER"),u=!n.matchOpToken("!");return{type:"typeCheck",typeName:a,nullOk:u,args:[r],op:function(e,n){if(t.typeCheck(n,a.value,u))return n;throw new Error("Typecheck failed! Expected: "+a.value)},evaluate:function(e){return t.unifiedEval(this,e)}}}return r}),y.addGrammarElement("logicalNot",function(e,t,n){if(n.matchToken("not")){var r=e.requireElement("unaryExpression",n);return{type:"logicalNot",root:r,args:[r],op:function(e,t){return!t},evaluate:function(e){return t.unifiedEval(this,e)}}}}),y.addGrammarElement("noExpression",function(e,t,n){if(n.matchToken("no")){var r=e.requireElement("unaryExpression",n);return{type:"noExpression",root:r,args:[r],op:function(e,n){return t.isEmpty(n)},evaluate:function(e){return t.unifiedEval(this,e)}}}}),y.addLeafExpression("some",function(e,t,n){if(n.matchToken("some")){var r=e.requireElement("expression",n);return{type:"noExpression",root:r,args:[r],op:function(e,n){return!t.isEmpty(n)},evaluate:function(e){return t.unifiedEval(this,e)}}}}),y.addGrammarElement("negativeNumber",function(e,t,n){if(n.matchOpToken("-")){var r=e.requireElement("unaryExpression",n);return{type:"negativeNumber",root:r,args:[r],op:function(e,t){return-1*t},evaluate:function(e){return t.unifiedEval(this,e)}}}}),y.addGrammarElement("unaryExpression",function(e,t,n){return e.parseAnyOf(["logicalNot","relativePositionalExpression","positionalExpression","noExpression","negativeNumber","postfixExpression"],n)});var S=function(e,t,n,r){var o=[];T.forEach(t,function(t){(t.matches(n)||t===e)&&o.push(t)});for(var i=0;i=0;i--){var a=o[i];if(a.compareDocumentPosition(e)===Node.DOCUMENT_POSITION_FOLLOWING)return a}if(r)return o[o.length-1]}(n,i,l,c)},evaluate:function(e){return t.unifiedEval(this,e)}}}}),y.addGrammarElement("positionalExpression",function(e,t,n){var r=n.matchAnyToken("first","last","random");if(r){n.matchAnyToken("in","from","of");var o=e.requireElement("unaryExpression",n),i=r.value;return{type:"positionalExpression",rhs:o,operator:r.value,args:[o],op:function(e,t){if(t&&!Array.isArray(t)&&(t=t.children?t.children:Array.from(t)),t){if("first"===i)return t[0];if("last"===i)return t[t.length-1];if("random"===i)return t[Math.floor(Math.random()*t.length)]}},evaluate:function(e){return t.unifiedEval(this,e)}}}}),y.addGrammarElement("mathOperator",function(e,t,n){var r,o=e.parseElement("unaryExpression",n),i=null;for(r=n.matchAnyOpToken("+","-","*","/","%");r;){var a=r.value;(i=i||r).value!==a&&e.raiseParseError(n,"You must parenthesize math operations with different operators");var u=e.parseElement("unaryExpression",n);o={type:"mathOperator",lhs:o,rhs:u,operator:a,args:[o,u],op:function(e,t,n){return"+"===a?t+n:"-"===a?t-n:"*"===a?t*n:"/"===a?t/n:"%"===a?t%n:void 0},evaluate:function(e){return t.unifiedEval(this,e)}},r=n.matchAnyOpToken("+","-","*","/","%")}return o}),y.addGrammarElement("mathExpression",function(e,t,n){return e.parseAnyOf(["mathOperator","unaryExpression"],n)}),y.addGrammarElement("comparisonOperator",function(e,t,n){var r=e.parseElement("mathExpression",n),o=n.matchAnyOpToken("<",">","<=",">=","==","===","!=","!=="),i=o?o.value:null,a=!0,u=!1;if(null==i&&(n.matchToken("is")||n.matchToken("am")?n.matchToken("not")?n.matchToken("in")?i="not in":n.matchToken("a")?(i="not a",u=!0):n.matchToken("empty")?(i="not empty",a=!1):i="!=":n.matchToken("in")?i="in":n.matchToken("a")?(i="a",u=!0):n.matchToken("empty")?(i="empty",a=!1):n.matchToken("less")?(n.requireToken("than"),n.matchToken("or")?(n.requireToken("equal"),n.requireToken("to"),i="<="):i="<"):n.matchToken("greater")?(n.requireToken("than"),n.matchToken("or")?(n.requireToken("equal"),n.requireToken("to"),i=">="):i=">"):i="==":n.matchToken("exist")||n.matchToken("exists")?(i="exist",a=!1):n.matchToken("matches")||n.matchToken("match")?i="match":n.matchToken("contains")||n.matchToken("contain")?i="contain":n.matchToken("includes")||n.matchToken("include")?i="include":(n.matchToken("do")||n.matchToken("does"))&&(n.requireToken("not"),n.matchToken("matches")||n.matchToken("match")?i="not match":n.matchToken("contains")||n.matchToken("contain")?i="not contain":n.matchToken("exist")||n.matchToken("exist")?(i="not exist",a=!1):n.matchToken("include")?i="not include":e.raiseParseError(n,"Expected matches or contains"))),i){if(u)var s=n.requireTokenType("IDENTIFIER"),l=!n.matchOpToken("!");else if(a){var c=e.requireElement("mathExpression",n);"match"!==i&&"not match"!==i||(c=c.css?c.css:c)}var f=r;r={type:"comparisonOperator",operator:i,typeName:s,nullOk:l,lhs:r,rhs:c,args:[r,c],op:function(e,n,r){if("=="===i)return n==r;if("!="===i)return n!=r;if("match"===i)return null!=n&&g(f,n,r);if("not match"===i)return null==n||!g(f,n,r);if("in"===i)return null!=r&&k(c,r,n);if("not in"===i)return null==r||!k(c,r,n);if("contain"===i)return null!=n&&k(f,n,r);if("not contain"===i)return null==n||!k(f,n,r);if("include"===i)return null!=n&&k(f,n,r);if("not include"===i)return null==n||!k(f,n,r);if("==="===i)return n===r;if("!=="===i)return n!==r;if("<"===i)return n"===i)return n>r;if("<="===i)return n<=r;if(">="===i)return n>=r;if("empty"===i)return t.isEmpty(n);if("not empty"===i)return!t.isEmpty(n);if("exist"===i)return t.doesExist(n);if("not exist"===i)return!t.doesExist(n);if("a"===i)return t.typeCheck(n,s.value,l);if("not a"===i)return!t.typeCheck(n,s.value,l);throw"Unknown comparison : "+i},evaluate:function(e){return t.unifiedEval(this,e)}}}return r}),y.addGrammarElement("comparisonExpression",function(e,t,n){return e.parseAnyOf(["comparisonOperator","mathExpression"],n)}),y.addGrammarElement("logicalOperator",function(e,t,n){var r,o=e.parseElement("comparisonExpression",n),i=null;r=n.matchToken("and")||n.matchToken("or");for(var a=function(){(i=i||r).value!==r.value&&e.raiseParseError(n,"You must parenthesize logical operations with different operators"),u=e.requireElement("comparisonExpression",n);var a=r.value;o={type:"logicalOperator",operator:a,lhs:o,rhs:u,args:[o,u],op:function(e,t,n){return"and"===a?t&&n:t||n},evaluate:function(e){return t.unifiedEval(this,e)}},r=n.matchToken("and")||n.matchToken("or")};r;){var u;a()}return o}),y.addGrammarElement("logicalExpression",function(e,t,n){return e.parseAnyOf(["logicalOperator","mathExpression"],n)}),y.addGrammarElement("asyncExpression",function(e,t,n){return n.matchToken("async")?{type:"asyncExpression",value:e.requireElement("logicalExpression",n),evaluate:function(e){return{asyncWrapper:!0,value:this.value.evaluate(e)}}}:e.parseElement("logicalExpression",n)}),y.addGrammarElement("expression",function(e,t,n){return n.matchToken("the"),e.parseElement("asyncExpression",n)}),y.addGrammarElement("assignableExpression",function(e,t,n){n.matchToken("the");var r=e.parseElement("primaryExpression",n);return!r||"symbol"!==r.type&&"ofExpression"!==r.type&&"propertyAccess"!==r.type&&"attributeRefAccess"!==r.type&&"attributeRef"!==r.type&&"styleRef"!==r.type&&"possessive"!==r.type?(y.raiseParseError(n,"A target expression must be writable. The expression type '"+(r&&r.type)+"' is not."),r):r}),y.addGrammarElement("hyperscript",function(e,t,n){var r=[];if(n.hasMore())for(;e.featureStart(n.currentToken())||"("===n.currentToken().value;){var o=e.requireElement("feature",n);r.push(o),n.matchToken("end")}return{type:"hyperscript",features:r,apply:function(e,t,n){for(var o,i=l(r);!(o=i()).done;)o.value.install(e,t,n)}}});var N=function(e){var t=[];if("("===e.token(0).value&&(")"===e.token(1).value||","===e.token(2).value||")"===e.token(2).value)){e.matchOpToken("(");do{t.push(e.requireTokenType("IDENTIFIER"))}while(e.matchOpToken(","));e.requireOpToken(")")}return t};y.addFeature("on",function(e,t,n){if(n.matchToken("on")){var r=!1;n.matchToken("every")&&(r=!0);var o=[],i=null;do{var a=e.requireElement("eventName",n,"Expected event name").evaluate();i=i?i+" or "+a:"on "+a;var u=N(n),s=null;if(n.matchOpToken("[")&&(s=e.requireElement("expression",n),n.requireOpToken("]")),"NUMBER"===n.currentToken().type){var f=n.consumeToken(),m=parseInt(f.value);if(n.matchToken("to"))var p=n.consumeToken(),d=parseInt(p.value);else if(n.matchToken("and")){var h=!0;n.requireToken("on")}}if("intersection"===a){var v={};if(n.matchToken("with")&&(v.with=e.requireElement("expression",n).evaluate()),n.matchToken("having"))do{n.matchToken("margin")?v.rootMargin=e.requireElement("stringLike",n).evaluate():n.matchToken("threshold")?v.threshold=e.requireElement("expression",n).evaluate():e.raiseParseError(n,"Unknown intersection config specification")}while(n.matchToken("and"))}else if("mutation"===a){var y={};if(n.matchToken("of"))do{if(n.matchToken("anything"))y.attributes=!0,y.subtree=!0,y.characterData=!0,y.childList=!0;else if(n.matchToken("childList"))y.childList=!0;else if(n.matchToken("attributes"))y.attributes=!0,y.attributeOldValue=!0;else if(n.matchToken("subtree"))y.subtree=!0;else if(n.matchToken("characterData"))y.characterData=!0,y.characterDataOldValue=!0;else if("ATTRIBUTE_REF"===n.currentToken().type){var E=n.consumeToken();null==y.attributeFilter&&(y.attributeFilter=[]),0==E.value.indexOf("@")?y.attributeFilter.push(E.value.substring(1)):e.raiseParseError(n,"Only shorthand attribute references are allowed here")}else e.raiseParseError(n,"Unknown mutation config specification")}while(n.matchToken("or"));else y.attributes=!0,y.characterData=!0,y.childList=!0}var k=null,g=!1;if(n.matchToken("from")&&(n.matchToken("elsewhere")?g=!0:(k=e.parseElement("expression",n))||e.raiseParseError(n,'Expected either target value or "elsewhere".')),null===k&&!1===g&&n.matchToken("elsewhere")&&(g=!0),n.matchToken("in"))var x=e.parseAnyOf(["idRef","queryRef","classRef"],n);if(n.matchToken("debounced")){n.requireToken("at");var b=e.requireElement("expression",n).evaluate({})}else if(n.matchToken("throttled")){n.requireToken("at");var w=e.requireElement("expression",n).evaluate({})}o.push({execCount:0,every:r,on:a,args:u,filter:s,from:k,inExpr:x,elsewhere:g,startCount:m,endCount:d,unbounded:h,debounceTime:b,throttleTime:w,mutationSpec:y,intersectionSpec:v,debounced:void 0,lastExec:void 0})}while(n.matchToken("or"));var q=!0;if(!r&&n.matchToken("queue"))if(n.matchToken("all"))q=!1;else if(n.matchToken("first"))var S=!0;else if(n.matchToken("none"))var C=!0;else n.requireToken("last");var L=e.requireElement("commandList",n);if(e.ensureTerminated(L),n.matchToken("catch")){var O=n.requireTokenType("IDENTIFIER").value,R=e.requireElement("commandList",n);e.ensureTerminated(R)}if(n.matchToken("finally")){var I=e.requireElement("commandList",n);e.ensureTerminated(I)}var A={displayName:i,events:o,start:L,every:r,execCount:0,errorHandler:R,errorSymbol:O,execute:function(e){var n=t.getEventQueueFor(e.me,A);if(n.executing&&!1===r){if(C||S&&n.queue.length>0)return;return q&&(n.queue.length=0),void n.queue.push(e)}A.execCount++,n.executing=!0,e.meta.onHalt=function(){n.executing=!1;var e=n.queue.shift();e&&setTimeout(function(){A.execute(e)},1)},e.meta.reject=function(n){console.error(n.message?n.message:n);var r=t.getHyperTrace(e,n);r&&r.print(),t.triggerEvent(e.me,"exception",{error:n})},L.execute(e)},install:function(e,n){for(var r,o=function(){var n=r.value;a=n.elsewhere?[document]:n.from?n.from.evaluate(t.makeContext(e,A,e,null)):[e],t.implicitLoop(a,function(r){var o=n.on;if(n.mutationSpec&&(o="hyperscript:mutation",new MutationObserver(function(e,t){A.executing||T.triggerEvent(r,o,{mutationList:e,observer:t})}).observe(r,n.mutationSpec)),n.intersectionSpec){o="hyperscript:insersection";var i=new IntersectionObserver(function(e){for(var t,n=l(e);!(t=n()).done;){var a=t.value,u={observer:i};(u=c(u,a)).intersecting=a.isIntersecting,T.triggerEvent(r,o,u)}},n.intersectionSpec);i.observe(r)}(r.addEventListener||r.on).call(r,o,function i(a){if("undefined"!=typeof Node&&e instanceof Node&&r!==e&&!e.isConnected)r.removeEventListener(o,i);else{var u=t.makeContext(e,A,e,a);if(!n.elsewhere||!e.contains(a.target)){n.from&&(u.result=r);for(var s,c=l(n.args);!(s=c()).done;){var f=s.value,m=u.event[f.value];void 0!==m?u[f.value]=m:"detail"in u.event&&(u[f.value]=u.event.detail[f.value])}if(u.meta.errorHandler=R,u.meta.errorSymbol=O,u.meta.finallyHandler=I,n.filter){var p=u.meta.context;u.meta.context=u.event;try{if(!n.filter.evaluate(u))return}finally{u.meta.context=p}}if(n.inExpr)for(var d=a.target;;){if(d.matches&&d.matches(n.inExpr.css)){u.result=d;break}if(null==(d=d.parentElement))return}if(n.execCount++,n.startCount)if(n.endCount){if(n.execCountn.endCount)return}else if(n.unbounded){if(n.execCount=0?null:"noTimeout"===o?e(-1):"timeout"===o?function(t){return e(parseInt(t))}:function(){for(var e=F(),t=[],r=0;r=0&&setTimeout(function(){a[e]&&a[e].reject("Timed out"),delete a[e]},n),s}}})}(s),v={raw:d,dispatchEvent:function(e){var t=e.detail;delete t.sender,delete t._namedArgList_,d.send(JSON.stringify(c({type:e.type},t)))},rpc:h},y={name:i,socket:v,install:function(e){n.assignToNamespace(e,o,i,v)}};return d.onmessage=function(e){var t=e.data;try{var r=JSON.parse(t)}catch(e){}if(r&&r.iid&&(r.throw?a[r.iid].reject(r.throw):a[r.iid].resolve(r.return),delete a[r.iid]),f){var o=n.makeContext(v,y,v);if(l){if(!r)throw"Received non-JSON message from socket: "+t;o.message=r,o.result=r}else o.message=t,o.result=t;f.execute(o)}},d.addEventListener("close",function(e){d=null}),y}})}(A),function(e){e.addFeature("eventsource",function(e,t,n){if(n.matchToken("eventsource")){var r,o=function(e,n){return function(r){var o=i(r.data,e),a=t.makeContext(c,f,c);a.event=r,a.result=o,n.execute(a)}},i=function(e,t){return"json"==t?JSON.parse(e):e},a=function e(n){if(n.next)return e(n.next);n.next={type:"implicitReturn",op:function(e){return t.HALT},execute:function(e){}}},u=!1,s=e.requireElement("dotOrColonPath",n).evaluate().split("."),l=s.pop();n.matchToken("from")&&(r=e.requireElement("stringLike",n)),n.matchToken("with")&&n.matchToken("credentials")&&(u=!0);for(var c={eventSource:null,listeners:[],retryCount:0,open:function(e){if(null==e){if(null==c.eventSource||null==c.eventSource.url)throw"no url defined for EventSource.";e=c.eventSource.url}if(null!=c.eventSource)if(e!=c.eventSource.url)c.eventSource.close();else if(c.eventSource.readyState!=EventSource.CLOSED)return;c.eventSource=new EventSource(e,{withCredentials:u}),c.eventSource.addEventListener("open",function(e){c.retryCount=0}),c.eventSource.addEventListener("error",function(e){if(c.eventSource.readyState==EventSource.CLOSED){c.retryCount=Math.min(7,c.retryCount+1);var t=Math.random()*(2^c.retryCount)*500;window.setTimeout(c.open,t)}});for(var t=0;t/g,">").replace(/\x22/g,""").replace(/\x27/g,"'");throw new Error("Unknown escape: "+r)},evaluate:function(e){return t.unifiedEval(this,e)}}}})}(A),function(e){function t(t,n,r){this.ctx=t,this.runtime=n,this.cmd=r,this._hyperscript=e,this.cmdMap=[],this.bus=new EventTarget}e.addCommand("breakpoint",function(e,n,r){var o;if(r.matchToken("breakpoint"))return{op:function(e){globalThis.hdb=o=new t(e,n,this);try{return o.break(e)}catch(e){console.error(e,e.stack)}}}}),t.prototype.break=function(e){var t=this;return console.log("=== HDB///_hyperscript/debugger ==="),this.ui(),new Promise(function(n,r){t.bus.addEventListener("continue",function(){if(t.ctx!==e){for(var r in e)delete e[r];Object.assign(e,t.ctx)}delete window.hdb,n(t.runtime.findNext(t.cmd,t.ctx))},{once:!0})})},t.prototype.continueExec=function(){this.bus.dispatchEvent(new Event("continue"))},t.prototype.stepOver=function(){var e=this;if(!this.cmd)return this.continueExec();var t=this.cmd&&"breakpointCommand"===this.cmd.type?this.runtime.findNext(this.cmd,this.ctx):this.runtime.unifiedEval(this.cmd,this.ctx);return"implicitReturn"===t.type?this.stepOut():t&&t.then instanceof Function?t.then(function(t){e.cmd=t,e.bus.dispatchEvent(new Event("step")),e.logCommand()}):void(t.halt_flag?this.bus.dispatchEvent(new Event("continue")):(this.cmd=t,this.bus.dispatchEvent(new Event("step")),this.logCommand()))},t.prototype.stepOut=function(){if(!this.ctx.meta.caller)return this.continueExec();var e=this.ctx.meta.callingCommand,t=this.ctx.me;this.ctx=this.ctx.meta.caller,console.log("[hdb] stepping out into "+this.ctx.meta.feature.displayName),this.ctx.me instanceof Element&&this.ctx.me!==t&&console.log("[hdb] me: ",this.ctx.me),this.cmd=this.runtime.findNext(e,this.ctx),this.cmd=this.runtime.findNext(this.cmd,this.ctx),this.logCommand(),this.bus.dispatchEvent(new Event("step"))},t.prototype.skipTo=function(e){this.cmd=e.cmd,this.bus.dispatchEvent(new Event("skip"))},t.prototype.rewrite=function(t,n){console.log("##",t);for(var r,o,i=t.cmd.parent,a=l(i.children);!(o=a()).done&&(r=o.value).next!==t.cmd;);var u=t.next,s=e.internals.lexer.tokenize(n),c=e.internals.parser.requireElement("command",s);console.log(c),c.startToken=t.startToken,c.endToken=t.endToken,c.programSource=t.programSource,c.sourceFor=function(){return n},r.next=c,c.next=u,c.parent=i,this.bus.dispatchEvent(new Event("step"))},t.prototype.logCommand=function(){var e=this.cmd.sourceFor instanceof Function?this.cmd.sourceFor():"-- "+this.cmd.type;console.log("[hdb] current command: "+e)},t.prototype.traverse=function(e){var t=[];return function e(n){t.push(n);for(var r=l(n.children);!r().done;)e(t)}(e),t},t.prototype.ui=function(){var t=document.createElement("div"),n=t.attachShadow({mode:"open"});t.style.cssText="all: initial",n.innerHTML='\n