aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md (renamed from lib/README.md)0
-rw-r--r--compat/lustre_animation/.gitignore4
-rw-r--r--compat/lustre_animation/README.md52
-rw-r--r--compat/lustre_animation/gleam.toml14
-rw-r--r--compat/lustre_animation/highlight.js5008
-rw-r--r--compat/lustre_animation/index.html95
-rw-r--r--compat/lustre_animation/lustre_animation.css90
-rw-r--r--compat/lustre_animation/manifest.toml13
-rw-r--r--compat/lustre_animation/package-lock.json790
-rw-r--r--compat/lustre_animation/package.json9
-rw-r--r--compat/lustre_animation/run_highlight.js3
-rw-r--r--compat/lustre_animation/src/ffi.mjs2
-rw-r--r--compat/lustre_animation/src/lustre/animation.gleam170
-rw-r--r--compat/lustre_animation/test/example_drops.gleam120
-rw-r--r--compat/lustre_animation/test/example_two_independent.gleam103
-rw-r--r--compat/lustre_animation/test/info.mjs2
-rw-r--r--compat/lustre_animation/test/lustre/animation_test.gleam39
-rw-r--r--compat/lustre_animation/test/lustre_animation_test.gleam5
-rw-r--r--compat/lustre_animation/test/start_examples.mjs5
-rw-r--r--compat/lustre_http/.gitignore2
-rw-r--r--compat/lustre_http/README.md17
-rw-r--r--compat/lustre_http/gleam.toml16
-rw-r--r--compat/lustre_http/manifest.toml16
-rw-r--r--compat/lustre_http/src/ffi.mjs16
-rw-r--r--compat/lustre_http/src/lustre_http.gleam126
-rw-r--r--compat/lustre_http/test/lustre_http_test.gleam15
-rw-r--r--compat/lustre_websocket/.gitignore1
-rw-r--r--compat/lustre_websocket/README.md51
-rw-r--r--compat/lustre_websocket/gleam.toml18
-rw-r--r--compat/lustre_websocket/manifest.toml13
-rw-r--r--compat/lustre_websocket/src/ffi.mjs39
-rw-r--r--compat/lustre_websocket/src/lustre_websocket.gleam85
-rw-r--r--compat/lustre_websocket/test/lustre_websocket_test.gleam15
-rw-r--r--docs/.gitignore4
-rw-r--r--docs/404.html56
-rw-r--r--docs/README.md24
-rw-r--r--docs/assets/styles.css16
-rw-r--r--docs/gleam.toml18
-rw-r--r--docs/index.html115
-rw-r--r--docs/manifest.toml13
-rw-r--r--docs/package-lock.json2595
-rw-r--r--docs/package.json19
-rw-r--r--docs/postcss.config.js6
-rw-r--r--docs/public/CNAME1
-rw-r--r--docs/public/fonts/NTDapper-black.woff2bin25336 -> 0 bytes
-rw-r--r--docs/public/fonts/NTDapper-bold.woff2bin25652 -> 0 bytes
-rw-r--r--docs/public/fonts/NTDapper-medium.woff2bin25584 -> 0 bytes
-rw-r--r--docs/public/fonts/NTDapper-regular.woff2bin24676 -> 0 bytes
-rw-r--r--docs/public/page/api/lustre.md237
-rw-r--r--docs/public/page/api/lustre/attribute.md290
-rw-r--r--docs/public/page/api/lustre/effect.md35
-rw-r--r--docs/public/page/api/lustre/element.md58
-rw-r--r--docs/public/page/api/lustre/element/html.md993
-rw-r--r--docs/public/page/api/lustre/element/svg.md462
-rw-r--r--docs/public/page/api/lustre/event.md146
-rw-r--r--docs/public/page/docs/components.md8
-rw-r--r--docs/public/page/docs/managing-state.md206
-rw-r--r--docs/public/page/docs/quickstart.md271
-rw-r--r--docs/public/page/docs/server-side-rendering.md8
-rw-r--r--docs/public/page/docs/side-effects.md8
-rw-r--r--docs/public/page/guides/mist.md8
-rw-r--r--docs/public/page/guides/wisp.md8
-rw-r--r--docs/src/app.ffi.mjs10
-rw-r--r--docs/src/app.gleam137
-rw-r--r--docs/src/app/effects.gleam0
-rw-r--r--docs/src/app/layout.gleam261
-rw-r--r--docs/src/app/ui/hooks.gleam120
-rw-r--r--docs/src/app/ui/markdown.gleam136
-rw-r--r--docs/src/app/ui/radix.gleam74
-rw-r--r--docs/src/highlight.ffi.mjs151
-rw-r--r--docs/src/markdown.ffi.mjs164
-rw-r--r--docs/tailwind.config.js20
-rw-r--r--docs/vite.config.js48
-rw-r--r--gleam.toml (renamed from lib/gleam.toml)0
-rw-r--r--manifest.toml (renamed from lib/manifest.toml)0
-rw-r--r--package-lock.json (renamed from lib/package-lock.json)0
-rw-r--r--package.json (renamed from lib/package.json)0
-rw-r--r--src/lustre.ffi.mjs (renamed from lib/src/lustre.ffi.mjs)0
-rw-r--r--src/lustre.gleam (renamed from lib/src/lustre.gleam)0
-rw-r--r--src/lustre/attribute.gleam (renamed from lib/src/lustre/attribute.gleam)0
-rw-r--r--src/lustre/effect.gleam (renamed from lib/src/lustre/effect.gleam)0
-rw-r--r--src/lustre/element.gleam (renamed from lib/src/lustre/element.gleam)0
-rw-r--r--src/lustre/element/html.gleam (renamed from lib/src/lustre/element/html.gleam)0
-rw-r--r--src/lustre/element/svg.gleam (renamed from lib/src/lustre/element/svg.gleam)0
-rw-r--r--src/lustre/event.gleam (renamed from lib/src/lustre/event.gleam)0
-rw-r--r--src/runtime.ffi.mjs (renamed from lib/src/runtime.ffi.mjs)0
-rw-r--r--test/examples/components.gleam (renamed from lib/test/examples/components.gleam)0
-rw-r--r--test/examples/components.html (renamed from lib/test/examples/components.html)0
-rw-r--r--test/examples/counter.gleam (renamed from lib/test/examples/counter.gleam)0
-rw-r--r--test/examples/counter.html (renamed from lib/test/examples/counter.html)0
-rw-r--r--test/examples/index.html (renamed from lib/test/examples/index.html)0
-rw-r--r--test/examples/input.gleam (renamed from lib/test/examples/input.gleam)0
-rw-r--r--test/examples/input.html (renamed from lib/test/examples/input.html)0
-rw-r--r--test/examples/nested.gleam (renamed from lib/test/examples/nested.gleam)0
-rw-r--r--test/examples/nested.html (renamed from lib/test/examples/nested.html)0
-rw-r--r--test/examples/svg.gleam (renamed from lib/test/examples/svg.gleam)0
-rw-r--r--test/examples/svg.html (renamed from lib/test/examples/svg.html)0
97 files changed, 0 insertions, 13680 deletions
diff --git a/lib/README.md b/README.md
index 9f393f5..9f393f5 100644
--- a/lib/README.md
+++ b/README.md
diff --git a/compat/lustre_animation/.gitignore b/compat/lustre_animation/.gitignore
deleted file mode 100644
index be616fc..0000000
--- a/compat/lustre_animation/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-build
-node_modules
-dist/main.js
-dist/assets/
diff --git a/compat/lustre_animation/README.md b/compat/lustre_animation/README.md
deleted file mode 100644
index 338e9c1..0000000
--- a/compat/lustre_animation/README.md
+++ /dev/null
@@ -1,52 +0,0 @@
-# Lustre Animation
-
-The basic usage is
- * keep 1 `Animations` value
- * add animations by some trigger
- * call `animation.cmd()` on your value and let your lustre `update()` return it.
- This will cause a dispatch on the next JS animation frame, unless all animations have finished (and auto-removed)
- * update the animations with the new time.
- * evaluate for each animation you are interested in.
-
-e.g. like this:
-```gleam
-import lustre/animation as a
-
-pub type Msg {
- Trigger
- Tick(Float)
-}
-
-pub fn update(model: Model, msg: Msg) {
- let m = case msg of {
- Trigger -> {
- let new_anim = a.add(model.animations, "id", 1.0, 2.0, 0.250)
- Model(1.0, animations: new_anim)
- }
- Tick(t) -> {
- let new_anim = a.tick(model.animations, t)
- let new_value = a.value(new_anim, "id", model.value)
- Model(new_value, new_anim)
- }
- }
- #(m, animation.cmd(m.animations, Tick))
-}
-```
-
-In the above `type Model`, `init` and `render` have been omitted.
-
-There are fully functional examples animations in the `test/` directory,
-which you can build by
-```bash
-gleam test
-npx vite
-````
-
-and then pointing your browser to the URL that vite indicates.
-
-## TODO
-* `every(Minute)`, etc
-* `after(seconds: 2.5)`
-* quadratic, cubic, etc interpolators
-* Compose animations
- `from("anim", 1.0) |> after(0.250) |> cubic(3.0, 0.250) |> after(0.250) |> quadr(2.0, 0.250)` \ No newline at end of file
diff --git a/compat/lustre_animation/gleam.toml b/compat/lustre_animation/gleam.toml
deleted file mode 100644
index 182203e..0000000
--- a/compat/lustre_animation/gleam.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-name = "lustre_animation"
-version = "0.2.0"
-description = "Animations for lustre, utilizing JS requestAnimationFrame"
-target = "javascript"
-licenses = ["MIT"]
-repository = { type = "custom", url = "https://git.chmeee.org/lustre_animation" }
-
-[dependencies]
-gleam_stdlib = "~> 0.30"
-lustre = { path = "../../lib" }
-
-
-[dev-dependencies]
-gleeunit = "~> 0.10"
diff --git a/compat/lustre_animation/highlight.js b/compat/lustre_animation/highlight.js
deleted file mode 100644
index aa0170b..0000000
--- a/compat/lustre_animation/highlight.js
+++ /dev/null
@@ -1,5008 +0,0 @@
-/*!
- Highlight.js v11.7.0 (git: 2f3d5ff18e)
- (c) 2006-2023 undefined and other contributors
- License: BSD-3-Clause
- */
-var hljs = (function () {
- 'use strict';
-
- var deepFreezeEs6 = {exports: {}};
-
- function deepFreeze(obj) {
- if (obj instanceof Map) {
- obj.clear = obj.delete = obj.set = function () {
- throw new Error('map is read-only');
- };
- } else if (obj instanceof Set) {
- obj.add = obj.clear = obj.delete = function () {
- throw new Error('set is read-only');
- };
- }
-
- // Freeze self
- Object.freeze(obj);
-
- Object.getOwnPropertyNames(obj).forEach(function (name) {
- var prop = obj[name];
-
- // Freeze prop if it is an object
- if (typeof prop == 'object' && !Object.isFrozen(prop)) {
- deepFreeze(prop);
- }
- });
-
- return obj;
- }
-
- deepFreezeEs6.exports = deepFreeze;
- deepFreezeEs6.exports.default = deepFreeze;
-
- /** @typedef {import('highlight.js').CallbackResponse} CallbackResponse */
- /** @typedef {import('highlight.js').CompiledMode} CompiledMode */
- /** @implements CallbackResponse */
-
- class Response {
- /**
- * @param {CompiledMode} mode
- */
- constructor(mode) {
- // eslint-disable-next-line no-undefined
- if (mode.data === undefined) mode.data = {};
-
- this.data = mode.data;
- this.isMatchIgnored = false;
- }
-
- ignoreMatch() {
- this.isMatchIgnored = true;
- }
- }
-
- /**
- * @param {string} value
- * @returns {string}
- */
- function escapeHTML(value) {
- return value
- .replace(/&/g, '&')
- .replace(/</g, '&lt;')
- .replace(/>/g, '&gt;')
- .replace(/"/g, '&quot;')
- .replace(/'/g, '&#x27;');
- }
-
- /**
- * performs a shallow merge of multiple objects into one
- *
- * @template T
- * @param {T} original
- * @param {Record<string,any>[]} objects
- * @returns {T} a single new object
- */
- function inherit$1(original, ...objects) {
- /** @type Record<string,any> */
- const result = Object.create(null);
-
- for (const key in original) {
- result[key] = original[key];
- }
- objects.forEach(function(obj) {
- for (const key in obj) {
- result[key] = obj[key];
- }
- });
- return /** @type {T} */ (result);
- }
-
- /**
- * @typedef {object} Renderer
- * @property {(text: string) => void} addText
- * @property {(node: Node) => void} openNode
- * @property {(node: Node) => void} closeNode
- * @property {() => string} value
- */
-
- /** @typedef {{scope?: string, language?: string, sublanguage?: boolean}} Node */
- /** @typedef {{walk: (r: Renderer) => void}} Tree */
- /** */
-
- const SPAN_CLOSE = '</span>';
-
- /**
- * Determines if a node needs to be wrapped in <span>
- *
- * @param {Node} node */
- const emitsWrappingTags = (node) => {
- // rarely we can have a sublanguage where language is undefined
- // TODO: track down why
- return !!node.scope || (node.sublanguage && node.language);
- };
-
- /**
- *
- * @param {string} name
- * @param {{prefix:string}} options
- */
- const scopeToCSSClass = (name, { prefix }) => {
- if (name.includes(".")) {
- const pieces = name.split(".");
- return [
- `${prefix}${pieces.shift()}`,
- ...(pieces.map((x, i) => `${x}${"_".repeat(i + 1)}`))
- ].join(" ");
- }
- return `${prefix}${name}`;
- };
-
- /** @type {Renderer} */
- class HTMLRenderer {
- /**
- * Creates a new HTMLRenderer
- *
- * @param {Tree} parseTree - the parse tree (must support `walk` API)
- * @param {{classPrefix: string}} options
- */
- constructor(parseTree, options) {
- this.buffer = "";
- this.classPrefix = options.classPrefix;
- parseTree.walk(this);
- }
-
- /**
- * Adds texts to the output stream
- *
- * @param {string} text */
- addText(text) {
- this.buffer += escapeHTML(text);
- }
-
- /**
- * Adds a node open to the output stream (if needed)
- *
- * @param {Node} node */
- openNode(node) {
- if (!emitsWrappingTags(node)) return;
-
- let className = "";
- if (node.sublanguage) {
- className = `language-${node.language}`;
- } else {
- className = scopeToCSSClass(node.scope, { prefix: this.classPrefix });
- }
- this.span(className);
- }
-
- /**
- * Adds a node close to the output stream (if needed)
- *
- * @param {Node} node */
- closeNode(node) {
- if (!emitsWrappingTags(node)) return;
-
- this.buffer += SPAN_CLOSE;
- }
-
- /**
- * returns the accumulated buffer
- */
- value() {
- return this.buffer;
- }
-
- // helpers
-
- /**
- * Builds a span element
- *
- * @param {string} className */
- span(className) {
- this.buffer += `<span class="${className}">`;
- }
- }
-
- /** @typedef {{scope?: string, language?: string, sublanguage?: boolean, children: Node[]} | string} Node */
- /** @typedef {{scope?: string, language?: string, sublanguage?: boolean, children: Node[]} } DataNode */
- /** @typedef {import('highlight.js').Emitter} Emitter */
- /** */
-
- /** @returns {DataNode} */
- const newNode = (opts = {}) => {
- /** @type DataNode */
- const result = { children: [] };
- Object.assign(result, opts);
- return result;
- };
-
- class TokenTree {
- constructor() {
- /** @type DataNode */
- this.rootNode = newNode();
- this.stack = [this.rootNode];
- }
-
- get top() {
- return this.stack[this.stack.length - 1];
- }
-
- get root() { return this.rootNode; }
-
- /** @param {Node} node */
- add(node) {
- this.top.children.push(node);
- }
-
- /** @param {string} scope */
- openNode(scope) {
- /** @type Node */
- const node = newNode({ scope });
- this.add(node);
- this.stack.push(node);
- }
-
- closeNode() {
- if (this.stack.length > 1) {
- return this.stack.pop();
- }
- // eslint-disable-next-line no-undefined
- return undefined;
- }
-
- closeAllNodes() {
- while (this.closeNode());
- }
-
- toJSON() {
- return JSON.stringify(this.rootNode, null, 4);
- }
-
- /**
- * @typedef { import("./html_renderer").Renderer } Renderer
- * @param {Renderer} builder
- */
- walk(builder) {
- // this does not
- return this.constructor._walk(builder, this.rootNode);
- // this works
- // return TokenTree._walk(builder, this.rootNode);
- }
-
- /**
- * @param {Renderer} builder
- * @param {Node} node
- */
- static _walk(builder, node) {
- if (typeof node === "string") {
- builder.addText(node);
- } else if (node.children) {
- builder.openNode(node);
- node.children.forEach((child) => this._walk(builder, child));
- builder.closeNode(node);
- }
- return builder;
- }
-
- /**
- * @param {Node} node
- */
- static _collapse(node) {
- if (typeof node === "string") return;
- if (!node.children) return;
-
- if (node.children.every(el => typeof el === "string")) {
- // node.text = node.children.join("");
- // delete node.children;
- node.children = [node.children.join("")];
- } else {
- node.children.forEach((child) => {
- TokenTree._collapse(child);
- });
- }
- }
- }
-
- /**
- Currently this is all private API, but this is the minimal API necessary
- that an Emitter must implement to fully support the parser.
-
- Minimal interface:
-
- - addKeyword(text, scope)
- - addText(text)
- - addSublanguage(emitter, subLanguageName)
- - finalize()
- - openNode(scope)
- - closeNode()
- - closeAllNodes()
- - toHTML()
-
- */
-
- /**
- * @implements {Emitter}
- */
- class TokenTreeEmitter extends TokenTree {
- /**
- * @param {*} options
- */
- constructor(options) {
- super();
- this.options = options;
- }
-
- /**
- * @param {string} text
- * @param {string} scope
- */
- addKeyword(text, scope) {
- if (text === "") { return; }
-
- this.openNode(scope);
- this.addText(text);
- this.closeNode();
- }
-
- /**
- * @param {string} text
- */
- addText(text) {
- if (text === "") { return; }
-
- this.add(text);
- }
-
- /**
- * @param {Emitter & {root: DataNode}} emitter
- * @param {string} name
- */
- addSublanguage(emitter, name) {
- /** @type DataNode */
- const node = emitter.root;
- node.sublanguage = true;
- node.language = name;
- this.add(node);
- }
-
- toHTML() {
- const renderer = new HTMLRenderer(this, this.options);
- return renderer.value();
- }
-
- finalize() {
- return true;
- }
- }
-
- /**
- * @param {string} value
- * @returns {RegExp}
- * */
-
- /**
- * @param {RegExp | string } re
- * @returns {string}
- */
- function source(re) {
- if (!re) return null;
- if (typeof re === "string") return re;
-
- return re.source;
- }
-
- /**
- * @param {RegExp | string } re
- * @returns {string}
- */
- function lookahead(re) {
- return concat('(?=', re, ')');
- }
-
- /**
- * @param {RegExp | string } re
- * @returns {string}
- */
- function anyNumberOfTimes(re) {
- return concat('(?:', re, ')*');
- }
-
- /**
- * @param {RegExp | string } re
- * @returns {string}
- */
- function optional(re) {
- return concat('(?:', re, ')?');
- }
-
- /**
- * @param {...(RegExp | string) } args
- * @returns {string}
- */
- function concat(...args) {
- const joined = args.map((x) => source(x)).join("");
- return joined;
- }
-
- /**
- * @param { Array<string | RegExp | Object> } args
- * @returns {object}
- */
- function stripOptionsFromArgs(args) {
- const opts = args[args.length - 1];
-
- if (typeof opts === 'object' && opts.constructor === Object) {
- args.splice(args.length - 1, 1);
- return opts;
- } else {
- return {};
- }
- }
-
- /** @typedef { {capture?: boolean} } RegexEitherOptions */
-
- /**
- * Any of the passed expresssions may match
- *
- * Creates a huge this | this | that | that match
- * @param {(RegExp | string)[] | [...(RegExp | string)[], RegexEitherOptions]} args
- * @returns {string}
- */
- function either(...args) {
- /** @type { object & {capture?: boolean} } */
- const opts = stripOptionsFromArgs(args);
- const joined = '('
- + (opts.capture ? "" : "?:")
- + args.map((x) => source(x)).join("|") + ")";
- return joined;
- }
-
- /**
- * @param {RegExp | string} re
- * @returns {number}
- */
- function countMatchGroups(re) {
- return (new RegExp(re.toString() + '|')).exec('').length - 1;
- }
-
- /**
- * Does lexeme start with a regular expression match at the beginning
- * @param {RegExp} re
- * @param {string} lexeme
- */
- function startsWith(re, lexeme) {
- const match = re && re.exec(lexeme);
- return match && match.index === 0;
- }
-
- // BACKREF_RE matches an open parenthesis or backreference. To avoid
- // an incorrect parse, it additionally matches the following:
- // - [...] elements, where the meaning of parentheses and escapes change
- // - other escape sequences, so we do not misparse escape sequences as
- // interesting elements
- // - non-matching or lookahead parentheses, which do not capture. These
- // follow the '(' with a '?'.
- const BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
-
- // **INTERNAL** Not intended for outside usage
- // join logically computes regexps.join(separator), but fixes the
- // backreferences so they continue to match.
- // it also places each individual regular expression into it's own
- // match group, keeping track of the sequencing of those match groups
- // is currently an exercise for the caller. :-)
- /**
- * @param {(string | RegExp)[]} regexps
- * @param {{joinWith: string}} opts
- * @returns {string}
- */
- function _rewriteBackreferences(regexps, { joinWith }) {
- let numCaptures = 0;
-
- return regexps.map((regex) => {
- numCaptures += 1;
- const offset = numCaptures;
- let re = source(regex);
- let out = '';
-
- while (re.length > 0) {
- const match = BACKREF_RE.exec(re);
- if (!match) {
- out += re;
- break;
- }
- out += re.substring(0, match.index);
- re = re.substring(match.index + match[0].length);
- if (match[0][0] === '\\' && match[1]) {
- // Adjust the backreference.
- out += '\\' + String(Number(match[1]) + offset);
- } else {
- out += match[0];
- if (match[0] === '(') {
- numCaptures++;
- }
- }
- }
- return out;
- }).map(re => `(${re})`).join(joinWith);
- }
-
- /** @typedef {import('highlight.js').Mode} Mode */
- /** @typedef {import('highlight.js').ModeCallback} ModeCallback */
-
- // Common regexps
- const MATCH_NOTHING_RE = /\b\B/;
- const IDENT_RE$1 = '[a-zA-Z]\\w*';
- const UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\w*';
- const NUMBER_RE = '\\b\\d+(\\.\\d+)?';
- const C_NUMBER_RE = '(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)'; // 0x..., 0..., decimal, float
- const BINARY_NUMBER_RE = '\\b(0b[01]+)'; // 0b...
- const RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~';
-
- /**
- * @param { Partial<Mode> & {binary?: string | RegExp} } opts
- */
- const SHEBANG = (opts = {}) => {
- const beginShebang = /^#![ ]*\//;
- if (opts.binary) {
- opts.begin = concat(
- beginShebang,
- /.*\b/,
- opts.binary,
- /\b.*/);
- }
- return inherit$1({
- scope: 'meta',
- begin: beginShebang,
- end: /$/,
- relevance: 0,
- /** @type {ModeCallback} */
- "on:begin": (m, resp) => {
- if (m.index !== 0) resp.ignoreMatch();
- }
- }, opts);
- };
-
- // Common modes
- const BACKSLASH_ESCAPE = {
- begin: '\\\\[\\s\\S]', relevance: 0
- };
- const APOS_STRING_MODE = {
- scope: 'string',
- begin: '\'',
- end: '\'',
- illegal: '\\n',
- contains: [BACKSLASH_ESCAPE]
- };
- const QUOTE_STRING_MODE = {
- scope: 'string',
- begin: '"',
- end: '"',
- illegal: '\\n',
- contains: [BACKSLASH_ESCAPE]
- };
- const PHRASAL_WORDS_MODE = {
- begin: /\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/
- };
- /**
- * Creates a comment mode
- *
- * @param {string | RegExp} begin
- * @param {string | RegExp} end
- * @param {Mode | {}} [modeOptions]
- * @returns {Partial<Mode>}
- */
- const COMMENT = function(begin, end, modeOptions = {}) {
- const mode = inherit$1(
- {
- scope: 'comment',
- begin,
- end,
- contains: []
- },
- modeOptions
- );
- mode.contains.push({
- scope: 'doctag',
- // hack to avoid the space from being included. the space is necessary to
- // match here to prevent the plain text rule below from gobbling up doctags
- begin: '[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)',
- end: /(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,
- excludeBegin: true,
- relevance: 0
- });
- const ENGLISH_WORD = either(
- // list of common 1 and 2 letter words in English
- "I",
- "a",
- "is",
- "so",
- "us",
- "to",
- "at",
- "if",
- "in",
- "it",
- "on",
- // note: this is not an exhaustive list of contractions, just popular ones
- /[A-Za-z]+['](d|ve|re|ll|t|s|n)/, // contractions - can't we'd they're let's, etc
- /[A-Za-z]+[-][a-z]+/, // `no-way`, etc.
- /[A-Za-z][a-z]{2,}/ // allow capitalized words at beginning of sentences
- );
- // looking like plain text, more likely to be a comment
- mode.contains.push(
- {
- // TODO: how to include ", (, ) without breaking grammars that use these for
- // comment delimiters?
- // begin: /[ ]+([()"]?([A-Za-z'-]{3,}|is|a|I|so|us|[tT][oO]|at|if|in|it|on)[.]?[()":]?([.][ ]|[ ]|\))){3}/
- // ---
-
- // this tries to find sequences of 3 english words in a row (without any
- // "programming" type syntax) this gives us a strong signal that we've
- // TRULY found a comment - vs perhaps scanning with the wrong language.
- // It's possible to find something that LOOKS like the start of the
- // comment - but then if there is no readable text - good chance it is a
- // false match and not a comment.
- //
- // for a visual example please see:
- // https://github.com/highlightjs/highlight.js/issues/2827
-
- begin: concat(
- /[ ]+/, // necessary to prevent us gobbling up doctags like /* @author Bob Mcgill */
- '(',
- ENGLISH_WORD,
- /[.]?[:]?([.][ ]|[ ])/,
- '){3}') // look for 3 words in a row
- }
- );
- return mode;
- };
- const C_LINE_COMMENT_MODE = COMMENT('//', '$');
- const C_BLOCK_COMMENT_MODE = COMMENT('/\\*', '\\*/');
- const HASH_COMMENT_MODE = COMMENT('#', '$');
- const NUMBER_MODE = {
- scope: 'number',
- begin: NUMBER_RE,
- relevance: 0
- };
- const C_NUMBER_MODE = {
- scope: 'number',
- begin: C_NUMBER_RE,
- relevance: 0
- };
- const BINARY_NUMBER_MODE = {
- scope: 'number',
- begin: BINARY_NUMBER_RE,
- relevance: 0
- };
- const REGEXP_MODE = {
- // this outer rule makes sure we actually have a WHOLE regex and not simply
- // an expression such as:
- //
- // 3 / something
- //
- // (which will then blow up when regex's `illegal` sees the newline)
- begin: /(?=\/[^/\n]*\/)/,
- contains: [{
- scope: 'regexp',
- begin: /\//,
- end: /\/[gimuy]*/,
- illegal: /\n/,
- contains: [
- BACKSLASH_ESCAPE,
- {
- begin: /\[/,
- end: /\]/,
- relevance: 0,
- contains: [BACKSLASH_ESCAPE]
- }
- ]
- }]
- };
- const TITLE_MODE = {
- scope: 'title',
- begin: IDENT_RE$1,
- relevance: 0
- };
- const UNDERSCORE_TITLE_MODE = {
- scope: 'title',
- begin: UNDERSCORE_IDENT_RE,
- relevance: 0
- };
- const METHOD_GUARD = {
- // excludes method names from keyword processing
- begin: '\\.\\s*' + UNDERSCORE_IDENT_RE,
- relevance: 0
- };
-
- /**
- * Adds end same as begin mechanics to a mode
- *
- * Your mode must include at least a single () match group as that first match
- * group is what is used for comparison
- * @param {Partial<Mode>} mode
- */
- const END_SAME_AS_BEGIN = function(mode) {
- return Object.assign(mode,
- {
- /** @type {ModeCallback} */
- 'on:begin': (m, resp) => { resp.data._beginMatch = m[1]; },
- /** @type {ModeCallback} */
- 'on:end': (m, resp) => { if (resp.data._beginMatch !== m[1]) resp.ignoreMatch(); }
- });
- };
-
- var MODES$1 = /*#__PURE__*/Object.freeze({
- __proto__: null,
- MATCH_NOTHING_RE: MATCH_NOTHING_RE,
- IDENT_RE: IDENT_RE$1,
- UNDERSCORE_IDENT_RE: UNDERSCORE_IDENT_RE,
- NUMBER_RE: NUMBER_RE,
- C_NUMBER_RE: C_NUMBER_RE,
- BINARY_NUMBER_RE: BINARY_NUMBER_RE,
- RE_STARTERS_RE: RE_STARTERS_RE,
- SHEBANG: SHEBANG,
- BACKSLASH_ESCAPE: BACKSLASH_ESCAPE,
- APOS_STRING_MODE: APOS_STRING_MODE,
- QUOTE_STRING_MODE: QUOTE_STRING_MODE,
- PHRASAL_WORDS_MODE: PHRASAL_WORDS_MODE,
- COMMENT: COMMENT,
- C_LINE_COMMENT_MODE: C_LINE_COMMENT_MODE,
- C_BLOCK_COMMENT_MODE: C_BLOCK_COMMENT_MODE,
- HASH_COMMENT_MODE: HASH_COMMENT_MODE,
- NUMBER_MODE: NUMBER_MODE,
- C_NUMBER_MODE: C_NUMBER_MODE,
- BINARY_NUMBER_MODE: BINARY_NUMBER_MODE,
- REGEXP_MODE: REGEXP_MODE,
- TITLE_MODE: TITLE_MODE,
- UNDERSCORE_TITLE_MODE: UNDERSCORE_TITLE_MODE,
- METHOD_GUARD: METHOD_GUARD,
- END_SAME_AS_BEGIN: END_SAME_AS_BEGIN
- });
-
- /**
- @typedef {import('highlight.js').CallbackResponse} CallbackResponse
- @typedef {import('highlight.js').CompilerExt} CompilerExt
- */
-
- // Grammar extensions / plugins
- // See: https://github.com/highlightjs/highlight.js/issues/2833
-
- // Grammar extensions allow "syntactic sugar" to be added to the grammar modes
- // without requiring any underlying changes to the compiler internals.
-
- // `compileMatch` being the perfect small example of now allowing a grammar
- // author to write `match` when they desire to match a single expression rather
- // than being forced to use `begin`. The extension then just moves `match` into
- // `begin` when it runs. Ie, no features have been added, but we've just made
- // the experience of writing (and reading grammars) a little bit nicer.
-
- // ------
-
- // TODO: We need negative look-behind support to do this properly
- /**
- * Skip a match if it has a preceding dot
- *
- * This is used for `beginKeywords` to prevent matching expressions such as
- * `bob.keyword.do()`. The mode compiler automatically wires this up as a
- * special _internal_ 'on:begin' callback for modes with `beginKeywords`
- * @param {RegExpMatchArray} match
- * @param {CallbackResponse} response
- */
- function skipIfHasPrecedingDot(match, response) {
- const before = match.input[match.index - 1];
- if (before === ".") {
- response.ignoreMatch();
- }
- }
-
- /**
- *
- * @type {CompilerExt}
- */
- function scopeClassName(mode, _parent) {
- // eslint-disable-next-line no-undefined
- if (mode.className !== undefined) {
- mode.scope = mode.className;
- delete mode.className;
- }
- }
-
- /**
- * `beginKeywords` syntactic sugar
- * @type {CompilerExt}
- */
- function beginKeywords(mode, parent) {
- if (!parent) return;
- if (!mode.beginKeywords) return;
-
- // for languages with keywords that include non-word characters checking for
- // a word boundary is not sufficient, so instead we check for a word boundary
- // or whitespace - this does no harm in any case since our keyword engine
- // doesn't allow spaces in keywords anyways and we still check for the boundary
- // first
- mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')(?!\\.)(?=\\b|\\s)';
- mode.__beforeBegin = skipIfHasPrecedingDot;
- mode.keywords = mode.keywords || mode.beginKeywords;
- delete mode.beginKeywords;
-
- // prevents double relevance, the keywords themselves provide
- // relevance, the mode doesn't need to double it
- // eslint-disable-next-line no-undefined
- if (mode.relevance === undefined) mode.relevance = 0;
- }
-
- /**
- * Allow `illegal` to contain an array of illegal values
- * @type {CompilerExt}
- */
- function compileIllegal(mode, _parent) {
- if (!Array.isArray(mode.illegal)) return;
-
- mode.illegal = either(...mode.illegal);
- }
-
- /**
- * `match` to match a single expression for readability
- * @type {CompilerExt}
- */
- function compileMatch(mode, _parent) {
- if (!mode.match) return;
- if (mode.begin || mode.end) throw new Error("begin & end are not supported with match");
-
- mode.begin = mode.match;
- delete mode.match;
- }
-
- /**
- * provides the default 1 relevance to all modes
- * @type {CompilerExt}
- */
- function compileRelevance(mode, _parent) {
- // eslint-disable-next-line no-undefined
- if (mode.relevance === undefined) mode.relevance = 1;
- }
-
- // allow beforeMatch to act as a "qualifier" for the match
- // the full match begin must be [beforeMatch][begin]
- const beforeMatchExt = (mode, parent) => {
- if (!mode.beforeMatch) return;
- // starts conflicts with endsParent which we need to make sure the child
- // rule is not matched multiple times
- if (mode.starts) throw new Error("beforeMatch cannot be used with starts");
-
- const originalMode = Object.assign({}, mode);
- Object.keys(mode).forEach((key) => { delete mode[key]; });
-
- mode.keywords = originalMode.keywords;
- mode.begin = concat(originalMode.beforeMatch, lookahead(originalMode.begin));
- mode.starts = {
- relevance: 0,
- contains: [
- Object.assign(originalMode, { endsParent: true })
- ]
- };
- mode.relevance = 0;
-
- delete originalMode.beforeMatch;
- };
-
- // keywords that should have no default relevance value
- const COMMON_KEYWORDS = [
- 'of',
- 'and',
- 'for',
- 'in',
- 'not',
- 'or',
- 'if',
- 'then',
- 'parent', // common variable name
- 'list', // common variable name
- 'value' // common variable name
- ];
-
- const DEFAULT_KEYWORD_SCOPE = "keyword";
-
- /**
- * Given raw keywords from a language definition, compile them.
- *
- * @param {string | Record<string,string|string[]> | Array<string>} rawKeywords
- * @param {boolean} caseInsensitive
- */
- function compileKeywords(rawKeywords, caseInsensitive, scopeName = DEFAULT_KEYWORD_SCOPE) {
- /** @type {import("highlight.js/private").KeywordDict} */
- const compiledKeywords = Object.create(null);
-
- // input can be a string of keywords, an array of keywords, or a object with
- // named keys representing scopeName (which can then point to a string or array)
- if (typeof rawKeywords === 'string') {
- compileList(scopeName, rawKeywords.split(" "));
- } else if (Array.isArray(rawKeywords)) {
- compileList(scopeName, rawKeywords);
- } else {
- Object.keys(rawKeywords).forEach(function(scopeName) {
- // collapse all our objects back into the parent object
- Object.assign(
- compiledKeywords,
- compileKeywords(rawKeywords[scopeName], caseInsensitive, scopeName)
- );
- });
- }
- return compiledKeywords;
-
- // ---
-
- /**
- * Compiles an individual list of keywords
- *
- * Ex: "for if when while|5"
- *
- * @param {string} scopeName
- * @param {Array<string>} keywordList
- */
- function compileList(scopeName, keywordList) {
- if (caseInsensitive) {
- keywordList = keywordList.map(x => x.toLowerCase());
- }
- keywordList.forEach(function(keyword) {
- const pair = keyword.split('|');
- compiledKeywords[pair[0]] = [scopeName, scoreForKeyword(pair[0], pair[1])];
- });
- }
- }
-
- /**
- * Returns the proper score for a given keyword
- *
- * Also takes into account comment keywords, which will be scored 0 UNLESS
- * another score has been manually assigned.
- * @param {string} keyword
- * @param {string} [providedScore]
- */
- function scoreForKeyword(keyword, providedScore) {
- // manual scores always win over common keywords
- // so you can force a score of 1 if you really insist
- if (providedScore) {
- return Number(providedScore);
- }
-
- return commonKeyword(keyword) ? 0 : 1;
- }
-
- /**
- * Determines if a given keyword is common or not
- *
- * @param {string} keyword */
- function commonKeyword(keyword) {
- return COMMON_KEYWORDS.includes(keyword.toLowerCase());
- }
-
- /*
-
- For the reasoning behind this please see:
- https://github.com/highlightjs/highlight.js/issues/2880#issuecomment-747275419
-
- */
-
- /**
- * @type {Record<string, boolean>}
- */
- const seenDeprecations = {};
-
- /**
- * @param {string} message
- */
- const error = (message) => {
- console.error(message);
- };
-
- /**
- * @param {string} message
- * @param {any} args
- */
- const warn = (message, ...args) => {
- console.log(`WARN: ${message}`, ...args);
- };
-
- /**
- * @param {string} version
- * @param {string} message
- */
- const deprecated = (version, message) => {
- if (seenDeprecations[`${version}/${message}`]) return;
-
- console.log(`Deprecated as of ${version}. ${message}`);
- seenDeprecations[`${version}/${message}`] = true;
- };
-
- /* eslint-disable no-throw-literal */
-
- /**
- @typedef {import('highlight.js').CompiledMode} CompiledMode
- */
-
- const MultiClassError = new Error();
-
- /**
- * Renumbers labeled scope names to account for additional inner match
- * groups that otherwise would break everything.
- *
- * Lets say we 3 match scopes:
- *
- * { 1 => ..., 2 => ..., 3 => ... }
- *
- * So what we need is a clean match like this:
- *
- * (a)(b)(c) => [ "a", "b", "c" ]
- *
- * But this falls apart with inner match groups:
- *
- * (a)(((b)))(c) => ["a", "b", "b", "b", "c" ]
- *
- * Our scopes are now "out of alignment" and we're repeating `b` 3 times.
- * What needs to happen is the numbers are remapped:
- *
- * { 1 => ..., 2 => ..., 5 => ... }
- *
- * We also need to know that the ONLY groups that should be output
- * are 1, 2, and 5. This function handles this behavior.
- *
- * @param {CompiledMode} mode
- * @param {Array<RegExp | string>} regexes
- * @param {{key: "beginScope"|"endScope"}} opts
- */
- function remapScopeNames(mode, regexes, { key }) {
- let offset = 0;
- const scopeNames = mode[key];
- /** @type Record<number,boolean> */
- const emit = {};
- /** @type Record<number,string> */
- const positions = {};
-
- for (let i = 1; i <= regexes.length; i++) {
- positions[i + offset] = scopeNames[i];
- emit[i + offset] = true;
- offset += countMatchGroups(regexes[i - 1]);
- }
- // we use _emit to keep track of which match groups are "top-level" to avoid double
- // output from inside match groups
- mode[key] = positions;
- mode[key]._emit = emit;
- mode[key]._multi = true;
- }
-
- /**
- * @param {CompiledMode} mode
- */
- function beginMultiClass(mode) {
- if (!Array.isArray(mode.begin)) return;
-
- if (mode.skip || mode.excludeBegin || mode.returnBegin) {
- error("skip, excludeBegin, returnBegin not compatible with beginScope: {}");
- throw MultiClassError;
- }
-
- if (typeof mode.beginScope !== "object" || mode.beginScope === null) {
- error("beginScope must be object");
- throw MultiClassError;
- }
-
- remapScopeNames(mode, mode.begin, { key: "beginScope" });
- mode.begin = _rewriteBackreferences(mode.begin, { joinWith: "" });
- }
-
- /**
- * @param {CompiledMode} mode
- */
- function endMultiClass(mode) {
- if (!Array.isArray(mode.end)) return;
-
- if (mode.skip || mode.excludeEnd || mode.returnEnd) {
- error("skip, excludeEnd, returnEnd not compatible with endScope: {}");
- throw MultiClassError;
- }
-
- if (typeof mode.endScope !== "object" || mode.endScope === null) {
- error("endScope must be object");
- throw MultiClassError;
- }
-
- remapScopeNames(mode, mode.end, { key: "endScope" });
- mode.end = _rewriteBackreferences(mode.end, { joinWith: "" });
- }
-
- /**
- * this exists only to allow `scope: {}` to be used beside `match:`
- * Otherwise `beginScope` would necessary and that would look weird
-
- {
- match: [ /def/, /\w+/ ]
- scope: { 1: "keyword" , 2: "title" }
- }
-
- * @param {CompiledMode} mode
- */
- function scopeSugar(mode) {
- if (mode.scope && typeof mode.scope === "object" && mode.scope !== null) {
- mode.beginScope = mode.scope;
- delete mode.scope;
- }
- }
-
- /**
- * @param {CompiledMode} mode
- */
- function MultiClass(mode) {
- scopeSugar(mode);
-
- if (typeof mode.beginScope === "string") {
- mode.beginScope = { _wrap: mode.beginScope };
- }
- if (typeof mode.endScope === "string") {
- mode.endScope = { _wrap: mode.endScope };
- }
-
- beginMultiClass(mode);
- endMultiClass(mode);
- }
-
- /**
- @typedef {import('highlight.js').Mode} Mode
- @typedef {import('highlight.js').CompiledMode} CompiledMode
- @typedef {import('highlight.js').Language} Language
- @typedef {import('highlight.js').HLJSPlugin} HLJSPlugin
- @typedef {import('highlight.js').CompiledLanguage} CompiledLanguage
- */
-
- // compilation
-
- /**
- * Compiles a language definition result
- *
- * Given the raw result of a language definition (Language), compiles this so
- * that it is ready for highlighting code.
- * @param {Language} language
- * @returns {CompiledLanguage}
- */
- function compileLanguage(language) {
- /**
- * Builds a regex with the case sensitivity of the current language
- *
- * @param {RegExp | string} value
- * @param {boolean} [global]
- */
- function langRe(value, global) {
- return new RegExp(
- source(value),
- 'm'
- + (language.case_insensitive ? 'i' : '')
- + (language.unicodeRegex ? 'u' : '')
- + (global ? 'g' : '')
- );
- }
-
- /**
- Stores multiple regular expressions and allows you to quickly search for
- them all in a string simultaneously - returning the first match. It does
- this by creating a huge (a|b|c) regex - each individual item wrapped with ()
- and joined by `|` - using match groups to track position. When a match is
- found checking which position in the array has content allows us to figure
- out which of the original regexes / match groups triggered the match.
-
- The match object itself (the result of `Regex.exec`) is returned but also
- enhanced by merging in any meta-data that was registered with the regex.
- This is how we keep track of which mode matched, and what type of rule
- (`illegal`, `begin`, end, etc).
- */
- class MultiRegex {
- constructor() {
- this.matchIndexes = {};
- // @ts-ignore
- this.regexes = [];
- this.matchAt = 1;
- this.position = 0;
- }
-
- // @ts-ignore
- addRule(re, opts) {
- opts.position = this.position++;
- // @ts-ignore
- this.matchIndexes[this.matchAt] = opts;
- this.regexes.push([opts, re]);
- this.matchAt += countMatchGroups(re) + 1;
- }
-
- compile() {
- if (this.regexes.length === 0) {
- // avoids the need to check length every time exec is called
- // @ts-ignore
- this.exec = () => null;
- }
- const terminators = this.regexes.map(el => el[1]);
- this.matcherRe = langRe(_rewriteBackreferences(terminators, { joinWith: '|' }), true);
- this.lastIndex = 0;
- }
-
- /** @param {string} s */
- exec(s) {
- this.matcherRe.lastIndex = this.lastIndex;
- const match = this.matcherRe.exec(s);
- if (!match) { return null; }
-
- // eslint-disable-next-line no-undefined
- const i = match.findIndex((el, i) => i > 0 && el !== undefined);
- // @ts-ignore
- const matchData = this.matchIndexes[i];
- // trim off any earlier non-relevant match groups (ie, the other regex
- // match groups that make up the multi-matcher)
- match.splice(0, i);
-
- return Object.assign(match, matchData);
- }
- }
-
- /*
- Created to solve the key deficiently with MultiRegex - there is no way to
- test for multiple matches at a single location. Why would we need to do
- that? In the future a more dynamic engine will allow certain matches to be
- ignored. An example: if we matched say the 3rd regex in a large group but
- decided to ignore it - we'd need to started testing again at the 4th
- regex... but MultiRegex itself gives us no real way to do that.
-
- So what this class creates MultiRegexs on the fly for whatever search
- position they are needed.
-
- NOTE: These additional MultiRegex objects are created dynamically. For most
- grammars most of the time we will never actually need anything more than the
- first MultiRegex - so this shouldn't have too much overhead.
-
- Say this is our search group, and we match regex3, but wish to ignore it.
-
- regex1 | regex2 | regex3 | regex4 | regex5 ' ie, startAt = 0
-
- What we need is a new MultiRegex that only includes the remaining
- possibilities:
-
- regex4 | regex5 ' ie, startAt = 3
-
- This class wraps all that complexity up in a simple API... `startAt` decides
- where in the array of expressions to start doing the matching. It
- auto-increments, so if a match is found at position 2, then startAt will be
- set to 3. If the end is reached startAt will return to 0.
-
- MOST of the time the parser will be setting startAt manually to 0.
- */
- class ResumableMultiRegex {
- constructor() {
- // @ts-ignore
- this.rules = [];
- // @ts-ignore
- this.multiRegexes = [];
- this.count = 0;
-
- this.lastIndex = 0;
- this.regexIndex = 0;
- }
-
- // @ts-ignore
- getMatcher(index) {
- if (this.multiRegexes[index]) return this.multiRegexes[index];
-
- const matcher = new MultiRegex();
- this.rules.slice(index).forEach(([re, opts]) => matcher.addRule(re, opts));
- matcher.compile();
- this.multiRegexes[index] = matcher;
- return matcher;
- }
-
- resumingScanAtSamePosition() {
- return this.regexIndex !== 0;
- }
-
- considerAll() {
- this.regexIndex = 0;
- }
-
- // @ts-ignore
- addRule(re, opts) {
- this.rules.push([re, opts]);
- if (opts.type === "begin") this.count++;
- }
-
- /** @param {string} s */
- exec(s) {
- const m = this.getMatcher(this.regexIndex);
- m.lastIndex = this.lastIndex;
- let result = m.exec(s);
-
- // The following is because we have no easy way to say "resume scanning at the
- // existing position but also skip the current rule ONLY". What happens is
- // all prior rules are also skipped which can result in matching the wrong
- // thing. Example of matching "booger":
-
- // our matcher is [string, "booger", number]
- //
- // ....booger....
-
- // if "booger" is ignored then we'd really need a regex to scan from the
- // SAME position for only: [string, number] but ignoring "booger" (if it
- // was the first match), a simple resume would scan ahead who knows how
- // far looking only for "number", ignoring potential string matches (or
- // future "booger" matches that might be valid.)
-
- // So what we do: We execute two matchers, one resuming at the same
- // position, but the second full matcher starting at the position after:
-
- // /--- resume first regex match here (for [number])
- // |/---- full match here for [string, "booger", number]
- // vv
- // ....booger....
-
- // Which ever results in a match first is then used. So this 3-4 step
- // process essentially allows us to say "match at this position, excluding
- // a prior rule that was ignored".
- //
- // 1. Match "booger" first, ignore. Also proves that [string] does non match.
- // 2. Resume matching for [number]
- // 3. Match at index + 1 for [string, "booger", number]
- // 4. If #2 and #3 result in matches, which came first?
- if (this.resumingScanAtSamePosition()) {
- if (result && result.index === this.lastIndex) ; else { // use the second matcher result
- const m2 = this.getMatcher(0);
- m2.lastIndex = this.lastIndex + 1;
- result = m2.exec(s);
- }
- }
-
- if (result) {
- this.regexIndex += result.position + 1;
- if (this.regexIndex === this.count) {
- // wrap-around to considering all matches again
- this.considerAll();
- }
- }
-
- return result;
- }
- }
-
- /**
- * Given a mode, builds a huge ResumableMultiRegex that can be used to walk
- * the content and find matches.
- *
- * @param {CompiledMode} mode
- * @returns {ResumableMultiRegex}
- */
- function buildModeRegex(mode) {
- const mm = new ResumableMultiRegex();
-
- mode.contains.forEach(term => mm.addRule(term.begin, { rule: term, type: "begin" }));
-
- if (mode.terminatorEnd) {
- mm.addRule(mode.terminatorEnd, { type: "end" });
- }
- if (mode.illegal) {
- mm.addRule(mode.illegal, { type: "illegal" });
- }
-
- return mm;
- }
-
- /** skip vs abort vs ignore
- *
- * @skip - The mode is still entered and exited normally (and contains rules apply),
- * but all content is held and added to the parent buffer rather than being
- * output when the mode ends. Mostly used with `sublanguage` to build up
- * a single large buffer than can be parsed by sublanguage.
- *
- * - The mode begin ands ends normally.
- * - Content matched is added to the parent mode buffer.
- * - The parser cursor is moved forward normally.
- *
- * @abort - A hack placeholder until we have ignore. Aborts the mode (as if it
- * never matched) but DOES NOT continue to match subsequent `contains`
- * modes. Abort is bad/suboptimal because it can result in modes
- * farther down not getting applied because an earlier rule eats the
- * content but then aborts.
- *
- * - The mode does not begin.
- * - Content matched by `begin` is added to the mode buffer.
- * - The parser cursor is moved forward accordingly.
- *
- * @ignore - Ignores the mode (as if it never matched) and continues to match any
- * subsequent `contains` modes. Ignore isn't technically possible with
- * the current parser implementation.
- *
- * - The mode does not begin.
- * - Content matched by `begin` is ignored.
- * - The parser cursor is not moved forward.
- */
-
- /**
- * Compiles an individual mode
- *
- * This can raise an error if the mode contains certain detectable known logic
- * issues.
- * @param {Mode} mode
- * @param {CompiledMode | null} [parent]
- * @returns {CompiledMode | never}
- */
- function compileMode(mode, parent) {
- const cmode = /** @type CompiledMode */ (mode);
- if (mode.isCompiled) return cmode;
-
- [
- scopeClassName,
- // do this early so compiler extensions generally don't have to worry about
- // the distinction between match/begin
- compileMatch,
- MultiClass,
- beforeMatchExt
- ].forEach(ext => ext(mode, parent));
-
- language.compilerExtensions.forEach(ext => ext(mode, parent));
-
- // __beforeBegin is considered private API, internal use only
- mode.__beforeBegin = null;
-
- [
- beginKeywords,
- // do this later so compiler extensions that come earlier have access to the
- // raw array if they wanted to perhaps manipulate it, etc.
- compileIllegal,
- // default to 1 relevance if not specified
- compileRelevance
- ].forEach(ext => ext(mode, parent));
-
- mode.isCompiled = true;
-
- let keywordPattern = null;
- if (typeof mode.keywords === "object" && mode.keywords.$pattern) {
- // we need a copy because keywords might be compiled multiple times
- // so we can't go deleting $pattern from the original on the first
- // pass
- mode.keywords = Object.assign({}, mode.keywords);
- keywordPattern = mode.keywords.$pattern;
- delete mode.keywords.$pattern;
- }
- keywordPattern = keywordPattern || /\w+/;
-
- if (mode.keywords) {
- mode.keywords = compileKeywords(mode.keywords, language.case_insensitive);
- }
-
- cmode.keywordPatternRe = langRe(keywordPattern, true);
-
- if (parent) {
- if (!mode.begin) mode.begin = /\B|\b/;
- cmode.beginRe = langRe(cmode.begin);
- if (!mode.end && !mode.endsWithParent) mode.end = /\B|\b/;
- if (mode.end) cmode.endRe = langRe(cmode.end);
- cmode.terminatorEnd = source(cmode.end) || '';
- if (mode.endsWithParent && parent.terminatorEnd) {
- cmode.terminatorEnd += (mode.end ? '|' : '') + parent.terminatorEnd;
- }
- }
- if (mode.illegal) cmode.illegalRe = langRe(/** @type {RegExp | string} */ (mode.illegal));
- if (!mode.contains) mode.contains = [];
-
- mode.contains = [].concat(...mode.contains.map(function(c) {
- return expandOrCloneMode(c === 'self' ? mode : c);
- }));
- mode.contains.forEach(function(c) { compileMode(/** @type Mode */ (c), cmode); });
-
- if (mode.starts) {
- compileMode(mode.starts, parent);
- }
-
- cmode.matcher = buildModeRegex(cmode);
- return cmode;
- }
-
- if (!language.compilerExtensions) language.compilerExtensions = [];
-
- // self is not valid at the top-level
- if (language.contains && language.contains.includes('self')) {
- throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");
- }
-
- // we need a null object, which inherit will guarantee
- language.classNameAliases = inherit$1(language.classNameAliases || {});
-
- return compileMode(/** @type Mode */ (language));
- }
-
- /**
- * Determines if a mode has a dependency on it's parent or not
- *
- * If a mode does have a parent dependency then often we need to clone it if
- * it's used in multiple places so that each copy points to the correct parent,
- * where-as modes without a parent can often safely be re-used at the bottom of
- * a mode chain.
- *
- * @param {Mode | null} mode
- * @returns {boolean} - is there a dependency on the parent?
- * */
- function dependencyOnParent(mode) {
- if (!mode) return false;
-
- return mode.endsWithParent || dependencyOnParent(mode.starts);
- }
-
- /**
- * Expands a mode or clones it if necessary
- *
- * This is necessary for modes with parental dependenceis (see notes on
- * `dependencyOnParent`) and for nodes that have `variants` - which must then be
- * exploded into their own individual modes at compile time.
- *
- * @param {Mode} mode
- * @returns {Mode | Mode[]}
- * */
- function expandOrCloneMode(mode) {
- if (mode.variants && !mode.cachedVariants) {
- mode.cachedVariants = mode.variants.map(function(variant) {
- return inherit$1(mode, { variants: null }, variant);
- });
- }
-
- // EXPAND
- // if we have variants then essentially "replace" the mode with the variants
- // this happens in compileMode, where this function is called from
- if (mode.cachedVariants) {
- return mode.cachedVariants;
- }
-
- // CLONE
- // if we have dependencies on parents then we need a unique
- // instance of ourselves, so we can be reused with many
- // different parents without issue
- if (dependencyOnParent(mode)) {
- return inherit$1(mode, { starts: mode.starts ? inherit$1(mode.starts) : null });
- }
-
- if (Object.isFrozen(mode)) {
- return inherit$1(mode);
- }
-
- // no special dependency issues, just return ourselves
- return mode;
- }
-
- var version = "11.7.0";
-
- class HTMLInjectionError extends Error {
- constructor(reason, html) {
- super(reason);
- this.name = "HTMLInjectionError";
- this.html = html;
- }
- }
-
- /*
- Syntax highlighting with language autodetection.
- https://highlightjs.org/
- */
-
- /**
- @typedef {import('highlight.js').Mode} Mode
- @typedef {import('highlight.js').CompiledMode} CompiledMode
- @typedef {import('highlight.js').CompiledScope} CompiledScope
- @typedef {import('highlight.js').Language} Language
- @typedef {import('highlight.js').HLJSApi} HLJSApi
- @typedef {import('highlight.js').HLJSPlugin} HLJSPlugin
- @typedef {import('highlight.js').PluginEvent} PluginEvent
- @typedef {import('highlight.js').HLJSOptions} HLJSOptions
- @typedef {import('highlight.js').LanguageFn} LanguageFn
- @typedef {import('highlight.js').HighlightedHTMLElement} HighlightedHTMLElement
- @typedef {import('highlight.js').BeforeHighlightContext} BeforeHighlightContext
- @typedef {import('highlight.js/private').MatchType} MatchType
- @typedef {import('highlight.js/private').KeywordData} KeywordData
- @typedef {import('highlight.js/private').EnhancedMatch} EnhancedMatch
- @typedef {import('highlight.js/private').AnnotatedError} AnnotatedError
- @typedef {import('highlight.js').AutoHighlightResult} AutoHighlightResult
- @typedef {import('highlight.js').HighlightOptions} HighlightOptions
- @typedef {import('highlight.js').HighlightResult} HighlightResult
- */
-
-
- const escape = escapeHTML;
- const inherit = inherit$1;
- const NO_MATCH = Symbol("nomatch");
- const MAX_KEYWORD_HITS = 7;
-
- /**
- * @param {any} hljs - object that is extended (legacy)
- * @returns {HLJSApi}
- */
- const HLJS = function(hljs) {
- // Global internal variables used within the highlight.js library.
- /** @type {Record<string, Language>} */
- const languages = Object.create(null);
- /** @type {Record<string, string>} */
- const aliases = Object.create(null);
- /** @type {HLJSPlugin[]} */
- const plugins = [];
-
- // safe/production mode - swallows more errors, tries to keep running
- // even if a single syntax or parse hits a fatal error
- let SAFE_MODE = true;
- const LANGUAGE_NOT_FOUND = "Could not find the language '{}', did you forget to load/include a language module?";
- /** @type {Language} */
- const PLAINTEXT_LANGUAGE = { disableAutodetect: true, name: 'Plain text', contains: [] };
-
- // Global options used when within external APIs. This is modified when
- // calling the `hljs.configure` function.
- /** @type HLJSOptions */
- let options = {
- ignoreUnescapedHTML: false,
- throwUnescapedHTML: false,
- noHighlightRe: /^(no-?highlight)$/i,
- languageDetectRe: /\blang(?:uage)?-([\w-]+)\b/i,
- classPrefix: 'hljs-',
- cssSelector: 'pre code',
- languages: null,
- // beta configuration options, subject to change, welcome to discuss
- // https://github.com/highlightjs/highlight.js/issues/1086
- __emitter: TokenTreeEmitter
- };
-
- /* Utility functions */
-
- /**
- * Tests a language name to see if highlighting should be skipped
- * @param {string} languageName
- */
- function shouldNotHighlight(languageName) {
- return options.noHighlightRe.test(languageName);
- }
-
- /**
- * @param {HighlightedHTMLElement} block - the HTML element to determine language for
- */
- function blockLanguage(block) {
- let classes = block.className + ' ';
-
- classes += block.parentNode ? block.parentNode.className : '';
-
- // language-* takes precedence over non-prefixed class names.
- const match = options.languageDetectRe.exec(classes);
- if (match) {
- const language = getLanguage(match[1]);
- if (!language) {
- warn(LANGUAGE_NOT_FOUND.replace("{}", match[1]));
- warn("Falling back to no-highlight mode for this block.", block);
- }
- return language ? match[1] : 'no-highlight';
- }
-
- return classes
- .split(/\s+/)
- .find((_class) => shouldNotHighlight(_class) || getLanguage(_class));
- }
-
- /**
- * Core highlighting function.
- *
- * OLD API
- * highlight(lang, code, ignoreIllegals, continuation)
- *
- * NEW API
- * highlight(code, {lang, ignoreIllegals})
- *
- * @param {string} codeOrLanguageName - the language to use for highlighting
- * @param {string | HighlightOptions} optionsOrCode - the code to highlight
- * @param {boolean} [ignoreIllegals] - whether to ignore illegal matches, default is to bail
- *
- * @returns {HighlightResult} Result - an object that represents the result
- * @property {string} language - the language name
- * @property {number} relevance - the relevance score
- * @property {string} value - the highlighted HTML code
- * @property {string} code - the original raw code
- * @property {CompiledMode} top - top of the current mode stack
- * @property {boolean} illegal - indicates whether any illegal matches were found
- */
- function highlight(codeOrLanguageName, optionsOrCode, ignoreIllegals) {
- let code = "";
- let languageName = "";
- if (typeof optionsOrCode === "object") {
- code = codeOrLanguageName;
- ignoreIllegals = optionsOrCode.ignoreIllegals;
- languageName = optionsOrCode.language;
- } else {
- // old API
- deprecated("10.7.0", "highlight(lang, code, ...args) has been deprecated.");
- deprecated("10.7.0", "Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277");
- languageName = codeOrLanguageName;
- code = optionsOrCode;
- }
-
- // https://github.com/highlightjs/highlight.js/issues/3149
- // eslint-disable-next-line no-undefined
- if (ignoreIllegals === undefined) { ignoreIllegals = true; }
-
- /** @type {BeforeHighlightContext} */
- const context = {
- code,
- language: languageName
- };
- // the plugin can change the desired language or the code to be highlighted
- // just be changing the object it was passed
- fire("before:highlight", context);
-
- // a before plugin can usurp the result completely by providing it's own
- // in which case we don't even need to call highlight
- const result = context.result
- ? context.result
- : _highlight(context.language, context.code, ignoreIllegals);
-
- result.code = context.code;
- // the plugin can change anything in result to suite it
- fire("after:highlight", result);
-
- return result;
- }
-
- /**
- * private highlight that's used internally and does not fire callbacks
- *
- * @param {string} languageName - the language to use for highlighting
- * @param {string} codeToHighlight - the code to highlight
- * @param {boolean?} [ignoreIllegals] - whether to ignore illegal matches, default is to bail
- * @param {CompiledMode?} [continuation] - current continuation mode, if any
- * @returns {HighlightResult} - result of the highlight operation
- */
- function _highlight(languageName, codeToHighlight, ignoreIllegals, continuation) {
- const keywordHits = Object.create(null);
-
- /**
- * Return keyword data if a match is a keyword
- * @param {CompiledMode} mode - current mode
- * @param {string} matchText - the textual match
- * @returns {KeywordData | false}
- */
- function keywordData(mode, matchText) {
- return mode.keywords[matchText];
- }
-
- function processKeywords() {
- if (!top.keywords) {
- emitter.addText(modeBuffer);
- return;
- }
-
- let lastIndex = 0;
- top.keywordPatternRe.lastIndex = 0;
- let match = top.keywordPatternRe.exec(modeBuffer);
- let buf = "";
-
- while (match) {
- buf += modeBuffer.substring(lastIndex, match.index);
- const word = language.case_insensitive ? match[0].toLowerCase() : match[0];
- const data = keywordData(top, word);
- if (data) {
- const [kind, keywordRelevance] = data;
- emitter.addText(buf);
- buf = "";
-
- keywordHits[word] = (keywordHits[word] || 0) + 1;
- if (keywordHits[word] <= MAX_KEYWORD_HITS) relevance += keywordRelevance;
- if (kind.startsWith("_")) {
- // _ implied for relevance only, do not highlight
- // by applying a class name
- buf += match[0];
- } else {
- const cssClass = language.classNameAliases[kind] || kind;
- emitter.addKeyword(match[0], cssClass);
- }
- } else {
- buf += match[0];
- }
- lastIndex = top.keywordPatternRe.lastIndex;
- match = top.keywordPatternRe.exec(modeBuffer);
- }
- buf += modeBuffer.substring(lastIndex);
- emitter.addText(buf);
- }
-
- function processSubLanguage() {
- if (modeBuffer === "") return;
- /** @type HighlightResult */
- let result = null;
-
- if (typeof top.subLanguage === 'string') {
- if (!languages[top.subLanguage]) {
- emitter.addText(modeBuffer);
- return;
- }
- result = _highlight(top.subLanguage, modeBuffer, true, continuations[top.subLanguage]);
- continuations[top.subLanguage] = /** @type {CompiledMode} */ (result._top);
- } else {
- result = highlightAuto(modeBuffer, top.subLanguage.length ? top.subLanguage : null);
- }
-
- // Counting embedded language score towards the host language may be disabled
- // with zeroing the containing mode relevance. Use case in point is Markdown that
- // allows XML everywhere and makes every XML snippet to have a much larger Markdown
- // score.
- if (top.relevance > 0) {
- relevance += result.relevance;
- }
- emitter.addSublanguage(result._emitter, result.language);
- }
-
- function processBuffer() {
- if (top.subLanguage != null) {
- processSubLanguage();
- } else {
- processKeywords();
- }
- modeBuffer = '';
- }
-
- /**
- * @param {CompiledScope} scope
- * @param {RegExpMatchArray} match
- */
- function emitMultiClass(scope, match) {
- let i = 1;
- const max = match.length - 1;
- while (i <= max) {
- if (!scope._emit[i]) { i++; continue; }
- const klass = language.classNameAliases[scope[i]] || scope[i];
- const text = match[i];
- if (klass) {
- emitter.addKeyword(text, klass);
- } else {
- modeBuffer = text;
- processKeywords();
- modeBuffer = "";
- }
- i++;
- }
- }
-
- /**
- * @param {CompiledMode} mode - new mode to start
- * @param {RegExpMatchArray} match
- */
- function startNewMode(mode, match) {
- if (mode.scope && typeof mode.scope === "string") {
- emitter.openNode(language.classNameAliases[mode.scope] || mode.scope);
- }
- if (mode.beginScope) {
- // beginScope just wraps the begin match itself in a scope
- if (mode.beginScope._wrap) {
- emitter.addKeyword(modeBuffer, language.classNameAliases[mode.beginScope._wrap] || mode.beginScope._wrap);
- modeBuffer = "";
- } else if (mode.beginScope._multi) {
- // at this point modeBuffer should just be the match
- emitMultiClass(mode.beginScope, match);
- modeBuffer = "";
- }
- }
-
- top = Object.create(mode, { parent: { value: top } });
- return top;
- }
-
- /**
- * @param {CompiledMode } mode - the mode to potentially end
- * @param {RegExpMatchArray} match - the latest match
- * @param {string} matchPlusRemainder - match plus remainder of content
- * @returns {CompiledMode | void} - the next mode, or if void continue on in current mode
- */
- function endOfMode(mode, match, matchPlusRemainder) {
- let matched = startsWith(mode.endRe, matchPlusRemainder);
-
- if (matched) {
- if (mode["on:end"]) {
- const resp = new Response(mode);
- mode["on:end"](match, resp);
- if (resp.isMatchIgnored) matched = false;
- }
-
- if (matched) {
- while (mode.endsParent && mode.parent) {
- mode = mode.parent;
- }
- return mode;
- }
- }
- // even if on:end fires an `ignore` it's still possible
- // that we might trigger the end node because of a parent mode
- if (mode.endsWithParent) {
- return endOfMode(mode.parent, match, matchPlusRemainder);
- }
- }
-
- /**
- * Handle matching but then ignoring a sequence of text
- *
- * @param {string} lexeme - string containing full match text
- */
- function doIgnore(lexeme) {
- if (top.matcher.regexIndex === 0) {
- // no more regexes to potentially match here, so we move the cursor forward one
- // space
- modeBuffer += lexeme[0];
- return 1;
- } else {
- // no need to move the cursor, we still have additional regexes to try and
- // match at this very spot
- resumeScanAtSamePosition = true;
- return 0;
- }
- }
-
- /**
- * Handle the start of a new potential mode match
- *
- * @param {EnhancedMatch} match - the current match
- * @returns {number} how far to advance the parse cursor
- */
- function doBeginMatch(match) {
- const lexeme = match[0];
- const newMode = match.rule;
-
- const resp = new Response(newMode);
- // first internal before callbacks, then the public ones
- const beforeCallbacks = [newMode.__beforeBegin, newMode["on:begin"]];
- for (const cb of beforeCallbacks) {
- if (!cb) continue;
- cb(match, resp);
- if (resp.isMatchIgnored) return doIgnore(lexeme);
- }
-
- if (newMode.skip) {
- modeBuffer += lexeme;
- } else {
- if (newMode.excludeBegin) {
- modeBuffer += lexeme;
- }
- processBuffer();
- if (!newMode.returnBegin && !newMode.excludeBegin) {
- modeBuffer = lexeme;
- }
- }
- startNewMode(newMode, match);
- return newMode.returnBegin ? 0 : lexeme.length;
- }
-
- /**
- * Handle the potential end of mode
- *
- * @param {RegExpMatchArray} match - the current match
- */
- function doEndMatch(match) {
- const lexeme = match[0];
- const matchPlusRemainder = codeToHighlight.substring(match.index);
-
- const endMode = endOfMode(top, match, matchPlusRemainder);
- if (!endMode) { return NO_MATCH; }
-
- const origin = top;
- if (top.endScope && top.endScope._wrap) {
- processBuffer();
- emitter.addKeyword(lexeme, top.endScope._wrap);
- } else if (top.endScope && top.endScope._multi) {
- processBuffer();
- emitMultiClass(top.endScope, match);
- } else if (origin.skip) {
- modeBuffer += lexeme;
- } else {
- if (!(origin.returnEnd || origin.excludeEnd)) {
- modeBuffer += lexeme;
- }
- processBuffer();
- if (origin.excludeEnd) {
- modeBuffer = lexeme;
- }
- }
- do {
- if (top.scope) {
- emitter.closeNode();
- }
- if (!top.skip && !top.subLanguage) {
- relevance += top.relevance;
- }
- top = top.parent;
- } while (top !== endMode.parent);
- if (endMode.starts) {
- startNewMode(endMode.starts, match);
- }
- return origin.returnEnd ? 0 : lexeme.length;
- }
-
- function processContinuations() {
- const list = [];
- for (let current = top; current !== language; current = current.parent) {
- if (current.scope) {
- list.unshift(current.scope);
- }
- }
- list.forEach(item => emitter.openNode(item));
- }
-
- /** @type {{type?: MatchType, index?: number, rule?: Mode}}} */
- let lastMatch = {};
-
- /**
- * Process an individual match
- *
- * @param {string} textBeforeMatch - text preceding the match (since the last match)
- * @param {EnhancedMatch} [match] - the match itself
- */
- function processLexeme(textBeforeMatch, match) {
- const lexeme = match && match[0];
-
- // add non-matched text to the current mode buffer
- modeBuffer += textBeforeMatch;
-
- if (lexeme == null) {
- processBuffer();
- return 0;
- }
-
- // we've found a 0 width match and we're stuck, so we need to advance
- // this happens when we have badly behaved rules that have optional matchers to the degree that
- // sometimes they can end up matching nothing at all
- // Ref: https://github.com/highlightjs/highlight.js/issues/2140
- if (lastMatch.type === "begin" && match.type === "end" && lastMatch.index === match.index && lexeme === "") {
- // spit the "skipped" character that our regex choked on back into the output sequence
- modeBuffer += codeToHighlight.slice(match.index, match.index + 1);
- if (!SAFE_MODE) {
- /** @type {AnnotatedError} */
- const err = new Error(`0 width match regex (${languageName})`);
- err.languageName = languageName;
- err.badRule = lastMatch.rule;
- throw err;
- }
- return 1;
- }
- lastMatch = match;
-
- if (match.type === "begin") {
- return doBeginMatch(match);
- } else if (match.type === "illegal" && !ignoreIllegals) {
- // illegal match, we do not continue processing
- /** @type {AnnotatedError} */
- const err = new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.scope || '<unnamed>') + '"');
- err.mode = top;
- throw err;
- } else if (match.type === "end") {
- const processed = doEndMatch(match);
- if (processed !== NO_MATCH) {
- return processed;
- }
- }
-
- // edge case for when illegal matches $ (end of line) which is technically
- // a 0 width match but not a begin/end match so it's not caught by the
- // first handler (when ignoreIllegals is true)
- if (match.type === "illegal" && lexeme === "") {
- // advance so we aren't stuck in an infinite loop
- return 1;
- }
-
- // infinite loops are BAD, this is a last ditch catch all. if we have a
- // decent number of iterations yet our index (cursor position in our
- // parsing) still 3x behind our index then something is very wrong
- // so we bail
- if (iterations > 100000 && iterations > match.index * 3) {
- const err = new Error('potential infinite loop, way more iterations than matches');
- throw err;
- }
-
- /*
- Why might be find ourselves here? An potential end match that was
- triggered but could not be completed. IE, `doEndMatch` returned NO_MATCH.
- (this could be because a callback requests the match be ignored, etc)
-
- This causes no real harm other than stopping a few times too many.
- */
-
- modeBuffer += lexeme;
- return lexeme.length;
- }
-
- const language = getLanguage(languageName);
- if (!language) {
- error(LANGUAGE_NOT_FOUND.replace("{}", languageName));
- throw new Error('Unknown language: "' + languageName + '"');
- }
-
- const md = compileLanguage(language);
- let result = '';
- /** @type {CompiledMode} */
- let top = continuation || md;
- /** @type Record<string,CompiledMode> */
- const continuations = {}; // keep continuations for sub-languages
- const emitter = new options.__emitter(options);
- processContinuations();
- let modeBuffer = '';
- let relevance = 0;
- let index = 0;
- let iterations = 0;
- let resumeScanAtSamePosition = false;
-
- try {
- top.matcher.considerAll();
-
- for (;;) {
- iterations++;
- if (resumeScanAtSamePosition) {
- // only regexes not matched previously will now be
- // considered for a potential match
- resumeScanAtSamePosition = false;
- } else {
- top.matcher.considerAll();
- }
- top.matcher.lastIndex = index;
-
- const match = top.matcher.exec(codeToHighlight);
- // console.log("match", match[0], match.rule && match.rule.begin)
-
- if (!match) break;
-
- const beforeMatch = codeToHighlight.substring(index, match.index);
- const processedCount = processLexeme(beforeMatch, match);
- index = match.index + processedCount;
- }
- processLexeme(codeToHighlight.substring(index));
- emitter.closeAllNodes();
- emitter.finalize();
- result = emitter.toHTML();
-
- return {
- language: languageName,
- value: result,
- relevance: relevance,
- illegal: false,
- _emitter: emitter,
- _top: top
- };
- } catch (err) {
- if (err.message && err.message.includes('Illegal')) {
- return {
- language: languageName,
- value: escape(codeToHighlight),
- illegal: true,
- relevance: 0,
- _illegalBy: {
- message: err.message,
- index: index,
- context: codeToHighlight.slice(index - 100, index + 100),
- mode: err.mode,
- resultSoFar: result
- },
- _emitter: emitter
- };
- } else if (SAFE_MODE) {
- return {
- language: languageName,
- value: escape(codeToHighlight),
- illegal: false,
- relevance: 0,
- errorRaised: err,
- _emitter: emitter,
- _top: top
- };
- } else {
- throw err;
- }
- }
- }
-
- /**
- * returns a valid highlight result, without actually doing any actual work,
- * auto highlight starts with this and it's possible for small snippets that
- * auto-detection may not find a better match
- * @param {string} code
- * @returns {HighlightResult}
- */
- function justTextHighlightResult(code) {
- const result = {
- value: escape(code),
- illegal: false,
- relevance: 0,
- _top: PLAINTEXT_LANGUAGE,
- _emitter: new options.__emitter(options)
- };
- result._emitter.addText(code);
- return result;
- }
-
- /**
- Highlighting with language detection. Accepts a string with the code to
- highlight. Returns an object with the following properties:
-
- - language (detected language)
- - relevance (int)
- - value (an HTML string with highlighting markup)
- - secondBest (object with the same structure for second-best heuristically
- detected language, may be absent)
-
- @param {string} code
- @param {Array<string>} [languageSubset]
- @returns {AutoHighlightResult}
- */
- function highlightAuto(code, languageSubset) {
- languageSubset = languageSubset || options.languages || Object.keys(languages);
- const plaintext = justTextHighlightResult(code);
-
- const results = languageSubset.filter(getLanguage).filter(autoDetection).map(name =>
- _highlight(name, code, false)
- );
- results.unshift(plaintext); // plaintext is always an option
-
- const sorted = results.sort((a, b) => {
- // sort base on relevance
- if (a.relevance !== b.relevance) return b.relevance - a.relevance;
-
- // always award the tie to the base language
- // ie if C++ and Arduino are tied, it's more likely to be C++
- if (a.language && b.language) {
- if (getLanguage(a.language).supersetOf === b.language) {
- return 1;
- } else if (getLanguage(b.language).supersetOf === a.language) {
- return -1;
- }
- }
-
- // otherwise say they are equal, which has the effect of sorting on
- // relevance while preserving the original ordering - which is how ties
- // have historically been settled, ie the language that comes first always
- // wins in the case of a tie
- return 0;
- });
-
- const [best, secondBest] = sorted;
-
- /** @type {AutoHighlightResult} */
- const result = best;
- result.secondBest = secondBest;
-
- return result;
- }
-
- /**
- * Builds new class name for block given the language name
- *
- * @param {HTMLElement} element
- * @param {string} [currentLang]
- * @param {string} [resultLang]
- */
- function updateClassName(element, currentLang, resultLang) {
- const language = (currentLang && aliases[currentLang]) || resultLang;
-
- element.classList.add("hljs");
- element.classList.add(`language-${language}`);
- }
-
- /**
- * Applies highlighting to a DOM node containing code.
- *
- * @param {HighlightedHTMLElement} element - the HTML element to highlight
- */
- function highlightElement(element) {
- /** @type HTMLElement */
- let node = null;
- const language = blockLanguage(element);
-
- if (shouldNotHighlight(language)) return;
-
- fire("before:highlightElement",
- { el: element, language: language });
-
- // we should be all text, no child nodes (unescaped HTML) - this is possibly
- // an HTML injection attack - it's likely too late if this is already in
- // production (the code has likely already done its damage by the time
- // we're seeing it)... but we yell loudly about this so that hopefully it's
- // more likely to be caught in development before making it to production
- if (element.children.length > 0) {
- if (!options.ignoreUnescapedHTML) {
- console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk.");
- console.warn("https://github.com/highlightjs/highlight.js/wiki/security");
- console.warn("The element with unescaped HTML:");
- console.warn(element);
- }
- if (options.throwUnescapedHTML) {
- const err = new HTMLInjectionError(
- "One of your code blocks includes unescaped HTML.",
- element.innerHTML
- );
- throw err;
- }
- }
-
- node = element;
- const text = node.textContent;
- const result = language ? highlight(text, { language, ignoreIllegals: true }) : highlightAuto(text);
-
- element.innerHTML = result.value;
- updateClassName(element, language, result.language);
- element.result = {
- language: result.language,
- // TODO: remove with version 11.0
- re: result.relevance,
- relevance: result.relevance
- };
- if (result.secondBest) {
- element.secondBest = {
- language: result.secondBest.language,
- relevance: result.secondBest.relevance
- };
- }
-
- fire("after:highlightElement", { el: element, result, text });
- }
-
- /**
- * Updates highlight.js global options with the passed options
- *
- * @param {Partial<HLJSOptions>} userOptions
- */
- function configure(userOptions) {
- options = inherit(options, userOptions);
- }
-
- // TODO: remove v12, deprecated
- const initHighlighting = () => {
- highlightAll();
- deprecated("10.6.0", "initHighlighting() deprecated. Use highlightAll() now.");
- };
-
- // TODO: remove v12, deprecated
- function initHighlightingOnLoad() {
- highlightAll();
- deprecated("10.6.0", "initHighlightingOnLoad() deprecated. Use highlightAll() now.");
- }
-
- let wantsHighlight = false;
-
- /**
- * auto-highlights all pre>code elements on the page
- */
- function highlightAll() {
- // if we are called too early in the loading process
- if (document.readyState === "loading") {
- wantsHighlight = true;
- return;
- }
-
- const blocks = document.querySelectorAll(options.cssSelector);
- blocks.forEach(highlightElement);
- }
-
- function boot() {
- // if a highlight was requested before DOM was loaded, do now
- if (wantsHighlight) highlightAll();
- }
-
- // make sure we are in the browser environment
- if (typeof window !== 'undefined' && window.addEventListener) {
- window.addEventListener('DOMContentLoaded', boot, false);
- }
-
- /**
- * Register a language grammar module
- *
- * @param {string} languageName
- * @param {LanguageFn} languageDefinition
- */
- function registerLanguage(languageName, languageDefinition) {
- let lang = null;
- try {
- lang = languageDefinition(hljs);
- } catch (error$1) {
- error("Language definition for '{}' could not be registered.".replace("{}", languageName));
- // hard or soft error
- if (!SAFE_MODE) { throw error$1; } else { error(error$1); }
- // languages that have serious errors are replaced with essentially a
- // "plaintext" stand-in so that the code blocks will still get normal
- // css classes applied to them - and one bad language won't break the
- // entire highlighter
- lang = PLAINTEXT_LANGUAGE;
- }
- // give it a temporary name if it doesn't have one in the meta-data
- if (!lang.name) lang.name = languageName;
- languages[languageName] = lang;
- lang.rawDefinition = languageDefinition.bind(null, hljs);
-
- if (lang.aliases) {
- registerAliases(lang.aliases, { languageName });
- }
- }
-
- /**
- * Remove a language grammar module
- *
- * @param {string} languageName
- */
- function unregisterLanguage(languageName) {
- delete languages[languageName];
- for (const alias of Object.keys(aliases)) {
- if (aliases[alias] === languageName) {
- delete aliases[alias];
- }
- }
- }
-
- /**
- * @returns {string[]} List of language internal names
- */
- function listLanguages() {
- return Object.keys(languages);
- }
-
- /**
- * @param {string} name - name of the language to retrieve
- * @returns {Language | undefined}
- */
- function getLanguage(name) {
- name = (name || '').toLowerCase();
- return languages[name] || languages[aliases[name]];
- }
-
- /**
- *
- * @param {string|string[]} aliasList - single alias or list of aliases
- * @param {{languageName: string}} opts
- */
- function registerAliases(aliasList, { languageName }) {
- if (typeof aliasList === 'string') {
- aliasList = [aliasList];
- }
- aliasList.forEach(alias => { aliases[alias.toLowerCase()] = languageName; });
- }
-
- /**
- * Determines if a given language has auto-detection enabled
- * @param {string} name - name of the language
- */
- function autoDetection(name) {
- const lang = getLanguage(name);
- return lang && !lang.disableAutodetect;
- }
-
- /**
- * Upgrades the old highlightBlock plugins to the new
- * highlightElement API
- * @param {HLJSPlugin} plugin
- */
- function upgradePluginAPI(plugin) {
- // TODO: remove with v12
- if (plugin["before:highlightBlock"] && !plugin["before:highlightElement"]) {
- plugin["before:highlightElement"] = (data) => {
- plugin["before:highlightBlock"](
- Object.assign({ block: data.el }, data)
- );
- };
- }
- if (plugin["after:highlightBlock"] && !plugin["after:highlightElement"]) {
- plugin["after:highlightElement"] = (data) => {
- plugin["after:highlightBlock"](
- Object.assign({ block: data.el }, data)
- );
- };
- }
- }
-
- /**
- * @param {HLJSPlugin} plugin
- */
- function addPlugin(plugin) {
- upgradePluginAPI(plugin);
- plugins.push(plugin);
- }
-
- /**
- *
- * @param {PluginEvent} event
- * @param {any} args
- */
- function fire(event, args) {
- const cb = event;
- plugins.forEach(function(plugin) {
- if (plugin[cb]) {
- plugin[cb](args);
- }
- });
- }
-
- /**
- * DEPRECATED
- * @param {HighlightedHTMLElement} el
- */
- function deprecateHighlightBlock(el) {
- deprecated("10.7.0", "highlightBlock will be removed entirely in v12.0");
- deprecated("10.7.0", "Please use highlightElement now.");
-
- return highlightElement(el);
- }
-
- /* Interface definition */
- Object.assign(hljs, {
- highlight,
- highlightAuto,
- highlightAll,
- highlightElement,
- // TODO: Remove with v12 API
- highlightBlock: deprecateHighlightBlock,
- configure,
- initHighlighting,
- initHighlightingOnLoad,
- registerLanguage,
- unregisterLanguage,
- listLanguages,
- getLanguage,
- registerAliases,
- autoDetection,
- inherit,
- addPlugin
- });
-
- hljs.debugMode = function() { SAFE_MODE = false; };
- hljs.safeMode = function() { SAFE_MODE = true; };
- hljs.versionString = version;
-
- hljs.regex = {
- concat: concat,
- lookahead: lookahead,
- either: either,
- optional: optional,
- anyNumberOfTimes: anyNumberOfTimes
- };
-
- for (const key in MODES$1) {
- // @ts-ignore
- if (typeof MODES$1[key] === "object") {
- // @ts-ignore
- deepFreezeEs6.exports(MODES$1[key]);
- }
- }
-
- // merge all the modes/regexes into our main object
- Object.assign(hljs, MODES$1);
-
- return hljs;
- };
-
- // export an "instance" of the highlighter
- var HighlightJS = HLJS({});
-
- /*
- Language: Gleam
- Description: Gleam is a general-purpose functional language, which is compiled to both Erlang and JS
- Category: functional
- */
-
- /** @type LanguageFn */
- function gleam (hljs) {
- const KEYWORDS =
- "as assert case const external fn if import let " +
- "use opaque pub todo try tuple type";
- const STRING = {
- className: "string",
- variants: [{ begin: /"/, end: /"/ }],
- contains: [hljs.BACKSLASH_ESCAPE],
- relevance: 0,
- };
- const NAME = {
- className: "variable",
- begin: "\\b[a-z][a-z0-9_]*\\b",
- relevance: 0,
- };
- const DISCARD_NAME = {
- className: "comment",
- begin: "\\b_[a-z][a-z0-9_]*\\b",
- relevance: 0,
- };
- const NUMBER = {
- className: "number",
- variants: [
- {
- // binary
- begin: "\\b0[bB](?:_?[01]+)+",
- },
- {
- // octal
- begin: "\\b0[oO](?:_?[0-7]+)+",
- },
- {
- // hex
- begin: "\\b0[xX](?:_?[0-9a-fA-F]+)+",
- },
- {
- // dec, float
- begin: "\\b\\d(?:_?\\d+)*(?:\\.(?:\\d(?:_?\\d+)*)*)?",
- },
- ],
- relevance: 0,
- };
-
- return {
- name: "Gleam",
- aliases: ["gleam"],
- contains: [
- hljs.C_LINE_COMMENT_MODE,
- STRING,
- {
- // bit string
- begin: "&lt;&lt;",
- end: ">>",
- contains: [
- {
- className: "keyword",
- beginKeywords:
- "binary bytes int float bit_string bits utf8 utf16 utf32 " +
- "utf8_codepoint utf16_codepoint utf32_codepoint signed unsigned " +
- "big little native unit size",
- },
- KEYWORDS,
- STRING,
- NAME,
- DISCARD_NAME,
- NUMBER,
- ],
- relevance: 10,
- },
- {
- className: "function",
- beginKeywords: "fn",
- end: "\\(",
- excludeEnd: true,
- contains: [
- {
- className: "title",
- begin: "[a-z][a-z0-9_]*\\w*",
- relevance: 0,
- },
- ],
- },
- {
- className: "keyword",
- beginKeywords: KEYWORDS,
- },
- {
- // Type names and constructors
- className: "title",
- begin: "\\b[A-Z][A-Za-z0-9]*\\b",
- relevance: 0,
- },
- {
- className: "operator",
- begin: "[+\\-*/%!=<>&|.]+",
- relevance: 0,
- },
- NAME,
- DISCARD_NAME,
- NUMBER,
- ],
- };
- }
-
- /*
- Language: Erlang
- Description: Erlang is a general-purpose functional language, with strict evaluation, single assignment, and dynamic typing.
- Author: Nikolay Zakharov <nikolay.desh@gmail.com>, Dmitry Kovega <arhibot@gmail.com>
- Website: https://www.erlang.org
- Category: functional
- */
-
- /** @type LanguageFn */
- function erlang(hljs) {
- const BASIC_ATOM_RE = '[a-z\'][a-zA-Z0-9_\']*';
- const FUNCTION_NAME_RE = '(' + BASIC_ATOM_RE + ':' + BASIC_ATOM_RE + '|' + BASIC_ATOM_RE + ')';
- const ERLANG_RESERVED = {
- keyword:
- 'after and andalso|10 band begin bnot bor bsl bzr bxor case catch cond div end fun if '
- + 'let not of orelse|10 query receive rem try when xor',
- literal:
- 'false true'
- };
-
- const COMMENT = hljs.COMMENT('%', '$');
- const NUMBER = {
- className: 'number',
- begin: '\\b(\\d+(_\\d+)*#[a-fA-F0-9]+(_[a-fA-F0-9]+)*|\\d+(_\\d+)*(\\.\\d+(_\\d+)*)?([eE][-+]?\\d+)?)',
- relevance: 0
- };
- const NAMED_FUN = { begin: 'fun\\s+' + BASIC_ATOM_RE + '/\\d+' };
- const FUNCTION_CALL = {
- begin: FUNCTION_NAME_RE + '\\(',
- end: '\\)',
- returnBegin: true,
- relevance: 0,
- contains: [
- {
- begin: FUNCTION_NAME_RE,
- relevance: 0
- },
- {
- begin: '\\(',
- end: '\\)',
- endsWithParent: true,
- returnEnd: true,
- relevance: 0
- // "contains" defined later
- }
- ]
- };
- const TUPLE = {
- begin: /\{/,
- end: /\}/,
- relevance: 0
- // "contains" defined later
- };
- const VAR1 = {
- begin: '\\b_([A-Z][A-Za-z0-9_]*)?',
- relevance: 0
- };
- const VAR2 = {
- begin: '[A-Z][a-zA-Z0-9_]*',
- relevance: 0
- };
- const RECORD_ACCESS = {
- begin: '#' + hljs.UNDERSCORE_IDENT_RE,
- relevance: 0,
- returnBegin: true,
- contains: [
- {
- begin: '#' + hljs.UNDERSCORE_IDENT_RE,
- relevance: 0
- },
- {
- begin: /\{/,
- end: /\}/,
- relevance: 0
- // "contains" defined later
- }
- ]
- };
-
- const BLOCK_STATEMENTS = {
- beginKeywords: 'fun receive if try case',
- end: 'end',
- keywords: ERLANG_RESERVED
- };
- BLOCK_STATEMENTS.contains = [
- COMMENT,
- NAMED_FUN,
- hljs.inherit(hljs.APOS_STRING_MODE, { className: '' }),
- BLOCK_STATEMENTS,
- FUNCTION_CALL,
- hljs.QUOTE_STRING_MODE,
- NUMBER,
- TUPLE,
- VAR1,
- VAR2,
- RECORD_ACCESS
- ];
-
- const BASIC_MODES = [
- COMMENT,
- NAMED_FUN,
- BLOCK_STATEMENTS,
- FUNCTION_CALL,
- hljs.QUOTE_STRING_MODE,
- NUMBER,
- TUPLE,
- VAR1,
- VAR2,
- RECORD_ACCESS
- ];
- FUNCTION_CALL.contains[1].contains = BASIC_MODES;
- TUPLE.contains = BASIC_MODES;
- RECORD_ACCESS.contains[1].contains = BASIC_MODES;
-
- const DIRECTIVES = [
- "-module",
- "-record",
- "-undef",
- "-export",
- "-ifdef",
- "-ifndef",
- "-author",
- "-copyright",
- "-doc",
- "-vsn",
- "-import",
- "-include",
- "-include_lib",
- "-compile",
- "-define",
- "-else",
- "-endif",
- "-file",
- "-behaviour",
- "-behavior",
- "-spec"
- ];
-
- const PARAMS = {
- className: 'params',
- begin: '\\(',
- end: '\\)',
- contains: BASIC_MODES
- };
- return {
- name: 'Erlang',
- aliases: [ 'erl' ],
- keywords: ERLANG_RESERVED,
- illegal: '(</|\\*=|\\+=|-=|/\\*|\\*/|\\(\\*|\\*\\))',
- contains: [
- {
- className: 'function',
- begin: '^' + BASIC_ATOM_RE + '\\s*\\(',
- end: '->',
- returnBegin: true,
- illegal: '\\(|#|//|/\\*|\\\\|:|;',
- contains: [
- PARAMS,
- hljs.inherit(hljs.TITLE_MODE, { begin: BASIC_ATOM_RE })
- ],
- starts: {
- end: ';|\\.',
- keywords: ERLANG_RESERVED,
- contains: BASIC_MODES
- }
- },
- COMMENT,
- {
- begin: '^-',
- end: '\\.',
- relevance: 0,
- excludeEnd: true,
- returnBegin: true,
- keywords: {
- $pattern: '-' + hljs.IDENT_RE,
- keyword: DIRECTIVES.map(x => `${x}|1.5`).join(" ")
- },
- contains: [ PARAMS ]
- },
- NUMBER,
- hljs.QUOTE_STRING_MODE,
- RECORD_ACCESS,
- VAR1,
- VAR2,
- TUPLE,
- { begin: /\.$/ } // relevance booster
- ]
- };
- }
-
- /*
- Language: HTML, XML
- Website: https://www.w3.org/XML/
- Category: common, web
- Audit: 2020
- */
-
- /** @type LanguageFn */
- function xml(hljs) {
- const regex = hljs.regex;
- // XML names can have the following additional letters: https://www.w3.org/TR/xml/#NT-NameChar
- // OTHER_NAME_CHARS = /[:\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]/;
- // Element names start with NAME_START_CHAR followed by optional other Unicode letters, ASCII digits, hyphens, underscores, and periods
- // const TAG_NAME_RE = regex.concat(/[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/, regex.optional(/[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*:/), /[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*/);;
- // const XML_IDENT_RE = /[A-Z_a-z:\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]+/;
- // const TAG_NAME_RE = regex.concat(/[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/, regex.optional(/[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*:/), /[A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*/);
- // however, to cater for performance and more Unicode support rely simply on the Unicode letter class
- const TAG_NAME_RE = regex.concat(/[\p{L}_]/u, regex.optional(/[\p{L}0-9_.-]*:/u), /[\p{L}0-9_.-]*/u);
- const XML_IDENT_RE = /[\p{L}0-9._:-]+/u;
- const XML_ENTITIES = {
- className: 'symbol',
- begin: /&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/
- };
- const XML_META_KEYWORDS = {
- begin: /\s/,
- contains: [
- {
- className: 'keyword',
- begin: /#?[a-z_][a-z1-9_-]+/,
- illegal: /\n/
- }
- ]
- };
- const XML_META_PAR_KEYWORDS = hljs.inherit(XML_META_KEYWORDS, {
- begin: /\(/,
- end: /\)/
- });
- const APOS_META_STRING_MODE = hljs.inherit(hljs.APOS_STRING_MODE, { className: 'string' });
- const QUOTE_META_STRING_MODE = hljs.inherit(hljs.QUOTE_STRING_MODE, { className: 'string' });
- const TAG_INTERNALS = {
- endsWithParent: true,
- illegal: /</,
- relevance: 0,
- contains: [
- {
- className: 'attr',
- begin: XML_IDENT_RE,
- relevance: 0
- },
- {
- begin: /=\s*/,
- relevance: 0,
- contains: [
- {
- className: 'string',
- endsParent: true,
- variants: [
- {
- begin: /"/,
- end: /"/,
- contains: [ XML_ENTITIES ]
- },
- {
- begin: /'/,
- end: /'/,
- contains: [ XML_ENTITIES ]
- },
- { begin: /[^\s"'=<>`]+/ }
- ]
- }
- ]
- }
- ]
- };
- return {
- name: 'HTML, XML',
- aliases: [
- 'html',
- 'xhtml',
- 'rss',
- 'atom',
- 'xjb',
- 'xsd',
- 'xsl',
- 'plist',
- 'wsf',
- 'svg'
- ],
- case_insensitive: true,
- unicodeRegex: true,
- contains: [
- {
- className: 'meta',
- begin: /<![a-z]/,
- end: />/,
- relevance: 10,
- contains: [
- XML_META_KEYWORDS,
- QUOTE_META_STRING_MODE,
- APOS_META_STRING_MODE,
- XML_META_PAR_KEYWORDS,
- {
- begin: /\[/,
- end: /\]/,
- contains: [
- {
- className: 'meta',
- begin: /<![a-z]/,
- end: />/,
- contains: [
- XML_META_KEYWORDS,
- XML_META_PAR_KEYWORDS,
- QUOTE_META_STRING_MODE,
- APOS_META_STRING_MODE
- ]
- }
- ]
- }
- ]
- },
- hljs.COMMENT(
- /<!--/,
- /-->/,
- { relevance: 10 }
- ),
- {
- begin: /<!\[CDATA\[/,
- end: /\]\]>/,
- relevance: 10
- },
- XML_ENTITIES,
- // xml processing instructions
- {
- className: 'meta',
- end: /\?>/,
- variants: [
- {
- begin: /<\?xml/,
- relevance: 10,
- contains: [
- QUOTE_META_STRING_MODE
- ]
- },
- {
- begin: /<\?[a-z][a-z0-9]+/,
- }
- ]
-
- },
- {
- className: 'tag',
- /*
- The lookahead pattern (?=...) ensures that 'begin' only matches
- '<style' as a single word, followed by a whitespace or an
- ending bracket.
- */
- begin: /<style(?=\s|>)/,
- end: />/,
- keywords: { name: 'style' },
- contains: [ TAG_INTERNALS ],
- starts: {
- end: /<\/style>/,
- returnEnd: true,
- subLanguage: [
- 'css',
- 'xml'
- ]
- }
- },
- {
- className: 'tag',
- // See the comment in the <style tag about the lookahead pattern
- begin: /<script(?=\s|>)/,
- end: />/,
- keywords: { name: 'script' },
- contains: [ TAG_INTERNALS ],
- starts: {
- end: /<\/script>/,
- returnEnd: true,
- subLanguage: [
- 'javascript',
- 'handlebars',
- 'xml'
- ]
- }
- },
- // we need this for now for jSX
- {
- className: 'tag',
- begin: /<>|<\/>/
- },
- // open tag
- {
- className: 'tag',
- begin: regex.concat(
- /</,
- regex.lookahead(regex.concat(
- TAG_NAME_RE,
- // <tag/>
- // <tag>
- // <tag ...
- regex.either(/\/>/, />/, /\s/)
- ))
- ),
- end: /\/?>/,
- contains: [
- {
- className: 'name',
- begin: TAG_NAME_RE,
- relevance: 0,
- starts: TAG_INTERNALS
- }
- ]
- },
- // close tag
- {
- className: 'tag',
- begin: regex.concat(
- /<\//,
- regex.lookahead(regex.concat(
- TAG_NAME_RE, />/
- ))
- ),
- contains: [
- {
- className: 'name',
- begin: TAG_NAME_RE,
- relevance: 0
- },
- {
- begin: />/,
- relevance: 0,
- endsParent: true
- }
- ]
- }
- ]
- };
- }
-
- const MODES = (hljs) => {
- return {
- IMPORTANT: {
- scope: 'meta',
- begin: '!important'
- },
- BLOCK_COMMENT: hljs.C_BLOCK_COMMENT_MODE,
- HEXCOLOR: {
- scope: 'number',
- begin: /#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/
- },
- FUNCTION_DISPATCH: {
- className: "built_in",
- begin: /[\w-]+(?=\()/
- },
- ATTRIBUTE_SELECTOR_MODE: {
- scope: 'selector-attr',
- begin: /\[/,
- end: /\]/,
- illegal: '$',
- contains: [
- hljs.APOS_STRING_MODE,
- hljs.QUOTE_STRING_MODE
- ]
- },
- CSS_NUMBER_MODE: {
- scope: 'number',
- begin: hljs.NUMBER_RE + '(' +
- '%|em|ex|ch|rem' +
- '|vw|vh|vmin|vmax' +
- '|cm|mm|in|pt|pc|px' +
- '|deg|grad|rad|turn' +
- '|s|ms' +
- '|Hz|kHz' +
- '|dpi|dpcm|dppx' +
- ')?',
- relevance: 0
- },
- CSS_VARIABLE: {
- className: "attr",
- begin: /--[A-Za-z][A-Za-z0-9_-]*/
- }
- };
- };
-
- const TAGS = [
- 'a',
- 'abbr',
- 'address',
- 'article',
- 'aside',
- 'audio',
- 'b',
- 'blockquote',
- 'body',
- 'button',
- 'canvas',
- 'caption',
- 'cite',
- 'code',
- 'dd',
- 'del',
- 'details',
- 'dfn',
- 'div',
- 'dl',
- 'dt',
- 'em',
- 'fieldset',
- 'figcaption',
- 'figure',
- 'footer',
- 'form',
- 'h1',
- 'h2',
- 'h3',
- 'h4',
- 'h5',
- 'h6',
- 'header',
- 'hgroup',
- 'html',
- 'i',
- 'iframe',
- 'img',
- 'input',
- 'ins',
- 'kbd',
- 'label',
- 'legend',
- 'li',
- 'main',
- 'mark',
- 'menu',
- 'nav',
- 'object',
- 'ol',
- 'p',
- 'q',
- 'quote',
- 'samp',
- 'section',
- 'span',
- 'strong',
- 'summary',
- 'sup',
- 'table',
- 'tbody',
- 'td',
- 'textarea',
- 'tfoot',
- 'th',
- 'thead',
- 'time',
- 'tr',
- 'ul',
- 'var',
- 'video'
- ];
-
- const MEDIA_FEATURES = [
- 'any-hover',
- 'any-pointer',
- 'aspect-ratio',
- 'color',
- 'color-gamut',
- 'color-index',
- 'device-aspect-ratio',
- 'device-height',
- 'device-width',
- 'display-mode',
- 'forced-colors',
- 'grid',
- 'height',
- 'hover',
- 'inverted-colors',
- 'monochrome',
- 'orientation',
- 'overflow-block',
- 'overflow-inline',
- 'pointer',
- 'prefers-color-scheme',
- 'prefers-contrast',
- 'prefers-reduced-motion',
- 'prefers-reduced-transparency',
- 'resolution',
- 'scan',
- 'scripting',
- 'update',
- 'width',
- // TODO: find a better solution?
- 'min-width',
- 'max-width',
- 'min-height',
- 'max-height'
- ];
-
- // https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes
- const PSEUDO_CLASSES = [
- 'active',
- 'any-link',
- 'blank',
- 'checked',
- 'current',
- 'default',
- 'defined',
- 'dir', // dir()
- 'disabled',
- 'drop',
- 'empty',
- 'enabled',
- 'first',
- 'first-child',
- 'first-of-type',
- 'fullscreen',
- 'future',
- 'focus',
- 'focus-visible',
- 'focus-within',
- 'has', // has()
- 'host', // host or host()
- 'host-context', // host-context()
- 'hover',
- 'indeterminate',
- 'in-range',
- 'invalid',
- 'is', // is()
- 'lang', // lang()
- 'last-child',
- 'last-of-type',
- 'left',
- 'link',
- 'local-link',
- 'not', // not()
- 'nth-child', // nth-child()
- 'nth-col', // nth-col()
- 'nth-last-child', // nth-last-child()
- 'nth-last-col', // nth-last-col()
- 'nth-last-of-type', //nth-last-of-type()
- 'nth-of-type', //nth-of-type()
- 'only-child',
- 'only-of-type',
- 'optional',
- 'out-of-range',
- 'past',
- 'placeholder-shown',
- 'read-only',
- 'read-write',
- 'required',
- 'right',
- 'root',
- 'scope',
- 'target',
- 'target-within',
- 'user-invalid',
- 'valid',
- 'visited',
- 'where' // where()
- ];
-
- // https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements
- const PSEUDO_ELEMENTS = [
- 'after',
- 'backdrop',
- 'before',
- 'cue',
- 'cue-region',
- 'first-letter',
- 'first-line',
- 'grammar-error',
- 'marker',
- 'part',
- 'placeholder',
- 'selection',
- 'slotted',
- 'spelling-error'
- ];
-
- const ATTRIBUTES = [
- 'align-content',
- 'align-items',
- 'align-self',
- 'all',
- 'animation',
- 'animation-delay',
- 'animation-direction',
- 'animation-duration',
- 'animation-fill-mode',
- 'animation-iteration-count',
- 'animation-name',
- 'animation-play-state',
- 'animation-timing-function',
- 'backface-visibility',
- 'background',
- 'background-attachment',
- 'background-blend-mode',
- 'background-clip',
- 'background-color',
- 'background-image',
- 'background-origin',
- 'background-position',
- 'background-repeat',
- 'background-size',
- 'block-size',
- 'border',
- 'border-block',
- 'border-block-color',
- 'border-block-end',
- 'border-block-end-color',
- 'border-block-end-style',
- 'border-block-end-width',
- 'border-block-start',
- 'border-block-start-color',
- 'border-block-start-style',
- 'border-block-start-width',
- 'border-block-style',
- 'border-block-width',
- 'border-bottom',
- 'border-bottom-color',
- 'border-bottom-left-radius',
- 'border-bottom-right-radius',
- 'border-bottom-style',
- 'border-bottom-width',
- 'border-collapse',
- 'border-color',
- 'border-image',
- 'border-image-outset',
- 'border-image-repeat',
- 'border-image-slice',
- 'border-image-source',
- 'border-image-width',
- 'border-inline',
- 'border-inline-color',
- 'border-inline-end',
- 'border-inline-end-color',
- 'border-inline-end-style',
- 'border-inline-end-width',
- 'border-inline-start',
- 'border-inline-start-color',
- 'border-inline-start-style',
- 'border-inline-start-width',
- 'border-inline-style',
- 'border-inline-width',
- 'border-left',
- 'border-left-color',
- 'border-left-style',
- 'border-left-width',
- 'border-radius',
- 'border-right',
- 'border-right-color',
- 'border-right-style',
- 'border-right-width',
- 'border-spacing',
- 'border-style',
- 'border-top',
- 'border-top-color',
- 'border-top-left-radius',
- 'border-top-right-radius',
- 'border-top-style',
- 'border-top-width',
- 'border-width',
- 'bottom',
- 'box-decoration-break',
- 'box-shadow',
- 'box-sizing',
- 'break-after',
- 'break-before',
- 'break-inside',
- 'caption-side',
- 'caret-color',
- 'clear',
- 'clip',
- 'clip-path',
- 'clip-rule',
- 'color',
- 'column-count',
- 'column-fill',
- 'column-gap',
- 'column-rule',
- 'column-rule-color',
- 'column-rule-style',
- 'column-rule-width',
- 'column-span',
- 'column-width',
- 'columns',
- 'contain',
- 'content',
- 'content-visibility',
- 'counter-increment',
- 'counter-reset',
- 'cue',
- 'cue-after',
- 'cue-before',
- 'cursor',
- 'direction',
- 'display',
- 'empty-cells',
- 'filter',
- 'flex',
- 'flex-basis',
- 'flex-direction',
- 'flex-flow',
- 'flex-grow',
- 'flex-shrink',
- 'flex-wrap',
- 'float',
- 'flow',
- 'font',
- 'font-display',
- 'font-family',
- 'font-feature-settings',
- 'font-kerning',
- 'font-language-override',
- 'font-size',
- 'font-size-adjust',
- 'font-smoothing',
- 'font-stretch',
- 'font-style',
- 'font-synthesis',
- 'font-variant',
- 'font-variant-caps',
- 'font-variant-east-asian',
- 'font-variant-ligatures',
- 'font-variant-numeric',
- 'font-variant-position',
- 'font-variation-settings',
- 'font-weight',
- 'gap',
- 'glyph-orientation-vertical',
- 'grid',
- 'grid-area',
- 'grid-auto-columns',
- 'grid-auto-flow',
- 'grid-auto-rows',
- 'grid-column',
- 'grid-column-end',
- 'grid-column-start',
- 'grid-gap',
- 'grid-row',
- 'grid-row-end',
- 'grid-row-start',
- 'grid-template',
- 'grid-template-areas',
- 'grid-template-columns',
- 'grid-template-rows',
- 'hanging-punctuation',
- 'height',
- 'hyphens',
- 'icon',
- 'image-orientation',
- 'image-rendering',
- 'image-resolution',
- 'ime-mode',
- 'inline-size',
- 'isolation',
- 'justify-content',
- 'left',
- 'letter-spacing',
- 'line-break',
- 'line-height',
- 'list-style',
- 'list-style-image',
- 'list-style-position',
- 'list-style-type',
- 'margin',
- 'margin-block',
- 'margin-block-end',
- 'margin-block-start',
- 'margin-bottom',
- 'margin-inline',
- 'margin-inline-end',
- 'margin-inline-start',
- 'margin-left',
- 'margin-right',
- 'margin-top',
- 'marks',
- 'mask',
- 'mask-border',
- 'mask-border-mode',
- 'mask-border-outset',
- 'mask-border-repeat',
- 'mask-border-slice',
- 'mask-border-source',
- 'mask-border-width',
- 'mask-clip',
- 'mask-composite',
- 'mask-image',
- 'mask-mode',
- 'mask-origin',
- 'mask-position',
- 'mask-repeat',
- 'mask-size',
- 'mask-type',
- 'max-block-size',
- 'max-height',
- 'max-inline-size',
- 'max-width',
- 'min-block-size',
- 'min-height',
- 'min-inline-size',
- 'min-width',
- 'mix-blend-mode',
- 'nav-down',
- 'nav-index',
- 'nav-left',
- 'nav-right',
- 'nav-up',
- 'none',
- 'normal',
- 'object-fit',
- 'object-position',
- 'opacity',
- 'order',
- 'orphans',
- 'outline',
- 'outline-color',
- 'outline-offset',
- 'outline-style',
- 'outline-width',
- 'overflow',
- 'overflow-wrap',
- 'overflow-x',
- 'overflow-y',
- 'padding',
- 'padding-block',
- 'padding-block-end',
- 'padding-block-start',
- 'padding-bottom',
- 'padding-inline',
- 'padding-inline-end',
- 'padding-inline-start',
- 'padding-left',
- 'padding-right',
- 'padding-top',
- 'page-break-after',
- 'page-break-before',
- 'page-break-inside',
- 'pause',
- 'pause-after',
- 'pause-before',
- 'perspective',
- 'perspective-origin',
- 'pointer-events',
- 'position',
- 'quotes',
- 'resize',
- 'rest',
- 'rest-after',
- 'rest-before',
- 'right',
- 'row-gap',
- 'scroll-margin',
- 'scroll-margin-block',
- 'scroll-margin-block-end',
- 'scroll-margin-block-start',
- 'scroll-margin-bottom',
- 'scroll-margin-inline',
- 'scroll-margin-inline-end',
- 'scroll-margin-inline-start',
- 'scroll-margin-left',
- 'scroll-margin-right',
- 'scroll-margin-top',
- 'scroll-padding',
- 'scroll-padding-block',
- 'scroll-padding-block-end',
- 'scroll-padding-block-start',
- 'scroll-padding-bottom',
- 'scroll-padding-inline',
- 'scroll-padding-inline-end',
- 'scroll-padding-inline-start',
- 'scroll-padding-left',
- 'scroll-padding-right',
- 'scroll-padding-top',
- 'scroll-snap-align',
- 'scroll-snap-stop',
- 'scroll-snap-type',
- 'scrollbar-color',
- 'scrollbar-gutter',
- 'scrollbar-width',
- 'shape-image-threshold',
- 'shape-margin',
- 'shape-outside',
- 'speak',
- 'speak-as',
- 'src', // @font-face
- 'tab-size',
- 'table-layout',
- 'text-align',
- 'text-align-all',
- 'text-align-last',
- 'text-combine-upright',
- 'text-decoration',
- 'text-decoration-color',
- 'text-decoration-line',
- 'text-decoration-style',
- 'text-emphasis',
- 'text-emphasis-color',
- 'text-emphasis-position',
- 'text-emphasis-style',
- 'text-indent',
- 'text-justify',
- 'text-orientation',
- 'text-overflow',
- 'text-rendering',
- 'text-shadow',
- 'text-transform',
- 'text-underline-position',
- 'top',
- 'transform',
- 'transform-box',
- 'transform-origin',
- 'transform-style',
- 'transition',
- 'transition-delay',
- 'transition-duration',
- 'transition-property',
- 'transition-timing-function',
- 'unicode-bidi',
- 'vertical-align',
- 'visibility',
- 'voice-balance',
- 'voice-duration',
- 'voice-family',
- 'voice-pitch',
- 'voice-range',
- 'voice-rate',
- 'voice-stress',
- 'voice-volume',
- 'white-space',
- 'widows',
- 'width',
- 'will-change',
- 'word-break',
- 'word-spacing',
- 'word-wrap',
- 'writing-mode',
- 'z-index'
- // reverse makes sure longer attributes `font-weight` are matched fully
- // instead of getting false positives on say `font`
- ].reverse();
-
- /*
- Language: CSS
- Category: common, css, web
- Website: https://developer.mozilla.org/en-US/docs/Web/CSS
- */
-
- /** @type LanguageFn */
- function css(hljs) {
- const regex = hljs.regex;
- const modes = MODES(hljs);
- const VENDOR_PREFIX = { begin: /-(webkit|moz|ms|o)-(?=[a-z])/ };
- const AT_MODIFIERS = "and or not only";
- const AT_PROPERTY_RE = /@-?\w[\w]*(-\w+)*/; // @-webkit-keyframes
- const IDENT_RE = '[a-zA-Z-][a-zA-Z0-9_-]*';
- const STRINGS = [
- hljs.APOS_STRING_MODE,
- hljs.QUOTE_STRING_MODE
- ];
-
- return {
- name: 'CSS',
- case_insensitive: true,
- illegal: /[=|'\$]/,
- keywords: { keyframePosition: "from to" },
- classNameAliases: {
- // for visual continuity with `tag {}` and because we
- // don't have a great class for this?
- keyframePosition: "selector-tag" },
- contains: [
- modes.BLOCK_COMMENT,
- VENDOR_PREFIX,
- // to recognize keyframe 40% etc which are outside the scope of our
- // attribute value mode
- modes.CSS_NUMBER_MODE,
- {
- className: 'selector-id',
- begin: /#[A-Za-z0-9_-]+/,
- relevance: 0
- },
- {
- className: 'selector-class',
- begin: '\\.' + IDENT_RE,
- relevance: 0
- },
- modes.ATTRIBUTE_SELECTOR_MODE,
- {
- className: 'selector-pseudo',
- variants: [
- { begin: ':(' + PSEUDO_CLASSES.join('|') + ')' },
- { begin: ':(:)?(' + PSEUDO_ELEMENTS.join('|') + ')' }
- ]
- },
- // we may actually need this (12/2020)
- // { // pseudo-selector params
- // begin: /\(/,
- // end: /\)/,
- // contains: [ hljs.CSS_NUMBER_MODE ]
- // },
- modes.CSS_VARIABLE,
- {
- className: 'attribute',
- begin: '\\b(' + ATTRIBUTES.join('|') + ')\\b'
- },
- // attribute values
- {
- begin: /:/,
- end: /[;}{]/,
- contains: [
- modes.BLOCK_COMMENT,
- modes.HEXCOLOR,
- modes.IMPORTANT,
- modes.CSS_NUMBER_MODE,
- ...STRINGS,
- // needed to highlight these as strings and to avoid issues with
- // illegal characters that might be inside urls that would tigger the
- // languages illegal stack
- {
- begin: /(url|data-uri)\(/,
- end: /\)/,
- relevance: 0, // from keywords
- keywords: { built_in: "url data-uri" },
- contains: [
- ...STRINGS,
- {
- className: "string",
- // any character other than `)` as in `url()` will be the start
- // of a string, which ends with `)` (from the parent mode)
- begin: /[^)]/,
- endsWithParent: true,
- excludeEnd: true
- }
- ]
- },
- modes.FUNCTION_DISPATCH
- ]
- },
- {
- begin: regex.lookahead(/@/),
- end: '[{;]',
- relevance: 0,
- illegal: /:/, // break on Less variables @var: ...
- contains: [
- {
- className: 'keyword',
- begin: AT_PROPERTY_RE
- },
- {
- begin: /\s/,
- endsWithParent: true,
- excludeEnd: true,
- relevance: 0,
- keywords: {
- $pattern: /[a-z-]+/,
- keyword: AT_MODIFIERS,
- attribute: MEDIA_FEATURES.join(" ")
- },
- contains: [
- {
- begin: /[a-z-]+(?=:)/,
- className: "attribute"
- },
- ...STRINGS,
- modes.CSS_NUMBER_MODE
- ]
- }
- ]
- },
- {
- className: 'selector-tag',
- begin: '\\b(' + TAGS.join('|') + ')\\b'
- }
- ]
- };
- }
-
- const IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*';
- const KEYWORDS = [
- "as", // for exports
- "in",
- "of",
- "if",
- "for",
- "while",
- "finally",
- "var",
- "new",
- "function",
- "do",
- "return",
- "void",
- "else",
- "break",
- "catch",
- "instanceof",
- "with",
- "throw",
- "case",
- "default",
- "try",
- "switch",
- "continue",
- "typeof",
- "delete",
- "let",
- "yield",
- "const",
- "class",
- // JS handles these with a special rule
- // "get",
- // "set",
- "debugger",
- "async",
- "await",
- "static",
- "import",
- "from",
- "export",
- "extends"
- ];
- const LITERALS = [
- "true",
- "false",
- "null",
- "undefined",
- "NaN",
- "Infinity"
- ];
-
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects
- const TYPES = [
- // Fundamental objects
- "Object",
- "Function",
- "Boolean",
- "Symbol",
- // numbers and dates
- "Math",
- "Date",
- "Number",
- "BigInt",
- // text
- "String",
- "RegExp",
- // Indexed collections
- "Array",
- "Float32Array",
- "Float64Array",
- "Int8Array",
- "Uint8Array",
- "Uint8ClampedArray",
- "Int16Array",
- "Int32Array",
- "Uint16Array",
- "Uint32Array",
- "BigInt64Array",
- "BigUint64Array",
- // Keyed collections
- "Set",
- "Map",
- "WeakSet",
- "WeakMap",
- // Structured data
- "ArrayBuffer",
- "SharedArrayBuffer",
- "Atomics",
- "DataView",
- "JSON",
- // Control abstraction objects
- "Promise",
- "Generator",
- "GeneratorFunction",
- "AsyncFunction",
- // Reflection
- "Reflect",
- "Proxy",
- // Internationalization
- "Intl",
- // WebAssembly
- "WebAssembly"
- ];
-
- const ERROR_TYPES = [
- "Error",
- "EvalError",
- "InternalError",
- "RangeError",
- "ReferenceError",
- "SyntaxError",
- "TypeError",
- "URIError"
- ];
-
- const BUILT_IN_GLOBALS = [
- "setInterval",
- "setTimeout",
- "clearInterval",
- "clearTimeout",
-
- "require",
- "exports",
-
- "eval",
- "isFinite",
- "isNaN",
- "parseFloat",
- "parseInt",
- "decodeURI",
- "decodeURIComponent",
- "encodeURI",
- "encodeURIComponent",
- "escape",
- "unescape"
- ];
-
- const BUILT_IN_VARIABLES = [
- "arguments",
- "this",
- "super",
- "console",
- "window",
- "document",
- "localStorage",
- "sessionStorage",
- "module",
- "global" // Node.js
- ];
-
- const BUILT_INS = [].concat(
- BUILT_IN_GLOBALS,
- TYPES,
- ERROR_TYPES
- );
-
- /*
- Language: JavaScript
- Description: JavaScript (JS) is a lightweight, interpreted, or just-in-time compiled programming language with first-class functions.
- Category: common, scripting, web
- Website: https://developer.mozilla.org/en-US/docs/Web/JavaScript
- */
-
- /** @type LanguageFn */
- function javascript(hljs) {
- const regex = hljs.regex;
- /**
- * Takes a string like "<Booger" and checks to see
- * if we can find a matching "</Booger" later in the
- * content.
- * @param {RegExpMatchArray} match
- * @param {{after:number}} param1
- */
- const hasClosingTag = (match, { after }) => {
- const tag = "</" + match[0].slice(1);
- const pos = match.input.indexOf(tag, after);
- return pos !== -1;
- };
-
- const IDENT_RE$1 = IDENT_RE;
- const FRAGMENT = {
- begin: '<>',
- end: '</>'
- };
- // to avoid some special cases inside isTrulyOpeningTag
- const XML_SELF_CLOSING = /<[A-Za-z0-9\\._:-]+\s*\/>/;
- const XML_TAG = {
- begin: /<[A-Za-z0-9\\._:-]+/,
- end: /\/[A-Za-z0-9\\._:-]+>|\/>/,
- /**
- * @param {RegExpMatchArray} match
- * @param {CallbackResponse} response
- */
- isTrulyOpeningTag: (match, response) => {
- const afterMatchIndex = match[0].length + match.index;
- const nextChar = match.input[afterMatchIndex];
- if (
- // HTML should not include another raw `<` inside a tag
- // nested type?
- // `<Array<Array<number>>`, etc.
- nextChar === "<" ||
- // the , gives away that this is not HTML
- // `<T, A extends keyof T, V>`
- nextChar === ","
- ) {
- response.ignoreMatch();
- return;
- }
-
- // `<something>`
- // Quite possibly a tag, lets look for a matching closing tag...
- if (nextChar === ">") {
- // if we cannot find a matching closing tag, then we
- // will ignore it
- if (!hasClosingTag(match, { after: afterMatchIndex })) {
- response.ignoreMatch();
- }
- }
-
- // `<blah />` (self-closing)
- // handled by simpleSelfClosing rule
-
- let m;
- const afterMatch = match.input.substring(afterMatchIndex);
-
- // some more template typing stuff
- // <T = any>(key?: string) => Modify<
- if ((m = afterMatch.match(/^\s*=/))) {
- response.ignoreMatch();
- return;
- }
-
- // `<From extends string>`
- // technically this could be HTML, but it smells like a type
- // NOTE: This is ugh, but added specifically for https://github.com/highlightjs/highlight.js/issues/3276
- if ((m = afterMatch.match(/^\s+extends\s+/))) {
- if (m.index === 0) {
- response.ignoreMatch();
- // eslint-disable-next-line no-useless-return
- return;
- }
- }
- }
- };
- const KEYWORDS$1 = {
- $pattern: IDENT_RE,
- keyword: KEYWORDS,
- literal: LITERALS,
- built_in: BUILT_INS,
- "variable.language": BUILT_IN_VARIABLES
- };
-
- // https://tc39.es/ecma262/#sec-literals-numeric-literals
- const decimalDigits = '[0-9](_?[0-9])*';
- const frac = `\\.(${decimalDigits})`;
- // DecimalIntegerLiteral, including Annex B NonOctalDecimalIntegerLiteral
- // https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals
- const decimalInteger = `0|[1-9](_?[0-9])*|0[0-7]*[89][0-9]*`;
- const NUMBER = {
- className: 'number',
- variants: [
- // DecimalLiteral
- { begin: `(\\b(${decimalInteger})((${frac})|\\.)?|(${frac}))` +
- `[eE][+-]?(${decimalDigits})\\b` },
- { begin: `\\b(${decimalInteger})\\b((${frac})\\b|\\.)?|(${frac})\\b` },
-
- // DecimalBigIntegerLiteral
- { begin: `\\b(0|[1-9](_?[0-9])*)n\\b` },
-
- // NonDecimalIntegerLiteral
- { begin: "\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?\\b" },
- { begin: "\\b0[bB][0-1](_?[0-1])*n?\\b" },
- { begin: "\\b0[oO][0-7](_?[0-7])*n?\\b" },
-
- // LegacyOctalIntegerLiteral (does not include underscore separators)
- // https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals
- { begin: "\\b0[0-7]+n?\\b" },
- ],
- relevance: 0
- };
-
- const SUBST = {
- className: 'subst',
- begin: '\\$\\{',
- end: '\\}',
- keywords: KEYWORDS$1,
- contains: [] // defined later
- };
- const HTML_TEMPLATE = {
- begin: 'html`',
- end: '',
- starts: {
- end: '`',
- returnEnd: false,
- contains: [
- hljs.BACKSLASH_ESCAPE,
- SUBST
- ],
- subLanguage: 'xml'
- }
- };
- const CSS_TEMPLATE = {
- begin: 'css`',
- end: '',
- starts: {
- end: '`',
- returnEnd: false,
- contains: [
- hljs.BACKSLASH_ESCAPE,
- SUBST
- ],
- subLanguage: 'css'
- }
- };
- const TEMPLATE_STRING = {
- className: 'string',
- begin: '`',
- end: '`',
- contains: [
- hljs.BACKSLASH_ESCAPE,
- SUBST
- ]
- };
- const JSDOC_COMMENT = hljs.COMMENT(
- /\/\*\*(?!\/)/,
- '\\*/',
- {
- relevance: 0,
- contains: [
- {
- begin: '(?=@[A-Za-z]+)',
- relevance: 0,
- contains: [
- {
- className: 'doctag',
- begin: '@[A-Za-z]+'
- },
- {
- className: 'type',
- begin: '\\{',
- end: '\\}',
- excludeEnd: true,
- excludeBegin: true,
- relevance: 0
- },
- {
- className: 'variable',
- begin: IDENT_RE$1 + '(?=\\s*(-)|$)',
- endsParent: true,
- relevance: 0
- },
- // eat spaces (not newlines) so we can find
- // types or variables
- {
- begin: /(?=[^\n])\s/,
- relevance: 0
- }
- ]
- }
- ]
- }
- );
- const COMMENT = {
- className: "comment",
- variants: [
- JSDOC_COMMENT,
- hljs.C_BLOCK_COMMENT_MODE,
- hljs.C_LINE_COMMENT_MODE
- ]
- };
- const SUBST_INTERNALS = [
- hljs.APOS_STRING_MODE,
- hljs.QUOTE_STRING_MODE,
- HTML_TEMPLATE,
- CSS_TEMPLATE,
- TEMPLATE_STRING,
- // Skip numbers when they are part of a variable name
- { match: /\$\d+/ },
- NUMBER,
- // This is intentional:
- // See https://github.com/highlightjs/highlight.js/issues/3288
- // hljs.REGEXP_MODE
- ];
- SUBST.contains = SUBST_INTERNALS
- .concat({
- // we need to pair up {} inside our subst to prevent
- // it from ending too early by matching another }
- begin: /\{/,
- end: /\}/,
- keywords: KEYWORDS$1,
- contains: [
- "self"
- ].concat(SUBST_INTERNALS)
- });
- const SUBST_AND_COMMENTS = [].concat(COMMENT, SUBST.contains);
- const PARAMS_CONTAINS = SUBST_AND_COMMENTS.concat([
- // eat recursive parens in sub expressions
- {
- begin: /\(/,
- end: /\)/,
- keywords: KEYWORDS$1,
- contains: ["self"].concat(SUBST_AND_COMMENTS)
- }
- ]);
- const PARAMS = {
- className: 'params',
- begin: /\(/,
- end: /\)/,
- excludeBegin: true,
- excludeEnd: true,
- keywords: KEYWORDS$1,
- contains: PARAMS_CONTAINS
- };
-
- // ES6 classes
- const CLASS_OR_EXTENDS = {
- variants: [
- // class Car extends vehicle
- {
- match: [
- /class/,
- /\s+/,
- IDENT_RE$1,
- /\s+/,
- /extends/,
- /\s+/,
- regex.concat(IDENT_RE$1, "(", regex.concat(/\./, IDENT_RE$1), ")*")
- ],
- scope: {
- 1: "keyword",
- 3: "title.class",
- 5: "keyword",
- 7: "title.class.inherited"
- }
- },
- // class Car
- {
- match: [
- /class/,
- /\s+/,
- IDENT_RE$1
- ],
- scope: {
- 1: "keyword",
- 3: "title.class"
- }
- },
-
- ]
- };
-
- const CLASS_REFERENCE = {
- relevance: 0,
- match:
- regex.either(
- // Hard coded exceptions
- /\bJSON/,
- // Float32Array, OutT
- /\b[A-Z][a-z]+([A-Z][a-z]*|\d)*/,
- // CSSFactory, CSSFactoryT
- /\b[A-Z]{2,}([A-Z][a-z]+|\d)+([A-Z][a-z]*)*/,
- // FPs, FPsT
- /\b[A-Z]{2,}[a-z]+([A-Z][a-z]+|\d)*([A-Z][a-z]*)*/,
- // P
- // single letters are not highlighted
- // BLAH
- // this will be flagged as a UPPER_CASE_CONSTANT instead
- ),
- className: "title.class",
- keywords: {
- _: [
- // se we still get relevance credit for JS library classes
- ...TYPES,
- ...ERROR_TYPES
- ]
- }
- };
-
- const USE_STRICT = {
- label: "use_strict",
- className: 'meta',
- relevance: 10,
- begin: /^\s*['"]use (strict|asm)['"]/
- };
-
- const FUNCTION_DEFINITION = {
- variants: [
- {
- match: [
- /function/,
- /\s+/,
- IDENT_RE$1,
- /(?=\s*\()/
- ]
- },
- // anonymous function
- {
- match: [
- /function/,
- /\s*(?=\()/
- ]
- }
- ],
- className: {
- 1: "keyword",
- 3: "title.function"
- },
- label: "func.def",
- contains: [ PARAMS ],
- illegal: /%/
- };
-
- const UPPER_CASE_CONSTANT = {
- relevance: 0,
- match: /\b[A-Z][A-Z_0-9]+\b/,
- className: "variable.constant"
- };
-
- function noneOf(list) {
- return regex.concat("(?!", list.join("|"), ")");
- }
-
- const FUNCTION_CALL = {
- match: regex.concat(
- /\b/,
- noneOf([
- ...BUILT_IN_GLOBALS,
- "super",
- "import"
- ]),
- IDENT_RE$1, regex.lookahead(/\(/)),
- className: "title.function",
- relevance: 0
- };
-
- const PROPERTY_ACCESS = {
- begin: regex.concat(/\./, regex.lookahead(
- regex.concat(IDENT_RE$1, /(?![0-9A-Za-z$_(])/)
- )),
- end: IDENT_RE$1,
- excludeBegin: true,
- keywords: "prototype",
- className: "property",
- relevance: 0
- };
-
- const GETTER_OR_SETTER = {
- match: [
- /get|set/,
- /\s+/,
- IDENT_RE$1,
- /(?=\()/
- ],
- className: {
- 1: "keyword",
- 3: "title.function"
- },
- contains: [
- { // eat to avoid empty params
- begin: /\(\)/
- },
- PARAMS
- ]
- };
-
- const FUNC_LEAD_IN_RE = '(\\(' +
- '[^()]*(\\(' +
- '[^()]*(\\(' +
- '[^()]*' +
- '\\)[^()]*)*' +
- '\\)[^()]*)*' +
- '\\)|' + hljs.UNDERSCORE_IDENT_RE + ')\\s*=>';
-
- const FUNCTION_VARIABLE = {
- match: [
- /const|var|let/, /\s+/,
- IDENT_RE$1, /\s*/,
- /=\s*/,
- /(async\s*)?/, // async is optional
- regex.lookahead(FUNC_LEAD_IN_RE)
- ],
- keywords: "async",
- className: {
- 1: "keyword",
- 3: "title.function"
- },
- contains: [
- PARAMS
- ]
- };
-
- return {
- name: 'Javascript',
- aliases: ['js', 'jsx', 'mjs', 'cjs'],
- keywords: KEYWORDS$1,
- // this will be extended by TypeScript
- exports: { PARAMS_CONTAINS, CLASS_REFERENCE },
- illegal: /#(?![$_A-z])/,
- contains: [
- hljs.SHEBANG({
- label: "shebang",
- binary: "node",
- relevance: 5
- }),
- USE_STRICT,
- hljs.APOS_STRING_MODE,
- hljs.QUOTE_STRING_MODE,
- HTML_TEMPLATE,
- CSS_TEMPLATE,
- TEMPLATE_STRING,
- COMMENT,
- // Skip numbers when they are part of a variable name
- { match: /\$\d+/ },
- NUMBER,
- CLASS_REFERENCE,
- {
- className: 'attr',
- begin: IDENT_RE$1 + regex.lookahead(':'),
- relevance: 0
- },
- FUNCTION_VARIABLE,
- { // "value" container
- begin: '(' + hljs.RE_STARTERS_RE + '|\\b(case|return|throw)\\b)\\s*',
- keywords: 'return throw case',
- relevance: 0,
- contains: [
- COMMENT,
- hljs.REGEXP_MODE,
- {
- className: 'function',
- // we have to count the parens to make sure we actually have the
- // correct bounding ( ) before the =>. There could be any number of
- // sub-expressions inside also surrounded by parens.
- begin: FUNC_LEAD_IN_RE,
- returnBegin: true,
- end: '\\s*=>',
- contains: [
- {
- className: 'params',
- variants: [
- {
- begin: hljs.UNDERSCORE_IDENT_RE,
- relevance: 0
- },
- {
- className: null,
- begin: /\(\s*\)/,
- skip: true
- },
- {
- begin: /\(/,
- end: /\)/,
- excludeBegin: true,
- excludeEnd: true,
- keywords: KEYWORDS$1,
- contains: PARAMS_CONTAINS
- }
- ]
- }
- ]
- },
- { // could be a comma delimited list of params to a function call
- begin: /,/,
- relevance: 0
- },
- {
- match: /\s+/,
- relevance: 0
- },
- { // JSX
- variants: [
- { begin: FRAGMENT.begin, end: FRAGMENT.end },
- { match: XML_SELF_CLOSING },
- {
- begin: XML_TAG.begin,
- // we carefully check the opening tag to see if it truly
- // is a tag and not a false positive
- 'on:begin': XML_TAG.isTrulyOpeningTag,
- end: XML_TAG.end
- }
- ],
- subLanguage: 'xml',
- contains: [
- {
- begin: XML_TAG.begin,
- end: XML_TAG.end,
- skip: true,
- contains: ['self']
- }
- ]
- }
- ],
- },
- FUNCTION_DEFINITION,
- {
- // prevent this from getting swallowed up by function
- // since they appear "function like"
- beginKeywords: "while if switch catch for"
- },
- {
- // we have to count the parens to make sure we actually have the correct
- // bounding ( ). There could be any number of sub-expressions inside
- // also surrounded by parens.
- begin: '\\b(?!function)' + hljs.UNDERSCORE_IDENT_RE +
- '\\(' + // first parens
- '[^()]*(\\(' +
- '[^()]*(\\(' +
- '[^()]*' +
- '\\)[^()]*)*' +
- '\\)[^()]*)*' +
- '\\)\\s*\\{', // end parens
- returnBegin:true,
- label: "func.def",
- contains: [
- PARAMS,
- hljs.inherit(hljs.TITLE_MODE, { begin: IDENT_RE$1, className: "title.function" })
- ]
- },
- // catch ... so it won't trigger the property rule below
- {
- match: /\.\.\./,
- relevance: 0
- },
- PROPERTY_ACCESS,
- // hack: prevents detection of keywords in some circumstances
- // .keyword()
- // $keyword = x
- {
- match: '\\$' + IDENT_RE$1,
- relevance: 0
- },
- {
- match: [ /\bconstructor(?=\s*\()/ ],
- className: { 1: "title.function" },
- contains: [ PARAMS ]
- },
- FUNCTION_CALL,
- UPPER_CASE_CONSTANT,
- CLASS_OR_EXTENDS,
- GETTER_OR_SETTER,
- {
- match: /\$[(.]/ // relevance booster for a pattern common to JS libs: `$(something)` and `$.something`
- }
- ]
- };
- }
-
- /*
- Language: Bash
- Author: vah <vahtenberg@gmail.com>
- Contributrors: Benjamin Pannell <contact@sierrasoftworks.com>
- Website: https://www.gnu.org/software/bash/
- Category: common
- */
-
- /** @type LanguageFn */
- function bash(hljs) {
- const regex = hljs.regex;
- const VAR = {};
- const BRACED_VAR = {
- begin: /\$\{/,
- end: /\}/,
- contains: [
- "self",
- {
- begin: /:-/,
- contains: [ VAR ]
- } // default values
- ]
- };
- Object.assign(VAR, {
- className: 'variable',
- variants: [
- { begin: regex.concat(/\$[\w\d#@][\w\d_]*/,
- // negative look-ahead tries to avoid matching patterns that are not
- // Perl at all like $ident$, @ident@, etc.
- `(?![\\w\\d])(?![$])`) },
- BRACED_VAR
- ]
- });
-
- const SUBST = {
- className: 'subst',
- begin: /\$\(/,
- end: /\)/,
- contains: [ hljs.BACKSLASH_ESCAPE ]
- };
- const HERE_DOC = {
- begin: /<<-?\s*(?=\w+)/,
- starts: { contains: [
- hljs.END_SAME_AS_BEGIN({
- begin: /(\w+)/,
- end: /(\w+)/,
- className: 'string'
- })
- ] }
- };
- const QUOTE_STRING = {
- className: 'string',
- begin: /"/,
- end: /"/,
- contains: [
- hljs.BACKSLASH_ESCAPE,
- VAR,
- SUBST
- ]
- };
- SUBST.contains.push(QUOTE_STRING);
- const ESCAPED_QUOTE = {
- className: '',
- begin: /\\"/
-
- };
- const APOS_STRING = {
- className: 'string',
- begin: /'/,
- end: /'/
- };
- const ARITHMETIC = {
- begin: /\$?\(\(/,
- end: /\)\)/,
- contains: [
- {
- begin: /\d+#[0-9a-f]+/,
- className: "number"
- },
- hljs.NUMBER_MODE,
- VAR
- ]
- };
- const SH_LIKE_SHELLS = [
- "fish",
- "bash",
- "zsh",
- "sh",
- "csh",
- "ksh",
- "tcsh",
- "dash",
- "scsh",
- ];
- const KNOWN_SHEBANG = hljs.SHEBANG({
- binary: `(${SH_LIKE_SHELLS.join("|")})`,
- relevance: 10
- });
- const FUNCTION = {
- className: 'function',
- begin: /\w[\w\d_]*\s*\(\s*\)\s*\{/,
- returnBegin: true,
- contains: [ hljs.inherit(hljs.TITLE_MODE, { begin: /\w[\w\d_]*/ }) ],
- relevance: 0
- };
-
- const KEYWORDS = [
- "if",
- "then",
- "else",
- "elif",
- "fi",
- "for",
- "while",
- "in",
- "do",
- "done",
- "case",
- "esac",
- "function"
- ];
-
- const LITERALS = [
- "true",
- "false"
- ];
-
- // to consume paths to prevent keyword matches inside them
- const PATH_MODE = { match: /(\/[a-z._-]+)+/ };
-
- // http://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html
- const SHELL_BUILT_INS = [
- "break",
- "cd",
- "continue",
- "eval",
- "exec",
- "exit",
- "export",
- "getopts",
- "hash",
- "pwd",
- "readonly",
- "return",
- "shift",
- "test",
- "times",
- "trap",
- "umask",
- "unset"
- ];
-
- const BASH_BUILT_INS = [
- "alias",
- "bind",
- "builtin",
- "caller",
- "command",
- "declare",
- "echo",
- "enable",
- "help",
- "let",
- "local",
- "logout",
- "mapfile",
- "printf",
- "read",
- "readarray",
- "source",
- "type",
- "typeset",
- "ulimit",
- "unalias"
- ];
-
- const ZSH_BUILT_INS = [
- "autoload",
- "bg",
- "bindkey",
- "bye",
- "cap",
- "chdir",
- "clone",
- "comparguments",
- "compcall",
- "compctl",
- "compdescribe",
- "compfiles",
- "compgroups",
- "compquote",
- "comptags",
- "comptry",
- "compvalues",
- "dirs",
- "disable",
- "disown",
- "echotc",
- "echoti",
- "emulate",
- "fc",
- "fg",
- "float",
- "functions",
- "getcap",
- "getln",
- "history",
- "integer",
- "jobs",
- "kill",
- "limit",
- "log",
- "noglob",
- "popd",
- "print",
- "pushd",
- "pushln",
- "rehash",
- "sched",
- "setcap",
- "setopt",
- "stat",
- "suspend",
- "ttyctl",
- "unfunction",
- "unhash",
- "unlimit",
- "unsetopt",
- "vared",
- "wait",
- "whence",
- "where",
- "which",
- "zcompile",
- "zformat",
- "zftp",
- "zle",
- "zmodload",
- "zparseopts",
- "zprof",
- "zpty",
- "zregexparse",
- "zsocket",
- "zstyle",
- "ztcp"
- ];
-
- const GNU_CORE_UTILS = [
- "chcon",
- "chgrp",
- "chown",
- "chmod",
- "cp",
- "dd",
- "df",
- "dir",
- "dircolors",
- "ln",
- "ls",
- "mkdir",
- "mkfifo",
- "mknod",
- "mktemp",
- "mv",
- "realpath",
- "rm",
- "rmdir",
- "shred",
- "sync",
- "touch",
- "truncate",
- "vdir",
- "b2sum",
- "base32",
- "base64",
- "cat",
- "cksum",
- "comm",
- "csplit",
- "cut",
- "expand",
- "fmt",
- "fold",
- "head",
- "join",
- "md5sum",
- "nl",
- "numfmt",
- "od",
- "paste",
- "ptx",
- "pr",
- "sha1sum",
- "sha224sum",
- "sha256sum",
- "sha384sum",
- "sha512sum",
- "shuf",
- "sort",
- "split",
- "sum",
- "tac",
- "tail",
- "tr",
- "tsort",
- "unexpand",
- "uniq",
- "wc",
- "arch",
- "basename",
- "chroot",
- "date",
- "dirname",
- "du",
- "echo",
- "env",
- "expr",
- "factor",
- // "false", // keyword literal already
- "groups",
- "hostid",
- "id",
- "link",
- "logname",
- "nice",
- "nohup",
- "nproc",
- "pathchk",
- "pinky",
- "printenv",
- "printf",
- "pwd",
- "readlink",
- "runcon",
- "seq",
- "sleep",
- "stat",
- "stdbuf",
- "stty",
- "tee",
- "test",
- "timeout",
- // "true", // keyword literal already
- "tty",
- "uname",
- "unlink",
- "uptime",
- "users",
- "who",
- "whoami",
- "yes"
- ];
-
- return {
- name: 'Bash',
- aliases: [ 'sh' ],
- keywords: {
- $pattern: /\b[a-z][a-z0-9._-]+\b/,
- keyword: KEYWORDS,
- literal: LITERALS,
- built_in: [
- ...SHELL_BUILT_INS,
- ...BASH_BUILT_INS,
- // Shell modifiers
- "set",
- "shopt",
- ...ZSH_BUILT_INS,
- ...GNU_CORE_UTILS
- ]
- },
- contains: [
- KNOWN_SHEBANG, // to catch known shells and boost relevancy
- hljs.SHEBANG(), // to catch unknown shells but still highlight the shebang
- FUNCTION,
- ARITHMETIC,
- hljs.HASH_COMMENT_MODE,
- HERE_DOC,
- PATH_MODE,
- QUOTE_STRING,
- ESCAPED_QUOTE,
- APOS_STRING,
- VAR
- ]
- };
- }
-
- var builtIns = /*#__PURE__*/Object.freeze({
- __proto__: null,
- grmr_gleam: gleam,
- grmr_erlang: erlang,
- grmr_xml: xml,
- grmr_css: css,
- grmr_javascript: javascript,
- grmr_bash: bash
- });
-
- const hljs = HighlightJS;
-
- for (const key of Object.keys(builtIns)) {
- // our builtInLanguages Rollup plugin has to use `_` to allow identifiers to be
- // compatible with `export` naming conventions, so we need to convert the
- // identifiers back into the more typical dash style that we use for language
- // naming via the API
- const languageName = key.replace("grmr_", "").replace("_", "-");
- hljs.registerLanguage(languageName, builtIns[key]);
- }
-
- return hljs;
-
-})();
-if (typeof exports === 'object' && typeof module !== 'undefined') { module.exports = hljs; }
diff --git a/compat/lustre_animation/index.html b/compat/lustre_animation/index.html
deleted file mode 100644
index 5d15471..0000000
--- a/compat/lustre_animation/index.html
+++ /dev/null
@@ -1,95 +0,0 @@
-<html>
-
-<head>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Lustre Animation Example</title>
- <style>
- head,
- body {
- margin: 0;
- padding: 1em;
- background: linear-gradient(to bottom, #ffaff3, white);
- }
- </style>
- <link rel="stylesheet" href="lustre_animation.css" />
-</head>
-
-<body>
- <script type="text/javascript" src="highlight.js"></script>
- <h1>Lustre Animation</h1>
- You can use this package within Gleam with
- <pre><code class="language-bash">gleam add lustre_animation</code></pre>
- You can get the repository with
- <pre><code class="no-highlight">git clone https://git.chmeee.org/lustre_animation</code></pre>
- <h1>Usage</h1>
- The basic usage is
- <ol>
- <li>keep 1 `Animations` value</li>
- <li>add animations by some trigger</li>
- <li>call `animation.cmd()` on your value and let your lustre `update()` return it.
- This will cause a dispatch on the next JS animation frame, unless all animations have finished (and
- auto-removed).</li>
- <li>update the animations with the new time.</li>
- <li>evaluate for each animation you are interested in.</li>
- </ol>
- e.g. like this:
- <pre><code class="language-gleam">import lustre/animation as a
-
-pub type Msg {
- Trigger
- Tick(Float)
-}
-
-pub fn update(model: Model, msg: Msg) {
- let m = case msg of {
- Trigger -> {
- let new_anim = a.add(model.animations, "id", 1.0, 2.0, 0.250)
- Model(1.0, animations: new_anim)
- }
- Tick(t) -> {
- let new_anim = a.tick(model.animations, t)
- let new_value = a.value(new_anim, "id", model.value)
- Model(new_value, new_anim)
- }
- }
- #(m, animation.cmd(m.animations, Tick))
-}</code></pre>
-
- In the above <code>type Model</code>, <code>init</code> and <code>render</code> have been omitted.
-
- <h1>Examples</h1>
- Below are two working examples, of which the code is in the git repository.
- <div style="display: flex; flex-wrap: wrap; overflow-y: auto; overflow-x: hidden;">
- <div style="width: 320; margin-right: 2em;">
- <h2>1. Two independent animations</h2>
- <p>Click on the four buttons to manipulate the text horizontally,
- and vertically.</p>
- <p>See <code>./test/example_move_around.gleam</code></p>
- <div id="root"
- style="width: calc(320px - 2em); height: 480; border: 2px solid grey; padding: 0 1em 1em 1em;">
- <h1>Lustre Animation Example</h1>
- Please wait for the JavaScript (compiled Gleam) to take over.
- <noscript>
- <p>This site needs JavaScript to run, please enable/allow it.</p>
- </noscript>
- </div>
- </div>
-
- <div style="width: 320;">
- <h2>2. Many animations that are all 'the same'</h2>
- <p>Each drop behaves in the same way. Click in the area to generate them.</p>
- <p>See <code>./test/example_drops.gleam</code></p>
- <div id="drops" style="width: calc(320px - 2em); height: 480; border: 2px solid grey; padding: 1em;">
- <h1>Lustre Animation Example</h1>
- Please wait for the JavaScript (compiled Gleam) to take over.
- <noscript>
- <p>This site needs JavaScript to run, please enable/allow it.</p>
- </noscript>
- </div>
- </div>
- </div>
- <script type="text/javascript" src="run_highlight.js"></script>
- <script src="./test/start_examples.mjs" type="module"></script>
-</body>
-
-</html>
diff --git a/compat/lustre_animation/lustre_animation.css b/compat/lustre_animation/lustre_animation.css
deleted file mode 100644
index 3e6bc47..0000000
--- a/compat/lustre_animation/lustre_animation.css
+++ /dev/null
@@ -1,90 +0,0 @@
-code {
- color: #333;
- border: 1px solid #847;
- border-radius: 0.5ex;
- padding: 0 0.5ex;
-}
-
-pre code {
- border: 0;
- padding: 0;
-}
-
-pre {
- background: linear-gradient(to bottom, white, #ffaff3);
- overflow-x: auto;
- border: 1px solid #847;
- border-radius: 1ex;
- padding: 0.5ex 1.5ex;
- margin: 1ex 0;
-}
-
-.hljs-comment,
-.hljs-quote {
- color: #a0a1a7;
- font-style: italic
-}
-
-.hljs-doctag,
-.hljs-formula,
-.hljs-keyword {
- color: #a626a4
-}
-
-.hljs-deletion,
-.hljs-name,
-.hljs-section,
-.hljs-selector-tag,
-.hljs-subst {
- color: #e45649
-}
-
-.hljs-literal {
- color: #0184bb
-}
-
-.hljs-addition,
-.hljs-attribute,
-.hljs-meta .hljs-string,
-.hljs-regexp,
-.hljs-string {
- color: #50a14f
-}
-
-.hljs-attr,
-.hljs-number,
-.hljs-selector-attr,
-.hljs-selector-class,
-.hljs-selector-pseudo,
-.hljs-template-variable,
-.hljs-type,
-.hljs-variable {
- color: #986801
-}
-
-.hljs-bullet,
-.hljs-link,
-.hljs-meta,
-.hljs-selector-id,
-.hljs-symbol,
-.hljs-title {
- color: #4078f2
-}
-
-.hljs-built_in,
-.hljs-class .hljs-title,
-.hljs-title.class_ {
- color: #c18401
-}
-
-.hljs-emphasis {
- font-style: italic
-}
-
-.hljs-strong {
- font-weight: 700
-}
-
-.hljs-link {
- text-decoration: underline
-}
diff --git a/compat/lustre_animation/manifest.toml b/compat/lustre_animation/manifest.toml
deleted file mode 100644
index d420871..0000000
--- a/compat/lustre_animation/manifest.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-# This file was generated by Gleam
-# You typically do not need to edit this file
-
-packages = [
- { name = "gleam_stdlib", version = "0.30.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "704258528887F95075FFED7AAE1CCF836A9B88E3AADA2F69F9DA15815F94A4F9" },
- { name = "gleeunit", version = "0.10.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "ECEA2DE4BE6528D36AFE74F42A21CDF99966EC36D7F25DEB34D47DD0F7977BAF" },
- { name = "lustre", version = "3.0.0-rc.8", build_tools = ["gleam"], requirements = ["gleam_stdlib"], source = "local", path = "/Users/hayleigh/dev/gleam/lustre/lib" },
-]
-
-[requirements]
-gleam_stdlib = { version = "~> 0.30" }
-gleeunit = { version = "~> 0.10" }
-lustre = { path = "../../lib" }
diff --git a/compat/lustre_animation/package-lock.json b/compat/lustre_animation/package-lock.json
deleted file mode 100644
index 5c43ad9..0000000
--- a/compat/lustre_animation/package-lock.json
+++ /dev/null
@@ -1,790 +0,0 @@
-{
- "name": "lustre_animation",
- "lockfileVersion": 2,
- "requires": true,
- "packages": {
- "": {
- "devDependencies": {
- "vite": "^4.4.9"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
- "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
- "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
- "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
- "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
- "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
- "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
- "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
- "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
- "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
- "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
- "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
- "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
- "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
- "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
- "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
- "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
- "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
- "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
- "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
- "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
- "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
- "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
- "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
- "dev": true,
- "hasInstallScript": true,
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/android-arm": "0.18.20",
- "@esbuild/android-arm64": "0.18.20",
- "@esbuild/android-x64": "0.18.20",
- "@esbuild/darwin-arm64": "0.18.20",
- "@esbuild/darwin-x64": "0.18.20",
- "@esbuild/freebsd-arm64": "0.18.20",
- "@esbuild/freebsd-x64": "0.18.20",
- "@esbuild/linux-arm": "0.18.20",
- "@esbuild/linux-arm64": "0.18.20",
- "@esbuild/linux-ia32": "0.18.20",
- "@esbuild/linux-loong64": "0.18.20",
- "@esbuild/linux-mips64el": "0.18.20",
- "@esbuild/linux-ppc64": "0.18.20",
- "@esbuild/linux-riscv64": "0.18.20",
- "@esbuild/linux-s390x": "0.18.20",
- "@esbuild/linux-x64": "0.18.20",
- "@esbuild/netbsd-x64": "0.18.20",
- "@esbuild/openbsd-x64": "0.18.20",
- "@esbuild/sunos-x64": "0.18.20",
- "@esbuild/win32-arm64": "0.18.20",
- "@esbuild/win32-ia32": "0.18.20",
- "@esbuild/win32-x64": "0.18.20"
- }
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/nanoid": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
- "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
- },
- "node_modules/postcss": {
- "version": "8.4.28",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz",
- "integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "nanoid": "^3.3.6",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/rollup": {
- "version": "3.28.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.1.tgz",
- "integrity": "sha512-R9OMQmIHJm9znrU3m3cpE8uhN0fGdXiawME7aZIpQqvpS/85+Vt1Hq1/yVIcYfOmaQiHjvXkQAoJukvLpau6Yw==",
- "dev": true,
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=14.18.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/vite": {
- "version": "4.4.9",
- "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz",
- "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==",
- "dev": true,
- "dependencies": {
- "esbuild": "^0.18.10",
- "postcss": "^8.4.27",
- "rollup": "^3.27.1"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- },
- "peerDependencies": {
- "@types/node": ">= 14",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.4.0"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- }
- }
- }
- },
- "dependencies": {
- "@esbuild/android-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
- "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
- "dev": true,
- "optional": true
- },
- "@esbuild/android-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
- "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
- "dev": true,
- "optional": true
- },
- "@esbuild/android-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
- "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
- "dev": true,
- "optional": true
- },
- "@esbuild/darwin-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
- "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
- "dev": true,
- "optional": true
- },
- "@esbuild/darwin-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
- "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
- "dev": true,
- "optional": true
- },
- "@esbuild/freebsd-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
- "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
- "dev": true,
- "optional": true
- },
- "@esbuild/freebsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
- "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
- "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
- "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
- "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-loong64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
- "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-mips64el": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
- "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-ppc64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
- "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-riscv64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
- "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-s390x": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
- "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
- "dev": true,
- "optional": true
- },
- "@esbuild/linux-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
- "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
- "dev": true,
- "optional": true
- },
- "@esbuild/netbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
- "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
- "dev": true,
- "optional": true
- },
- "@esbuild/openbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
- "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
- "dev": true,
- "optional": true
- },
- "@esbuild/sunos-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
- "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
- "dev": true,
- "optional": true
- },
- "@esbuild/win32-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
- "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
- "dev": true,
- "optional": true
- },
- "@esbuild/win32-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
- "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
- "dev": true,
- "optional": true
- },
- "@esbuild/win32-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
- "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
- "dev": true,
- "optional": true
- },
- "esbuild": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
- "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
- "dev": true,
- "requires": {
- "@esbuild/android-arm": "0.18.20",
- "@esbuild/android-arm64": "0.18.20",
- "@esbuild/android-x64": "0.18.20",
- "@esbuild/darwin-arm64": "0.18.20",
- "@esbuild/darwin-x64": "0.18.20",
- "@esbuild/freebsd-arm64": "0.18.20",
- "@esbuild/freebsd-x64": "0.18.20",
- "@esbuild/linux-arm": "0.18.20",
- "@esbuild/linux-arm64": "0.18.20",
- "@esbuild/linux-ia32": "0.18.20",
- "@esbuild/linux-loong64": "0.18.20",
- "@esbuild/linux-mips64el": "0.18.20",
- "@esbuild/linux-ppc64": "0.18.20",
- "@esbuild/linux-riscv64": "0.18.20",
- "@esbuild/linux-s390x": "0.18.20",
- "@esbuild/linux-x64": "0.18.20",
- "@esbuild/netbsd-x64": "0.18.20",
- "@esbuild/openbsd-x64": "0.18.20",
- "@esbuild/sunos-x64": "0.18.20",
- "@esbuild/win32-arm64": "0.18.20",
- "@esbuild/win32-ia32": "0.18.20",
- "@esbuild/win32-x64": "0.18.20"
- }
- },
- "fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "optional": true
- },
- "nanoid": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
- "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
- "dev": true
- },
- "picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
- },
- "postcss": {
- "version": "8.4.28",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz",
- "integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==",
- "dev": true,
- "requires": {
- "nanoid": "^3.3.6",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
- }
- },
- "rollup": {
- "version": "3.28.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.1.tgz",
- "integrity": "sha512-R9OMQmIHJm9znrU3m3cpE8uhN0fGdXiawME7aZIpQqvpS/85+Vt1Hq1/yVIcYfOmaQiHjvXkQAoJukvLpau6Yw==",
- "dev": true,
- "requires": {
- "fsevents": "~2.3.2"
- }
- },
- "source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true
- },
- "vite": {
- "version": "4.4.9",
- "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz",
- "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==",
- "dev": true,
- "requires": {
- "esbuild": "^0.18.10",
- "fsevents": "~2.3.2",
- "postcss": "^8.4.27",
- "rollup": "^3.27.1"
- }
- }
- }
-}
diff --git a/compat/lustre_animation/package.json b/compat/lustre_animation/package.json
deleted file mode 100644
index a0831d3..0000000
--- a/compat/lustre_animation/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "scripts": {
- "dev": "gleam build && vite",
- "build": "gleam build && vite build"
- },
- "devDependencies": {
- "vite": "^4.4.9"
- }
-}
diff --git a/compat/lustre_animation/run_highlight.js b/compat/lustre_animation/run_highlight.js
deleted file mode 100644
index d73c817..0000000
--- a/compat/lustre_animation/run_highlight.js
+++ /dev/null
@@ -1,3 +0,0 @@
-document.querySelectorAll('code').forEach((el) => {
- hljs.highlightElement(el);
-});
diff --git a/compat/lustre_animation/src/ffi.mjs b/compat/lustre_animation/src/ffi.mjs
deleted file mode 100644
index fd5d9d3..0000000
--- a/compat/lustre_animation/src/ffi.mjs
+++ /dev/null
@@ -1,2 +0,0 @@
-export const request_animation_frame = f => requestAnimationFrame(f)
-export const cancel_animation_frame = id => cancelAnimationFrame(id) \ No newline at end of file
diff --git a/compat/lustre_animation/src/lustre/animation.gleam b/compat/lustre_animation/src/lustre/animation.gleam
deleted file mode 100644
index 8f3312e..0000000
--- a/compat/lustre_animation/src/lustre/animation.gleam
+++ /dev/null
@@ -1,170 +0,0 @@
-import lustre/effect.{Effect}
-import gleam/list.{filter, find, map}
-
-/// A singleton holding all your animations, and a timestamp
-///
-/// Hayleigh note: since the stdlib got some improvmements a while ago, I think
-/// you could use a `Map(String, Animation)` now instead of `List.find`ing all
-/// over the place.
-pub opaque type Animations {
- Animations(t: Float, List(Animation))
-}
-
-type Animation {
- Animation(name: String, range: #(Float, Float), state: AnimationState)
-}
-
-// InParallel(Animations)
-// InSequence(Animations)
-// Repeat(Animation)
-// Cancelled(Animation)
-
-// The State Done will guarantee the `stop` value is returned, before the Animation is removed from the list
-type AnimationState {
- NotStarted(seconds: Float)
- Running(seconds: Float, since: Float)
- Done
-}
-
-pub fn new() {
- Animations(0.0, [])
-}
-
-/// Add an animation (linear interpolation) from `start` to `stop`, for `seconds` duration.
-/// The `name` should be unique, so the animation can be retrieved and evaluated by `value()` later.
-/// The animation is started when a subsequent command from `effect()` is returned by your
-/// lustre `update()` function; followed by a call to `tick()`.
-pub fn add(
- animations: Animations,
- name,
- start: Float,
- stop: Float,
- seconds: Float,
-) -> Animations {
- use list <- change_list(animations)
- [Animation(name, #(start, stop), NotStarted(seconds)), ..list]
-}
-
-/// Remove an animation if it should stop before it is finished.
-/// If an animation runs to its end normally, you do not have to `remove()` it manually,
-/// will be automatically removed by `tick()`.
-pub fn remove(animations: Animations, name) -> Animations {
- use list <- change_list(animations)
- filter(list, does_not_have_name(_, name))
- // Would not filter, but replace w/ Cancelled and filtered in the next call, see comments at bottom of this file
-}
-
-fn change_list(
- animations: Animations,
- f: fn(List(Animation)) -> List(Animation),
-) -> Animations {
- let assert Animations(t, list) = animations
- Animations(t, f(list))
-}
-
-fn does_not_have_name(animation: Animation, name: String) {
- let assert Animation(n, _, _) = animation
- n != name
-}
-
-/// When called for the first time on an animation, its start time is
-/// set to time-Offset. Its stop time then is the start time plus the
-/// duration.
-///
-/// When called for the *first* time for animations that have finished,
-/// they will be marked as such in the result. `value()` will return the `stop` value
-/// that you passed with `add()`
-///
-/// When called the *second* time for animations that have finished, they will be absent
-/// from the returned value.
-pub fn tick(animations: Animations, time_offset) -> Animations {
- let assert Animations(_, list) = animations
- let new_list =
- list
- |> filter(not_done)
- |> map(tick_animation(_, time_offset))
- Animations(time_offset, new_list)
-}
-
-fn not_done(animation: Animation) -> Bool {
- case animation {
- Animation(_, _, Done) -> False
- _ -> True
- }
-}
-
-fn tick_animation(animation: Animation, time: Float) -> Animation {
- let assert Animation(name, range, state) = animation
- let new_state = case state {
- NotStarted(seconds) -> Running(seconds, since: time)
- Running(seconds, since) ->
- case time -. since >=. seconds *. 1000.0 {
- True -> Done
- False -> state
- }
- Done -> Done
- }
- Animation(name, range, new_state)
-}
-
-/// Returns `effect.none()` if none of the animations is running.
-/// Otherwise returns an opaque `Effect` that will cause `msg(time)` to
-/// be dispatched on a JavaScript `requestAnimationFrame`
-///
-/// Hayleigh note: Maybe this could have a better name like `next_tick` or
-/// `request_tick`?
-pub fn effect(animations: Animations, msg: fn(Float) -> m) -> Effect(m) {
- case animations {
- Animations(_, []) -> effect.none()
- _ -> request_animation_frame(msg)
- }
-}
-
-/// If the animation specified by `which` is not found, returns `default`.
-/// Otherwise, the interpolated value for the `time` passed to `tick()` is returned.
-pub fn value(animations: Animations, which: String, default: Float) -> Float {
- let assert Animations(t, list) = animations
- case find(list, has_name(_, which)) {
- Ok(animation) -> evaluate(animation, t)
- Error(Nil) -> default
- }
-}
-
-fn has_name(animation: Animation, name: String) {
- let assert Animation(n, _, _) = animation
- n == name
-}
-
-fn evaluate(animation: Animation, time: Float) -> Float {
- let assert Animation(_, #(start, stop), state) = animation
- case state {
- NotStarted(_) -> start
- Running(seconds, since) -> {
- let dt = time -. since
- let delta = dt /. { seconds *. 1000.0 }
- start +. { stop -. start } *. delta
- }
- Done -> stop
- }
-}
-
-pub fn request_animation_frame(msg: fn(Float) -> m) -> Effect(m) {
- effect.from(fn(dispatch) {
- js_request_animation_frame(fn(time_offset: Float) {
- dispatch(msg(time_offset))
- })
- Nil
- })
-}
-
-pub type RequestedFrame
-
-// The returned 'long' can be passed to 'cancelAnimationFrame' - except we do not have any means to
-// TODO Push the 'long' down into JS land, with the Animation, so we can
-// make a mapping from Animation to RequestFrame and a `cancelFrame(Animation, msg) -> Effect(m)`
-// that (again in JS land) *can* cancel the appropriate request frame.
-external fn js_request_animation_frame(f) -> RequestedFrame =
- "../ffi.mjs" "request_animation_frame"
-
-pub external fn cancel_animation_frame(frame: RequestedFrame) -> Nil =
- "../ffi.mjs" "cancel_animation_frame"
diff --git a/compat/lustre_animation/test/example_drops.gleam b/compat/lustre_animation/test/example_drops.gleam
deleted file mode 100644
index dd69f5c..0000000
--- a/compat/lustre_animation/test/example_drops.gleam
+++ /dev/null
@@ -1,120 +0,0 @@
-import lustre
-import lustre/animation.{Animations}
-import lustre/attribute.{id, style}
-import lustre/effect.{Effect}
-import lustre/element.{Element, text}
-import lustre/element/html.{div, h3}
-import lustre/event.{on}
-import gleam/float
-import gleam/int
-import gleam/list.{filter, map}
-import gleam/dynamic.{Dynamic} as d
-import gleam/option.{Some}
-
-pub type Msg {
- Click(x: Float, y: Float)
- Tick(time_offset: Float)
-}
-
-pub type Drop {
- Drop(id: String, x: Float, y: Float, r: Float)
-}
-
-pub type Model {
- Model(counter: Int, drops: List(Drop), animations: Animations)
-}
-
-pub fn main() {
- lustre.application(init, update, render)
- |> lustre.start("#drops", Nil)
-}
-
-fn init(_) {
- #(Model(0, [], animation.new()), effect.none())
-}
-
-const to_s = int.to_string
-
-pub fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
- let m = case msg {
- Click(x, y) -> {
- let id = "drop" <> to_s(model.counter)
- let new_animations = animation.add(model.animations, id, 0.0, 1.0, 1.5)
- let new_drop = Drop(id, x, y, 0.0)
- Model(model.counter + 1, [new_drop, ..model.drops], new_animations)
- }
- Tick(time_offset) -> {
- let new_animations = animation.tick(model.animations, time_offset)
- let new_drops =
- model.drops
- |> filter(fn(drop) { drop.r != 1.0 })
- |> map(fn(drop) {
- let r = animation.value(new_animations, drop.id, drop.r)
- Drop(..drop, r: r)
- })
- Model(..model, drops: new_drops, animations: new_animations)
- }
- }
- #(m, animation.effect(m.animations, Tick))
-}
-
-pub fn render(model: Model) -> Element(Msg) {
- div(
- [
- style([
- #("width", "100%"),
- #("height", "100%"),
- #("display", "grid"),
- #("grid-template-rows", "auto 1fr"),
- ]),
- ],
- [
- h3([style([#("text-align", "center")])], [text("Click to make drops")]),
- div(
- [
- id("pond"),
- style([#("position", "relative")]),
- on(
- "mouseDown",
- fn(event) {
- let assert Ok(x) = d.field("clientX", d.float)(event)
- let assert Ok(y) = d.field("clientY", d.float)(event)
- let rect = bounding_client_rect("pond")
- let assert Ok(top) = d.field("top", d.float)(rect)
- let assert Ok(left) = d.field("left", d.float)(rect)
-
- Some(Click(x -. left, y -. top))
- },
- ),
- ],
- map(model.drops, render_drop),
- ),
- ],
- )
-}
-
-fn render_drop(drop: Drop) {
- let r = drop.r *. 50.0
- let rad = float.to_string(r *. 2.0)
- let rw = float.to_string(drop.r *. 2.5)
- let alpha =
- 1.0 -. drop.r
- |> float.to_string
- div(
- [
- style([
- #("position", "absolute"),
- #("left", float.to_string(drop.x -. r) <> "px"),
- #("top", float.to_string(drop.y -. r) <> "px"),
- #("width", rad <> "px"),
- #("height", rad <> "px"),
- #("border", rw <> "px solid rgba(0, 0, 0, " <> alpha <> ")"),
- #("border-radius", "50%"),
- ]),
- ],
- [],
- )
-}
-
-external fn bounding_client_rect(String) -> Dynamic =
- "./info.mjs" "bounding_client_rect"
diff --git a/compat/lustre_animation/test/example_two_independent.gleam b/compat/lustre_animation/test/example_two_independent.gleam
deleted file mode 100644
index 61e687d..0000000
--- a/compat/lustre_animation/test/example_two_independent.gleam
+++ /dev/null
@@ -1,103 +0,0 @@
-import lustre
-import lustre/animation.{Animations}
-import lustre/attribute.{style}
-import lustre/effect.{Effect}
-import lustre/element.{text}
-import lustre/element/html.{button, div, h3, span}
-import lustre/event.{on_click}
-import gleam/float
-
-pub type Msg {
- Left
- Right
- Top
- Bottom
- Tick(time_offset: Float)
-}
-
-pub type Model {
- Model(x: Float, y: Float, animations: Animations)
-}
-
-pub fn main() {
- lustre.application(init, update, render)
- |> lustre.start("#root", Nil)
-}
-
-fn init(_) {
- #(Model(0.5, 0.5, animation.new()), effect.none())
-}
-
-pub fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
- let m = case msg {
- Left -> {
- let new_animations =
- animation.add(model.animations, "x", model.x, 0.0, 2.5)
- Model(..model, animations: new_animations)
- }
- Right -> {
- let new_animations =
- animation.add(model.animations, "x", model.x, 1.0, 2.5)
- Model(..model, animations: new_animations)
- }
- Top -> {
- let new_animations =
- animation.add(model.animations, "y", model.y, 0.0, 2.5)
- Model(..model, animations: new_animations)
- }
- Bottom -> {
- let new_animations =
- animation.add(model.animations, "y", model.y, 1.0, 2.5)
- Model(..model, animations: new_animations)
- }
- Tick(time_offset) -> {
- let new_animations = animation.tick(model.animations, time_offset)
- let x = animation.value(new_animations, "x", model.x)
- let y = animation.value(new_animations, "y", model.y)
- Model(x: x, y: y, animations: new_animations)
- }
- }
- #(m, animation.effect(m.animations, Tick))
-}
-
-pub fn render(model: Model) {
- let sp = span([], [])
- let to_s = float.to_string
- div(
- [
- style([
- #("display", "grid"),
- #("grid-template-rows", "1fr auto"),
- #("width", "100%"),
- #("height", "100%"),
- ]),
- ],
- [
- div(
- [
- style([
- #("display", "grid"),
- #(
- "grid-template-rows",
- to_s(model.y) <> "fr auto " <> to_s(1.0 -. model.y) <> "fr",
- ),
- #(
- "grid-template-columns",
- to_s(model.x) <> "fr auto " <> to_s(1.0 -. model.x) <> "fr",
- ),
- ]),
- ],
- [sp, sp, sp, sp, h3([], [text("Move me around")]), sp, sp, sp, sp],
- ),
- div(
- [],
- [
- button([on_click(Left)], [text("Move to the Left")]),
- button([on_click(Right)], [text("Move to the Right")]),
- button([on_click(Top)], [text("Move to the Top")]),
- button([on_click(Bottom)], [text("Move to the Bottom")]),
- ],
- ),
- ],
- )
-}
diff --git a/compat/lustre_animation/test/info.mjs b/compat/lustre_animation/test/info.mjs
deleted file mode 100644
index d58e440..0000000
--- a/compat/lustre_animation/test/info.mjs
+++ /dev/null
@@ -1,2 +0,0 @@
-export const bounding_client_rect = id => document.getElementById(id).getBoundingClientRect()
-
diff --git a/compat/lustre_animation/test/lustre/animation_test.gleam b/compat/lustre_animation/test/lustre/animation_test.gleam
deleted file mode 100644
index 98ded63..0000000
--- a/compat/lustre_animation/test/lustre/animation_test.gleam
+++ /dev/null
@@ -1,39 +0,0 @@
-import gleeunit/should
-import lustre/animation.{add, new, tick, value}
-
-pub fn evaluate_test() {
- new()
- |> add("a", 7.0, 42.0, 2.0)
- |> value("a", 0.0)
- |> should.equal(7.0)
-}
-
-pub fn evaluate_start_test() {
- new()
- |> add("a", 7.0, 42.0, 2.0)
- |> tick(1000.0)
- |> value("a", 0.0)
- |> should.equal(7.0)
-}
-
-pub fn evaluate_done_test() {
- new()
- |> add("a", 7.0, 42.0, 2.0)
- |> tick(1000.0)
- |> tick(3000.0)
- |> value("a", 0.0)
- |> should.equal(42.0)
-}
-
-pub fn evaluate_gone_test() {
- new()
- |> add("a", 7.0, 42.0, 2.0)
- // start
- |> tick(1000.0)
- // Done
- |> tick(3000.0001)
- // remove
- |> tick(3000.1)
- |> value("a", 0.0)
- |> should.equal(0.0)
-}
diff --git a/compat/lustre_animation/test/lustre_animation_test.gleam b/compat/lustre_animation/test/lustre_animation_test.gleam
deleted file mode 100644
index ecd12ad..0000000
--- a/compat/lustre_animation/test/lustre_animation_test.gleam
+++ /dev/null
@@ -1,5 +0,0 @@
-import gleeunit
-
-pub fn main() {
- gleeunit.main()
-}
diff --git a/compat/lustre_animation/test/start_examples.mjs b/compat/lustre_animation/test/start_examples.mjs
deleted file mode 100644
index 6d792c7..0000000
--- a/compat/lustre_animation/test/start_examples.mjs
+++ /dev/null
@@ -1,5 +0,0 @@
-import * as two from "../build/dev/javascript/lustre_animation/example_two_independent.mjs";
-import * as drops from "../build/dev/javascript/lustre_animation/example_drops.mjs";
-
-two.main();
-drops.main();
diff --git a/compat/lustre_http/.gitignore b/compat/lustre_http/.gitignore
deleted file mode 100644
index e03d74b..0000000
--- a/compat/lustre_http/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-build
-*tar
diff --git a/compat/lustre_http/README.md b/compat/lustre_http/README.md
deleted file mode 100644
index 1117b93..0000000
--- a/compat/lustre_http/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# lustre_http
-
-[![Package Version](https://img.shields.io/hexpm/v/lustre_http)](https://hex.pm/packages/lustre_http)
-[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/lustre_http/)
-
-Make HTTP requests from `lustre` via its `cmd` interface.
-Makes life easy when such requests are initiated by the user.
-
-## Quick start
-
-Add to your Gleam project:
-
-```sh
-gleam add lustre_http
-```
-
-View the documentation at <https://hexdocs.pm/lustre_http>, although only `get_as_text` is documented a.t.m.
diff --git a/compat/lustre_http/gleam.toml b/compat/lustre_http/gleam.toml
deleted file mode 100644
index 19bf4bc..0000000
--- a/compat/lustre_http/gleam.toml
+++ /dev/null
@@ -1,16 +0,0 @@
-name = "lustre_http"
-version = "0.3.0"
-target = "javascript"
-
-licences = ["MIT"]
-description = "HTTP requests from lustre"
-repository = { type = "custom", url = "https://git.chmeee.org/lustre_http" }
-links = [{ title = "Package", href = "https://hex.pm/packages/lustre_http" }]
-
-[dependencies]
-gleam_stdlib = "~> 0.30"
-gleam_json = "~> 0.6"
-lustre = { path = "../../lib" }
-
-[dev-dependencies]
-gleeunit = "~> 0.10" \ No newline at end of file
diff --git a/compat/lustre_http/manifest.toml b/compat/lustre_http/manifest.toml
deleted file mode 100644
index 7b77a95..0000000
--- a/compat/lustre_http/manifest.toml
+++ /dev/null
@@ -1,16 +0,0 @@
-# This file was generated by Gleam
-# You typically do not need to edit this file
-
-packages = [
- { name = "gleam_json", version = "0.6.0", build_tools = ["gleam"], requirements = ["thoas", "gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "C6CC5BEECA525117E97D0905013AB3F8836537455645DDDD10FE31A511B195EF" },
- { name = "gleam_stdlib", version = "0.30.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "704258528887F95075FFED7AAE1CCF836A9B88E3AADA2F69F9DA15815F94A4F9" },
- { name = "gleeunit", version = "0.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "1397E5C4AC4108769EE979939AC39BF7870659C5AFB714630DEEEE16B8272AD5" },
- { name = "lustre", version = "3.0.0-rc.8", build_tools = ["gleam"], requirements = ["gleam_stdlib"], source = "local", path = "/Users/hayleigh/dev/gleam/lustre/lib" },
- { name = "thoas", version = "0.4.1", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "4918D50026C073C4AB1388437132C77A6F6F7C8AC43C60C13758CC0ADCE2134E" },
-]
-
-[requirements]
-gleam_json = { version = "~> 0.6" }
-gleam_stdlib = { version = "~> 0.30" }
-gleeunit = { version = "~> 0.10" }
-lustre = { path = "../../lib" }
diff --git a/compat/lustre_http/src/ffi.mjs b/compat/lustre_http/src/ffi.mjs
deleted file mode 100644
index bb01b09..0000000
--- a/compat/lustre_http/src/ffi.mjs
+++ /dev/null
@@ -1,16 +0,0 @@
-export const do_request = (method, url, body, on_success, on_error) => {
- let xhr = new XMLHttpRequest()
- xhr.onerror = _evt => {
- console.log("error for", method, url, ":", xhr)
- on_error(888, "oops!")
- }
- xhr.onloadend = _evt => {
- switch (xhr.status) {
- case 200:
- case 204: on_success(xhr.responseText); break;
- default: on_error(xhr.status, xhr.responseText)
- }
- }
- xhr.open(method, url)
- xhr.send(body);
-}
diff --git a/compat/lustre_http/src/lustre_http.gleam b/compat/lustre_http/src/lustre_http.gleam
deleted file mode 100644
index a066faa..0000000
--- a/compat/lustre_http/src/lustre_http.gleam
+++ /dev/null
@@ -1,126 +0,0 @@
-import gleam/json
-import lustre/effect.{Effect}
-
-pub type HttpError {
- Unauthorized
- NotFound
- InternalServerError(String)
- OtherError(Int, String)
-}
-
-pub type StringResult =
- Result(String, HttpError)
-
-pub type HttpOrJsonError {
- H(HttpError)
- J(json.DecodeError)
-}
-
-pub type JsonResult(t) =
- Result(t, HttpOrJsonError)
-
-external fn do_request(
- method: String,
- url: String,
- body: String,
- on_success: fn(String) -> Nil,
- on_error: fn(Int, String) -> Nil,
-) -> Nil =
- "./ffi.mjs" "do_request"
-
-fn do_get(url, on_success, on_error) {
- do_request("GET", url, "", on_success, on_error)
-}
-
-fn do_post(url, body, on_success, on_error) {
- do_request("POST", url, body, on_success, on_error)
-}
-
-/// ### Usage
-/// ```
-/// import lustre_http as http
-///
-/// type Msg {
-/// SomeInteraction
-/// TextReceived(StringResult)
-/// }
-///
-/// pub fn update(model, msg) {
-/// case msg {
-/// SomeInteraction -> #(model, http.get_as_text("the_text", TextReceived))
-/// TextReceived(Ok(text)) -> #(apply(text, model), effect.none())
-/// TextReceived(Error(e)) -> #(indicate_problem(e, model), effect.none())
-/// }
-/// }
-/// ```
-pub fn get_as_text(url: String, to_msg: fn(StringResult) -> msg) -> Effect(msg) {
- use dispatch <- effect.from
-
- do_get(
- url,
- fn(body) { dispatch(to_msg(Ok(body))) },
- fn(code, msg) {
- decode_error(code, msg)
- |> Error
- |> to_msg
- |> dispatch
- },
- )
-}
-
-fn decode_error(code, msg) {
- case code {
- 401 -> Unauthorized
- 404 -> NotFound
- 500 -> InternalServerError(msg)
- _ -> OtherError(code, msg)
- }
-}
-
-/// Will automatically try to decode the JSON for you.
-/// The error-type is a bit complicated. In a future version will probably
-/// (a) force "text/json" in the headers (b) not decode for you.
-pub fn get_as_json(
- url: String,
- to_msg: fn(JsonResult(String)) -> msg,
- decoder,
-) -> Effect(msg) {
- use dispatch <- effect.from
-
- do_get(
- url,
- fn(body) {
- case json.decode(from: body, using: decoder) {
- Ok(json) -> dispatch(to_msg(Ok(json)))
- Error(json_error) -> dispatch(to_msg(Error(J(json_error))))
- }
- },
- fn(code, msg) {
- let http_error = case code {
- 401 -> Unauthorized
- 404 -> NotFound
- 500 -> InternalServerError(msg)
- _ -> OtherError(code, msg)
- }
- dispatch(to_msg(Error(H(http_error))))
- },
- )
-}
-
-/// Future versions will force headers in both the request and the response
-/// so you can post json and receive text, post text and receive json, etc.
-pub fn post_text(url: String, body: String, to_msg: fn(StringResult) -> msg) {
- use dispatch <- effect.from
-
- do_post(
- url,
- body,
- fn(body) { dispatch(to_msg(Ok(body))) },
- fn(code, msg) {
- decode_error(code, msg)
- |> Error
- |> to_msg
- |> dispatch
- },
- )
-}
diff --git a/compat/lustre_http/test/lustre_http_test.gleam b/compat/lustre_http/test/lustre_http_test.gleam
deleted file mode 100644
index e426a70..0000000
--- a/compat/lustre_http/test/lustre_http_test.gleam
+++ /dev/null
@@ -1,15 +0,0 @@
-import lustre_http as http
-import gleeunit
-
-pub fn main() {
- gleeunit.main()
-}
-
-pub type ToMsgProvider {
- Wrapper(http.StringResult)
-}
-
-// We cannot run the resulting lustre.Cmd, but we can at least ensure it can be used/compiled this way
-pub fn compilation_test() {
- http.get_as_text("http://localhost:8080/not_here", Wrapper)
-}
diff --git a/compat/lustre_websocket/.gitignore b/compat/lustre_websocket/.gitignore
deleted file mode 100644
index 378eac2..0000000
--- a/compat/lustre_websocket/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-build
diff --git a/compat/lustre_websocket/README.md b/compat/lustre_websocket/README.md
deleted file mode 100644
index 5e30c8e..0000000
--- a/compat/lustre_websocket/README.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# lustre_websocket
-
-[![Package Version](https://img.shields.io/hexpm/v/lustre_websocket)](https://hex.pm/packages/lustre_websocket)
-[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/lustre_websocket/)
-
-Use websockets from your `lustre` application!
-
-## Quick start
-
-Add to your Gleam project:
-
-```sh
-gleam add lustre_websocket
-```
-
-Typical usage looks like
-```
-import lustre_websocket as ws
-
-pub type Msg {
- WsWrapper(ws.WebSocketEvent)
-}
-
-let init = #(Model(None), ws.init("/path", WsWrapper))
-```
-and then you pass `init` as first argument to `lustre.application`.
-But you can create a socket at any time, esp. re-create it after it is closed by the server.
-
-The events can be handled like this:
-```
-update(model, msg) {
- case msg {
- WsWrapper(OnOpen(socket)) -> #(Model(..model, ws: Some(socket)), ws.send(socket, "client-init"))
- WsWrapper(OnMessage(msg)) -> todo
- WsWrapper(OnClose(reason)) -> #(Model(..model, ws: None), cmd.none())
- }
-}
-```
-which also demonstrates how you send a text message over the socket.
-
-### Caveat
-
-*This package cannot handle more than 1 socket on a server endpoint*
-
-### TODO:
- * support protocol choice, including one websocket per protocol per endpoint
- * support binary data
- * allow client to close the socket
- * provide errors to the application, when I have a clue on what those might actually be
- * prevent sending over closed sockets
- * maybe auto-reopen sockets that were closed because of Normal
diff --git a/compat/lustre_websocket/gleam.toml b/compat/lustre_websocket/gleam.toml
deleted file mode 100644
index ba11fd3..0000000
--- a/compat/lustre_websocket/gleam.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-name = "lustre_websocket"
-version = "0.6.0"
-target = "javascript"
-
-licences = ["MIT"]
-description = "Web Socket requests from lustre"
-repository = { type = "custom", url = "https://git.chmeee.org/lustre_websocket" }
-links = [
- { title = "Package", href = "https://hex.pm/packages/lustre_websocket" },
-]
-
-[dependencies]
-gleam_stdlib = "~> 0.30"
-lustre = { path = "../../lib" }
-
-
-[dev-dependencies]
-gleeunit = "~> 0.10" \ No newline at end of file
diff --git a/compat/lustre_websocket/manifest.toml b/compat/lustre_websocket/manifest.toml
deleted file mode 100644
index 7cf6fc0..0000000
--- a/compat/lustre_websocket/manifest.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-# This file was generated by Gleam
-# You typically do not need to edit this file
-
-packages = [
- { name = "gleam_stdlib", version = "0.30.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "704258528887F95075FFED7AAE1CCF836A9B88E3AADA2F69F9DA15815F94A4F9" },
- { name = "gleeunit", version = "0.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "1397E5C4AC4108769EE979939AC39BF7870659C5AFB714630DEEEE16B8272AD5" },
- { name = "lustre", version = "3.0.0-rc.8", build_tools = ["gleam"], requirements = ["gleam_stdlib"], source = "local", path = "/Users/hayleigh/dev/gleam/lustre/lib" },
-]
-
-[requirements]
-gleam_stdlib = { version = "~> 0.30" }
-gleeunit = { version = "~> 0.10" }
-lustre = { path = "../../lib" }
diff --git a/compat/lustre_websocket/src/ffi.mjs b/compat/lustre_websocket/src/ffi.mjs
deleted file mode 100644
index 56f11fd..0000000
--- a/compat/lustre_websocket/src/ffi.mjs
+++ /dev/null
@@ -1,39 +0,0 @@
-let ws_handler_registry = {}
-
-export const init_websocket = path => {
- let ws
- if (typeof WebSocket === "function") {
- // we're in the browser
- let url = new URL(document.URL)
- let protocol = url.protocol === "http:" ? "ws" : "wss"
- let ws_url = protocol + "://" + url.host + url.pathname + path
- ws = new WebSocket(ws_url)
- } else {
- // we're NOT in the browser, prolly running tests
- ws = {}
- }
- ws_handler_registry[ws.url] = { ws: ws }
-
- ws.onopen = evt => {
- ws_handler_registry[ws.url]?.on_open?.()
- }
- ws.onclose = evt => {
- ws_handler_registry[ws.url]?.on_close?.(evt.code)
- delete ws_handler_registry[ws.url]
- }
- ws.onmessage = event => ws_handler_registry[ws.url]?.on_message?.(event.data)
- ws.onerror = error => console.log("ws", ws.url, "error", error, "no handler, since I have no clue what errors we might be talking about")
- return ws
-}
-
-export const register_websocket_handler = (ws, on_open, on_message, on_close) => {
- const reg_entry = ws_handler_registry[ws.url]
- reg_entry.on_open = on_open
- reg_entry.on_message = on_message
- reg_entry.on_close = on_close
- console.log("ws reg", ws_handler_registry)
-}
-
-export const send_over_websocket = (ws, msg) => {
- ws.send(msg)
-}
diff --git a/compat/lustre_websocket/src/lustre_websocket.gleam b/compat/lustre_websocket/src/lustre_websocket.gleam
deleted file mode 100644
index ce46a4a..0000000
--- a/compat/lustre_websocket/src/lustre_websocket.gleam
+++ /dev/null
@@ -1,85 +0,0 @@
-import lustre/effect.{Effect}
-
-pub type WebSocket
-
-pub type WebSocketCloseReason {
- // 1000
- Normal
- // 1001
- GoingAway
- // 1002
- ProtocolError
- // 1003
- UnexpectedTypeOfData
- // 1004 Reserved
- // 1005
- NoCodeFromServer
- // 1006, no close frame
- AbnormalClose
- // 1007
- IncomprehensibleFrame
- // 1008
- PolicyViolated
- // 1009
- MessageTooBig
- // 1010
- FailedExtensionNegotation
- // 1011
- UnexpectedFailure
- // 1015
- FailedTLSHandshake
-}
-
-pub type WebSocketEvent {
- OnOpen(WebSocket)
- OnMessage(String)
- OnClose(WebSocketCloseReason)
-}
-
-/// Initialize a websocket. These constructs are fully asynchronous, so you must provide a wrapper
-/// that takes a `WebSocketEvent` and turns it into a lustre message of your application.
-pub fn init(path: String, wrapper: fn(WebSocketEvent) -> a) -> Effect(a) {
- let ws = do_init(path)
- use dispatch <- effect.from
- let on_open = fn() { dispatch(wrapper(OnOpen(ws))) }
- let on_message = fn(in_msg) { dispatch(wrapper(OnMessage(in_msg))) }
- let on_close = fn(code) {
- case code {
- 1000 -> dispatch(wrapper(OnClose(Normal)))
- 1001 -> dispatch(wrapper(OnClose(GoingAway)))
- 1002 -> dispatch(wrapper(OnClose(ProtocolError)))
- 1003 -> dispatch(wrapper(OnClose(UnexpectedTypeOfData)))
- 1005 -> dispatch(wrapper(OnClose(NoCodeFromServer)))
- 1006 -> dispatch(wrapper(OnClose(AbnormalClose)))
- 1007 -> dispatch(wrapper(OnClose(IncomprehensibleFrame)))
- 1008 -> dispatch(wrapper(OnClose(PolicyViolated)))
- 1009 -> dispatch(wrapper(OnClose(MessageTooBig)))
- 1010 -> dispatch(wrapper(OnClose(FailedExtensionNegotation)))
- 1011 -> dispatch(wrapper(OnClose(UnexpectedFailure)))
- 1015 -> dispatch(wrapper(OnClose(FailedTLSHandshake)))
- }
- }
-
- do_register(ws, on_open, on_message, on_close)
-}
-
-external fn do_init(path) -> WebSocket =
- "./ffi.mjs" "init_websocket"
-
-external fn do_register(
- ws: WebSocket,
- on_open: fn() -> Nil,
- on_message: fn(String) -> Nil,
- on_close: fn(Int) -> Nil,
-) -> Nil =
- "./ffi.mjs" "register_websocket_handler"
-
-/// Send a text message over the web socket. This is asynchronous. There is no
-/// expectation of a reply. See `init`. Only works on an Non-Closed socket.
-/// Returns a `Effect(a)` that you must pass as second entry in the lustre `update` return.
-pub fn send(ws: WebSocket, msg: String) -> Effect(a) {
- effect.from(fn(_) { do_send(ws, msg) })
-}
-
-external fn do_send(ws: WebSocket, msg: String) -> Nil =
- "./ffi.mjs" "send_over_websocket"
diff --git a/compat/lustre_websocket/test/lustre_websocket_test.gleam b/compat/lustre_websocket/test/lustre_websocket_test.gleam
deleted file mode 100644
index 2ce0f90..0000000
--- a/compat/lustre_websocket/test/lustre_websocket_test.gleam
+++ /dev/null
@@ -1,15 +0,0 @@
-import gleeunit
-import lustre_websocket as ws
-
-pub fn main() {
- gleeunit.main()
-}
-
-pub type Wrapper {
- Wrapper(ws.WebSocketEvent)
-}
-
-pub fn rather_thin_compilation_test() {
- let _cmd = ws.init("/blah", Wrapper)
- // We cannot run the resulting lustre.Cmd, but we can at least ensure it can be used/compiled this way
-}
diff --git a/docs/.gitignore b/docs/.gitignore
deleted file mode 100644
index 170cca9..0000000
--- a/docs/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-*.beam
-*.ez
-build
-erl_crash.dump
diff --git a/docs/404.html b/docs/404.html
deleted file mode 100644
index 57e4984..0000000
--- a/docs/404.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8" />
- <title>Lustre</title>
-
- <script type="module">
- // Single Page Apps for GitHub Pages
- // MIT License
- // https://github.com/rafgraph/spa-github-pages
- // This script takes the current url and converts the path and query
- // string into just a query string, and then redirects the browser
- // to the new url with only a query string and hash fragment,
- // e.g. https://www.foo.tld/one/two?a=b&c=d#qwe, becomes
- // https://www.foo.tld/?/one/two&a=b~and~c=d#qwe
- // Note: this 404.html file must be at least 512 bytes for it to work
- // with Internet Explorer (it is currently > 512 bytes)
-
- // If you're creating a Project Pages site and NOT using a custom domain,
- // then set pathSegmentsToKeep to 1 (enterprise users may need to set it to > 1).
- // This way the code will only replace the route part of the path, and not
- // the real directory in which the app resides, for example:
- // https://username.github.io/repo-name/one/two?a=b&c=d#qwe becomes
- // https://username.github.io/repo-name/?/one/two&a=b~and~c=d#qwe
- // Otherwise, leave pathSegmentsToKeep as 0.
- const pathSegmentsToKeep = import.meta.env.BASE_URL === "/" ? 0 : 1;
-
- if (window.location.pathname.startsWith("/lustre")) {
- const protocol = window.location.protocol;
- const hostname = window.location.hostname;
- const port = window.location.port;
- const pathname = window.location.pathname
- .split("/")
- .slice(0, 1 + pathSegmentsToKeep)
- .join("/");
- const query = window.location.pathname
- .slice(1)
- .split("/")
- .slice(pathSegmentsToKeep)
- .join("/")
- .replace(/&/g, "~and~");
- const search = window.location.search
- ? "&" + window.location.search.slice(1).replace(/&/g, "~and~")
- : "";
- const hash = window.location.hash;
-
- window.location.replace(
- `${protocol}//${hostname}${
- port ? ":" + port : ""
- }${pathname}/?/${query}${search}${hash}`
- );
- }
- </script>
- </head>
- <body></body>
-</html>
diff --git a/docs/README.md b/docs/README.md
deleted file mode 100644
index dc75be1..0000000
--- a/docs/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# docs
-
-[![Package Version](https://img.shields.io/hexpm/v/docs)](https://hex.pm/packages/docs)
-[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/docs/)
-
-A Gleam project
-
-## Quick start
-
-```sh
-gleam run # Run the project
-gleam test # Run the tests
-gleam shell # Run an Erlang shell
-```
-
-## Installation
-
-If available on Hex this package can be added to your Gleam project:
-
-```sh
-gleam add docs
-```
-
-and its documentation can be found at <https://hexdocs.pm/docs>.
diff --git a/docs/assets/styles.css b/docs/assets/styles.css
deleted file mode 100644
index 308e6e8..0000000
--- a/docs/assets/styles.css
+++ /dev/null
@@ -1,16 +0,0 @@
-@import url("https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400&family=Inter:wght@300&display=swap");
-
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-
-@layer base {
- h1,
- h2,
- h3,
- h4,
- h5,
- h6 {
- @apply font-serif;
- }
-}
diff --git a/docs/gleam.toml b/docs/gleam.toml
deleted file mode 100644
index f239493..0000000
--- a/docs/gleam.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-name = "docs"
-version = "0.1.0"
-description = "A Gleam project"
-target = "javascript"
-
-# Fill out these fields if you intend to generate HTML documentation or publish
-# your project to the Hex package manager.
-#
-# licences = ["Apache-2.0"]
-# repository = { type = "github", user = "username", repo = "project" }
-# links = [{ title = "Website", href = "https://gleam.run" }]
-
-[dependencies]
-gleam_stdlib = "~> 0.30"
-lustre = { path = "../lib" }
-
-[dev-dependencies]
-gleeunit = "~> 0.10"
diff --git a/docs/index.html b/docs/index.html
deleted file mode 100644
index 82c2697..0000000
--- a/docs/index.html
+++ /dev/null
@@ -1,115 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>Lustre</title>
-
- <link rel="stylesheet" href="./assets/styles.css" />
-
- <!-- Start Single Page Apps for GitHub Pages -->
- <script type="text/javascript">
- // Single Page Apps for GitHub Pages
- // MIT License
- // https://github.com/rafgraph/spa-github-pages
- // This script checks to see if a redirect is present in the query string,
- // converts it back into the correct url and adds it to the
- // browser's history using window.history.replaceState(...),
- // which won't cause the browser to attempt to load the new url.
- // When the single page app is loaded further down in this file,
- // the correct url will be waiting in the browser's history for
- // the single page app to route accordingly.
- if (window.location.search[1] === "/") {
- const decoded = window.location.search
- .slice(1)
- .split("&")
- .map((s) => s.replace(/~and~/g, "&"))
- .join("?");
-
- window.history.replaceState(
- null,
- null,
- window.location.pathname.slice(0, -1) + decoded + window.location.hash
- );
- }
- </script>
- <!-- End Single Page Apps for GitHub Pages -->
-
- <script type="module">
- import {
- main,
- Route,
- OnRouteChange,
- OnRouteHover,
- } from "./src/app.gleam";
-
- const strip_base = (path) =>
- `/${path.slice(import.meta.env.BASE_URL.length)}`;
-
- document.addEventListener("DOMContentLoaded", () => {
- const url = new URL(window.location.href);
-
- const dispatch = main({
- path: strip_base(url.pathname),
- hash: url.hash,
- });
-
- // We want to trap click events on anchor elements so we can do our own
- // client side routing.
- document.addEventListener("click", (e) => {
- let target = e.target;
-
- while (target) {
- if (target === document.body) return;
- if (target.tagName === "A") {
- const url = new URL(target.href);
- if (url.origin !== window.location.origin) return;
- const route = new Route(strip_base(url.pathname), url.hash);
-
- e.preventDefault();
- window.requestAnimationFrame(() => {
- window.history.pushState({}, "", url.href);
-
- if (url.pathname === window.location.pathname && url.hash) {
- document.querySelector(url.hash)?.scrollIntoView();
- } else {
- window.scrollTo(0, 0);
- }
- });
-
- return void dispatch(new OnRouteChange(route));
- }
-
- target = target.parentNode;
- }
- });
-
- document.addEventListener("mouseover", (e) => {
- let target = e.target;
-
- while (target) {
- if (target === document.body) return;
- if (target.tagName === "A") {
- const url = new URL(target.href);
- if (url.origin !== window.location.origin) return;
- const route = new Route(strip_base(url.pathname), url.hash);
- return void dispatch(new OnRouteHover(route));
- }
-
- target = target.parentNode;
- }
- });
-
- // This lets us listen to the back and forward buttons in the browser
- // and trigger our app's routing.
- window.addEventListener("popstate", () => {
- const url = new URL(window.location.href);
- const route = new Route(strip_base(url.pathname), url.hash);
-
- dispatch(new OnRouteChange(route));
- });
- });
- </script>
- </head>
- <body></body>
-</html>
diff --git a/docs/manifest.toml b/docs/manifest.toml
deleted file mode 100644
index 459f584..0000000
--- a/docs/manifest.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-# This file was generated by Gleam
-# You typically do not need to edit this file
-
-packages = [
- { name = "gleam_stdlib", version = "0.30.1", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "704258528887F95075FFED7AAE1CCF836A9B88E3AADA2F69F9DA15815F94A4F9" },
- { name = "gleeunit", version = "0.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "1397E5C4AC4108769EE979939AC39BF7870659C5AFB714630DEEEE16B8272AD5" },
- { name = "lustre", version = "3.0.0-rc.8", build_tools = ["gleam"], requirements = ["gleam_stdlib"], source = "local", path = "/Users/hayleigh/dev/gleam/lustre/lib" },
-]
-
-[requirements]
-gleam_stdlib = { version = "~> 0.30" }
-gleeunit = { version = "~> 0.10" }
-lustre = { path = "../lib" }
diff --git a/docs/package-lock.json b/docs/package-lock.json
deleted file mode 100644
index dabf565..0000000
--- a/docs/package-lock.json
+++ /dev/null
@@ -1,2595 +0,0 @@
-{
- "name": "docs",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "dependencies": {
- "highlight.js": "^11.8.0",
- "mdast-util-from-markdown": "^2.0.0"
- },
- "devDependencies": {
- "@tailwindcss/typography": "^0.5.9",
- "autoprefixer": "^10.4.15",
- "postcss": "^8.4.28",
- "tailwindcss": "^3.3.3",
- "vite": "^4.4.9",
- "vite-gleam": "^0.2.4",
- "vite-plugin-gh-pages": "^0.4.1"
- }
- },
- "node_modules/@alloc/quick-lru": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
- "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
- "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
- "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
- "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
- "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
- "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
- "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
- "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
- "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
- "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
- "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
- "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
- "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
- "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
- "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
- "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
- "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
- "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
- "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
- "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
- "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
- "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
- "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
- "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
- "dev": true,
- "dependencies": {
- "@jridgewell/set-array": "^1.0.1",
- "@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.9"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
- "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
- "dev": true,
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/set-array": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
- "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
- "dev": true,
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.15",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
- "dev": true
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.19",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz",
- "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==",
- "dev": true,
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@tailwindcss/typography": {
- "version": "0.5.9",
- "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.9.tgz",
- "integrity": "sha512-t8Sg3DyynFysV9f4JDOVISGsjazNb48AeIYQwcL+Bsq5uf4RYL75C1giZ43KISjeDGBaTN3Kxh7Xj/vRSMJUUg==",
- "dev": true,
- "dependencies": {
- "lodash.castarray": "^4.4.0",
- "lodash.isplainobject": "^4.0.6",
- "lodash.merge": "^4.6.2",
- "postcss-selector-parser": "6.0.10"
- },
- "peerDependencies": {
- "tailwindcss": ">=3.0.0 || insiders"
- }
- },
- "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": {
- "version": "6.0.10",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
- "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
- "dev": true,
- "dependencies": {
- "cssesc": "^3.0.0",
- "util-deprecate": "^1.0.2"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@types/debug": {
- "version": "4.1.8",
- "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz",
- "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==",
- "dependencies": {
- "@types/ms": "*"
- }
- },
- "node_modules/@types/mdast": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.0.tgz",
- "integrity": "sha512-YLeG8CujC9adtj/kuDzq1N4tCDYKoZ5l/bnjq8d74+t/3q/tHquJOJKUQXJrLCflOHpKjXgcI/a929gpmLOEng==",
- "dependencies": {
- "@types/unist": "*"
- }
- },
- "node_modules/@types/ms": {
- "version": "0.7.31",
- "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz",
- "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA=="
- },
- "node_modules/@types/unist": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.0.tgz",
- "integrity": "sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w=="
- },
- "node_modules/any-promise": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
- "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
- "dev": true
- },
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/arg": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
- "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
- "dev": true
- },
- "node_modules/array-union": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
- "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==",
- "dev": true,
- "dependencies": {
- "array-uniq": "^1.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/array-uniq": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
- "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/async": {
- "version": "2.6.4",
- "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
- "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
- "dev": true,
- "dependencies": {
- "lodash": "^4.17.14"
- }
- },
- "node_modules/autoprefixer": {
- "version": "10.4.15",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.15.tgz",
- "integrity": "sha512-KCuPB8ZCIqFdA4HwKXsvz7j6gvSDNhDP7WnUjBleRkKjPdvCmHFuQ77ocavI8FT6NdvlBnE2UFr2H4Mycn8Vew==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/autoprefixer"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "browserslist": "^4.21.10",
- "caniuse-lite": "^1.0.30001520",
- "fraction.js": "^4.2.0",
- "normalize-range": "^0.1.2",
- "picocolors": "^1.0.0",
- "postcss-value-parser": "^4.2.0"
- },
- "bin": {
- "autoprefixer": "bin/autoprefixer"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- },
- "peerDependencies": {
- "postcss": "^8.1.0"
- }
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
- },
- "node_modules/binary-extensions": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
- "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
- "dependencies": {
- "fill-range": "^7.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/browserslist": {
- "version": "4.21.10",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz",
- "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "caniuse-lite": "^1.0.30001517",
- "electron-to-chromium": "^1.4.477",
- "node-releases": "^2.0.13",
- "update-browserslist-db": "^1.0.11"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "node_modules/camelcase-css": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
- "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/caniuse-lite": {
- "version": "1.0.30001522",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001522.tgz",
- "integrity": "sha512-TKiyTVZxJGhsTszLuzb+6vUZSjVOAhClszBr2Ta2k9IwtNBT/4dzmL6aywt0HCgEZlmwJzXJd8yNiob6HgwTRg==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ]
- },
- "node_modules/character-entities": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
- "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
- "node_modules/chokidar": {
- "version": "3.5.3",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
- "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
- "dev": true,
- "funding": [
- {
- "type": "individual",
- "url": "https://paulmillr.com/funding/"
- }
- ],
- "dependencies": {
- "anymatch": "~3.1.2",
- "braces": "~3.0.2",
- "glob-parent": "~5.1.2",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.6.0"
- },
- "engines": {
- "node": ">= 8.10.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/chokidar/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/commander": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
- "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/commondir": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
- "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
- "dev": true
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
- },
- "node_modules/cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
- "bin": {
- "cssesc": "bin/cssesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/decode-named-character-reference": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz",
- "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==",
- "dependencies": {
- "character-entities": "^2.0.0"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
- "node_modules/dequal": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
- "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/devlop": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
- "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
- "dependencies": {
- "dequal": "^2.0.0"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
- "node_modules/didyoumean": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
- "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
- "dev": true
- },
- "node_modules/dlv": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
- "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
- "dev": true
- },
- "node_modules/electron-to-chromium": {
- "version": "1.4.496",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.496.tgz",
- "integrity": "sha512-qeXC3Zbykq44RCrBa4kr8v/dWzYJA8rAwpyh9Qd+NKWoJfjG5vvJqy9XOJ9H4P/lqulZBCgUWAYi+FeK5AuJ8g==",
- "dev": true
- },
- "node_modules/email-addresses": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz",
- "integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==",
- "dev": true
- },
- "node_modules/esbuild": {
- "version": "0.18.20",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
- "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
- "dev": true,
- "hasInstallScript": true,
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/android-arm": "0.18.20",
- "@esbuild/android-arm64": "0.18.20",
- "@esbuild/android-x64": "0.18.20",
- "@esbuild/darwin-arm64": "0.18.20",
- "@esbuild/darwin-x64": "0.18.20",
- "@esbuild/freebsd-arm64": "0.18.20",
- "@esbuild/freebsd-x64": "0.18.20",
- "@esbuild/linux-arm": "0.18.20",
- "@esbuild/linux-arm64": "0.18.20",
- "@esbuild/linux-ia32": "0.18.20",
- "@esbuild/linux-loong64": "0.18.20",
- "@esbuild/linux-mips64el": "0.18.20",
- "@esbuild/linux-ppc64": "0.18.20",
- "@esbuild/linux-riscv64": "0.18.20",
- "@esbuild/linux-s390x": "0.18.20",
- "@esbuild/linux-x64": "0.18.20",
- "@esbuild/netbsd-x64": "0.18.20",
- "@esbuild/openbsd-x64": "0.18.20",
- "@esbuild/sunos-x64": "0.18.20",
- "@esbuild/win32-arm64": "0.18.20",
- "@esbuild/win32-ia32": "0.18.20",
- "@esbuild/win32-x64": "0.18.20"
- }
- },
- "node_modules/escalade": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
- "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "dev": true,
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/fast-glob": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
- "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/fast-glob/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/fastq": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
- "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
- "dev": true,
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
- "node_modules/filename-reserved-regex": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
- "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/filenamify": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz",
- "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==",
- "dev": true,
- "dependencies": {
- "filename-reserved-regex": "^2.0.0",
- "strip-outer": "^1.0.1",
- "trim-repeated": "^1.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/find-cache-dir": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
- "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
- "dev": true,
- "dependencies": {
- "commondir": "^1.0.1",
- "make-dir": "^3.0.2",
- "pkg-dir": "^4.1.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
- }
- },
- "node_modules/find-up": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
- "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
- "dev": true,
- "dependencies": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/fraction.js": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.1.tgz",
- "integrity": "sha512-/KxoyCnPM0GwYI4NN0Iag38Tqt+od3/mLuguepLgCAKPn0ZhC544nssAW0tG2/00zXEYl9W+7hwAIpLHo6Oc7Q==",
- "dev": true,
- "engines": {
- "node": "*"
- },
- "funding": {
- "type": "patreon",
- "url": "https://www.patreon.com/infusion"
- }
- },
- "node_modules/fs-extra": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
- "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
- "dev": true,
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^4.0.0",
- "universalify": "^0.1.0"
- },
- "engines": {
- "node": ">=6 <7 || >=8"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
- },
- "node_modules/fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
- },
- "node_modules/gh-pages": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-4.0.0.tgz",
- "integrity": "sha512-p8S0T3aGJc68MtwOcZusul5qPSNZCalap3NWbhRUZYu1YOdp+EjZ+4kPmRM8h3NNRdqw00yuevRjlkuSzCn7iQ==",
- "dev": true,
- "dependencies": {
- "async": "^2.6.1",
- "commander": "^2.18.0",
- "email-addresses": "^3.0.1",
- "filenamify": "^4.3.0",
- "find-cache-dir": "^3.3.1",
- "fs-extra": "^8.1.0",
- "globby": "^6.1.0"
- },
- "bin": {
- "gh-pages": "bin/gh-pages.js",
- "gh-pages-clean": "bin/gh-pages-clean.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/gh-pages/node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true
- },
- "node_modules/glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
- "dev": true,
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/globby": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
- "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==",
- "dev": true,
- "dependencies": {
- "array-union": "^1.0.1",
- "glob": "^7.0.3",
- "object-assign": "^4.0.1",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "dev": true
- },
- "node_modules/has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/highlight.js": {
- "version": "11.8.0",
- "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.8.0.tgz",
- "integrity": "sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg==",
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "dev": true,
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
- },
- "node_modules/is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
- "dependencies": {
- "binary-extensions": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.13.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
- "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==",
- "dev": true,
- "dependencies": {
- "has": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/jiti": {
- "version": "1.19.3",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.3.tgz",
- "integrity": "sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w==",
- "dev": true,
- "bin": {
- "jiti": "bin/jiti.js"
- }
- },
- "node_modules/jsonfile": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
- "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
- "dev": true,
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/lilconfig": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
- "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/lines-and-columns": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true
- },
- "node_modules/locate-path": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
- "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
- "dev": true,
- "dependencies": {
- "p-locate": "^4.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
- "dev": true
- },
- "node_modules/lodash.castarray": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
- "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==",
- "dev": true
- },
- "node_modules/lodash.isplainobject": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
- "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
- "dev": true
- },
- "node_modules/lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true
- },
- "node_modules/magic-string": {
- "version": "0.30.2",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.2.tgz",
- "integrity": "sha512-lNZdu7pewtq/ZvWUp9Wpf/x7WzMTsR26TWV03BRZrXFsv+BI6dy8RAiKgm1uM/kyR0rCfUcqvOlXKG66KhIGug==",
- "dev": true,
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.4.15"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/make-dir": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
- "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
- "dev": true,
- "dependencies": {
- "semver": "^6.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/mdast-util-from-markdown": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz",
- "integrity": "sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==",
- "dependencies": {
- "@types/mdast": "^4.0.0",
- "@types/unist": "^3.0.0",
- "decode-named-character-reference": "^1.0.0",
- "devlop": "^1.0.0",
- "mdast-util-to-string": "^4.0.0",
- "micromark": "^4.0.0",
- "micromark-util-decode-numeric-character-reference": "^2.0.0",
- "micromark-util-decode-string": "^2.0.0",
- "micromark-util-normalize-identifier": "^2.0.0",
- "micromark-util-symbol": "^2.0.0",
- "micromark-util-types": "^2.0.0",
- "unist-util-stringify-position": "^4.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/mdast-util-to-string": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
- "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==",
- "dependencies": {
- "@types/mdast": "^4.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/micromark": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz",
- "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "@types/debug": "^4.0.0",
- "debug": "^4.0.0",
- "decode-named-character-reference": "^1.0.0",
- "devlop": "^1.0.0",
- "micromark-core-commonmark": "^2.0.0",
- "micromark-factory-space": "^2.0.0",
- "micromark-util-character": "^2.0.0",
- "micromark-util-chunked": "^2.0.0",
- "micromark-util-combine-extensions": "^2.0.0",
- "micromark-util-decode-numeric-character-reference": "^2.0.0",
- "micromark-util-encode": "^2.0.0",
- "micromark-util-normalize-identifier": "^2.0.0",
- "micromark-util-resolve-all": "^2.0.0",
- "micromark-util-sanitize-uri": "^2.0.0",
- "micromark-util-subtokenize": "^2.0.0",
- "micromark-util-symbol": "^2.0.0",
- "micromark-util-types": "^2.0.0"
- }
- },
- "node_modules/micromark-core-commonmark": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz",
- "integrity": "sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "decode-named-character-reference": "^1.0.0",
- "devlop": "^1.0.0",
- "micromark-factory-destination": "^2.0.0",
- "micromark-factory-label": "^2.0.0",
- "micromark-factory-space": "^2.0.0",
- "micromark-factory-title": "^2.0.0",
- "micromark-factory-whitespace": "^2.0.0",
- "micromark-util-character": "^2.0.0",
- "micromark-util-chunked": "^2.0.0",
- "micromark-util-classify-character": "^2.0.0",
- "micromark-util-html-tag-name": "^2.0.0",
- "micromark-util-normalize-identifier": "^2.0.0",
- "micromark-util-resolve-all": "^2.0.0",
- "micromark-util-subtokenize": "^2.0.0",
- "micromark-util-symbol": "^2.0.0",
- "micromark-util-types": "^2.0.0"
- }
- },
- "node_modules/micromark-factory-destination": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz",
- "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-util-character": "^2.0.0",
- "micromark-util-symbol": "^2.0.0",
- "micromark-util-types": "^2.0.0"
- }
- },
- "node_modules/micromark-factory-label": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz",
- "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "devlop": "^1.0.0",
- "micromark-util-character": "^2.0.0",
- "micromark-util-symbol": "^2.0.0",
- "micromark-util-types": "^2.0.0"
- }
- },
- "node_modules/micromark-factory-space": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz",
- "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-util-character": "^2.0.0",
- "micromark-util-types": "^2.0.0"
- }
- },
- "node_modules/micromark-factory-title": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz",
- "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-factory-space": "^2.0.0",
- "micromark-util-character": "^2.0.0",
- "micromark-util-symbol": "^2.0.0",
- "micromark-util-types": "^2.0.0"
- }
- },
- "node_modules/micromark-factory-whitespace": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz",
- "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-factory-space": "^2.0.0",
- "micromark-util-character": "^2.0.0",
- "micromark-util-symbol": "^2.0.0",
- "micromark-util-types": "^2.0.0"
- }
- },
- "node_modules/micromark-util-character": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.0.1.tgz",
- "integrity": "sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-util-symbol": "^2.0.0",
- "micromark-util-types": "^2.0.0"
- }
- },
- "node_modules/micromark-util-chunked": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz",
- "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-util-symbol": "^2.0.0"
- }
- },
- "node_modules/micromark-util-classify-character": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz",
- "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-util-character": "^2.0.0",
- "micromark-util-symbol": "^2.0.0",
- "micromark-util-types": "^2.0.0"
- }
- },
- "node_modules/micromark-util-combine-extensions": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz",
- "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-util-chunked": "^2.0.0",
- "micromark-util-types": "^2.0.0"
- }
- },
- "node_modules/micromark-util-decode-numeric-character-reference": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.0.tgz",
- "integrity": "sha512-pIgcsGxpHEtTG/rPJRz/HOLSqp5VTuIIjXlPI+6JSDlK2oljApusG6KzpS8AF0ENUMCHlC/IBb5B9xdFiVlm5Q==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-util-symbol": "^2.0.0"
- }
- },
- "node_modules/micromark-util-decode-string": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz",
- "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "decode-named-character-reference": "^1.0.0",
- "micromark-util-character": "^2.0.0",
- "micromark-util-decode-numeric-character-reference": "^2.0.0",
- "micromark-util-symbol": "^2.0.0"
- }
- },
- "node_modules/micromark-util-encode": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz",
- "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ]
- },
- "node_modules/micromark-util-html-tag-name": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz",
- "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ]
- },
- "node_modules/micromark-util-normalize-identifier": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz",
- "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-util-symbol": "^2.0.0"
- }
- },
- "node_modules/micromark-util-resolve-all": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz",
- "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-util-types": "^2.0.0"
- }
- },
- "node_modules/micromark-util-sanitize-uri": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz",
- "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "micromark-util-character": "^2.0.0",
- "micromark-util-encode": "^2.0.0",
- "micromark-util-symbol": "^2.0.0"
- }
- },
- "node_modules/micromark-util-subtokenize": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz",
- "integrity": "sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ],
- "dependencies": {
- "devlop": "^1.0.0",
- "micromark-util-chunked": "^2.0.0",
- "micromark-util-symbol": "^2.0.0",
- "micromark-util-types": "^2.0.0"
- }
- },
- "node_modules/micromark-util-symbol": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz",
- "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ]
- },
- "node_modules/micromark-util-types": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz",
- "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==",
- "funding": [
- {
- "type": "GitHub Sponsors",
- "url": "https://github.com/sponsors/unifiedjs"
- },
- {
- "type": "OpenCollective",
- "url": "https://opencollective.com/unified"
- }
- ]
- },
- "node_modules/micromatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
- "dependencies": {
- "braces": "^3.0.2",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
- },
- "node_modules/mz": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
- "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
- "dev": true,
- "dependencies": {
- "any-promise": "^1.0.0",
- "object-assign": "^4.0.1",
- "thenify-all": "^1.0.0"
- }
- },
- "node_modules/nanoid": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
- "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/node-releases": {
- "version": "2.0.13",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
- "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
- "dev": true
- },
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/normalize-range": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
- "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-hash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
- "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
- "dependencies": {
- "p-try": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
- "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
- "dev": true,
- "dependencies": {
- "p-limit": "^2.2.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true
- },
- "node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
- },
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/pinkie": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
- "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/pinkie-promise": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
- "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
- "dev": true,
- "dependencies": {
- "pinkie": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/pirates": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
- "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/pkg-dir": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
- "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
- "dev": true,
- "dependencies": {
- "find-up": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/postcss": {
- "version": "8.4.28",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz",
- "integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "nanoid": "^3.3.6",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/postcss-import": {
- "version": "15.1.0",
- "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
- "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
- "dev": true,
- "dependencies": {
- "postcss-value-parser": "^4.0.0",
- "read-cache": "^1.0.0",
- "resolve": "^1.1.7"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "postcss": "^8.0.0"
- }
- },
- "node_modules/postcss-js": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
- "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
- "dev": true,
- "dependencies": {
- "camelcase-css": "^2.0.1"
- },
- "engines": {
- "node": "^12 || ^14 || >= 16"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- "peerDependencies": {
- "postcss": "^8.4.21"
- }
- },
- "node_modules/postcss-load-config": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz",
- "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==",
- "dev": true,
- "dependencies": {
- "lilconfig": "^2.0.5",
- "yaml": "^2.1.1"
- },
- "engines": {
- "node": ">= 14"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- "peerDependencies": {
- "postcss": ">=8.0.9",
- "ts-node": ">=9.0.0"
- },
- "peerDependenciesMeta": {
- "postcss": {
- "optional": true
- },
- "ts-node": {
- "optional": true
- }
- }
- },
- "node_modules/postcss-nested": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
- "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
- "dev": true,
- "dependencies": {
- "postcss-selector-parser": "^6.0.11"
- },
- "engines": {
- "node": ">=12.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- "peerDependencies": {
- "postcss": "^8.2.14"
- }
- },
- "node_modules/postcss-selector-parser": {
- "version": "6.0.13",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz",
- "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==",
- "dev": true,
- "dependencies": {
- "cssesc": "^3.0.0",
- "util-deprecate": "^1.0.2"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/postcss-value-parser": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
- "dev": true
- },
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/read-cache": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
- "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
- "dev": true,
- "dependencies": {
- "pify": "^2.3.0"
- }
- },
- "node_modules/readdirp": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "dev": true,
- "dependencies": {
- "picomatch": "^2.2.1"
- },
- "engines": {
- "node": ">=8.10.0"
- }
- },
- "node_modules/resolve": {
- "version": "1.22.4",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz",
- "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==",
- "dev": true,
- "dependencies": {
- "is-core-module": "^2.13.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true,
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
- "node_modules/rollup": {
- "version": "3.28.0",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.0.tgz",
- "integrity": "sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==",
- "dev": true,
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=14.18.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
- "node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/strip-outer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
- "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
- "dev": true,
- "dependencies": {
- "escape-string-regexp": "^1.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/sucrase": {
- "version": "3.34.0",
- "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz",
- "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==",
- "dev": true,
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.2",
- "commander": "^4.0.0",
- "glob": "7.1.6",
- "lines-and-columns": "^1.1.6",
- "mz": "^2.7.0",
- "pirates": "^4.0.1",
- "ts-interface-checker": "^0.1.9"
- },
- "bin": {
- "sucrase": "bin/sucrase",
- "sucrase-node": "bin/sucrase-node"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/tailwindcss": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz",
- "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==",
- "dev": true,
- "dependencies": {
- "@alloc/quick-lru": "^5.2.0",
- "arg": "^5.0.2",
- "chokidar": "^3.5.3",
- "didyoumean": "^1.2.2",
- "dlv": "^1.1.3",
- "fast-glob": "^3.2.12",
- "glob-parent": "^6.0.2",
- "is-glob": "^4.0.3",
- "jiti": "^1.18.2",
- "lilconfig": "^2.1.0",
- "micromatch": "^4.0.5",
- "normalize-path": "^3.0.0",
- "object-hash": "^3.0.0",
- "picocolors": "^1.0.0",
- "postcss": "^8.4.23",
- "postcss-import": "^15.1.0",
- "postcss-js": "^4.0.1",
- "postcss-load-config": "^4.0.1",
- "postcss-nested": "^6.0.1",
- "postcss-selector-parser": "^6.0.11",
- "resolve": "^1.22.2",
- "sucrase": "^3.32.0"
- },
- "bin": {
- "tailwind": "lib/cli.js",
- "tailwindcss": "lib/cli.js"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/thenify": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
- "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
- "dev": true,
- "dependencies": {
- "any-promise": "^1.0.0"
- }
- },
- "node_modules/thenify-all": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
- "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
- "dev": true,
- "dependencies": {
- "thenify": ">= 3.1.0 < 4"
- },
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/toml": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
- "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==",
- "dev": true
- },
- "node_modules/trim-repeated": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
- "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==",
- "dev": true,
- "dependencies": {
- "escape-string-regexp": "^1.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/ts-interface-checker": {
- "version": "0.1.13",
- "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
- "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
- "dev": true
- },
- "node_modules/unist-util-stringify-position": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
- "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
- "dependencies": {
- "@types/unist": "^3.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/unified"
- }
- },
- "node_modules/universalify": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
- "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
- "dev": true,
- "engines": {
- "node": ">= 4.0.0"
- }
- },
- "node_modules/update-browserslist-db": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",
- "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "escalade": "^3.1.1",
- "picocolors": "^1.0.0"
- },
- "bin": {
- "update-browserslist-db": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
- }
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true
- },
- "node_modules/vite": {
- "version": "4.4.9",
- "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz",
- "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==",
- "dev": true,
- "dependencies": {
- "esbuild": "^0.18.10",
- "postcss": "^8.4.27",
- "rollup": "^3.27.1"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- },
- "peerDependencies": {
- "@types/node": ">= 14",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.4.0"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- }
- }
- },
- "node_modules/vite-gleam": {
- "version": "0.2.4",
- "resolved": "https://registry.npmjs.org/vite-gleam/-/vite-gleam-0.2.4.tgz",
- "integrity": "sha512-eZ6raXxbdbGkTwH4vABcgklbMP1hdQDL2B/uYhj9fLZquqBAQKBe//2nWBPwBTdOtSc7ABEG6VUctaUwuN+zUw==",
- "dev": true,
- "dependencies": {
- "magic-string": "^0.30.2",
- "rollup": "^3.28.0",
- "toml": "^3.0.0",
- "vite": "^4.4.5"
- }
- },
- "node_modules/vite-plugin-gh-pages": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/vite-plugin-gh-pages/-/vite-plugin-gh-pages-0.4.1.tgz",
- "integrity": "sha512-le3VEvsI7GURftAiXPsgd+8noO/W1+gv363gFZdVNQ2uZGO78/nKl7um+0873ZH5paO8+iA5tXAss8TM6z4pyA==",
- "dev": true,
- "dependencies": {
- "gh-pages": "^4.0.0"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true
- },
- "node_modules/yaml": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz",
- "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==",
- "dev": true,
- "engines": {
- "node": ">= 14"
- }
- }
- }
-}
diff --git a/docs/package.json b/docs/package.json
deleted file mode 100644
index 3b74037..0000000
--- a/docs/package.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "scripts": {
- "dev": "vite",
- "deploy": "vite build"
- },
- "devDependencies": {
- "@tailwindcss/typography": "^0.5.9",
- "autoprefixer": "^10.4.15",
- "postcss": "^8.4.28",
- "tailwindcss": "^3.3.3",
- "vite": "^4.4.9",
- "vite-gleam": "^0.2.4",
- "vite-plugin-gh-pages": "^0.4.1"
- },
- "dependencies": {
- "highlight.js": "^11.8.0",
- "mdast-util-from-markdown": "^2.0.0"
- }
-}
diff --git a/docs/postcss.config.js b/docs/postcss.config.js
deleted file mode 100644
index 33ad091..0000000
--- a/docs/postcss.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-module.exports = {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
-}
diff --git a/docs/public/CNAME b/docs/public/CNAME
deleted file mode 100644
index b9c16b8..0000000
--- a/docs/public/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-pkg.hayleigh.dev \ No newline at end of file
diff --git a/docs/public/fonts/NTDapper-black.woff2 b/docs/public/fonts/NTDapper-black.woff2
deleted file mode 100644
index c7a7e10..0000000
--- a/docs/public/fonts/NTDapper-black.woff2
+++ /dev/null
Binary files differ
diff --git a/docs/public/fonts/NTDapper-bold.woff2 b/docs/public/fonts/NTDapper-bold.woff2
deleted file mode 100644
index b444ff7..0000000
--- a/docs/public/fonts/NTDapper-bold.woff2
+++ /dev/null
Binary files differ
diff --git a/docs/public/fonts/NTDapper-medium.woff2 b/docs/public/fonts/NTDapper-medium.woff2
deleted file mode 100644
index 9ef71f2..0000000
--- a/docs/public/fonts/NTDapper-medium.woff2
+++ /dev/null
Binary files differ
diff --git a/docs/public/fonts/NTDapper-regular.woff2 b/docs/public/fonts/NTDapper-regular.woff2
deleted file mode 100644
index fb82049..0000000
--- a/docs/public/fonts/NTDapper-regular.woff2
+++ /dev/null
Binary files differ
diff --git a/docs/public/page/api/lustre.md b/docs/public/page/api/lustre.md
deleted file mode 100644
index 4be06d4..0000000
--- a/docs/public/page/api/lustre.md
+++ /dev/null
@@ -1,237 +0,0 @@
-# lustre
-
-## Applications
-
-On the client, Lustre applications are built on the Model-View-Update architecture.
-This pattern was popularised by the Elm programming language before being adopted
-by other state mangement libraries like Redux and Vuex.
-
-Your applications will be made up of three fundamental parts:
-
-- A `Model` that represents the entire state of your application and an `init`
- function to create it.
-- A `Msg` type that represents all the ways the outside world can communicate
- with your application and an `update` function that that modifies the model
- in response to these messages.
-- A `view` function that renders the current state of your application to the
- DOM.
-
-```
- ┌--------+
- | |
- | update |
- | |
- +--------+
- ^ |
- | |
- Msg | | #(Model, Effect(Msg))
- | |
- | v
-┌------+ ┌------------------------+
-| | #(Model, Effect(Msg)) | |
-| init |------------------------>| Lustre Runtime |
-| | | |
-+------+ +------------------------+
- ^ |
- | |
- Msg | | Model
- | |
- | v
- ┌--------+
- | |
- | view |
- | |
- +--------+
-```
-
-### App | erlang javascript
-
-```gleam
-pub type App(flags, model, msg)
-```
-
-The `App` type represents all the parts that make up a Lustre program in the
-Model-View-Update architecture along with the runtime necessary to run it.
-
-Although the type itself is exposed to both the Erlang and JavaScript targets,
-the functions in this module to construct an `App` are only available in the
-JavaScript target, and `start` will only succeed when ran in the browser.
-
-In the future we may have a way to run Lustre applications on the backend, if
-you have any ideas on how to achieve this I'd love to hear about them!
-
-### Error | erlang javascript
-
-```gleam
-pub type Error {
- AppAlreadyStarted
- AppNotYetStarted
- BadComponentName
- ComponentAlreadyRegistered
- ElementNotFound
- NotABrowser
-}
-```
-
-The `Error` type represents all the ways that a Lustre program can fail. These
-include things like trying to start an application that has already been started,
-registering a component with a name that is not valid, or trying to start an
-application in a context that is not a browser.
-
-Often you will want to perform a couple of these actions together, and unifying
-the error type makes this easy. In many of the examples we `let assert` that the
-result is `Ok` but if you wanted to be a bit more dilligent you might use
-`result.try` instead:
-
-```gleam
-import gleam/result
-import lustre
-
-pub fn main () {
- use _ <- result.try(lustre.component("my-component", ...))
- let app = lustre.application(...)
- use dispatch <- result.try(lustre.start(app, "[data-lustre-app]", Nil))
-
- ...
-}
-```
-
-### element | javascript
-
-```gleam
-pub fn element(el: Element(msg)) -> App(Nil, Nil, msg)
-```
-
-An `element` application is the simplest kind of Lustre program. It takes an
-`Element` to render and renders it to the DOM. These applications hold no state
-and do not respond to messages, but that doesn't mean they are not interactive!
-
-It is possible for [`components`](#component) to be rendered inside an
-`element` application, and these components can be interactive with their own
-contained state and update loops.
-
-### simple | javascript
-
-```gleam
-pub fn simple(
- init: fn(flags) -> model,
- update: fn(model, msg) -> model,
- view: fn(model) -> Element(msg)
-) -> App(flags, model, msg)
-```
-
-A `simple` program introduces the Model-View-Update architecture but leaves out
-the ability to dispatch side effects. This means your programs are interactive
-but cannot talk to the outside world.
-
-### application | javascript
-
-```gleam
-pub fn application(
- init: fn(flags) -> #(model, Effect(msg)),
- update: fn(model, msg) -> #(model, Effect(msg)),
- view: fn(model) -> Element(msg)
-) -> App(flags, model, msg)
-```
-
-The `application` constructor is the most complete way to build a Lustre app. As
-with [`simple`](#simple) it uses the Model-View-Update architecture, but now your
-init and update functions can return side effects to be performed by the runtime
-in the form of an [`Effect`](/api/lustre/effect#effect-type).
-
-### start | javascript
-
-```gleam
-pub fn start(
- app: App(flags, model, msg),
- selector: String,
- flags: flags,
-) -> Result(fn(msg) -> Nil, Error)
-```
-
-Start an application by providing a CSS selector to find the element to mount the
-application onto and any flags to pass to the application on first init. This
-function returns a `Result` and may fail for a number of reasons. Check out the
-[`Error`](#error-type) type for more information.
-
-### destroy | javascript
-
-```gleam
-pub fn destroy(app: App(flags, model, msg)) -> Result(Nil, Error)
-```
-
-Tear down a running application and remove it from the DOM. This can fail if the
-application has not yet been started.
-
-## Components
-
-Components take the same Model-View-Update building blocks used to create Lustre
-applications and allow them to be used as reusable stateful components. This is
-slightly different to how components are used in other frameworks like React
-where "component" refers more generally to any reusable piece of UI.
-
-In Lustre, functions that return an `Element` are known as "view functions" and
-components are more specific abstractions that encapsulate state and behaviour
-you might not want to deal with in your top-level application.
-
-Resist the urge to reach for components too early. The Elm community has managed
-to make do without components at all: you can get surprisingly far storing state
-in your top level application and passing it down to different view functions.
-This comes with the added benefit of it being much easier to reason about your
-UI as a whole.
-
-### component | javascript
-
-```gleam
-pub fn component(
- name: String,
- init: fn() -> #(model, Effect(msg)),
- update: fn(model, msg) -> #(model, Effect(msg)),
- view: fn(model) -> Element(msg),
- on_attribute_change: Map(String, Decoder(msg)),
-) -> Result(Nil, Error)
-```
-
-Register a component with the runtime from the familiar Model-View-Update building
-blocks. Compared to an application, we have two additional arguments:
-
-- A name for the component. This name must follow the same rules laid out in the
- [custom element spec](https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name)
- and should contain a hyphen (`-`) to avoid clashes with built-in HTML elements.
-- A map of attribute names to listen for changes to and a decoder for each to
- decode those attributes into messages to send to your component's `update`
- function.
-
-If it feels like the API for registering components is a little more verbose than
-you're used to, that's because it is! You can get surprisingly far storing state
-in your top level application and passing it down to different view functions
-without needing to use components at all. In fact, for communities like Elm this
-is the _only_ way to do things.
-
-## Utilities
-
-### is_browser | erlang javascript
-
-```gleam
-pub fn is_browser() -> Bool
-```
-
-Gleam has conditional compilation depending on whether you are targetting Erlang
-or JavaScript, but sometimes you want to be a bit more specific than that and
-check if you're running in the browser.
-
-This is a runtime check that will tell you just that. You could use this to create
-a view function that renders something simple on the backend but more complex or
-interactive on the frontend.
-
-### is_registered | erlang javascript
-
-```gleam
-pub fn is_registered(name: String) -> Bool
-```
-
-Lustre's components are built directly on the
-[custom element spec](https://html.spec.whatwg.org/multipage/custom-elements.html)
-which means they share the same global registery as other custom elements. This
-function can tell you if the name you want to use is already registered, by another
-Lustre component or otherwise.
diff --git a/docs/public/page/api/lustre/attribute.md b/docs/public/page/api/lustre/attribute.md
deleted file mode 100644
index b23000b..0000000
--- a/docs/public/page/api/lustre/attribute.md
+++ /dev/null
@@ -1,290 +0,0 @@
-# lustre/attribute
-
-## Constructing attributes
-
-### Attribute | erlang javascript
-
-```gleam
-pub opaque type Attribute(msg)
-```
-
-### attribute | erlang javascript
-
-```gleam
-pub fn attribute(name: String, value: String) -> Attribute(msg)
-```
-
-### property | erlang javascript
-
-```gleam
-pub fn property(name: String, value: any) -> Attribute(msg)
-```
-
-### on | erlang javascript
-
-```gleam
-pub fn on(
- name: String,
- handler: fn(Dynamic) -> Result(msg, error)
-) -> Attribute(msg)
-```
-
-## Mapping attributes
-
-### map | erlang javascript
-
-```gleam
-pub fn map(attr: Attribute(a), f: fn(a) -> b) -> Attribute(b)
-```
-
-## Conversions
-
-### to_string | erlang javascript
-
-```gleam
-pub fn to_string(attr: Attribute(msg)) -> String
-```
-
-### to_string_builder | erlang javascript
-
-```gleam
-pub fn to_string_builder(attr: Attribute(msg)) -> StringBuilder
-```
-
-## Common attributes
-
-### style | erlang javascript
-
-```gleam
-pub fn style(properties: List(#(String, String))) -> Attribute(msg)
-```
-
-### class | erlang javascript
-
-```gleam
-pub fn class(name: String) -> Attribute(msg)
-```
-
-### classes | erlang javascript
-
-```gleam
-pub fn classes(names: List(#(String, Bool))) -> Attribute(msg)
-```
-
-### id | erlang javascript
-
-```gleam
-pub fn id(name: String) -> Attribute(msg)
-```
-
-## Input attributes
-
-### type\_ | erlang javascript
-
-```gleam
-pub fn type_(name: String) -> Attribute(msg)
-```
-
-### value | erlang javascript
-
-```gleam
-pub fn value(val: Dynamic) -> Attribute(msg)
-```
-
-### checked | erlang javascript
-
-```gleam
-pub fn checked(is_checked: Bool) -> Attribute(msg)
-```
-
-### placeholder | erlang javascript
-
-```gleam
-pub fn placeholder(text: String) -> Attribute(msg)
-```
-
-### selected | erlang javascript
-
-```gleam
-pub fn selected(is_selected: Bool) -> Attribute(msg
-```
-
-## More input attributes
-
-### accept | erlang javascript
-
-```gleam
-pub fn accept(types: List(String)) -> Attribute(msg)
-```
-
-### accept_charset | erlang javascript
-
-```gleam
-pub fn accept_charset(types: List(String)) -> Attribute(msg)
-```
-
-### msg | erlang javascript
-
-```gleam
-pub fn msg(uri: String) -> Attribute(msg)
-```
-
-### autocomplete | erlang javascript
-
-```gleam
-pub fn autocomplete(name: String) -> Attribute(msg)
-```
-
-### autofocus | erlang javascript
-
-```gleam
-pub fn autofocus(should_autofocus: Bool) -> Attribute(msg)
-```
-
-### disabled | erlang javascript
-
-```gleam
-pub fn disabled(is_disabled: Bool) -> Attribute(msg)
-```
-
-### name | erlang javascript
-
-```gleam
-pub fn name(name: String) -> Attribute(msg)
-```
-
-### pattern | erlang javascript
-
-```gleam
-pub fn pattern(regex: String) -> Attribute(msg)
-```
-
-### readonly | erlang javascript
-
-```gleam
-pub fn readonly(is_readonly: Bool) -> Attribute(msg)
-```
-
-### required | erlang javascript
-
-```gleam
-pub fn required(is_required: Bool) -> Attribute(msg)
-```
-
-### for | erlang javascript
-
-```gleam
-pub fn for(id: String) -> Attribute(msg)
-```
-
-## Range attributes
-
-### max | erlang javascript
-
-```gleam
-pub fn max(val: String) -> Attribute(msg)
-```
-
-### min | erlang javascript
-
-```gleam
-pub fn min(val: String) -> Attribute(msg)
-```
-
-### step | erlang javascript
-
-```gleam
-pub fn step(val: String) -> Attribute(msg)
-```
-
-## Textarea attributes
-
-### cols | erlang javascript
-
-```gleam
-pub fn cols(val: Int) -> Attribute(msg)
-```
-
-### rows | erlang javascript
-
-```gleam
-pub fn rows(val: Int) -> Attribute(msg)
-```
-
-### wrap | erlang javascript
-
-```gleam
-pub fn wrap(mode: String) -> Attribute(msg)
-```
-
-## Link attributes
-
-### href | erlang javascript
-
-```gleam
-pub fn href(uri: String) -> Attribute(msg)
-```
-
-### target | erlang javascript
-
-```gleam
-pub fn target(target: String) -> Attribute(msg)
-```
-
-### download | erlang javascript
-
-```gleam
-pub fn download(filename: String) -> Attribute(msg)
-```
-
-### rel | erlang javascript
-
-```gleam
-pub fn rel(relationship: String) -> Attribute(msg)
-```
-
-## Embedded content
-
-### gleam | erlang javascript
-
-```gleam
-pub fn src(uri: String) -> Attribute(msg)
-```
-
-### gleam | erlang javascript
-
-```gleam
-pub fn height(val: Int) -> Attribute(msg)
-```
-
-### gleam | erlang javascript
-
-```gleam
-pub fn width(val: Int) -> Attribute(msg)
-```
-
-### gleam | erlang javascript
-
-```gleam
-pub fn alt(text: String) -> Attribute(msg)
-```
-
-## Audio and video attributes
-
-### autoplay | erlang javascript
-
-```gleam
-pub fn autoplay(should_autoplay: Bool) -> Attribute(msg)
-```
-
-### controls | erlang javascript
-
-```gleam
-pub fn controls(visible: Bool) -> Attribute(msg)
-```
-
-### loop | erlang javascript
-
-```gleam
-pub fn loop(should_loop: Bool) -> Attribute(msg)
-```
diff --git a/docs/public/page/api/lustre/effect.md b/docs/public/page/api/lustre/effect.md
deleted file mode 100644
index 3a0bf11..0000000
--- a/docs/public/page/api/lustre/effect.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# lustre/effect
-
-## Constructing Effects
-
-### Effect | erlang javascript
-
-```gleam
-pub opaque type Effect(msg)
-```
-
-### from | erlang javascript
-
-```gleam
-pub fn from(effect: fn(fn(msg) -> Nil) -> Nil) -> Effect(msg)
-```
-
-### none | erlang javascript
-
-```gleam
-pub fn none() -> Effect(msg)
-```
-
-### batch | erlang javascript
-
-```gleam
-pub fn batch(effects: List(Effect(msg))) -> Effect(msg)
-```
-
-## Manipulating Effects
-
-### map | erlang javascript
-
-```gleam
-pub fn map(effect: Effect(a), f: fn(a) -> b) -> Effect(b)
-```
diff --git a/docs/public/page/api/lustre/element.md b/docs/public/page/api/lustre/element.md
deleted file mode 100644
index 3510acd..0000000
--- a/docs/public/page/api/lustre/element.md
+++ /dev/null
@@ -1,58 +0,0 @@
-# lustre/element
-
-## Constructing elements
-
-### Element | erlang javascript
-
-```gleam
-pub opaque type Element(msg)
-```
-
-### element | erlang javascript
-
-```gleam
-pub fn element(
- tag: String,
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### namespaced | erlang javascript
-
-```gleam
-pub fn namespaced(
- namespace: String,
- tag: String,
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### text | erlang javascript
-
-```gleam
-pub fn text(content: String) -> Element(msg)
-```
-
-## Mapping elements
-
-### map | erlang javascript
-
-```gleam
-pub fn map(element: Element(a), f: fn(a) -> b) -> Element(b)
-```
-
-## Conversions
-
-### to_string | erlang javascript
-
-```gleam
-pub fn to_string(element: Element(msg)) -> String
-```
-
-### to_string_builder | erlang javascript
-
-```gleam
-pub fn to_string_builder(element: Element(msg)) -> StringBuilder
-```
diff --git a/docs/public/page/api/lustre/element/html.md b/docs/public/page/api/lustre/element/html.md
deleted file mode 100644
index 883c66c..0000000
--- a/docs/public/page/api/lustre/element/html.md
+++ /dev/null
@@ -1,993 +0,0 @@
-# lustre/element/html
-
-## Main Root
-
-### html | erlang javascript
-
-```gleam
-pub fn html(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-## Document Metadata
-
-### base | erlang javascript
-
-```gleam
-pub fn base(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### head | erlang javascript
-
-```gleam
-pub fn head(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### link | erlang javascript
-
-```gleam
-pub fn link(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### meta | erlang javascript
-
-```gleam
-pub fn meta(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### style | erlang javascript
-
-```gleam
-pub fn style(attrs: List(Attribute(msg)), css: String) -> Element(msg)
-```
-
-### title | erlang javascript
-
-```gleam
-pub fn title(attrs: List(Attribute(msg)), content: String) -> Element(msg)
-```
-
-## Sectioning root
-
-### body | erlang javascript
-
-```gleam
-pub fn body(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-## Content sectioning
-
-### address | erlang javascript
-
-```gleam
-pub fn address(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### article | erlang javascript
-
-```gleam
-pub fn article(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### aside | erlang javascript
-
-```gleam
-pub fn aside(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### footer | erlang javascript
-
-```gleam
-pub fn footer(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### header | erlang javascript
-
-```gleam
-pub fn header(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### h1 | erlang javascript
-
-```gleam
-pub fn h1(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### h2 | erlang javascript
-
-```gleam
-pub fn h2(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### h3 | erlang javascript
-
-```gleam
-pub fn h3(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### h4 | erlang javascript
-
-```gleam
-pub fn h4(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### h5 | erlang javascript
-
-```gleam
-pub fn h5(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### h6 | erlang javascript
-
-```gleam
-pub fn h6(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### hgroup | erlang javascript
-
-```gleam
-pub fn hgroup(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### main | erlang javascript
-
-```gleam
-pub fn main(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### nav | erlang javascript
-
-```gleam
-pub fn nav(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### section | erlang javascript
-
-```gleam
-pub fn section(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### search | erlang javascript
-
-```gleam
-pub fn search(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-## Text content
-
-### blockquote | erlang javascript
-
-```gleam
-pub fn blockquote(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### dd | erlang javascript
-
-```gleam
-pub fn dd(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### div | erlang javascript
-
-```gleam
-pub fn div(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### dl | erlang javascript
-
-```gleam
-pub fn dl(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### dt | erlang javascript
-
-```gleam
-pub fn dt(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### figcaption | erlang javascript
-
-```gleam
-pub fn figcaption(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### figure | erlang javascript
-
-```gleam
-pub fn figure(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### hr | erlang javascript
-
-```gleam
-pub fn hr(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### li | erlang javascript
-
-```gleam
-pub fn li(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### menu | erlang javascript
-
-```gleam
-pub fn menu(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### ol | erlang javascript
-
-```gleam
-pub fn ol(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### p | erlang javascript
-
-```gleam
-pub fn p(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### pre | erlang javascript
-
-```gleam
-pub fn pre(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### ul | erlang javascript
-
-```gleam
-pub fn ul(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-## Inline text semantics
-
-### a | erlang javascript
-
-```gleam
-pub fn a(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### abbr | erlang javascript
-
-```gleam
-pub fn abbr(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### b | erlang javascript
-
-```gleam
-pub fn b(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### bdi | erlang javascript
-
-```gleam
-pub fn bdi(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### bdo | erlang javascript
-
-```gleam
-pub fn bdo(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### br | erlang javascript
-
-```gleam
-pub fn br(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### cite | erlang javascript
-
-```gleam
-pub fn cite(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### code | erlang javascript
-
-```gleam
-pub fn code(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### data | erlang javascript
-
-```gleam
-pub fn data(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### dfn | erlang javascript
-
-```gleam
-pub fn dfn(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### em | erlang javascript
-
-```gleam
-pub fn em(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### i | erlang javascript
-
-```gleam
-pub fn i(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### kbd | erlang javascript
-
-```gleam
-pub fn kbd(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### mark | erlang javascript
-
-```gleam
-pub fn mark(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### q | erlang javascript
-
-```gleam
-pub fn q(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### rp | erlang javascript
-
-```gleam
-pub fn rp(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### rt | erlang javascript
-
-```gleam
-pub fn rt(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### ruby | erlang javascript
-
-```gleam
-pub fn ruby(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### s | erlang javascript
-
-```gleam
-pub fn s(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### samp | erlang javascript
-
-```gleam
-pub fn samp(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### small | erlang javascript
-
-```gleam
-pub fn small(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### span | erlang javascript
-
-```gleam
-pub fn span(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### strong | erlang javascript
-
-```gleam
-pub fn strong(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### sub | erlang javascript
-
-```gleam
-pub fn sub(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### sup | erlang javascript
-
-```gleam
-pub fn sup(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### time | erlang javascript
-
-```gleam
-pub fn time(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### u | erlang javascript
-
-```gleam
-pub fn u(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### var | erlang javascript
-
-```gleam
-pub fn var(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### wbr | erlang javascript
-
-```gleam
-pub fn wbr(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-## Image and multimedia
-
-### area | erlang javascript
-
-```gleam
-pub fn area(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### audio | erlang javascript
-
-```gleam
-pub fn audio(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### img | erlang javascript
-
-```gleam
-pub fn img(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### map | erlang javascript
-
-```gleam
-pub fn map(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### track | erlang javascript
-
-```gleam
-pub fn track(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### video | erlang javascript
-
-```gleam
-pub fn video(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-## Embedded content
-
-### embed | erlang javascript
-
-```gleam
-pub fn embed(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### iframe | erlang javascript
-
-```gleam
-pub fn iframe(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### object | erlang javascript
-
-```gleam
-pub fn object(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### picture | erlang javascript
-
-```gleam
-pub fn picture(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### portal | erlang javascript
-
-```gleam
-pub fn portal(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### source | erlang javascript
-
-```gleam
-pub fn source(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-## SVG and MathML
-
-### svg | erlang javascript
-
-````gleam
-pub fn svg(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-
-### math | erlang javascript
-
-```gleam
-pub fn math(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-````
-
-## Scripting
-
-### canvas | erlang javascript
-
-```gleam
-pub fn canvas(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### noscript | erlang javascript
-
-```gleam
-pub fn noscript(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### script | erlang javascript
-
-```gleam
-pub fn script(attrs: List(Attribute(msg)), js: String) -> Element(msg)
-```
-
-## Demarcating edits
-
-### del | erlang javascript
-
-```gleam
-pub fn del(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### ins | erlang javascript
-
-```gleam
-pub fn ins(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-## Table content
-
-### caption | erlang javascript
-
-```gleam
-pub fn caption(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### col | erlang javascript
-
-```gleam
-pub fn col(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### colgroup | erlang javascript
-
-```gleam
-pub fn colgroup(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### table | erlang javascript
-
-```gleam
-pub fn table(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### tbody | erlang javascript
-
-```gleam
-pub fn tbody(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### td | erlang javascript
-
-```gleam
-pub fn td(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### tfoot | erlang javascript
-
-```gleam
-pub fn tfoot(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### th | erlang javascript
-
-```gleam
-pub fn th(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### thead | erlang javascript
-
-```gleam
-pub fn thead(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### tr | erlang javascript
-
-```gleam
-pub fn tr(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-## Forms
-
-### button | erlang javascript
-
-```gleam
-pub fn button(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### datalist | erlang javascript
-
-```gleam
-pub fn datalist(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### fieldset | erlang javascript
-
-```gleam
-pub fn fieldset(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### form | erlang javascript
-
-```gleam
-pub fn form(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### input | erlang javascript
-
-```gleam
-pub fn input(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### label | erlang javascript
-
-```gleam
-pub fn label(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### legend | erlang javascript
-
-```gleam
-pub fn legend(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### meter | erlang javascript
-
-```gleam
-pub fn meter(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### optgroup | erlang javascript
-
-```gleam
-pub fn optgroup(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### option | erlang javascript
-
-```gleam
-pub fn option(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### output | erlang javascript
-
-```gleam
-pub fn output(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### progress | erlang javascript
-
-```gleam
-pub fn progress(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### select | erlang javascript
-
-```gleam
-pub fn select(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### textarea | erlang javascript
-
-```gleam
-pub fn textarea(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-## Interactive elements
-
-### details | erlang javascript
-
-```gleam
-pub fn details(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### dialog | erlang javascript
-
-```gleam
-pub fn dialog(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### summary | erlang javascript
-
-```gleam
-pub fn summary(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-## Web components
-
-### slot | erlang javascript
-
-```gleam
-pub fn slot(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### template | erlang javascript
-
-```gleam
-pub fn template(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
diff --git a/docs/public/page/api/lustre/element/svg.md b/docs/public/page/api/lustre/element/svg.md
deleted file mode 100644
index a7a0ec2..0000000
--- a/docs/public/page/api/lustre/element/svg.md
+++ /dev/null
@@ -1,462 +0,0 @@
-# lustre/element/svg
-
-## Animation elements
-
-### animate | erlang javascript
-
-```gleam
-pub fn animate(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### animate_motion | erlang javascript
-
-```gleam
-pub fn animate_motion(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### animate_transform | erlang javascript
-
-```gleam
-pub fn animate_transform(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### mpath | erlang javascript
-
-```gleam
-pub fn mpath(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### set | erlang javascript
-
-```gleam
-pub fn set(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-## Basic shapes
-
-### circle | erlang javascript
-
-```gleam
-pub fn circle(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### ellipse | erlang javascript
-
-```gleam
-pub fn ellipse(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### line | erlang javascript
-
-```gleam
-pub fn line(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### polygon | erlang javascript
-
-```gleam
-pub fn polygon(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### polyline | erlang javascript
-
-```gleam
-pub fn polyline(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### rect | erlang javascript
-
-```gleam
-pub fn rect(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-## Container elements
-
-### a | erlang javascript
-
-```gleam
-pub fn a(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### defs | erlang javascript
-
-```gleam
-pub fn defs(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### g | erlang javascript
-
-```gleam
-pub fn g(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### marker | erlang javascript
-
-```gleam
-pub fn marker(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### mask | erlang javascript
-
-```gleam
-pub fn mask(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### missing_glyph | erlang javascript
-
-```gleam
-pub fn missing_glyph(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### pattern | erlang javascript
-
-```gleam
-pub fn pattern(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### svg | erlang javascript
-
-```gleam
-pub fn svg(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### switch | erlang javascript
-
-```gleam
-pub fn switch(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### symbol | erlang javascript
-
-```gleam
-pub fn symbol(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-## Descriptive elements
-
-### desc | erlang javascript
-
-```gleam
-pub fn desc(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### metadata | erlang javascript
-
-```gleam
-pub fn metadata(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### title | erlang javascript
-
-```gleam
-pub fn title(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-## Filter effects
-
-### fe_blend | erlang javascript
-
-```gleam
-pub fn fe_blend(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_color_matrix | erlang javascript
-
-```gleam
-pub fn fe_color_matrix(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_component_transfer | erlang javascript
-
-```gleam
-pub fn fe_component_transfer(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_composite | erlang javascript
-
-```gleam
-pub fn fe_composite(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_convolve_matrix | erlang javascript
-
-```gleam
-pub fn fe_convolve_matrix(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_diffuse_lighting | erlang javascript
-
-```gleam
-pub fn fe_diffuse_lighting(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### fe_displacement_map | erlang javascript
-
-```gleam
-pub fn fe_displacement_map(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_drop_shadow | erlang javascript
-
-```gleam
-pub fn fe_drop_shadow(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_flood | erlang javascript
-
-```gleam
-pub fn fe_flood(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_func_a | erlang javascript
-
-```gleam
-pub fn fe_func_a(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_func_b | erlang javascript
-
-```gleam
-pub fn fe_func_b(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_func_g | erlang javascript
-
-```gleam
-pub fn fe_func_g(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_func_r | erlang javascript
-
-```gleam
-pub fn fe_func_r(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_gaussian_blur | erlang javascript
-
-```gleam
-pub fn fe_gaussian_blur(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_image | erlang javascript
-
-```gleam
-pub fn fe_image(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_merge | erlang javascript
-
-```gleam
-pub fn fe_merge(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### fe_merge_node | erlang javascript
-
-```gleam
-pub fn fe_merge_node(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_morphology | erlang javascript
-
-```gleam
-pub fn fe_morphology(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_offset | erlang javascript
-
-```gleam
-pub fn fe_offset(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_specular_lighting | erlang javascript
-
-```gleam
-pub fn fe_specular_lighting(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### fe_tile | erlang javascript
-
-```gleam
-pub fn fe_tile(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### fe_turbulence | erlang javascript
-
-```gleam
-pub fn fe_turbulence(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-## Gradient elements
-
-### linear_gradient | erlang javascript
-
-```gleam
-pub fn linear_gradient(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### radial_gradient | erlang javascript
-
-```gleam
-pub fn radial_gradient(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### stop | erlang javascript
-
-```gleam
-pub fn stop(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-## Graphical elements
-
-### image | erlang javascript
-
-```gleam
-pub fn image(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### path | erlang javascript
-
-```gleam
-pub fn path(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### text | erlang javascript
-
-```gleam
-pub fn text(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### use\_ | erlang javascript
-
-```gleam
-pub fn use_(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-## Lighting elements
-
-### fe_distant_light | erlang javascript
-
-```gleam
-pub fn fe_distant_light(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_point_light | erlang javascript
-
-```gleam
-pub fn fe_point_light(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-### fe_spot_light | erlang javascript
-
-```gleam
-pub fn fe_spot_light(attrs: List(Attribute(msg))) -> Element(msg)
-```
-
-## Non-rendered elements
-
-### clip_path | erlang javascript
-
-```gleam
-pub fn clip_path(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### script | erlang javascript
-
-```gleam
-pub fn script(attrs: List(Attribute(msg)), js: String) -> Element(msg)
-```
-
-### style | erlang javascript
-
-```gleam
-pub fn style(attrs: List(Attribute(msg)), css: String) -> Element(msg)
-```
-
-## Renderable elements
-
-### foreign_object | erlang javascript
-
-```gleam
-pub fn foreign_object(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### text_path | erlang javascript
-
-```gleam
-pub fn text_path(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
-
-### tspan | erlang javascript
-
-```gleam
-pub fn tspan(
- attrs: List(Attribute(msg)),
- children: List(Element(msg)),
-) -> Element(msg)
-```
diff --git a/docs/public/page/api/lustre/event.md b/docs/public/page/api/lustre/event.md
deleted file mode 100644
index 3385e9f..0000000
--- a/docs/public/page/api/lustre/event.md
+++ /dev/null
@@ -1,146 +0,0 @@
-# lustre/event
-
-## Mouse events
-
-### on_click | erlang javascript
-
-```gleam
-pub fn on_click(msg: msg) -> Attribute(msg)
-```
-
-### on_mouse_down | erlang javascript
-
-```gleam
-pub fn on_mouse_down(msg: msg) -> Attribute(msg)
-```
-
-### on_mouse_up | erlang javascript
-
-```gleam
-pub fn on_mouse_up(msg: msg) -> Attribute(msg)
-```
-
-### on_mouse_enter | erlang javascript
-
-```gleam
-pub fn on_mouse_enter(msg: msg) -> Attribute(msg)
-```
-
-### on_mouse_leave | erlang javascript
-
-```gleam
-pub fn on_mouse_leave(msg: msg) -> Attribute(msg)
-```
-
-### on_mouse_over | erlang javascript
-
-```gleam
-pub fn on_mouse_over(msg: msg) -> Attribute(msg)
-```
-
-### on_mouse_out | erlang javascript
-
-```gleam
-pub fn on_mouse_out(msg: msg) -> Attribute(msg)
-```
-
-## Keyboard events
-
-### on_keypress | erlang javascript
-
-```gleam
-pub fn on_keypress(msg: fn(String) -> msg) -> Attribute(msg)
-```
-
-### on_keydown | erlang javascript
-
-```gleam
-pub fn on_keydown(msg: fn(String) -> msg) -> Attribute(msg)
-```
-
-### on_keyup | erlang javascript
-
-```gleam
-pub fn on_keyup(msg: fn(String) -> msg) -> Attribute(msg)
-```
-
-## Form messages
-
-### on_input | erlang javascript
-
-```gleam
-pub fn on_input(msg: fn(String) -> msg) -> Attribute(msg)
-```
-
-### on_change | erlang javascript
-
-```gleam
-pub fn on_change(msg: fn(Bool) -> msg) -> Attribute(msg)
-```
-
-### on_submit | erlang javascript
-
-```gleam
-pub fn on_submit(msg: msg) -> Attribute(msg)
-```
-
-## Focus events
-
-### on_focus | erlang javascript
-
-```gleam
-pub fn on_focus(msg: msg) -> Attribute(msg)
-```
-
-### on_blur | erlang javascript
-
-```gleam
-pub fn on_blur(msg: msg) -> Attribute(msg)
-```
-
-## Custom events
-
-### on | erlang javascript
-
-```gleam
-pub fn on(
- name: String,
- handler: fn(Dynamic) -> Result(msg, error)
-) -> Attribute(msg)
-```
-
-### prevent_default | erlang javascript
-
-```gleam
-pub fn prevent_default(event: Dynamic) -> Nil
-```
-
-### stop_propagation | erlang javascript
-
-```gleam
-pub fn stop_propagation(event: Dynamic) -> Nil
-```
-
-### value | erlang javascript
-
-```gleam
-pub fn value(event: Dynamic) -> Decoder(String)
-```
-
-### checked | erlang javascript
-
-```gleam
-pub fn checked(event: Dynamic) -> Decoder(Bool)
-```
-
-### mouse_position | erlang javascript
-
-```gleam
-pub fn mouse_position(event: Dynamic) -> Decoder(#(Float, Float))
-```
-
-### emit | javascript
-
-```gleam
-pub fn emit(event: String, data: any) -> Effect(msg)
-```
diff --git a/docs/public/page/docs/components.md b/docs/public/page/docs/components.md
deleted file mode 100644
index 6fecf43..0000000
--- a/docs/public/page/docs/components.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Components
-
-Whoopsie, I haven't got round to writing this guide yet. If you haven't checked
-out the [quickstart guide](/docs/quickstart) that is probably the best place to
-go to get up to speed.
-
-If you have any questions, feel free to ping `@hayleigh.dev` over on the Gleam
-[Discord server](https://discord.gg/Fm8Pwmy) and I'd be happy to help you out!
diff --git a/docs/public/page/docs/managing-state.md b/docs/public/page/docs/managing-state.md
deleted file mode 100644
index f541980..0000000
--- a/docs/public/page/docs/managing-state.md
+++ /dev/null
@@ -1,206 +0,0 @@
-# Managing state
-
-We saw in the quickstart guide that Lustre applications are built using the
-Model-View-Update architecture. For folks used to building with React or most
-other frontend frameworks, it can be a bit of a shock to work without access to
-local component state.
-
-In this guide we'll look at how to manage state in a variety of scenarios
-_without_ using local component state. It's important to get a solid grasp on
-this _before_ looking at Lustre's approach to components because they're built on
-the same principles!
-
-## Semi-encapsulated components
-
-Before reaching for Lustre's stateful components, you might consider a
-semi-encapsulated approach. This is where you have a separate Gleam module that
-defines it's own `Model`, `init`, `Msg`, and `update` (and optionally a `view`
-too) but still manage things from your top-level application.
-
-For example, we may define a `counter` module:
-
-```gleam
-// app/counter.gleam
-
-import gleam/int
-import lustre/element.{Element}
-import lustre/element/html
-import lustre/event
-
-pub opaque type Model {
- Model(Int)
-}
-
-pub fn init() -> Model {
- Model(0)
-}
-
-pub type Msg {
- Incr
- Decr
- Double
- Reset
-}
-
-pub fn update(model: Model, msg: Msg) -> Model {
- let Model(count) = model
- case msg {
- Incr -> Model(count + 1)
- Decr -> Model(count - 1)
- Double -> Model(count * 2)
- Reset -> Model(0)
- }
-}
-
-pub fn view(model: Model) -> Element(Msg) {
- let Model(count) = model
- let count = int.to_string(count)
-
- html.div([], [
- html.p([], [element.text(count)]),
- html.button([event.on_click(Decr)], [html.text("-")]),
- html.button([event.on_click(Incr)], [html.text("+")]),
- html.button([event.on_click(Double)], [html.text("x2")]),
- html.button([event.on_click(Reset)], [html.text("Reset")]),
- ])
-}
-```
-
-Now we can create and manage multiple counters in our main application:
-
-```gleam
-// app.gleam
-
-import app/counter
-import lustre
-import lustre/element.{Element}
-import lustre/element/html
-
-pub fn main() {
- let app = lustre.simple(init, update, view)
- let assert Ok(_) = lustre.start(app, "[data-lustre-app]", Nil)
-}
-
-pub type Model {
- Model(
- // Our model will hold two separate counters, each with their own independent
- // state.
- counter1: counter.Model,
- counter2: counter.Model,
- )
-}
-
-pub fn init() -> Model {
- Model(
- counter.init(),
- counter.init(),
- )
-}
-
-pub type Msg {
- //
- Counter1(counter.Msg)
- Counter2(counter.Msg)
-}
-
-pub fn update(model: Model, msg: Msg) -> Model {
- case msg {
- Counter1(msg) -> Model(..model,
- counter1: counter.update(model.counter1, msg)
- )
-
- Counter2(msg) -> Model(..model,
- counter2: counter.update(model.counter2, msg)
- )
- }
-}
-
-pub fn view(model: Model) -> Element(Msg) {
- let Model(counter1, counter2) = model
-
- html.div([], [
- counter.view(counter1) |> element.map(Counter1),
- counter.view(counter2) |> element.map(Counter2),
- ])
-}
-```
-
-Note that we're using [`element.map`](/api/lustre/element#map) to map the events
-from each counter view to a `Msg` type our application understands! In Lustre,
-the [`Element`](/api/lustre/element#element-type) type is parameterised by the
-type of messages they can emit. This is how Lustre achieves type-safe event handling.
-
-This approach can get quite sophisticated. For example you may want to make your
-component's `Model` type opaque and optionally provide some helper functions to
-extract any data parents may need to know about. You might also choose to split
-your component's `Msg` type and keep a separate `InternalMsg` type that can't
-be constructed outside of the module.
-
-Taking the counter example from above, perhaps we want parents to only be able to
-reset the counter and query the current count, but all other messages are handled
-internally:
-
-```gleam
-pub type Msg {
- Reset
- Internal(InternalMsg)
-}
-
-pub opaque type InternalMsg {
- Incr
- Decr
- Double
-}
-
-pub fn count(model: Model) -> Int {
- let Model(count) = model
- count
-}
-```
-
-The parent could still have a button to reset all counters back to `0`, but it
-wouldn't be able to mess with the internal state in any other way.
-
-After a while you may you find your semi-encapsulated components have a lot of
-internal state or many messages that are only relevant to that component. If that
-happens, it may be time to consider a [stateful component](/docs/components)
-instead.
-
-## Separating page state
-
-```gleam
-type Model {
-
-}
-```
-
-## Preserving state across page changes
-
-```gleam
-type Model = Map(String, PageModel)
-
-type PageModel {
-
-}
-```
-
-## Sharing state between pages
-
-```gleam
-import gleam/map.{Map}
-
-type Model {
- Model(
- shared: SharedModel,
- pages: Map(String, PageModel)
- )
-}
-
-type SharedModel {
- SharedModel()
-}
-
-type PageModel {
-
-}
-```
diff --git a/docs/public/page/docs/quickstart.md b/docs/public/page/docs/quickstart.md
deleted file mode 100644
index 7146f85..0000000
--- a/docs/public/page/docs/quickstart.md
+++ /dev/null
@@ -1,271 +0,0 @@
-# Quickstart
-
-Lustre is a frontend web framework for Gleam. It is primarily focused on helping
-you build robust single-page applications (SPAs), but it can also be used on the
-server to render static HTML. To get an idea of what it's all about, here's a
-quick overview of Lustre's key features:
-
-- Elm-inspired runtime with state management and controlled side effects out of
- the box.
-- A simple, declarative API for building type-safe user interfaces.
-- Stateful components built as custom elements and useable just like any other
- HTML element.
-- Static HTML rendering anywhere Gleam can run: the BEAM, Node.js, Deno, or the
- browser.
-
-In this quickstart guide we'll take a look at how to get up and running with
-Lustre in both the browser and on the server.
-
-## In the browser | javascript
-
-To get started, we'll scaffold a new Gleam project using `gleam new`. If you've
-found your way to this guide but don't already know what Gleam is you can read
-about it over at [gleam.run](https://gleam.run).
-
-```shell
-$ gleam new lustre_quickstart && cd lustre_quickstart && gleam add lustre
-```
-
-In a real project you probably want to use a build tool like [vite](https://vitejs.dev)
-along with the [vite-gleam](https://github.com/Enderchief/vite-gleam) plugin, but
-to keep this guide simple we'll just show you what code you need to write and leave
-the details on serving the app up to you. MDN have a handy guide covering some
-different options to [set up a local web server for development](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Tools_and_setup/set_up_a_local_testing_server)
-if you need some ideas.
-
-### Basic HTML setup
-
-With our Gleam project scaffolded, go ahead and create an `index.html` in the root
-of the project. This is the minimal code you'll typically want to get started:
-
-```html
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>Lustre Quickstart</title>
-
- <script type="module">
- import { main } from "./build/dev/javascript/lustre_quickstart/app.mjs";
-
- document.addEventListener("DOMContentLoaded", () => {
- main();
- });
- </script>
- </head>
-
- <body>
- <div data-lustre-app></div>
- </body>
-</html>
-```
-
-We wait until the DOM has loaded before calling the our app's `main` function.
-This will mount the Lustre app and start rendering. We also add the `data-lustre-app`
-attribute to the element we want to mount the app to. You could use a class or an
-id instead, or none of that: [`lustre.start`](/api/lustre#start) takes a CSS
-selector so go wild!
-
-### Hello, world!
-
-Go ahead and rename the generated `lustre_quickstart.gleam` file to `app.gleam`
-and replace the contents with the following:
-
-```gleam
-import lustre
-import lustre/element.{text}
-
-pub fn main() {
- let app = lustre.element(text("Hello, world!"))
- let assert Ok(_) = lustre.start(app, "[data-lustre-app]", Nil)
-
- Nil
-}
-```
-
-This will create a static Lustre app and mount it onto the element that matches
-the CSS selector. While we're asserting everything is OK here, it is possible
-for `lustre.start` to fail in a couple of ways. Check out the docs for the
-[`lustre.Error`](/api/lustre#error-type) type if you want to know more.
-
-Run `gleam build` and serve the HTML with your preferred static file server (this
-step is necessary: JavaScript modules can't be imported when just opening a HTML
-file) and admire your handiwork.
-
-### Adding interactivity
-
-Now that we know how to get things up and running, let's try something a little
-more exciting and add some interactivity. Replace the contents of your `app.gleam`
-file with the code below and rebuild the project.
-
-```gleam
-import gleam/int
-import lustre
-import lustre/element.{text}
-import lustre/element/html.{div, button, p}
-import lustre/event.{on_click}
-
-pub fn main() {
- let app = lustre.simple(init, update, view)
- let assert Ok(_) = lustre.start(app, "[data-lustre-app]", Nil)
-
- Nil
-}
-
-fn init(_) {
- 0
-}
-
-type Msg {
- Incr
- Decr
-}
-
-fn update(model, msg) {
- case msg {
- Incr -> model + 1
- Decr -> model - 1
- }
-}
-
-fn view(model) {
- let count = int.to_string(model)
-
- div([], [
- button([on_click(Decr)], [text(" - ")]),
- p([], [text(count)]),
- button([on_click(Incr)], [text(" + ")])
- ])
-}
-```
-
-You should now have a very exciting counter app! Almost every Lustre app will
-boil down to the same three parts:
-
-- A `Model` type that represents your application's state and a function to
- `init` it.
-- A `Msg` type and an `update` function to update that state based on incoming
- messages.
-- A `view` function that takes the current state and renders some HTML.
-
-This architecture is not unique to Lustre. It was introduced by the Elm community
-and known as the [Elm Architecture](https://guide.elm-lang.org/architecture/)
-before making its way to React as [Redux](https://redux.js.org) and beyond, known
-more generally as the Model-View-Update architecture. If you work through the
-rest of our guides you'll see how this architecture helps keep side effects out
-of our view code and how to create components that can encapsulate their own state
-and update logic.
-
-For now though, we'll leave things here. If you're interested in seeing how Lustre
-can be used to render static HTML on the server, read on! Otherwise, you can take
-this counter application as a base and start building something of your own.
-
-## On the server | erlang javascript
-
-As we've seen, Lustre is primarily meant to be used in the browser to build
-interactive SPAs. It is possible to render Lustre elements to static HTML and
-simply use Lustre as a templating DSL. As before, we'll start by scaffolding a
-new Gleam project and adding Lustre as a dependency:
-
-```shell
-$ gleam new lustre_quickstart && cd lustre_quickstart && gleam add lustre
-```
-
-The [`lustre/element`](/api/lustre/element) module contains functions to render
-an element as either a `String` or `StringBuilder`. Copy the following code into
-`lustre_quickstart.gleam`:
-
-```gleam
-import gleam/io
-import lustre/attribute.{attribute}
-import lustre/element.{text}
-import lustre/element/html.{html, head, title, body, div, h1}
-
-pub fn main() {
- html([attribute("lang", "en")], [
- head([], [
- title([], [text("Lustre Quickstart")])
- ]),
- body([], [
- h1([], [text("Hello, world!")])
- ])
- ])
- |> element.to_string
- |> io.println
-}
-```
-
-We can test this out by running `gleam run` and seeing the HTML printed to the
-console. From here we could set up a web server using [Mist](/guides/mist) or
-[Wisp](/guides/wisp) to serve the HTML to the browser or write it to a file using
-[simplifile](https://hexdocs.pm/simplifile/). Because the API is the same for
-both client and server rendering, it is easy to create reusable components that
-can be rendered anywhere Gleam can run!
-
-### An example with Wisp
-
-Before we go, let's just take a quick look at what it would look like to use
-Lustre in a [Wisp](https://hexdocs.pm/wisp) application. We won't scaffold out a
-real app in this example, but we'll adapt one of the examples from Wisp's own
-documentation.
-
-Specifically, we'll take a look at the `show_form` function from the
-["working with form data"](https://github.com/lpil/wisp/blob/ea8a40bc20745f172695c8cc2dc0a63769f890a7/examples/2-working-with-form-data/src/app/router.gleam#L20)
-example:
-
-```gleam
-...
-
-pub fn show_form() {
- // In a larger application a template library or HTML form library might
- // be used here instead of a string literal.
- let html =
- string_builder.from_string(
- "<form method='post'>
- <label>Title:
- <input type='text' name='title'>
- </label>
- <label>Name:
- <input type='text' name='name'>
- </label>
- <input type='submit' value='Submit'>
- </form>",
- )
- wisp.ok()
- |> wisp.html_body(html)
-}
-```
-
-They've helpfully left a comment telling us that in a larger application we might
-want to use a template library, and Lustre is up to the task! Let's refactor this
-using Lustre:
-
-```gleam
-import gleam/string
-import lustre/attribute.{attribute}
-import lustre/element
-import lustre/element/html
-...
-
-pub fn show_form() {
- html.form([attribute("method", "post")], [
- labelled_input("Title"),
- labelled_input("Name"),
- html.input([attribute("type", "submit"), attribute("value", "Submit")])
- ])
- |> element.to_string_builder
- |> wisp.html_body
- |> wisp.ok
-}
-
-fn labelled_input(name) {
- html.label([], [
- element.text(name <> ": "),
- html.input([
- attribute("type", "text"),
- attribute("name", string.lowercase(name))
- ])
- ])
-}
-```
diff --git a/docs/public/page/docs/server-side-rendering.md b/docs/public/page/docs/server-side-rendering.md
deleted file mode 100644
index 66d605c..0000000
--- a/docs/public/page/docs/server-side-rendering.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Server-side rendering
-
-Whoopsie, I haven't got round to writing this guide yet. If you haven't checked
-out the [quickstart guide](/docs/quickstart) that is probably the best place to
-go to get up to speed.
-
-If you have any questions, feel free to ping `@hayleigh.dev` over on the Gleam
-[Discord server](https://discord.gg/Fm8Pwmy) and I'd be happy to help you out!
diff --git a/docs/public/page/docs/side-effects.md b/docs/public/page/docs/side-effects.md
deleted file mode 100644
index 1cf21e2..0000000
--- a/docs/public/page/docs/side-effects.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Side effects
-
-Whoopsie, I haven't got round to writing this guide yet. If you haven't checked
-out the [quickstart guide](/docs/quickstart) that is probably the best place to
-go to get up to speed.
-
-If you have any questions, feel free to ping `@hayleigh.dev` over on the Gleam
-[Discord server](https://discord.gg/Fm8Pwmy) and I'd be happy to help you out!
diff --git a/docs/public/page/guides/mist.md b/docs/public/page/guides/mist.md
deleted file mode 100644
index 9afa83b..0000000
--- a/docs/public/page/guides/mist.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Using with Mist
-
-Whoopsie, I haven't got round to writing this guide yet. If you haven't checked
-out the [quickstart guide](/docs/quickstart) that is probably the best place to
-go to get up to speed.
-
-If you have any questions, feel free to ping `@hayleigh.dev` over on the Gleam
-[Discord server](https://discord.gg/Fm8Pwmy) and I'd be happy to help you out!
diff --git a/docs/public/page/guides/wisp.md b/docs/public/page/guides/wisp.md
deleted file mode 100644
index 84d4089..0000000
--- a/docs/public/page/guides/wisp.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Using with Wisp
-
-Whoopsie, I haven't got round to writing this guide yet. If you haven't checked
-out the [quickstart guide](/docs/quickstart) that is probably the best place to
-go to get up to speed.
-
-If you have any questions, feel free to ping `@hayleigh.dev` over on the Gleam
-[Discord server](https://discord.gg/Fm8Pwmy) and I'd be happy to help you out!
diff --git a/docs/src/app.ffi.mjs b/docs/src/app.ffi.mjs
deleted file mode 100644
index 3983f27..0000000
--- a/docs/src/app.ffi.mjs
+++ /dev/null
@@ -1,10 +0,0 @@
-export function base() {
- return import.meta.env.BASE_URL;
-}
-
-export const fetch_post = (path, dispatch) => {
- fetch(`${import.meta.env.BASE_URL}page/${path.slice(1)}.md`)
- .then((res) => res.text())
- .then((content) => dispatch(content))
- .catch(console.error);
-};
diff --git a/docs/src/app.gleam b/docs/src/app.gleam
deleted file mode 100644
index d448ef7..0000000
--- a/docs/src/app.gleam
+++ /dev/null
@@ -1,137 +0,0 @@
-// IMPORTS ---------------------------------------------------------------------
-
-import app/layout
-import gleam/function
-import gleam/map.{Map}
-import lustre
-import lustre/attribute
-import lustre/effect.{Effect}
-import lustre/element.{Element}
-import lustre/element/html
-
-// MAIN ------------------------------------------------------------------------
-
-pub fn main(route: Route) -> fn(Msg) -> Nil {
- let app = lustre.application(init, update, view)
- let assert Ok(dispatch) = lustre.start(app, "body", route)
-
- dispatch
-}
-
-// MODEL -----------------------------------------------------------------------
-
-type Model {
- Model(route: Route, content: String, history: Map(String, String))
-}
-
-fn init(route: Route) -> #(Model, Effect(Msg)) {
- let content = ""
- let history = map.new()
- let model = Model(route, content, history)
- let effects = case route.path {
- "/" -> fetch_post("/docs/quickstart", history)
- _ -> fetch_post(route.path, history)
- }
-
- #(model, effects)
-}
-
-// UPDATE ----------------------------------------------------------------------
-
-pub type Msg {
- OnRouteChange(Route)
- GotPost(String, String)
-}
-
-pub type Route {
- Route(path: String, hash: String)
-}
-
-fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
- // We need to do this because Gleam doesn't support record field access in
- // guards just yet.
- let current_path = model.route.path
-
- case msg {
- OnRouteChange(Route(path: "/", hash: _) as route) -> #(
- Model(..model, route: route),
- fetch_post("/docs/quickstart", model.history),
- )
-
- // Only fetch the markdown
- OnRouteChange(Route(path: path, hash: _) as route) if path != current_path -> #(
- Model(..model, route: route),
- fetch_post(path, model.history),
- )
-
- GotPost(path, content) -> #(
- Model(
- ..model,
- content: content,
- history: map.insert(model.history, path, content),
- ),
- effect.none(),
- )
- }
-}
-
-fn fetch_post(path: String, history: Map(String, String)) -> Effect(Msg) {
- use dispatch <- effect.from
-
- case map.get(history, path) {
- Ok(content) -> dispatch(GotPost(path, content))
- Error(_) ->
- fetch_post_content(path, function.compose(GotPost(path, _), dispatch))
- }
-}
-
-@external(javascript, "./app.ffi.mjs", "fetch_post")
-fn fetch_post_content(path: String, dispatch: fn(String) -> Nil) -> Nil
-
-// VIEW ------------------------------------------------------------------------
-
-fn view(model: Model) -> Element(Msg) {
- case model.route.path {
- "/" ->
- html.body(
- [],
- [
- html.div(
- [
- attribute.class(
- "w-screen h-screen flex justify-center items-center",
- ),
- attribute.style([
- #("background-color", "hsla(226,0%,100%,1)"),
- #(
- "background-image",
- " radial-gradient(at 62% 13%, hsla(170,76%,60%,1) 0px, transparent 65%),
- radial-gradient(at 67% 42%, hsla(234,89%,70%,1) 0px, transparent 65%),
- radial-gradient(at 10% 7%, hsla(213,93%,57%,1) 0px, transparent 65%),
- radial-gradient(at 32% 46%, hsla(291,93%,80%,1) 0px, transparent 65%)",
- ),
- ]),
- ],
- [
- html.hgroup(
- [],
- [
- html.h1(
- [attribute.class("text-8xl")],
- [element.text("Lustre.")],
- ),
- html.p(
- [attribute.class("pl-1")],
- [element.text("Web apps from space!")],
- ),
- ],
- ),
- ],
- ),
- layout.docs_section(model.content),
- ],
- )
-
- _ -> layout.docs_page(model.content)
- }
-}
diff --git a/docs/src/app/effects.gleam b/docs/src/app/effects.gleam
deleted file mode 100644
index e69de29..0000000
--- a/docs/src/app/effects.gleam
+++ /dev/null
diff --git a/docs/src/app/layout.gleam b/docs/src/app/layout.gleam
deleted file mode 100644
index 5ec9222..0000000
--- a/docs/src/app/layout.gleam
+++ /dev/null
@@ -1,261 +0,0 @@
-// IMPORTS ---------------------------------------------------------------------
-
-import app/ui/hooks
-import app/ui/radix
-import app/ui/markdown
-import gleam/list
-import gleam/string
-import lustre/attribute
-import lustre/element.{Element}
-import lustre/element/html
-import lustre/event
-
-pub fn docs_page(md: String) -> Element(msg) {
- let #(content, summary) = markdown.parse(md)
-
- html.body(
- [attribute.class("prose prose-lustre max-w-none")],
- [
- html.div(
- [attribute.class("max-w-[96rem] mx-auto grid grid-cols-8")],
- [docs_top(), docs_left(), docs_content(content), docs_right(summary)],
- ),
- ],
- )
-}
-
-pub fn docs_section(md: String) -> Element(msg) {
- let #(content, summary) = markdown.parse(md)
-
- html.div(
- [attribute.class("prose prose-lustre max-w-none")],
- [
- html.div(
- [attribute.class("max-w-[96rem] mx-auto grid grid-cols-8")],
- [docs_top(), docs_left(), docs_content(content), docs_right(summary)],
- ),
- ],
- )
-}
-
-fn docs_top() -> Element(msg) {
- html.header(
- [attribute.class("sticky top-0 z-10 col-span-8 lg:hidden bg-white")],
- [docs_top_toggle()],
- )
-}
-
-fn docs_top_toggle() -> Element(msg) {
- use open, set_open, _ <- hooks.use_state(False)
-
- case open {
- True -> docs_top_open(set_open(False))
- False -> docs_top_closed(set_open(True))
- }
-}
-
-fn docs_top_open(close: msg) -> Element(msg) {
- html.div(
- [attribute.class("relative")],
- [
- html.div(
- [attribute.class("flex justify-between items-center px-4 py-2")],
- [
- html.h2(
- [attribute.class("text-indigo-600 my-0")],
- [element.text("Lustre.")],
- ),
- html.button(
- [
- event.on_click(close),
- attribute.class("hover:bg-gray-200 rounded p-2"),
- ],
- [radix.cross([attribute.class("w-4 h-4")])],
- ),
- ],
- ),
- html.nav(
- [
- attribute.class(
- "absolute top-0 w-full rounded-b-2xl px-4 mt-12 bg-white shadow",
- ),
- ],
- docs_left_links(),
- ),
- ],
- )
-}
-
-fn docs_top_closed(open: msg) -> Element(msg) {
- html.div(
- [
- attribute.class(
- "flex justify-between items-center px-4 py-2 border-b shadow",
- ),
- ],
- [
- html.h2(
- [attribute.class("text-indigo-600 my-0")],
- [element.text("Lustre.")],
- ),
- html.button(
- [event.on_click(open), attribute.class("hover:bg-gray-100 rounded p-2")],
- [radix.hamburger([attribute.class("w-4 h-4")])],
- ),
- ],
- )
-}
-
-fn docs_left() -> Element(msg) {
- html.aside(
- [
- attribute.style([#("align-self", "start")]),
- attribute.class("relative sticky top-0 hidden px-4 pb-10 h-screen"),
- attribute.class("lg:block lg:col-span-2"),
- attribute.class("xl:col-span-2"),
- ],
- [
- html.div(
- [
- attribute.class(
- "absolute right-0 inset-y-0 w-[50vw] bg-gradient-to-b from-white to-gray-100 -z-10",
- ),
- ],
- [],
- ),
- html.div(
- [attribute.class("flex flex-col h-full overflow-y-scroll")],
- [
- html.h2(
- [attribute.class("mb-0")],
- [
- html.a(
- [
- attribute.href("/"),
- attribute.class("text-indigo-600 no-underline"),
- ],
- [element.text("Lustre")],
- ),
- ],
- ),
- html.p(
- [attribute.class("text-gray-400 font-bold")],
- [element.text("Web apps from space.")],
- ),
- ..docs_left_links()
- ],
- ),
- ],
- )
-}
-
-fn docs_left_links() -> List(Element(msg)) {
- let link = string.append(base_url(), _)
-
- [
- docs_left_section(
- "Docs",
- [
- #("Quickstart", link("docs/quickstart")),
- #("Managing state", link("docs/managing-state")),
- #("Side effects", link("docs/side-effects")),
- #("Components", link("docs/components")),
- #("Server-side rendering", link("docs/server-side-rendering")),
- ],
- ),
- docs_left_section(
- "Guides",
- [
- #("Using with Mist", link("guides/mist")),
- #("Using with Wisp", link("guides/wisp")),
- ],
- ),
- docs_left_section(
- "Reference",
- [
- #("lustre", link("api/lustre")),
- #("lustre/attribute", link("api/lustre/attribute")),
- #("lustre/effect", link("api/lustre/effect")),
- #("lustre/element", link("api/lustre/element")),
- #("lustre/element/html", link("api/lustre/element/html")),
- #("lustre/element/svg", link("api/lustre/element/svg")),
- #("lustre/event", link("api/lustre/event")),
- ],
- ),
- docs_left_section(
- "External",
- [
- #("GitHub", "https://github.com/hayleigh-dot-dev/gleam-lustre"),
- #("Discord", "https://discord.gg/Fm8Pwmy"),
- #("Buy me a coffee?", "https://github.com/sponsors/hayleigh-dot-dev"),
- ],
- ),
- ]
-}
-
-@external(javascript, "../app.ffi.mjs", "base")
-fn base_url() -> String {
- "/"
-}
-
-fn docs_left_section(
- title: String,
- pages: List(#(String, String)),
-) -> Element(msg) {
- html.nav(
- [],
- [
- html.h2([attribute.class("my-0 lg:mt-8 lg:mb-4")], [element.text(title)]),
- html.ul(
- [attribute.class("ml-2")],
- {
- use #(name, url) <- list.map(pages)
- html.li(
- [],
- [
- html.a(
- [attribute.href(url), attribute.class("font-serif")],
- [element.text(name)],
- ),
- ],
- )
- },
- ),
- ],
- )
-}
-
-fn docs_content(content: List(Element(msg))) -> Element(msg) {
- html.main(
- [
- attribute.class("col-span-8 pt-4 px-4 pb-32"),
- attribute.class("lg:px-8 lg:col-span-6"),
- attribute.class("xl:col-span-5"),
- ],
- content,
- )
-}
-
-fn docs_right(summary: List(Element(msg))) -> Element(msg) {
- html.aside(
- [
- attribute.style([#("align-self", "start")]),
- attribute.class("sticky relative top-0 hidden p-4 py-10 h-screen"),
- attribute.class("xl:block xl:col-span-1"),
- ],
- [
- html.div(
- [
- attribute.class(
- "absolute left-0 inset-y-0 w-[50vw] bg-gradient-to-b from-white to-gray-100 -z-10",
- ),
- ],
- [],
- ),
- html.div(
- [attribute.class("flex flex-col h-full overflow-y-scroll")],
- summary,
- ),
- ],
- )
-}
diff --git a/docs/src/app/ui/hooks.gleam b/docs/src/app/ui/hooks.gleam
deleted file mode 100644
index 5fd807e..0000000
--- a/docs/src/app/ui/hooks.gleam
+++ /dev/null
@@ -1,120 +0,0 @@
-// 🚨 This module makes quite judicious use of `dynamic.unsafe_coerce` to wire
-// things up. As things are, this is sound because we control things in such a
-// way that it's impossible to pass in things that don't match up to the expected
-// types.
-//
-// If you're defining a new hook to export for this module, pay extra attention
-// to make sure you aren't introducing any soundness issues! 🚨
-
-// IMPORTS ---------------------------------------------------------------------
-
-import gleam/dynamic.{Dynamic, dynamic}
-import gleam/function
-import gleam/map.{Map}
-import gleam/result
-import lustre.{Error}
-import lustre/attribute.{Attribute, property}
-import lustre/effect.{Effect}
-import lustre/element.{Element, element}
-import lustre/event
-
-// HOOKS: STATE ----------------------------------------------------------------
-
-///
-///
-pub fn use_state(
- init: state,
- view: fn(state, fn(state) -> Msg, fn(msg) -> Msg) -> Element(Msg),
-) -> Element(msg) {
- let attrs = [property("state", init), property("view", view), on_dispatch()]
- let assert Ok(_) = register_hook("use-state")
-
- element("use-state", attrs, [])
-}
-
-// HOOKS: REDUCER --------------------------------------------------------------
-
-///
-///
-pub fn use_reducer(
- init: state,
- update: fn(state, action) -> state,
- view: fn(state, fn(action) -> Msg, fn(action) -> Msg) -> Element(Msg),
-) -> Element(msg) {
- // The `use_reducer` hook is actually just the `use_state` hook under the hood
- // with a wrapper around the `set_state` callback. We could just call out to
- // `use_state` directly but we're doing it like this so that the DOM renders
- // a separate `use-reducer` element, which I think is nicer.
- let view = fn(state, set_state, emit) {
- view(state, function.compose(update(state, _), set_state), emit)
- }
- let attrs = [property("state", init), property("view", view), on_dispatch()]
- let assert Ok(_) = register_hook("use-reducer")
-
- element("use-reducer", attrs, [])
-}
-
-// HOOKS: INTERNAL COMPONENT ---------------------------------------------------
-
-fn register_hook(name: String) -> Result(Nil, Error) {
- // If a component is already registered we will just assume it's because this
- // hook as already been used before. This isn't really an error state so we'll
- // just return `Ok(Nil)` and let our hooks continue.
- case lustre.is_registered(name) {
- True -> Ok(Nil)
- False ->
- lustre.component(
- name,
- init_hook,
- update_hook,
- view_hook,
- map.from_list([
- #("state", dynamic.decode1(Set("state", _), Ok)),
- #("view", dynamic.decode1(Set("view", _), Ok)),
- ]),
- )
- }
-}
-
-type Model =
- Map(String, Dynamic)
-
-fn init_hook() -> #(Model, Effect(msg)) {
- #(map.new(), effect.none())
-}
-
-/// The type for messages handled internally by the different hooks. You typially
-/// won't need to import or refer to this type directly.
-///
-pub opaque type Msg {
- Set(String, Dynamic)
- Emit(Dynamic)
-}
-
-fn update_hook(model: Model, msg: Msg) -> #(Model, Effect(msg)) {
- case msg {
- Set(key, val) -> #(map.insert(model, key, val), effect.none())
- Emit(msg) -> #(model, event.emit("dispatch", msg))
- }
-}
-
-fn view_hook(model: Model) -> Element(Msg) {
- case map.get(model, "state"), map.get(model, "view") {
- Ok(state), Ok(view) -> {
- let state = dynamic.unsafe_coerce(state)
- let view = dynamic.unsafe_coerce(view)
-
- view(state, Set("state", _), Emit)
- }
- _, _ -> element.text("???")
- }
-}
-
-// EVENTS ----------------------------------------------------------------------
-
-fn on_dispatch() -> Attribute(msg) {
- use event <- event.on("dispatch")
- event
- |> dynamic.field("detail", dynamic)
- |> result.map(dynamic.unsafe_coerce)
-}
diff --git a/docs/src/app/ui/markdown.gleam b/docs/src/app/ui/markdown.gleam
deleted file mode 100644
index 5a78d0f..0000000
--- a/docs/src/app/ui/markdown.gleam
+++ /dev/null
@@ -1,136 +0,0 @@
-// IMPORTS ---------------------------------------------------------------------
-
-import gleam/int
-import gleam/list
-import lustre/attribute.{attribute}
-import lustre/element.{Element, element}
-import lustre/element/html
-
-@external(javascript, "../../markdown.ffi.mjs", "parse_markdown")
-pub fn parse(md: String) -> #(List(Element(msg)), List(Element(msg)))
-
-// MARKDOWN ELEMENTS -----------------------------------------------------------
-//
-// These are used in the FFI markdown renderer to convert the markdown AST into
-// lustre elements.
-//
-
-pub fn code(src: String, hash: String, lang: String) -> Element(msg) {
- html.pre(
- [attribute.class("not-prose rounded-xl")],
- [
- html.code(
- [
- attribute("data-hash", hash),
- attribute("data-lang", lang),
- attribute.class("language-" <> lang),
- attribute.style([#("background", "transparent")]),
- ],
- [element.text(src)],
- ),
- ],
- )
-}
-
-pub fn emphasis(content: List(Element(msg))) {
- html.em([], content)
-}
-
-pub fn heading(
- depth: Int,
- title: String,
- tags: List(String),
- id: String,
-) -> Element(msg) {
- let depth = int.min(depth, 3)
- let tags = list.map(tags, heading_tag)
-
- case depth {
- 1 ->
- html.h1(
- [attribute.class("flex items-center justify-between"), attribute.id(id)],
- [
- heading_title(title, id),
- html.p([attribute.class("flex gap-4 font-sans")], tags),
- ],
- )
- 2 ->
- html.h2(
- [
- attribute.class("flex items-center justify-between border-t"),
- attribute.id(id),
- ],
- [
- heading_title(title, id),
- html.p([attribute.class("flex gap-4 font-sans")], tags),
- ],
- )
- 3 ->
- html.h3(
- [attribute.class("flex items-center justify-between"), attribute.id(id)],
- [
- heading_title(title, id),
- html.p([attribute.class("flex gap-2 font-sans")], tags),
- ],
- )
- }
-}
-
-fn heading_title(title: String, href: String) -> Element(msg) {
- html.span(
- [attribute.class("group")],
- [
- element.text(title),
- html.a(
- [
- attribute.href("#" <> href),
- attribute.class("pl-2 text-gray-200 opacity-0 transition-opacity"),
- attribute.class("group-hover:underline group-hover:opacity-100"),
- ],
- [element.text("#")],
- ),
- ],
- )
-}
-
-fn heading_tag(tag: String) -> Element(msg) {
- html.span(
- [
- attribute.class(
- "px-2 py-1 text-xs text-gray-700 border border-gray-200 rounded",
- ),
- ],
- [element.text(tag)],
- )
-}
-
-pub fn inline_code(src: String) -> Element(msg) {
- html.code([], [element.text(src)])
-}
-
-pub fn link(href: String, content: List(Element(msg))) -> Element(msg) {
- html.a([attribute.href(href)], content)
-}
-
-pub fn list(ordered: Bool, items: List(Element(msg))) -> Element(msg) {
- case ordered {
- True -> html.ol([], items)
- False -> html.ul([], items)
- }
-}
-
-pub fn list_item(content: List(Element(msg))) -> Element(msg) {
- html.li([], content)
-}
-
-pub fn paragraph(content: List(Element(msg))) -> Element(msg) {
- html.p([], content)
-}
-
-pub fn strong(content: List(Element(msg))) -> Element(msg) {
- html.strong([], content)
-}
-
-pub fn text(content: String) -> Element(msg) {
- element.text(content)
-}
diff --git a/docs/src/app/ui/radix.gleam b/docs/src/app/ui/radix.gleam
deleted file mode 100644
index d6c9755..0000000
--- a/docs/src/app/ui/radix.gleam
+++ /dev/null
@@ -1,74 +0,0 @@
-// All these icons are created by the amazing folks at Radix, and can be found
-// here: https://www.radix-ui.com/icons
-//
-
-// IMPORTS ---------------------------------------------------------------------
-
-import lustre/attribute.{Attribute, attribute}
-import lustre/element.{Element}
-import lustre/element/html.{svg}
-import lustre/element/svg
-
-// BASE ICON -------------------------------------------------------------------
-
-fn icon(attrs: List(Attribute(msg)), path: String) -> Element(msg) {
- svg(
- [attribute("viewBox", "0 0 15 15"), attribute("fill", "none"), ..attrs],
- [
- svg.path([
- attribute("d", path),
- attribute("fill", "currentColor"),
- attribute("fill-rule", "evenodd"),
- attribute("clip-rule", "evenodd"),
- ]),
- ],
- )
-}
-
-// LOGOS -----------------------------------------------------------------------
-
-pub fn github(attrs: List(Attribute(msg))) -> Element(msg) {
- icon(
- attrs,
- "M7.49933 0.25C3.49635 0.25 0.25 3.49593 0.25 7.50024C0.25 10.703 2.32715 13.4206 5.2081 14.3797C5.57084 14.446 5.70302 14.2222 5.70302 14.0299C5.70302 13.8576 5.69679 13.4019 5.69323 12.797C3.67661 13.235 3.25112 11.825 3.25112 11.825C2.92132 10.9874 2.44599 10.7644 2.44599 10.7644C1.78773 10.3149 2.49584 10.3238 2.49584 10.3238C3.22353 10.375 3.60629 11.0711 3.60629 11.0711C4.25298 12.1788 5.30335 11.8588 5.71638 11.6732C5.78225 11.205 5.96962 10.8854 6.17658 10.7043C4.56675 10.5209 2.87415 9.89918 2.87415 7.12104C2.87415 6.32925 3.15677 5.68257 3.62053 5.17563C3.54576 4.99226 3.29697 4.25521 3.69174 3.25691C3.69174 3.25691 4.30015 3.06196 5.68522 3.99973C6.26337 3.83906 6.8838 3.75895 7.50022 3.75583C8.1162 3.75895 8.73619 3.83906 9.31523 3.99973C10.6994 3.06196 11.3069 3.25691 11.3069 3.25691C11.7026 4.25521 11.4538 4.99226 11.3795 5.17563C11.8441 5.68257 12.1245 6.32925 12.1245 7.12104C12.1245 9.9063 10.4292 10.5192 8.81452 10.6985C9.07444 10.9224 9.30633 11.3648 9.30633 12.0413C9.30633 13.0102 9.29742 13.7922 9.29742 14.0299C9.29742 14.2239 9.42828 14.4496 9.79591 14.3788C12.6746 13.4179 14.75 10.7025 14.75 7.50024C14.75 3.49593 11.5036 0.25 7.49933 0.25Z",
- )
-}
-
-pub fn discord(attrs: List(Attribute(msg))) -> Element(msg) {
- icon(
- attrs,
- "M5.07451 1.82584C5.03267 1.81926 4.99014 1.81825 4.94803 1.82284C4.10683 1.91446 2.82673 2.36828 2.07115 2.77808C2.02106 2.80525 1.97621 2.84112 1.93869 2.88402C1.62502 3.24266 1.34046 3.82836 1.11706 4.38186C0.887447 4.95076 0.697293 5.55032 0.588937 5.98354C0.236232 7.39369 0.042502 9.08728 0.0174948 10.6925C0.0162429 10.7729 0.0351883 10.8523 0.0725931 10.9234C0.373679 11.496 1.02015 12.027 1.66809 12.4152C2.32332 12.8078 3.08732 13.1182 3.70385 13.1778C3.85335 13.1922 4.00098 13.1358 4.10282 13.0255C4.2572 12.8581 4.5193 12.4676 4.71745 12.1643C4.80739 12.0267 4.89157 11.8953 4.95845 11.7901C5.62023 11.9106 6.45043 11.9801 7.50002 11.9801C8.54844 11.9801 9.37796 11.9107 10.0394 11.7905C10.1062 11.8957 10.1903 12.0269 10.2801 12.1643C10.4783 12.4676 10.7404 12.8581 10.8947 13.0255C10.9966 13.1358 11.1442 13.1922 11.2937 13.1778C11.9102 13.1182 12.6742 12.8078 13.3295 12.4152C13.9774 12.027 14.6239 11.496 14.925 10.9234C14.9624 10.8523 14.9813 10.7729 14.9801 10.6925C14.9551 9.08728 14.7613 7.39369 14.4086 5.98354C14.3003 5.55032 14.1101 4.95076 13.8805 4.38186C13.6571 3.82836 13.3725 3.24266 13.0589 2.88402C13.0214 2.84112 12.9765 2.80525 12.9264 2.77808C12.1708 2.36828 10.8907 1.91446 10.0495 1.82284C10.0074 1.81825 9.96489 1.81926 9.92305 1.82584C9.71676 1.85825 9.5391 1.96458 9.40809 2.06355C9.26977 2.16804 9.1413 2.29668 9.0304 2.42682C8.86968 2.61544 8.71437 2.84488 8.61428 3.06225C8.27237 3.03501 7.90138 3.02 7.5 3.02C7.0977 3.02 6.72593 3.03508 6.38337 3.06244C6.28328 2.84501 6.12792 2.61549 5.96716 2.42682C5.85626 2.29668 5.72778 2.16804 5.58947 2.06355C5.45846 1.96458 5.2808 1.85825 5.07451 1.82584ZM11.0181 11.5382C11.0395 11.5713 11.0615 11.6051 11.0838 11.6392C11.2169 11.843 11.3487 12.0385 11.4508 12.1809C11.8475 12.0916 12.352 11.8818 12.8361 11.5917C13.3795 11.2661 13.8098 10.8918 14.0177 10.5739C13.9852 9.06758 13.7993 7.50369 13.4773 6.21648C13.38 5.82759 13.2038 5.27021 12.9903 4.74117C12.7893 4.24326 12.5753 3.82162 12.388 3.5792C11.7376 3.24219 10.7129 2.88582 10.0454 2.78987C10.0308 2.79839 10.0113 2.81102 9.98675 2.82955C9.91863 2.881 9.84018 2.95666 9.76111 3.04945C9.71959 3.09817 9.68166 3.1471 9.64768 3.19449C9.953 3.25031 10.2253 3.3171 10.4662 3.39123C11.1499 3.6016 11.6428 3.89039 11.884 4.212C12.0431 4.42408 12.0001 4.72494 11.788 4.884C11.5759 5.04306 11.2751 5.00008 11.116 4.788C11.0572 4.70961 10.8001 4.4984 10.1838 4.30877C9.58933 4.12585 8.71356 3.98 7.5 3.98C6.28644 3.98 5.41067 4.12585 4.81616 4.30877C4.19988 4.4984 3.94279 4.70961 3.884 4.788C3.72494 5.00008 3.42408 5.04306 3.212 4.884C2.99992 4.72494 2.95694 4.42408 3.116 4.212C3.35721 3.89039 3.85011 3.6016 4.53383 3.39123C4.77418 3.31727 5.04571 3.25062 5.35016 3.19488C5.31611 3.14738 5.27808 3.09831 5.23645 3.04945C5.15738 2.95666 5.07893 2.881 5.01081 2.82955C4.98628 2.81102 4.96674 2.79839 4.95217 2.78987C4.28464 2.88582 3.25999 3.24219 2.60954 3.5792C2.42226 3.82162 2.20825 4.24326 2.00729 4.74117C1.79376 5.27021 1.61752 5.82759 1.52025 6.21648C1.19829 7.50369 1.01236 9.06758 0.97986 10.5739C1.18772 10.8918 1.61807 11.2661 2.16148 11.5917C2.64557 11.8818 3.15003 12.0916 3.5468 12.1809C3.64885 12.0385 3.78065 11.843 3.9138 11.6392C3.93626 11.6048 3.95838 11.5708 3.97996 11.5375C3.19521 11.2591 2.77361 10.8758 2.50064 10.4664C2.35359 10.2458 2.4132 9.94778 2.63377 9.80074C2.85435 9.65369 3.15236 9.71329 3.29941 9.93387C3.56077 10.3259 4.24355 11.0201 7.50002 11.0201C10.7565 11.0201 11.4392 10.326 11.7006 9.93386C11.8477 9.71329 12.1457 9.65369 12.3663 9.80074C12.5869 9.94779 12.6465 10.2458 12.4994 10.4664C12.2262 10.8762 11.8041 11.2598 11.0181 11.5382ZM4.08049 7.01221C4.32412 6.74984 4.65476 6.60162 5.00007 6.59998C5.34538 6.60162 5.67603 6.74984 5.91966 7.01221C6.16329 7.27459 6.30007 7.62974 6.30007 7.99998C6.30007 8.37021 6.16329 8.72536 5.91966 8.98774C5.67603 9.25011 5.34538 9.39833 5.00007 9.39998C4.65476 9.39833 4.32412 9.25011 4.08049 8.98774C3.83685 8.72536 3.70007 8.37021 3.70007 7.99998C3.70007 7.62974 3.83685 7.27459 4.08049 7.01221ZM9.99885 6.59998C9.65354 6.60162 9.3229 6.74984 9.07926 7.01221C8.83563 7.27459 8.69885 7.62974 8.69885 7.99998C8.69885 8.37021 8.83563 8.72536 9.07926 8.98774C9.3229 9.25011 9.65354 9.39833 9.99885 9.39998C10.3442 9.39833 10.6748 9.25011 10.9184 8.98774C11.1621 8.72536 11.2989 8.37021 11.2989 7.99998C11.2989 7.62974 11.1621 7.27459 10.9184 7.01221C10.6748 6.74984 10.3442 6.60162 9.99885 6.59998Z",
- )
-}
-
-// ABSTRACT --------------------------------------------------------------------
-
-pub fn hamburger(attrs: List(Attribute(msg))) -> Element(msg) {
- icon(
- attrs,
- "M1.5 3C1.22386 3 1 3.22386 1 3.5C1 3.77614 1.22386 4 1.5 4H13.5C13.7761 4 14 3.77614 14 3.5C14 3.22386 13.7761 3 13.5 3H1.5ZM1 7.5C1 7.22386 1.22386 7 1.5 7H13.5C13.7761 7 14 7.22386 14 7.5C14 7.77614 13.7761 8 13.5 8H1.5C1.22386 8 1 7.77614 1 7.5ZM1 11.5C1 11.2239 1.22386 11 1.5 11H13.5C13.7761 11 14 11.2239 14 11.5C14 11.7761 13.7761 12 13.5 12H1.5C1.22386 12 1 11.7761 1 11.5Z",
- )
-}
-
-pub fn cross(attrs: List(Attribute(msg))) -> Element(msg) {
- icon(
- attrs,
- "M12.8536 2.85355C13.0488 2.65829 13.0488 2.34171 12.8536 2.14645C12.6583 1.95118 12.3417 1.95118 12.1464 2.14645L7.5 6.79289L2.85355 2.14645C2.65829 1.95118 2.34171 1.95118 2.14645 2.14645C1.95118 2.34171 1.95118 2.65829 2.14645 2.85355L6.79289 7.5L2.14645 12.1464C1.95118 12.3417 1.95118 12.6583 2.14645 12.8536C2.34171 13.0488 2.65829 13.0488 2.85355 12.8536L7.5 8.20711L12.1464 12.8536C12.3417 13.0488 12.6583 13.0488 12.8536 12.8536C13.0488 12.6583 13.0488 12.3417 12.8536 12.1464L8.20711 7.5L12.8536 2.85355Z",
- )
-}
-
-// OBJECTS ---------------------------------------------------------------------
-
-pub fn sun(attrs: List(Attribute(msg))) -> Element(msg) {
- icon(
- attrs,
- "M7.5 0C7.77614 0 8 0.223858 8 0.5V2.5C8 2.77614 7.77614 3 7.5 3C7.22386 3 7 2.77614 7 2.5V0.5C7 0.223858 7.22386 0 7.5 0ZM2.1967 2.1967C2.39196 2.00144 2.70854 2.00144 2.90381 2.1967L4.31802 3.61091C4.51328 3.80617 4.51328 4.12276 4.31802 4.31802C4.12276 4.51328 3.80617 4.51328 3.61091 4.31802L2.1967 2.90381C2.00144 2.70854 2.00144 2.39196 2.1967 2.1967ZM0.5 7C0.223858 7 0 7.22386 0 7.5C0 7.77614 0.223858 8 0.5 8H2.5C2.77614 8 3 7.77614 3 7.5C3 7.22386 2.77614 7 2.5 7H0.5ZM2.1967 12.8033C2.00144 12.608 2.00144 12.2915 2.1967 12.0962L3.61091 10.682C3.80617 10.4867 4.12276 10.4867 4.31802 10.682C4.51328 10.8772 4.51328 11.1938 4.31802 11.3891L2.90381 12.8033C2.70854 12.9986 2.39196 12.9986 2.1967 12.8033ZM12.5 7C12.2239 7 12 7.22386 12 7.5C12 7.77614 12.2239 8 12.5 8H14.5C14.7761 8 15 7.77614 15 7.5C15 7.22386 14.7761 7 14.5 7H12.5ZM10.682 4.31802C10.4867 4.12276 10.4867 3.80617 10.682 3.61091L12.0962 2.1967C12.2915 2.00144 12.608 2.00144 12.8033 2.1967C12.9986 2.39196 12.9986 2.70854 12.8033 2.90381L11.3891 4.31802C11.1938 4.51328 10.8772 4.51328 10.682 4.31802ZM8 12.5C8 12.2239 7.77614 12 7.5 12C7.22386 12 7 12.2239 7 12.5V14.5C7 14.7761 7.22386 15 7.5 15C7.77614 15 8 14.7761 8 14.5V12.5ZM10.682 10.682C10.8772 10.4867 11.1938 10.4867 11.3891 10.682L12.8033 12.0962C12.9986 12.2915 12.9986 12.608 12.8033 12.8033C12.608 12.9986 12.2915 12.9986 12.0962 12.8033L10.682 11.3891C10.4867 11.1938 10.4867 10.8772 10.682 10.682ZM5.5 7.5C5.5 6.39543 6.39543 5.5 7.5 5.5C8.60457 5.5 9.5 6.39543 9.5 7.5C9.5 8.60457 8.60457 9.5 7.5 9.5C6.39543 9.5 5.5 8.60457 5.5 7.5ZM7.5 4.5C5.84315 4.5 4.5 5.84315 4.5 7.5C4.5 9.15685 5.84315 10.5 7.5 10.5C9.15685 10.5 10.5 9.15685 10.5 7.5C10.5 5.84315 9.15685 4.5 7.5 4.5Z",
- )
-}
-
-pub fn moon(attrs: List(Attribute(msg))) -> Element(msg) {
- icon(
- attrs,
- "M2.89998 0.499976C2.89998 0.279062 2.72089 0.0999756 2.49998 0.0999756C2.27906 0.0999756 2.09998 0.279062 2.09998 0.499976V1.09998H1.49998C1.27906 1.09998 1.09998 1.27906 1.09998 1.49998C1.09998 1.72089 1.27906 1.89998 1.49998 1.89998H2.09998V2.49998C2.09998 2.72089 2.27906 2.89998 2.49998 2.89998C2.72089 2.89998 2.89998 2.72089 2.89998 2.49998V1.89998H3.49998C3.72089 1.89998 3.89998 1.72089 3.89998 1.49998C3.89998 1.27906 3.72089 1.09998 3.49998 1.09998H2.89998V0.499976ZM5.89998 3.49998C5.89998 3.27906 5.72089 3.09998 5.49998 3.09998C5.27906 3.09998 5.09998 3.27906 5.09998 3.49998V4.09998H4.49998C4.27906 4.09998 4.09998 4.27906 4.09998 4.49998C4.09998 4.72089 4.27906 4.89998 4.49998 4.89998H5.09998V5.49998C5.09998 5.72089 5.27906 5.89998 5.49998 5.89998C5.72089 5.89998 5.89998 5.72089 5.89998 5.49998V4.89998H6.49998C6.72089 4.89998 6.89998 4.72089 6.89998 4.49998C6.89998 4.27906 6.72089 4.09998 6.49998 4.09998H5.89998V3.49998ZM1.89998 6.49998C1.89998 6.27906 1.72089 6.09998 1.49998 6.09998C1.27906 6.09998 1.09998 6.27906 1.09998 6.49998V7.09998H0.499976C0.279062 7.09998 0.0999756 7.27906 0.0999756 7.49998C0.0999756 7.72089 0.279062 7.89998 0.499976 7.89998H1.09998V8.49998C1.09998 8.72089 1.27906 8.89997 1.49998 8.89997C1.72089 8.89997 1.89998 8.72089 1.89998 8.49998V7.89998H2.49998C2.72089 7.89998 2.89998 7.72089 2.89998 7.49998C2.89998 7.27906 2.72089 7.09998 2.49998 7.09998H1.89998V6.49998ZM8.54406 0.98184L8.24618 0.941586C8.03275 0.917676 7.90692 1.1655 8.02936 1.34194C8.17013 1.54479 8.29981 1.75592 8.41754 1.97445C8.91878 2.90485 9.20322 3.96932 9.20322 5.10022C9.20322 8.37201 6.82247 11.0878 3.69887 11.6097C3.45736 11.65 3.20988 11.6772 2.96008 11.6906C2.74563 11.702 2.62729 11.9535 2.77721 12.1072C2.84551 12.1773 2.91535 12.2458 2.98667 12.3128L3.05883 12.3795L3.31883 12.6045L3.50684 12.7532L3.62796 12.8433L3.81491 12.9742L3.99079 13.089C4.11175 13.1651 4.23536 13.2375 4.36157 13.3059L4.62496 13.4412L4.88553 13.5607L5.18837 13.6828L5.43169 13.7686C5.56564 13.8128 5.70149 13.8529 5.83857 13.8885C5.94262 13.9155 6.04767 13.9401 6.15405 13.9622C6.27993 13.9883 6.40713 14.0109 6.53544 14.0298L6.85241 14.0685L7.11934 14.0892C7.24637 14.0965 7.37436 14.1002 7.50322 14.1002C11.1483 14.1002 14.1032 11.1453 14.1032 7.50023C14.1032 7.25044 14.0893 7.00389 14.0623 6.76131L14.0255 6.48407C13.991 6.26083 13.9453 6.04129 13.8891 5.82642C13.8213 5.56709 13.7382 5.31398 13.6409 5.06881L13.5279 4.80132L13.4507 4.63542L13.3766 4.48666C13.2178 4.17773 13.0353 3.88295 12.8312 3.60423L12.6782 3.40352L12.4793 3.16432L12.3157 2.98361L12.1961 2.85951L12.0355 2.70246L11.8134 2.50184L11.4925 2.24191L11.2483 2.06498L10.9562 1.87446L10.6346 1.68894L10.3073 1.52378L10.1938 1.47176L9.95488 1.3706L9.67791 1.2669L9.42566 1.1846L9.10075 1.09489L8.83599 1.03486L8.54406 0.98184ZM10.4032 5.30023C10.4032 4.27588 10.2002 3.29829 9.83244 2.40604C11.7623 3.28995 13.1032 5.23862 13.1032 7.50023C13.1032 10.593 10.596 13.1002 7.50322 13.1002C6.63646 13.1002 5.81597 12.9036 5.08355 12.5522C6.5419 12.0941 7.81081 11.2082 8.74322 10.0416C8.87963 10.2284 9.10028 10.3497 9.34928 10.3497C9.76349 10.3497 10.0993 10.0139 10.0993 9.59971C10.0993 9.24256 9.84965 8.94373 9.51535 8.86816C9.57741 8.75165 9.63653 8.63334 9.6926 8.51332C9.88358 8.63163 10.1088 8.69993 10.35 8.69993C11.0403 8.69993 11.6 8.14028 11.6 7.44993C11.6 6.75976 11.0406 6.20024 10.3505 6.19993C10.3853 5.90487 10.4032 5.60464 10.4032 5.30023Z",
- )
-}
diff --git a/docs/src/highlight.ffi.mjs b/docs/src/highlight.ffi.mjs
deleted file mode 100644
index a67dfe2..0000000
--- a/docs/src/highlight.ffi.mjs
+++ /dev/null
@@ -1,151 +0,0 @@
-import "highlight.js/styles/github.css";
-
-let did_register_html = false;
-let did_register_js = false;
-let did_register_sh = false;
-let did_register_gleam = false;
-
-export async function highlight_element(el, lang) {
- if (el.classList.contains("hljs")) return;
-
- const { default: highlight } = await import("highlight.js/lib/core");
-
- switch (lang) {
- case !did_register_html && "html":
- const { default: html } = await import("highlight.js/lib/languages/xml");
- highlight.registerLanguage("html", html);
- did_register_html = true;
- break;
-
- case !did_register_js && "javascript":
- const { default: js } = await import(
- "highlight.js/lib/languages/javascript"
- );
- highlight.registerLanguage("javascript", js);
- did_register_js = true;
- break;
-
- case !did_register_sh && "shell":
- const { default: sh } = await import("highlight.js/lib/languages/shell");
- highlight.registerLanguage("sh", sh);
- highlight.registerLanguage("shell", sh);
- did_register_sh = true;
- break;
-
- case !did_register_gleam && "gleam":
- highlight.registerLanguage("gleam", gleam);
- did_register_gleam = true;
- break;
- }
-
- highlight.highlightElement(el);
-}
-
-function gleam(hljs) {
- const KEYWORDS =
- "as assert case const fn if import let panic use opaque pub todo type";
- const STRING = {
- className: "string",
- variants: [{ begin: /"/, end: /"/ }],
- contains: [hljs.BACKSLASH_ESCAPE],
- relevance: 0,
- };
- const NAME = {
- className: "variable",
- begin: "\\b[a-z][a-z0-9_]*\\b",
- relevance: 0,
- };
- const DISCARD_NAME = {
- className: "comment",
- begin: "\\b_[a-z][a-z0-9_]*\\b",
- relevance: 0,
- };
- const NUMBER = {
- className: "number",
- variants: [
- {
- // binary
- begin: "\\b0[bB](?:_?[01]+)+",
- },
- {
- // octal
- begin: "\\b0[oO](?:_?[0-7]+)+",
- },
- {
- // hex
- begin: "\\b0[xX](?:_?[0-9a-fA-F]+)+",
- },
- {
- // dec, float
- begin: "\\b\\d(?:_?\\d+)*(?:\\.(?:\\d(?:_?\\d+)*)*)?",
- },
- ],
- relevance: 0,
- };
-
- return {
- name: "Gleam",
- aliases: ["gleam"],
- contains: [
- hljs.C_LINE_COMMENT_MODE,
- STRING,
- {
- // bit string
- begin: "<<",
- end: ">>",
- contains: [
- {
- className: "keyword",
- beginKeywords:
- "binary bytes int float bit_string bits utf8 utf16 utf32 " +
- "utf8_codepoint utf16_codepoint utf32_codepoint signed unsigned " +
- "big little native unit size",
- },
- KEYWORDS,
- STRING,
- NAME,
- DISCARD_NAME,
- NUMBER,
- ],
- relevance: 10,
- },
- {
- className: "function",
- beginKeywords: "fn",
- end: "\\(",
- excludeEnd: true,
- contains: [
- {
- className: "title",
- begin: "[a-z][a-z0-9_]*\\w*",
- relevance: 0,
- },
- ],
- },
- {
- className: "attribute",
- begin: "@",
- end: "\\(",
- excludeEnd: true,
- },
- {
- className: "keyword",
- beginKeywords: KEYWORDS,
- },
- {
- // Type names and constructors
- className: "title",
- begin: "\\b[A-Z][A-Za-z0-9]*\\b",
- relevance: 0,
- },
- {
- className: "operator",
- begin: "[+\\-*/%!=<>&|.]+",
- relevance: 0,
- },
- NAME,
- DISCARD_NAME,
- NUMBER,
- ],
- };
-}
diff --git a/docs/src/markdown.ffi.mjs b/docs/src/markdown.ffi.mjs
deleted file mode 100644
index 168e3e5..0000000
--- a/docs/src/markdown.ffi.mjs
+++ /dev/null
@@ -1,164 +0,0 @@
-import { attribute } from "../lustre/lustre/attribute.mjs";
-import { element, text } from "../lustre/lustre/element.mjs";
-import { List, Empty, NonEmpty } from "./gleam.mjs";
-import { fromMarkdown } from "mdast-util-from-markdown";
-import { highlight_element } from "./highlight.ffi.mjs";
-import * as Markdown from "./app/ui/markdown.mjs";
-
-const empty = new Empty();
-const singleton = (val) => new NonEmpty(val, empty);
-const fold_into_list = (arr, f) =>
- arr.reduceRight((acc, val) => new NonEmpty(f(val), acc), empty);
-
-function compute_hash(str) {
- let hash = 0;
- for (let i = 0, len = str.length; i < len; i++) {
- let chr = str.charCodeAt(i);
- hash = (hash << 5) - hash + chr;
- hash |= 0; // Convert to 32bit integer
- }
- return `${~hash}`;
-}
-
-function linkify(el) {
- for (const [t, url] of Object.entries(links)) {
- el.innerHTML = el.innerHTML.replace(
- new RegExp(`\\b${t}\\b`, "g"),
- `<a href="${url}" class="hover:underline">${t}</a>`
- );
- }
-}
-
-const base = import.meta.env.BASE_URL;
-const stdlib = "https://hexdocs.pm/gleam_stdlib/gleam/";
-const links = {
- App: `${base}api/lustre#app-type`,
- Attribute: `${base}api/lustre/attribute#attribute-type`,
- Bool: `${stdlib}bool.html`,
- Decoder: `${stdlib}dynamic.html#Decoder`,
- Dynamic: `${stdlib}dynamic.html#Dynamic`,
- Effect: `${base}api/lustre/effect#effect-type`,
- Element: `${base}api/lustre/element#element-type`,
- Error: `${base}api/lustre#error-type`,
- Float: `${stdlib}float.html`,
- Int: `${stdlib}int.html`,
- List: `${stdlib}list.html`,
- Map: `${stdlib}map.html#Map`,
- Option: `${stdlib}option.html#Option`,
- Result: `${stdlib}result.html`,
- String: `${stdlib}string.html`,
- StringBuilder: `${stdlib}string_builder.html#StringBuilder`,
-};
-
-const cashe = new Map();
-
-export function parse_markdown(md) {
- window.requestAnimationFrame(() => {
- const selector = `[data-hash]:not(.hljs)`;
-
- for (const code of document.querySelectorAll(selector)) {
- highlight_element(code, code.dataset.lang).then(() => {
- linkify(code);
- });
- }
- });
-
- if (cashe.has(md)) return cashe.get(md);
-
- const ast = fromMarkdown(md);
- const summary = [];
- const content = fold_into_list(
- ast.children,
- function to_lustre_element(node) {
- switch (node.type) {
- case "code":
- return Markdown.code(node.value, compute_hash(node.value), node.lang);
-
- case "emphasis":
- return Markdown.emphasis(
- fold_into_list(node.children, to_lustre_element)
- );
-
- case "heading": {
- const [title, rest] = node.children[0].value.split("|");
- const tags = List.fromArray(rest ? rest.trim().split(" ") : []);
- const id =
- /^[A-Z]/.test(title.trim()) &&
- node.depth === 3 &&
- window.location.pathname.includes("/api/")
- ? `${title
- .toLowerCase()
- .trim()
- .replace(/\s/g, "-")
- .replace(/[^a-zA-Z0-9-_]/g, "")}-type`
- : `${title
- .toLowerCase()
- .trim()
- .replace(/\s/g, "-")
- .replace(/[^a-zA-Z0-9-_]/g, "")}`;
-
- if (node.depth > 1) {
- summary.unshift(
- element(
- "a",
- List.fromArray([
- attribute("href", `#${id}`),
- attribute("class", "text-sm text-gray-400 no-underline"),
- attribute("class", "hover:text-gray-700 hover:underline"),
- attribute(
- "class",
- node.depth === 2 ? `mt-4 first:mt-0` : `ml-2`
- ),
- ]),
- singleton(text(title.trim()))
- )
- );
- }
-
- return Markdown.heading(node.depth, title.trim(), tags, id);
- }
-
- case "inlineCode":
- return Markdown.inline_code(node.value);
-
- case "link":
- return Markdown.link(
- node.url.startsWith("/")
- ? import.meta.env.BASE_URL + node.url.slice(1)
- : node.url,
- fold_into_list(node.children, to_lustre_element)
- );
-
- case "list":
- return Markdown.list(
- !!node.ordered,
- fold_into_list(node.children, to_lustre_element)
- );
-
- case "listItem":
- return Markdown.list_item(
- fold_into_list(node.children, to_lustre_element)
- );
-
- case "paragraph":
- return Markdown.paragraph(
- fold_into_list(node.children, to_lustre_element)
- );
-
- case "strong":
- return Markdown.strong(
- fold_into_list(node.children, to_lustre_element)
- );
-
- case "text":
- return Markdown.text(node.value);
-
- default:
- return Markdown.text("");
- }
- }
- );
-
- cashe.set(md, [content, List.fromArray(summary)]);
- return [content, List.fromArray(summary)];
-}
diff --git a/docs/tailwind.config.js b/docs/tailwind.config.js
deleted file mode 100644
index 2f45b89..0000000
--- a/docs/tailwind.config.js
+++ /dev/null
@@ -1,20 +0,0 @@
-export default {
- content: ["./index.html", "./src/**/*.{mjs,gleam}"],
- theme: {
- extend: {
- fontFamily: {
- serif: ["Fraunces", "serif"],
- sans: ["Inter", "sans-serif"],
- },
- typography: (theme) => ({
- lustre: {
- css: {
- "--tw-prose-pre-code": "var(--tw-prose-body)",
- "--tw-prose-pre-bg": theme("colors.gray[50]"),
- },
- },
- }),
- },
- },
- plugins: [require("@tailwindcss/typography")],
-};
diff --git a/docs/vite.config.js b/docs/vite.config.js
deleted file mode 100644
index bf6cad8..0000000
--- a/docs/vite.config.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import { defineConfig } from "vite";
-import { ghPages } from "vite-plugin-gh-pages";
-import { resolve } from "path";
-import gleam from "vite-gleam";
-import { execSync } from "child_process";
-
-const moveForDeployment = {
- name: "vite-plugin-move-for-deployment",
- apply: "build",
- closeBundle() {
- const temp = resolve(__dirname, ".temp");
- const dist = resolve(__dirname, "dist");
-
- execSync(`mkdir ${temp}`);
- execSync(`mv ${dist}/* ${temp}`);
- execSync(`rm -rf ${dist}`);
- execSync(`mkdir ${dist} && mkdir ${dist}/lustre`);
- execSync(`mv ${temp}/* ${dist}/lustre`);
- execSync(`rm -rf ${temp}`);
- execSync(`mv ${dist}/lustre/404.html ${dist}/404.html`);
- execSync(`mv ${dist}/lustre/CNAME ${dist}/CNAME`);
- },
-};
-
-export default defineConfig(({ command }) => ({
- base: command === "build" ? "/lustre/" : "/",
- server: {
- host: "0.0.0.0",
- },
- plugins: [
- gleam(),
- command === "build" && moveForDeployment,
- ghPages({
- branch: "docs",
- message: "🚀 Deploy to gh-pages.",
- }),
- ],
- build: {
- outDir: "dist",
- emptyOutDir: true,
- rollupOptions: {
- input: {
- main: resolve(__dirname, "index.html"),
- 404: resolve(__dirname, "404.html"),
- },
- },
- },
-}));
diff --git a/lib/gleam.toml b/gleam.toml
index f301d46..f301d46 100644
--- a/lib/gleam.toml
+++ b/gleam.toml
diff --git a/lib/manifest.toml b/manifest.toml
index b711276..b711276 100644
--- a/lib/manifest.toml
+++ b/manifest.toml
diff --git a/lib/package-lock.json b/package-lock.json
index 7a63f7a..7a63f7a 100644
--- a/lib/package-lock.json
+++ b/package-lock.json
diff --git a/lib/package.json b/package.json
index fdc091a..fdc091a 100644
--- a/lib/package.json
+++ b/package.json
diff --git a/lib/src/lustre.ffi.mjs b/src/lustre.ffi.mjs
index f29e7ea..f29e7ea 100644
--- a/lib/src/lustre.ffi.mjs
+++ b/src/lustre.ffi.mjs
diff --git a/lib/src/lustre.gleam b/src/lustre.gleam
index 4f8249a..4f8249a 100644
--- a/lib/src/lustre.gleam
+++ b/src/lustre.gleam
diff --git a/lib/src/lustre/attribute.gleam b/src/lustre/attribute.gleam
index 0c79692..0c79692 100644
--- a/lib/src/lustre/attribute.gleam
+++ b/src/lustre/attribute.gleam
diff --git a/lib/src/lustre/effect.gleam b/src/lustre/effect.gleam
index 964ddd2..964ddd2 100644
--- a/lib/src/lustre/effect.gleam
+++ b/src/lustre/effect.gleam
diff --git a/lib/src/lustre/element.gleam b/src/lustre/element.gleam
index 4608db7..4608db7 100644
--- a/lib/src/lustre/element.gleam
+++ b/src/lustre/element.gleam
diff --git a/lib/src/lustre/element/html.gleam b/src/lustre/element/html.gleam
index a69a5fd..a69a5fd 100644
--- a/lib/src/lustre/element/html.gleam
+++ b/src/lustre/element/html.gleam
diff --git a/lib/src/lustre/element/svg.gleam b/src/lustre/element/svg.gleam
index a1fc0ce..a1fc0ce 100644
--- a/lib/src/lustre/element/svg.gleam
+++ b/src/lustre/element/svg.gleam
diff --git a/lib/src/lustre/event.gleam b/src/lustre/event.gleam
index 7913ef5..7913ef5 100644
--- a/lib/src/lustre/event.gleam
+++ b/src/lustre/event.gleam
diff --git a/lib/src/runtime.ffi.mjs b/src/runtime.ffi.mjs
index dd02f8b..dd02f8b 100644
--- a/lib/src/runtime.ffi.mjs
+++ b/src/runtime.ffi.mjs
diff --git a/lib/test/examples/components.gleam b/test/examples/components.gleam
index b87cf84..b87cf84 100644
--- a/lib/test/examples/components.gleam
+++ b/test/examples/components.gleam
diff --git a/lib/test/examples/components.html b/test/examples/components.html
index f4b4530..f4b4530 100644
--- a/lib/test/examples/components.html
+++ b/test/examples/components.html
diff --git a/lib/test/examples/counter.gleam b/test/examples/counter.gleam
index 4faf00c..4faf00c 100644
--- a/lib/test/examples/counter.gleam
+++ b/test/examples/counter.gleam
diff --git a/lib/test/examples/counter.html b/test/examples/counter.html
index 2b120fd..2b120fd 100644
--- a/lib/test/examples/counter.html
+++ b/test/examples/counter.html
diff --git a/lib/test/examples/index.html b/test/examples/index.html
index 70d4196..70d4196 100644
--- a/lib/test/examples/index.html
+++ b/test/examples/index.html
diff --git a/lib/test/examples/input.gleam b/test/examples/input.gleam
index ff4d794..ff4d794 100644
--- a/lib/test/examples/input.gleam
+++ b/test/examples/input.gleam
diff --git a/lib/test/examples/input.html b/test/examples/input.html
index 3bd6463..3bd6463 100644
--- a/lib/test/examples/input.html
+++ b/test/examples/input.html
diff --git a/lib/test/examples/nested.gleam b/test/examples/nested.gleam
index 91c2da4..91c2da4 100644
--- a/lib/test/examples/nested.gleam
+++ b/test/examples/nested.gleam
diff --git a/lib/test/examples/nested.html b/test/examples/nested.html
index 420b159..420b159 100644
--- a/lib/test/examples/nested.html
+++ b/test/examples/nested.html
diff --git a/lib/test/examples/svg.gleam b/test/examples/svg.gleam
index e895f1a..e895f1a 100644
--- a/lib/test/examples/svg.gleam
+++ b/test/examples/svg.gleam
diff --git a/lib/test/examples/svg.html b/test/examples/svg.html
index 12af526..12af526 100644
--- a/lib/test/examples/svg.html
+++ b/test/examples/svg.html