`):
+ *
+ * ```javascript
+ * var hljs = require('highlight.js') // https://highlightjs.org/
+ *
+ * // Actual default values
+ * var md = require('markdown-it')({
+ * highlight: function (str, lang) {
+ * if (lang && hljs.getLanguage(lang)) {
+ * try {
+ * return '' +
+ * hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
+ * '
';
+ * } catch (__) {}
+ * }
+ *
+ * return '' + md.utils.escapeHtml(str) + '
';
+ * }
+ * });
+ * ```
+ *
+ **/ function MarkdownIt(presetName, options) {
+ if (!(this instanceof MarkdownIt)) {
+ return new MarkdownIt(presetName, options);
+ }
+ if (!options) {
+ if (!utils.isString(presetName)) {
+ options = presetName || {};
+ presetName = "default";
+ }
+ }
+ /**
+ * MarkdownIt#inline -> ParserInline
+ *
+ * Instance of [[ParserInline]]. You may need it to add new rules when
+ * writing plugins. For simple rules control use [[MarkdownIt.disable]] and
+ * [[MarkdownIt.enable]].
+ **/ this.inline = new parser_inline;
+ /**
+ * MarkdownIt#block -> ParserBlock
+ *
+ * Instance of [[ParserBlock]]. You may need it to add new rules when
+ * writing plugins. For simple rules control use [[MarkdownIt.disable]] and
+ * [[MarkdownIt.enable]].
+ **/ this.block = new parser_block;
+ /**
+ * MarkdownIt#core -> Core
+ *
+ * Instance of [[Core]] chain executor. You may need it to add new rules when
+ * writing plugins. For simple rules control use [[MarkdownIt.disable]] and
+ * [[MarkdownIt.enable]].
+ **/ this.core = new parser_core;
+ /**
+ * MarkdownIt#renderer -> Renderer
+ *
+ * Instance of [[Renderer]]. Use it to modify output look. Or to add rendering
+ * rules for new token types, generated by plugins.
+ *
+ * ##### Example
+ *
+ * ```javascript
+ * var md = require('markdown-it')();
+ *
+ * function myToken(tokens, idx, options, env, self) {
+ * //...
+ * return result;
+ * };
+ *
+ * md.renderer.rules['my_token'] = myToken
+ * ```
+ *
+ * See [[Renderer]] docs and [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js).
+ **/ this.renderer = new renderer;
+ /**
+ * MarkdownIt#linkify -> LinkifyIt
+ *
+ * [linkify-it](https://github.com/markdown-it/linkify-it) instance.
+ * Used by [linkify](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/linkify.js)
+ * rule.
+ **/ this.linkify = new linkifyIt;
+ /**
+ * MarkdownIt#validateLink(url) -> Boolean
+ *
+ * Link validation function. CommonMark allows too much in links. By default
+ * we disable `javascript:`, `vbscript:`, `file:` schemas, and almost all `data:...` schemas
+ * except some embedded image types.
+ *
+ * You can change this behaviour:
+ *
+ * ```javascript
+ * var md = require('markdown-it')();
+ * // enable everything
+ * md.validateLink = function () { return true; }
+ * ```
+ **/ this.validateLink = validateLink;
+ /**
+ * MarkdownIt#normalizeLink(url) -> String
+ *
+ * Function used to encode link url to a machine-readable format,
+ * which includes url-encoding, punycode, etc.
+ **/ this.normalizeLink = normalizeLink;
+ /**
+ * MarkdownIt#normalizeLinkText(url) -> String
+ *
+ * Function used to decode link url to a human-readable format`
+ **/ this.normalizeLinkText = normalizeLinkText;
+ // Expose utils & helpers for easy acces from plugins
+ /**
+ * MarkdownIt#utils -> utils
+ *
+ * Assorted utility functions, useful to write plugins. See details
+ * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/common/utils.js).
+ **/ this.utils = utils;
+ /**
+ * MarkdownIt#helpers -> helpers
+ *
+ * Link components parser functions, useful to write plugins. See details
+ * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/helpers).
+ **/ this.helpers = utils.assign({}, helpers);
+ this.options = {};
+ this.configure(presetName);
+ if (options) {
+ this.set(options);
+ }
+ }
+ /** chainable
+ * MarkdownIt.set(options)
+ *
+ * Set parser options (in the same format as in constructor). Probably, you
+ * will never need it, but you can change options after constructor call.
+ *
+ * ##### Example
+ *
+ * ```javascript
+ * var md = require('markdown-it')()
+ * .set({ html: true, breaks: true })
+ * .set({ typographer, true });
+ * ```
+ *
+ * __Note:__ To achieve the best possible performance, don't modify a
+ * `markdown-it` instance options on the fly. If you need multiple configurations
+ * it's best to create multiple instances and initialize each with separate
+ * config.
+ **/ MarkdownIt.prototype.set = function(options) {
+ utils.assign(this.options, options);
+ return this;
+ };
+ /** chainable, internal
+ * MarkdownIt.configure(presets)
+ *
+ * Batch load of all options and compenent settings. This is internal method,
+ * and you probably will not need it. But if you will - see available presets
+ * and data structure [here](https://github.com/markdown-it/markdown-it/tree/master/lib/presets)
+ *
+ * We strongly recommend to use presets instead of direct config loads. That
+ * will give better compatibility with next versions.
+ **/ MarkdownIt.prototype.configure = function(presets) {
+ var self = this, presetName;
+ if (utils.isString(presets)) {
+ presetName = presets;
+ presets = config[presetName];
+ if (!presets) {
+ throw new Error('Wrong `markdown-it` preset "' + presetName + '", check name');
+ }
+ }
+ if (!presets) {
+ throw new Error("Wrong `markdown-it` preset, can't be empty");
+ }
+ if (presets.options) {
+ self.set(presets.options);
+ }
+ if (presets.components) {
+ Object.keys(presets.components).forEach((function(name) {
+ if (presets.components[name].rules) {
+ self[name].ruler.enableOnly(presets.components[name].rules);
+ }
+ if (presets.components[name].rules2) {
+ self[name].ruler2.enableOnly(presets.components[name].rules2);
+ }
+ }));
+ }
+ return this;
+ };
+ /** chainable
+ * MarkdownIt.enable(list, ignoreInvalid)
+ * - list (String|Array): rule name or list of rule names to enable
+ * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
+ *
+ * Enable list or rules. It will automatically find appropriate components,
+ * containing rules with given names. If rule not found, and `ignoreInvalid`
+ * not set - throws exception.
+ *
+ * ##### Example
+ *
+ * ```javascript
+ * var md = require('markdown-it')()
+ * .enable(['sub', 'sup'])
+ * .disable('smartquotes');
+ * ```
+ **/ MarkdownIt.prototype.enable = function(list, ignoreInvalid) {
+ var result = [];
+ if (!Array.isArray(list)) {
+ list = [ list ];
+ }
+ [ "core", "block", "inline" ].forEach((function(chain) {
+ result = result.concat(this[chain].ruler.enable(list, true));
+ }), this);
+ result = result.concat(this.inline.ruler2.enable(list, true));
+ var missed = list.filter((function(name) {
+ return result.indexOf(name) < 0;
+ }));
+ if (missed.length && !ignoreInvalid) {
+ throw new Error("MarkdownIt. Failed to enable unknown rule(s): " + missed);
+ }
+ return this;
+ };
+ /** chainable
+ * MarkdownIt.disable(list, ignoreInvalid)
+ * - list (String|Array): rule name or list of rule names to disable.
+ * - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
+ *
+ * The same as [[MarkdownIt.enable]], but turn specified rules off.
+ **/ MarkdownIt.prototype.disable = function(list, ignoreInvalid) {
+ var result = [];
+ if (!Array.isArray(list)) {
+ list = [ list ];
+ }
+ [ "core", "block", "inline" ].forEach((function(chain) {
+ result = result.concat(this[chain].ruler.disable(list, true));
+ }), this);
+ result = result.concat(this.inline.ruler2.disable(list, true));
+ var missed = list.filter((function(name) {
+ return result.indexOf(name) < 0;
+ }));
+ if (missed.length && !ignoreInvalid) {
+ throw new Error("MarkdownIt. Failed to disable unknown rule(s): " + missed);
+ }
+ return this;
+ };
+ /** chainable
+ * MarkdownIt.use(plugin, params)
+ *
+ * Load specified plugin with given params into current parser instance.
+ * It's just a sugar to call `plugin(md, params)` with curring.
+ *
+ * ##### Example
+ *
+ * ```javascript
+ * var iterator = require('markdown-it-for-inline');
+ * var md = require('markdown-it')()
+ * .use(iterator, 'foo_replace', 'text', function (tokens, idx) {
+ * tokens[idx].content = tokens[idx].content.replace(/foo/g, 'bar');
+ * });
+ * ```
+ **/ MarkdownIt.prototype.use = function(plugin /*, params, ... */) {
+ var args = [ this ].concat(Array.prototype.slice.call(arguments, 1));
+ plugin.apply(plugin, args);
+ return this;
+ };
+ /** internal
+ * MarkdownIt.parse(src, env) -> Array
+ * - src (String): source string
+ * - env (Object): environment sandbox
+ *
+ * Parse input string and return list of block tokens (special token type
+ * "inline" will contain list of inline tokens). You should not call this
+ * method directly, until you write custom renderer (for example, to produce
+ * AST).
+ *
+ * `env` is used to pass data between "distributed" rules and return additional
+ * metadata like reference info, needed for the renderer. It also can be used to
+ * inject data in specific cases. Usually, you will be ok to pass `{}`,
+ * and then pass updated object to renderer.
+ **/ MarkdownIt.prototype.parse = function(src, env) {
+ if (typeof src !== "string") {
+ throw new Error("Input data should be a String");
+ }
+ var state = new this.core.State(src, this, env);
+ this.core.process(state);
+ return state.tokens;
+ };
+ /**
+ * MarkdownIt.render(src [, env]) -> String
+ * - src (String): source string
+ * - env (Object): environment sandbox
+ *
+ * Render markdown string into html. It does all magic for you :).
+ *
+ * `env` can be used to inject additional metadata (`{}` by default).
+ * But you will not need it with high probability. See also comment
+ * in [[MarkdownIt.parse]].
+ **/ MarkdownIt.prototype.render = function(src, env) {
+ env = env || {};
+ return this.renderer.render(this.parse(src, env), this.options, env);
+ };
+ /** internal
+ * MarkdownIt.parseInline(src, env) -> Array
+ * - src (String): source string
+ * - env (Object): environment sandbox
+ *
+ * The same as [[MarkdownIt.parse]] but skip all block rules. It returns the
+ * block tokens list with the single `inline` element, containing parsed inline
+ * tokens in `children` property. Also updates `env` object.
+ **/ MarkdownIt.prototype.parseInline = function(src, env) {
+ var state = new this.core.State(src, this, env);
+ state.inlineMode = true;
+ this.core.process(state);
+ return state.tokens;
+ };
+ /**
+ * MarkdownIt.renderInline(src [, env]) -> String
+ * - src (String): source string
+ * - env (Object): environment sandbox
+ *
+ * Similar to [[MarkdownIt.render]] but for single paragraph content. Result
+ * will NOT be wrapped into `` tags.
+ **/ MarkdownIt.prototype.renderInline = function(src, env) {
+ env = env || {};
+ return this.renderer.render(this.parseInline(src, env), this.options, env);
+ };
+ var lib = MarkdownIt;
+ var markdownIt = lib;
+ return markdownIt;
+}));
diff --git a/src/interface/desktop/assets/org.min.js b/src/interface/desktop/assets/org.min.js
new file mode 100644
index 00000000..a919b280
--- /dev/null
+++ b/src/interface/desktop/assets/org.min.js
@@ -0,0 +1,1823 @@
+// Generated by export.rb at Sat Feb 21 07:44:29 UTC 2015
+/*
+ Copyright (c) 2014 Masafumi Oyamada
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+var Org = (function () {
+ var exports = {};
+
+ // ------------------------------------------------------------
+ // Syntax
+ // ------------------------------------------------------------
+
+ var Syntax = {
+ rules: {},
+
+ define: function (name, syntax) {
+ this.rules[name] = syntax;
+ var methodName = "is" + name.substring(0, 1).toUpperCase() + name.substring(1);
+ this[methodName] = function (line) {
+ return this.rules[name].exec(line);
+ };
+ }
+ };
+
+ Syntax.define("header", /^(\*+)\s+(.*)$/); // m[1] => level, m[2] => content
+ Syntax.define("preformatted", /^(\s*):(?: (.*)$|$)/); // m[1] => indentation, m[2] => content
+ Syntax.define("unorderedListElement", /^(\s*)(?:-|\+|\s+\*)\s+(.*)$/); // m[1] => indentation, m[2] => content
+ Syntax.define("orderedListElement", /^(\s*)(\d+)(?:\.|\))\s+(.*)$/); // m[1] => indentation, m[2] => number, m[3] => content
+ Syntax.define("tableSeparator", /^(\s*)\|((?:\+|-)*?)\|?$/); // m[1] => indentation, m[2] => content
+ Syntax.define("tableRow", /^(\s*)\|(.*?)\|?$/); // m[1] => indentation, m[2] => content
+ Syntax.define("blank", /^$/);
+ Syntax.define("horizontalRule", /^(\s*)-{5,}$/); //
+ Syntax.define("directive", /^(\s*)#\+(?:(begin|end)_)?(.*)$/i); // m[1] => indentation, m[2] => type, m[3] => content
+ Syntax.define("comment", /^(\s*)#(.*)$/);
+ Syntax.define("line", /^(\s*)(.*)$/);
+
+ const propertyDrawer = /:PROPERTIES:(.*):END:/g;
+
+ // ------------------------------------------------------------
+ // Token
+ // ------------------------------------------------------------
+
+ function Token() {
+ }
+
+ Token.prototype = {
+ isListElement: function () {
+ return this.type === Lexer.tokens.orderedListElement ||
+ this.type === Lexer.tokens.unorderedListElement;
+ },
+
+ isTableElement: function () {
+ return this.type === Lexer.tokens.tableSeparator ||
+ this.type === Lexer.tokens.tableRow;
+ }
+ };
+
+ // ------------------------------------------------------------
+ // Lexer
+ // ------------------------------------------------------------
+
+ function Lexer(stream) {
+ this.stream = stream;
+ this.tokenStack = [];
+ }
+
+ Lexer.prototype = {
+ tokenize: function (line) {
+ var token = new Token();
+ token.fromLineNumber = this.stream.lineNumber;
+
+ if (Syntax.isHeader(line)) {
+ token.type = Lexer.tokens.header;
+ token.indentation = 0;
+ token.content = RegExp.$2;
+ // specific
+ token.level = 2;
+ } else if (Syntax.isPreformatted(line)) {
+ token.type = Lexer.tokens.preformatted;
+ token.indentation = RegExp.$1.length;
+ token.content = RegExp.$2;
+ } else if (Syntax.isUnorderedListElement(line)) {
+ token.type = Lexer.tokens.unorderedListElement;
+ token.indentation = RegExp.$1.length;
+ token.content = RegExp.$2;
+ } else if (Syntax.isOrderedListElement(line)) {
+ token.type = Lexer.tokens.orderedListElement;
+ token.indentation = RegExp.$1.length;
+ token.content = RegExp.$3;
+ // specific
+ token.number = RegExp.$2;
+ } else if (Syntax.isTableSeparator(line)) {
+ token.type = Lexer.tokens.tableSeparator;
+ token.indentation = RegExp.$1.length;
+ token.content = RegExp.$2;
+ } else if (Syntax.isTableRow(line)) {
+ token.type = Lexer.tokens.tableRow;
+ token.indentation = RegExp.$1.length;
+ token.content = RegExp.$2;
+ } else if (Syntax.isBlank(line)) {
+ token.type = Lexer.tokens.blank;
+ token.indentation = 0;
+ token.content = null;
+ } else if (Syntax.isHorizontalRule(line)) {
+ token.type = Lexer.tokens.horizontalRule;
+ token.indentation = RegExp.$1.length;
+ token.content = null;
+ } else if (Syntax.isDirective(line)) {
+ token.type = Lexer.tokens.directive;
+ token.indentation = RegExp.$1.length;
+ token.content = RegExp.$3;
+ // decide directive type (begin, end or oneshot)
+ var directiveTypeString = RegExp.$2;
+ if (/^begin/i.test(directiveTypeString))
+ token.beginDirective = true;
+ else if (/^end/i.test(directiveTypeString))
+ token.endDirective = true;
+ else
+ token.oneshotDirective = true;
+ } else if (Syntax.isComment(line)) {
+ token.type = Lexer.tokens.comment;
+ token.indentation = RegExp.$1.length;
+ token.content = RegExp.$2;
+ } else if (Syntax.isLine(line)) {
+ token.type = Lexer.tokens.line;
+ token.indentation = RegExp.$1.length;
+ token.content = RegExp.$2;
+ } else {
+ throw new Error("SyntaxError: Unknown line: " + line);
+ }
+
+ return token;
+ },
+
+ pushToken: function (token) {
+ this.tokenStack.push(token);
+ },
+
+ pushDummyTokenByType: function (type) {
+ var token = new Token();
+ token.type = type;
+ this.tokenStack.push(token);
+ },
+
+ peekStackedToken: function () {
+ return this.tokenStack.length > 0 ?
+ this.tokenStack[this.tokenStack.length - 1] : null;
+ },
+
+ getStackedToken: function () {
+ return this.tokenStack.length > 0 ?
+ this.tokenStack.pop() : null;
+ },
+
+ peekNextToken: function () {
+ return this.peekStackedToken() ||
+ this.tokenize(this.stream.peekNextLine());
+ },
+
+ getNextToken: function () {
+ return this.getStackedToken() ||
+ this.tokenize(this.stream.getNextLine());
+ },
+
+ hasNext: function () {
+ return this.stream.hasNext();
+ },
+
+ getLineNumber: function () {
+ return this.stream.lineNumber;
+ }
+ };
+
+ Lexer.tokens = {};
+ [
+ "header",
+ "orderedListElement",
+ "unorderedListElement",
+ "tableRow",
+ "tableSeparator",
+ "preformatted",
+ "line",
+ "horizontalRule",
+ "blank",
+ "directive",
+ "comment"
+ ].forEach(function (tokenName, i) {
+ Lexer.tokens[tokenName] = i;
+ });
+
+ // ------------------------------------------------------------
+ // Exports
+ // ------------------------------------------------------------
+
+ if (typeof exports !== "undefined")
+ exports.Lexer = Lexer;
+
+ function PrototypeNode(type, children) {
+ this.type = type;
+ this.children = [];
+
+ if (children) {
+ for (var i = 0, len = children.length; i < len; ++i) {
+ this.appendChild(children[i]);
+ }
+ }
+ }
+ PrototypeNode.prototype = {
+ previousSibling: null,
+ parent: null,
+ get firstChild() {
+ return this.children.length < 1 ?
+ null : this.children[0];
+ },
+ get lastChild() {
+ return this.children.length < 1 ?
+ null : this.children[this.children.length - 1];
+ },
+ appendChild: function (newChild) {
+ var previousSibling = this.children.length < 1 ?
+ null : this.lastChild;
+ this.children.push(newChild);
+ newChild.previousSibling = previousSibling;
+ newChild.parent = this;
+ },
+ toString: function () {
+ var string = "<" + this.type + ">";
+
+ if (typeof this.value !== "undefined") {
+ string += " " + this.value;
+ } else if (this.children) {
+ string += "\n" + this.children.map(function (child, idx) {
+ return "#" + idx + " " + child.toString();
+ }).join("\n").split("\n").map(function (line) {
+ return " " + line;
+ }).join("\n");
+ }
+
+ return string;
+ }
+ };
+
+ var Node = {
+ types: {},
+
+ define: function (name, postProcess) {
+ this.types[name] = name;
+
+ var methodName = "create" + name.substring(0, 1).toUpperCase() + name.substring(1);
+ var postProcessGiven = typeof postProcess === "function";
+
+ this[methodName] = function (children, options) {
+ var node = new PrototypeNode(name, children);
+
+ if (postProcessGiven)
+ postProcess(node, options || {});
+
+ return node;
+ };
+ }
+ };
+
+ Node.define("text", function (node, options) {
+ node.value = options.value;
+ });
+ Node.define("header", function (node, options) {
+ node.level = options.level;
+ });
+ Node.define("orderedList");
+ Node.define("unorderedList");
+ Node.define("definitionList");
+ Node.define("listElement");
+ Node.define("paragraph");
+ Node.define("preformatted");
+ Node.define("table");
+ Node.define("tableRow");
+ Node.define("tableCell");
+ Node.define("horizontalRule");
+ Node.define("directive");
+
+ // Inline
+ Node.define("inlineContainer");
+
+ Node.define("bold");
+ Node.define("italic");
+ Node.define("underline");
+ Node.define("code");
+ Node.define("verbatim");
+ Node.define("dashed");
+ Node.define("link", function (node, options) {
+ node.src = options.src;
+ });
+
+ if (typeof exports !== "undefined")
+ exports.Node = Node;
+
+ function Stream(sequence) {
+ this.sequences = sequence.split(/\r?\n/);
+ this.totalLines = this.sequences.length;
+ this.lineNumber = 0;
+ }
+
+ Stream.prototype.peekNextLine = function () {
+ return this.hasNext() ? this.sequences[this.lineNumber] : null;
+ };
+
+ Stream.prototype.getNextLine = function () {
+ return this.hasNext() ? this.sequences[this.lineNumber++] : null;
+ };
+
+ Stream.prototype.hasNext = function () {
+ return this.lineNumber < this.totalLines;
+ };
+
+ if (typeof exports !== "undefined") {
+ exports.Stream = Stream;
+ }
+
+ // var Stream = require("./stream.js").Stream;
+ // var Lexer = require("./lexer.js").Lexer;
+ // var Node = require("./node.js").Node;
+
+ function Parser() {
+ this.inlineParser = new InlineParser();
+ }
+
+ Parser.parseStream = function (stream, options) {
+ var parser = new Parser();
+ parser.initStatus(stream, options);
+ parser.parseNodes();
+ return parser.nodes;
+ };
+
+ Parser.prototype = {
+ initStatus: function (stream, options) {
+ if (typeof stream === "string")
+ stream = new Stream(stream);
+ this.lexer = new Lexer(stream);
+ this.nodes = [];
+ this.options = {
+ toc: true,
+ num: true,
+ "^": "{}",
+ multilineCell: false
+ };
+ // Override option values
+ if (options && typeof options === "object") {
+ for (var key in options) {
+ this.options[key] = options[key];
+ }
+ }
+ this.document = {
+ options: this.options,
+ directiveValues: {},
+ convert: function (ConverterClass, exportOptions) {
+ var converter = new ConverterClass(this, exportOptions);
+ return converter.result;
+ }
+ };
+ },
+
+ parse: function (stream, options) {
+ this.initStatus(stream, options);
+ this.parseDocument();
+ this.document.nodes = this.nodes;
+ return this.document;
+ },
+
+ createErrorReport: function (message) {
+ return new Error(message + " at line " + this.lexer.getLineNumber());
+ },
+
+ skipBlank: function () {
+ var blankToken = null;
+ while (this.lexer.peekNextToken().type === Lexer.tokens.blank)
+ blankToken = this.lexer.getNextToken();
+ return blankToken;
+ },
+
+ setNodeOriginFromToken: function (node, token) {
+ node.fromLineNumber = token.fromLineNumber;
+ return node;
+ },
+
+ appendNode: function (newNode) {
+ var previousSibling = this.nodes.length > 0 ? this.nodes[this.nodes.length - 1] : null;
+ this.nodes.push(newNode);
+ newNode.previousSibling = previousSibling;
+ },
+
+ // ------------------------------------------------------------
+ // ::= *
+ // ------------------------------------------------------------
+
+ parseDocument: function () {
+ this.parseTitle();
+ this.parseNodes();
+ },
+
+ parseNodes: function () {
+ while (this.lexer.hasNext()) {
+ var element = this.parseElement();
+ if (element) this.appendNode(element);
+ }
+ },
+
+ parseTitle: function () {
+ this.skipBlank();
+
+ if (this.lexer.hasNext() &&
+ this.lexer.peekNextToken().type === Lexer.tokens.line)
+ this.document.title = this.createTextNode(this.lexer.getNextToken().content);
+ else
+ this.document.title = null;
+
+ this.lexer.pushDummyTokenByType(Lexer.tokens.blank);
+ },
+
+ // ------------------------------------------------------------
+ // ::= ( |
+ // | |
+ // | )*
+ // ------------------------------------------------------------
+
+ parseElement: function () {
+ var element = null;
+
+ switch (this.lexer.peekNextToken().type) {
+ case Lexer.tokens.header:
+ element = this.parseHeader();
+ break;
+ case Lexer.tokens.preformatted:
+ element = this.parsePreformatted();
+ break;
+ case Lexer.tokens.orderedListElement:
+ case Lexer.tokens.unorderedListElement:
+ element = this.parseList();
+ break;
+ case Lexer.tokens.line:
+ element = this.parseText();
+ break;
+ case Lexer.tokens.tableRow:
+ case Lexer.tokens.tableSeparator:
+ element = this.parseTable();
+ break;
+ case Lexer.tokens.blank:
+ this.skipBlank();
+ if (this.lexer.hasNext()) {
+ if (this.lexer.peekNextToken().type === Lexer.tokens.line)
+ element = this.parseParagraph();
+ else
+ element = this.parseElement();
+ }
+ break;
+ case Lexer.tokens.horizontalRule:
+ this.lexer.getNextToken();
+ element = Node.createHorizontalRule();
+ break;
+ case Lexer.tokens.directive:
+ element = this.parseDirective();
+ break;
+ case Lexer.tokens.comment:
+ // Skip
+ this.lexer.getNextToken();
+ break;
+ default:
+ throw this.createErrorReport("Unhandled token: " + this.lexer.peekNextToken().type);
+ }
+
+ return element;
+ },
+
+ parseElementBesidesDirectiveEnd: function () {
+ try {
+ // Temporary, override the definition of `parseElement`
+ this.parseElement = this.parseElementBesidesDirectiveEndBody;
+ return this.parseElement();
+ } finally {
+ this.parseElement = this.originalParseElement;
+ }
+ },
+
+ parseElementBesidesDirectiveEndBody: function () {
+ if (this.lexer.peekNextToken().type === Lexer.tokens.directive &&
+ this.lexer.peekNextToken().endDirective) {
+ return null;
+ }
+
+ return this.originalParseElement();
+ },
+
+ // ------------------------------------------------------------
+ //
+ //
+ // : preformatted
+ // : block
+ // ------------------------------------------------------------
+
+ parseHeader: function () {
+ var headerToken = this.lexer.getNextToken();
+ var header = Node.createHeader([
+ this.createTextNode(headerToken.content) // TODO: Parse inline markups
+ ], { level: headerToken.level });
+ this.setNodeOriginFromToken(header, headerToken);
+
+ return header;
+ },
+
+ // ------------------------------------------------------------
+ //
+ //
+ // : preformatted
+ // : block
+ // ------------------------------------------------------------
+
+ parsePreformatted: function () {
+ var preformattedFirstToken = this.lexer.peekNextToken();
+ var preformatted = Node.createPreformatted([]);
+ this.setNodeOriginFromToken(preformatted, preformattedFirstToken);
+
+ var textContents = [];
+
+ while (this.lexer.hasNext()) {
+ var token = this.lexer.peekNextToken();
+ if (token.type !== Lexer.tokens.preformatted ||
+ token.indentation < preformattedFirstToken.indentation)
+ break;
+ this.lexer.getNextToken();
+ textContents.push(token.content);
+ }
+
+ preformatted.appendChild(this.createTextNode(textContents.join("\n"), true /* no emphasis */));
+
+ return preformatted;
+ },
+
+ // ------------------------------------------------------------
+ //
+ //
+ // - foo
+ // 1. bar
+ // 2. baz
+ // ------------------------------------------------------------
+
+ // XXX: not consider codes (e.g., =Foo::Bar=)
+ definitionPattern: /^(.*?) :: *(.*)$/,
+
+ parseList: function () {
+ var rootToken = this.lexer.peekNextToken();
+ var list;
+ var isDefinitionList = false;
+
+ if (this.definitionPattern.test(rootToken.content)) {
+ list = Node.createDefinitionList([]);
+ isDefinitionList = true;
+ } else {
+ list = rootToken.type === Lexer.tokens.unorderedListElement ?
+ Node.createUnorderedList([]) : Node.createOrderedList([]);
+ }
+ this.setNodeOriginFromToken(list, rootToken);
+
+ while (this.lexer.hasNext()) {
+ var nextToken = this.lexer.peekNextToken();
+ if (!nextToken.isListElement() || nextToken.indentation !== rootToken.indentation)
+ break;
+ list.appendChild(this.parseListElement(rootToken.indentation, isDefinitionList));
+ }
+
+ return list;
+ },
+
+ unknownDefinitionTerm: "???",
+
+ parseListElement: function (rootIndentation, isDefinitionList) {
+ var listElementToken = this.lexer.getNextToken();
+ var listElement = Node.createListElement([]);
+ this.setNodeOriginFromToken(listElement, listElementToken);
+
+ listElement.isDefinitionList = isDefinitionList;
+
+ if (isDefinitionList) {
+ var match = this.definitionPattern.exec(listElementToken.content);
+ listElement.term = [
+ this.createTextNode(match && match[1] ? match[1] : this.unknownDefinitionTerm)
+ ];
+ listElement.appendChild(this.createTextNode(match ? match[2] : listElementToken.content));
+ } else {
+ listElement.appendChild(this.createTextNode(listElementToken.content));
+ }
+
+ while (this.lexer.hasNext()) {
+ var blankToken = this.skipBlank();
+ if (!this.lexer.hasNext())
+ break;
+
+ var notBlankNextToken = this.lexer.peekNextToken();
+ if (blankToken && !notBlankNextToken.isListElement())
+ this.lexer.pushToken(blankToken); // Recover blank token only when next line is not listElement.
+ // End of the list if hit less indented line or end of directive
+ if (notBlankNextToken.indentation <= rootIndentation ||
+ (notBlankNextToken.type === Lexer.tokens.directive && notBlankNextToken.endDirective))
+ break;
+
+ var element = this.parseElement(); // recursive
+ if (element)
+ listElement.appendChild(element);
+ }
+
+ return listElement;
+ },
+
+ // ------------------------------------------------------------
+ // ::= +
+ // ------------------------------------------------------------
+
+ parseTable: function () {
+ var nextToken = this.lexer.peekNextToken();
+ var table = Node.createTable([]);
+ this.setNodeOriginFromToken(table, nextToken);
+ var sawSeparator = false;
+
+ var allowMultilineCell = nextToken.type === Lexer.tokens.tableSeparator && this.options.multilineCell;
+
+ while (this.lexer.hasNext() &&
+ (nextToken = this.lexer.peekNextToken()).isTableElement()) {
+ if (nextToken.type === Lexer.tokens.tableRow) {
+ var tableRow = this.parseTableRow(allowMultilineCell);
+ table.appendChild(tableRow);
+ } else {
+ // Lexer.tokens.tableSeparator
+ sawSeparator = true;
+ this.lexer.getNextToken();
+ }
+ }
+
+ if (sawSeparator && table.children.length) {
+ table.children[0].children.forEach(function (cell) {
+ cell.isHeader = true;
+ });
+ }
+
+ return table;
+ },
+
+ // ------------------------------------------------------------
+ // ::= +
+ // ------------------------------------------------------------
+
+ parseTableRow: function (allowMultilineCell) {
+ var tableRowTokens = [];
+
+ while (this.lexer.peekNextToken().type === Lexer.tokens.tableRow) {
+ tableRowTokens.push(this.lexer.getNextToken());
+ if (!allowMultilineCell) {
+ break;
+ }
+ }
+
+ if (!tableRowTokens.length) {
+ throw this.createErrorReport("Expected table row");
+ }
+
+ var firstTableRowToken = tableRowTokens.shift();
+ var tableCellTexts = firstTableRowToken.content.split("|");
+
+ tableRowTokens.forEach(function (rowToken) {
+ rowToken.content.split("|").forEach(function (cellText, cellIdx) {
+ tableCellTexts[cellIdx] = (tableCellTexts[cellIdx] || "") + "\n" + cellText;
+ });
+ });
+
+ // TODO: Prepare two pathes: (1)
+ var tableCells = tableCellTexts.map(
+ // TODO: consider '|' escape?
+ function (text) {
+ return Node.createTableCell(Parser.parseStream(text));
+ }, this);
+
+ return this.setNodeOriginFromToken(Node.createTableRow(tableCells), firstTableRowToken);
+ },
+
+ // ------------------------------------------------------------
+ // ::= "#+.*"
+ // ------------------------------------------------------------
+
+ parseDirective: function () {
+ var directiveToken = this.lexer.getNextToken();
+ var directiveNode = this.createDirectiveNodeFromToken(directiveToken);
+
+ if (directiveToken.endDirective)
+ throw this.createErrorReport("Unmatched 'end' directive for " + directiveNode.directiveName);
+
+ if (directiveToken.oneshotDirective) {
+ this.interpretDirective(directiveNode);
+ return directiveNode;
+ }
+
+ if (!directiveToken.beginDirective)
+ throw this.createErrorReport("Invalid directive " + directiveNode.directiveName);
+
+ // Parse begin ~ end
+ directiveNode.children = [];
+ if (this.isVerbatimDirective(directiveNode))
+ return this.parseDirectiveBlockVerbatim(directiveNode);
+ else
+ return this.parseDirectiveBlock(directiveNode);
+ },
+
+ createDirectiveNodeFromToken: function (directiveToken) {
+ var matched = /^[ ]*([^ ]*)[ ]*(.*)[ ]*$/.exec(directiveToken.content);
+
+ var directiveNode = Node.createDirective(null);
+ this.setNodeOriginFromToken(directiveNode, directiveToken);
+ directiveNode.directiveName = matched[1].toLowerCase();
+ directiveNode.directiveArguments = this.parseDirectiveArguments(matched[2]);
+ directiveNode.directiveOptions = this.parseDirectiveOptions(matched[2]);
+ directiveNode.directiveRawValue = matched[2];
+
+ return directiveNode;
+ },
+
+ isVerbatimDirective: function (directiveNode) {
+ var directiveName = directiveNode.directiveName;
+ return directiveName === "src" || directiveName === "example" || directiveName === "html";
+ },
+
+ parseDirectiveBlock: function (directiveNode, verbatim) {
+ this.lexer.pushDummyTokenByType(Lexer.tokens.blank);
+
+ while (this.lexer.hasNext()) {
+ var nextToken = this.lexer.peekNextToken();
+ if (nextToken.type === Lexer.tokens.directive &&
+ nextToken.endDirective &&
+ this.createDirectiveNodeFromToken(nextToken).directiveName === directiveNode.directiveName) {
+ // Close directive
+ this.lexer.getNextToken();
+ return directiveNode;
+ }
+ var element = this.parseElementBesidesDirectiveEnd();
+ if (element)
+ directiveNode.appendChild(element);
+ }
+
+ throw this.createErrorReport("Unclosed directive " + directiveNode.directiveName);
+ },
+
+ parseDirectiveBlockVerbatim: function (directiveNode) {
+ var textContent = [];
+
+ while (this.lexer.hasNext()) {
+ var nextToken = this.lexer.peekNextToken();
+ if (nextToken.type === Lexer.tokens.directive &&
+ nextToken.endDirective &&
+ this.createDirectiveNodeFromToken(nextToken).directiveName === directiveNode.directiveName) {
+ this.lexer.getNextToken();
+ directiveNode.appendChild(this.createTextNode(textContent.join("\n"), true));
+ return directiveNode;
+ }
+ textContent.push(this.lexer.stream.getNextLine());
+ }
+
+ throw this.createErrorReport("Unclosed directive " + directiveNode.directiveName);
+ },
+
+ parseDirectiveArguments: function (parameters) {
+ return parameters.split(/[ ]+/).filter(function (param) {
+ return param.length && param[0] !== "-";
+ });
+ },
+
+ parseDirectiveOptions: function (parameters) {
+ return parameters.split(/[ ]+/).filter(function (param) {
+ return param.length && param[0] === "-";
+ });
+ },
+
+ interpretDirective: function (directiveNode) {
+ // http://orgmode.org/manual/Export-options.html
+ switch (directiveNode.directiveName) {
+ case "options:":
+ this.interpretOptionDirective(directiveNode);
+ break;
+ case "title:":
+ this.document.title = directiveNode.directiveRawValue;
+ break;
+ case "author:":
+ this.document.author = directiveNode.directiveRawValue;
+ break;
+ case "email:":
+ this.document.email = directiveNode.directiveRawValue;
+ break;
+ default:
+ this.document.directiveValues[directiveNode.directiveName] = directiveNode.directiveRawValue;
+ break;
+ }
+ },
+
+ interpretOptionDirective: function (optionDirectiveNode) {
+ optionDirectiveNode.directiveArguments.forEach(function (pairString) {
+ var pair = pairString.split(":");
+ this.options[pair[0]] = this.convertLispyValue(pair[1]);
+ }, this);
+ },
+
+ convertLispyValue: function (lispyValue) {
+ switch (lispyValue) {
+ case "t":
+ return true;
+ case "nil":
+ return false;
+ default:
+ if (/^[0-9]+$/.test(lispyValue))
+ return parseInt(lispyValue);
+ return lispyValue;
+ }
+ },
+
+ // ------------------------------------------------------------
+ // ::= *
+ // ------------------------------------------------------------
+
+ parseParagraph: function () {
+ var paragraphFisrtToken = this.lexer.peekNextToken();
+ var paragraph = Node.createParagraph([]);
+ this.setNodeOriginFromToken(paragraph, paragraphFisrtToken);
+
+ var textContents = [];
+
+ while (this.lexer.hasNext()) {
+ var nextToken = this.lexer.peekNextToken();
+ if (nextToken.type !== Lexer.tokens.line
+ || nextToken.indentation < paragraphFisrtToken.indentation)
+ break;
+ this.lexer.getNextToken();
+ textContents.push(nextToken.content);
+ }
+
+ paragraph.appendChild(this.createTextNode(textContents.join("\n")));
+
+ return paragraph;
+ },
+
+ parseText: function (noEmphasis) {
+ var lineToken = this.lexer.getNextToken();
+ return this.createTextNode(lineToken.content, noEmphasis);
+ },
+
+ // ------------------------------------------------------------
+ // (DOM Like)
+ // ------------------------------------------------------------
+
+ createTextNode: function (text, noEmphasis) {
+ return noEmphasis ? Node.createText(null, { value: text })
+ : this.inlineParser.parseEmphasis(text);
+ }
+ };
+ Parser.prototype.originalParseElement = Parser.prototype.parseElement;
+
+ // ------------------------------------------------------------
+ // Parser for Inline Elements
+ //
+ // @refs org-emphasis-regexp-components
+ // ------------------------------------------------------------
+
+ function InlineParser() {
+ this.preEmphasis = " \t\\('\"";
+ this.postEmphasis = "- \t.,:!?;'\"\\)";
+ this.borderForbidden = " \t\r\n,\"'";
+ this.bodyRegexp = "[\\s\\S]*?";
+ this.markers = "*/_=~+";
+
+ this.emphasisPattern = this.buildEmphasisPattern();
+ this.linkPattern = /\[\[([^\]]*)\](?:\[([^\]]*)\])?\]/g; // \1 => link, \2 => text
+ }
+
+ InlineParser.prototype = {
+ parseEmphasis: function (text) {
+ var emphasisPattern = this.emphasisPattern;
+ emphasisPattern.lastIndex = 0;
+
+ var result = [],
+ match,
+ previousLast = 0,
+ savedLastIndex;
+
+ while ((match = emphasisPattern.exec(text))) {
+ var whole = match[0];
+ var pre = match[1];
+ var marker = match[2];
+ var body = match[3];
+ var post = match[4];
+
+ {
+ // parse links
+ var matchBegin = emphasisPattern.lastIndex - whole.length;
+ var beforeContent = text.substring(previousLast, matchBegin + pre.length);
+ savedLastIndex = emphasisPattern.lastIndex;
+ result.push(this.parseLink(beforeContent));
+ emphasisPattern.lastIndex = savedLastIndex;
+ }
+
+ var bodyNode = [Node.createText(null, { value: body })];
+ var bodyContainer = this.emphasizeElementByMarker(bodyNode, marker);
+ result.push(bodyContainer);
+
+ previousLast = emphasisPattern.lastIndex - post.length;
+ }
+
+ if (emphasisPattern.lastIndex === 0 ||
+ emphasisPattern.lastIndex !== text.length - 1)
+ result.push(this.parseLink(text.substring(previousLast)));
+
+ if (result.length === 1) {
+ // Avoid duplicated inline container wrapping
+ return result[0];
+ } else {
+ return Node.createInlineContainer(result);
+ }
+ },
+
+ depth: 0,
+ parseLink: function (text) {
+ var linkPattern = this.linkPattern;
+ linkPattern.lastIndex = 0;
+
+ var match,
+ result = [],
+ previousLast = 0,
+ savedLastIndex;
+
+ while ((match = linkPattern.exec(text))) {
+ var whole = match[0];
+ var src = match[1];
+ var title = match[2];
+
+ // parse before content
+ var matchBegin = linkPattern.lastIndex - whole.length;
+ var beforeContent = text.substring(previousLast, matchBegin);
+ result.push(Node.createText(null, { value: beforeContent }));
+
+ // parse link
+ var link = Node.createLink([]);
+ link.src = src;
+ if (title) {
+ savedLastIndex = linkPattern.lastIndex;
+ link.appendChild(this.parseEmphasis(title));
+ linkPattern.lastIndex = savedLastIndex;
+ } else {
+ link.appendChild(Node.createText(null, { value: src }));
+ }
+ result.push(link);
+
+ previousLast = linkPattern.lastIndex;
+ }
+
+ if (linkPattern.lastIndex === 0 ||
+ linkPattern.lastIndex !== text.length - 1)
+ result.push(Node.createText(null, { value: text.substring(previousLast) }));
+
+ return Node.createInlineContainer(result);
+ },
+
+ emphasizeElementByMarker: function (element, marker) {
+ switch (marker) {
+ case "*":
+ return Node.createBold(element);
+ case "/":
+ return Node.createItalic(element);
+ case "_":
+ return Node.createUnderline(element);
+ case "=":
+ case "~":
+ return Node.createCode(element);
+ case "+":
+ return Node.createDashed(element);
+ }
+ },
+
+ buildEmphasisPattern: function () {
+ return new RegExp(
+ "([" + this.preEmphasis + "]|^|\r?\n)" + // \1 => pre
+ "([" + this.markers + "])" + // \2 => marker
+ "([^" + this.borderForbidden + "]|" + // \3 => body
+ "[^" + this.borderForbidden + "]" +
+ this.bodyRegexp +
+ "[^" + this.borderForbidden + "])" +
+ "\\2" +
+ "([" + this.postEmphasis +"]|$|\r?\n)", // \4 => post
+ // flags
+ "g"
+ );
+ }
+ };
+
+ if (typeof exports !== "undefined") {
+ exports.Parser = Parser;
+ exports.InlineParser = InlineParser;
+ }
+
+ // var Node = require("../node.js").Node;
+
+ function Converter() {
+ }
+
+ Converter.prototype = {
+ exportOptions: {
+ headerOffset: 1,
+ exportFromLineNumber: false,
+ suppressSubScriptHandling: false,
+ suppressAutoLink: false,
+ // HTML
+ translateSymbolArrow: false,
+ suppressCheckboxHandling: false,
+ // { "directive:": function (node, childText, auxData) {} }
+ customDirectiveHandler: null,
+ // e.g., "org-js-"
+ htmlClassPrefix: null,
+ htmlIdPrefix: null
+ },
+
+ untitled: "Untitled",
+ result: null,
+
+ // TODO: Manage TODO lists
+
+ initialize: function (orgDocument, exportOptions) {
+ this.orgDocument = orgDocument;
+ this.documentOptions = orgDocument.options || {};
+ this.exportOptions = exportOptions || {};
+
+ this.headers = [];
+ this.headerOffset =
+ typeof this.exportOptions.headerOffset === "number" ? this.exportOptions.headerOffset : 1;
+ this.sectionNumbers = [0];
+ },
+
+ createTocItem: function (headerNode, parentTocs) {
+ var childTocs = [];
+ childTocs.parent = parentTocs;
+ var tocItem = { headerNode: headerNode, childTocs: childTocs };
+ return tocItem;
+ },
+
+ computeToc: function (exportTocLevel) {
+ if (typeof exportTocLevel !== "number")
+ exportTocLevel = Infinity;
+
+ var toc = [];
+ toc.parent = null;
+
+ var previousLevel = 1;
+ var currentTocs = toc; // first
+
+ for (var i = 0; i < this.headers.length; ++i) {
+ var headerNode = this.headers[i];
+
+ if (headerNode.level > exportTocLevel)
+ continue;
+
+ var levelDiff = headerNode.level - previousLevel;
+ if (levelDiff > 0) {
+ for (var j = 0; j < levelDiff; ++j) {
+ if (currentTocs.length === 0) {
+ // Create a dummy tocItem
+ var dummyHeader = Node.createHeader([], {
+ level: previousLevel + j
+ });
+ dummyHeader.sectionNumberText = "";
+ currentTocs.push(this.createTocItem(dummyHeader, currentTocs));
+ }
+ currentTocs = currentTocs[currentTocs.length - 1].childTocs;
+ }
+ } else if (levelDiff < 0) {
+ levelDiff = -levelDiff;
+ for (var k = 0; k < levelDiff; ++k) {
+ currentTocs = currentTocs.parent;
+ }
+ }
+
+ currentTocs.push(this.createTocItem(headerNode, currentTocs));
+
+ previousLevel = headerNode.level;
+ }
+
+ return toc;
+ },
+
+ convertNode: function (node, recordHeader, insideCodeElement) {
+ if (!insideCodeElement) {
+ if (node.type === Node.types.directive) {
+ if (node.directiveName === "example" ||
+ node.directiveName === "src") {
+ insideCodeElement = true;
+ }
+ } else if (node.type === Node.types.preformatted) {
+ insideCodeElement = true;
+ }
+ }
+
+ if (typeof node === "string") {
+ node = Node.createText(null, { value: node });
+ }
+
+ var childText = node.children ? this.convertNodesInternal(node.children, recordHeader, insideCodeElement) : "";
+ var text;
+
+ var auxData = this.computeAuxDataForNode(node);
+
+ switch (node.type) {
+ case Node.types.header:
+ // Compute section number
+ var sectionNumberText = null;
+ if (recordHeader) {
+ var thisHeaderLevel = node.level;
+ var previousHeaderLevel = this.sectionNumbers.length;
+ if (thisHeaderLevel > previousHeaderLevel) {
+ // Fill missing section number
+ var levelDiff = thisHeaderLevel - previousHeaderLevel;
+ for (var j = 0; j < levelDiff; ++j) {
+ this.sectionNumbers[thisHeaderLevel - 1 - j] = 0; // Extend
+ }
+ } else if (thisHeaderLevel < previousHeaderLevel) {
+ this.sectionNumbers.length = thisHeaderLevel; // Collapse
+ }
+ this.sectionNumbers[thisHeaderLevel - 1]++;
+ sectionNumberText = this.sectionNumbers.join(".");
+ node.sectionNumberText = sectionNumberText; // Can be used in ToC
+ }
+
+ text = this.convertHeader(node, childText, auxData, sectionNumberText);
+
+ if (recordHeader)
+ this.headers.push(node);
+ break;
+ case Node.types.orderedList:
+ text = this.convertOrderedList(node, childText, auxData);
+ break;
+ case Node.types.unorderedList:
+ text = this.convertUnorderedList(node, childText, auxData);
+ break;
+ case Node.types.definitionList:
+ text = this.convertDefinitionList(node, childText, auxData);
+ break;
+ case Node.types.listElement:
+ if (node.isDefinitionList) {
+ var termText = this.convertNodesInternal(node.term, recordHeader, insideCodeElement);
+ text = this.convertDefinitionItem(node, childText, auxData,
+ termText, childText);
+ } else {
+ text = this.convertListItem(node, childText, auxData);
+ }
+ break;
+ case Node.types.paragraph:
+ text = this.convertParagraph(node, childText, auxData);
+ break;
+ case Node.types.preformatted:
+ text = this.convertPreformatted(node, childText, auxData);
+ break;
+ case Node.types.table:
+ text = this.convertTable(node, childText, auxData);
+ break;
+ case Node.types.tableRow:
+ text = this.convertTableRow(node, childText, auxData);
+ break;
+ case Node.types.tableCell:
+ if (node.isHeader)
+ text = this.convertTableHeader(node, childText, auxData);
+ else
+ text = this.convertTableCell(node, childText, auxData);
+ break;
+ case Node.types.horizontalRule:
+ text = this.convertHorizontalRule(node, childText, auxData);
+ break;
+ // ============================================================ //
+ // Inline
+ // ============================================================ //
+ case Node.types.inlineContainer:
+ text = this.convertInlineContainer(node, childText, auxData);
+ break;
+ case Node.types.bold:
+ text = this.convertBold(node, childText, auxData);
+ break;
+ case Node.types.italic:
+ text = this.convertItalic(node, childText, auxData);
+ break;
+ case Node.types.underline:
+ text = this.convertUnderline(node, childText, auxData);
+ break;
+ case Node.types.code:
+ text = this.convertCode(node, childText, auxData);
+ break;
+ case Node.types.dashed:
+ text = this.convertDashed(node, childText, auxData);
+ break;
+ case Node.types.link:
+ text = this.convertLink(node, childText, auxData);
+ break;
+ case Node.types.directive:
+ switch (node.directiveName) {
+ case "quote":
+ text = this.convertQuote(node, childText, auxData);
+ break;
+ case "example":
+ text = this.convertExample(node, childText, auxData);
+ break;
+ case "src":
+ text = this.convertSrc(node, childText, auxData);
+ break;
+ case "html":
+ case "html:":
+ text = this.convertHTML(node, childText, auxData);
+ break;
+ default:
+ if (this.exportOptions.customDirectiveHandler &&
+ this.exportOptions.customDirectiveHandler[node.directiveName]) {
+ text = this.exportOptions.customDirectiveHandler[node.directiveName](
+ node, childText, auxData
+ );
+ } else {
+ text = childText;
+ }
+ }
+ break;
+ case Node.types.text:
+ text = this.convertText(node.value, insideCodeElement);
+ break;
+ default:
+ throw Error("Unknown node type: " + node.type);
+ }
+
+ if (typeof this.postProcess === "function") {
+ text = this.postProcess(node, text, insideCodeElement);
+ }
+
+ return text;
+ },
+
+ convertText: function (text, insideCodeElement) {
+ var escapedText = this.escapeSpecialChars(text, insideCodeElement);
+
+ if (!this.exportOptions.suppressSubScriptHandling && !insideCodeElement) {
+ escapedText = this.makeSubscripts(escapedText, insideCodeElement);
+ }
+ if (!this.exportOptions.suppressAutoLink) {
+ escapedText = this.linkURL(escapedText);
+ }
+
+ return escapedText;
+ },
+
+ // By default, ignore html
+ convertHTML: function (node, childText, auxData) {
+ return childText;
+ },
+
+ convertNodesInternal: function (nodes, recordHeader, insideCodeElement) {
+ var nodesTexts = [];
+ for (var i = 0; i < nodes.length; ++i) {
+ var node = nodes[i];
+ var nodeText = this.convertNode(node, recordHeader, insideCodeElement);
+ nodesTexts.push(nodeText);
+ }
+
+ // Return entries without their property drawers
+ return this.combineNodesTexts(nodesTexts).replace(propertyDrawer, '');
+ },
+
+ convertHeaderBlock: function (headerBlock, recordHeader) {
+ throw Error("convertHeaderBlock is not implemented");
+ },
+
+ convertHeaderTree: function (headerTree, recordHeader) {
+ return this.convertHeaderBlock(headerTree, recordHeader);
+ },
+
+ convertNodesToHeaderTree: function (nodes, nextBlockBegin, blockHeader) {
+ var childBlocks = [];
+ var childNodes = [];
+
+ if (typeof nextBlockBegin === "undefined") {
+ nextBlockBegin = 0;
+ }
+ if (typeof blockHeader === "undefined") {
+ blockHeader = null;
+ }
+
+ for (var i = nextBlockBegin; i < nodes.length;) {
+ var node = nodes[i];
+
+ var isHeader = node.type === Node.types.header;
+
+ if (!isHeader) {
+ childNodes.push(node);
+ i = i + 1;
+ continue;
+ }
+
+ // Header
+ if (blockHeader && node.level <= blockHeader.level) {
+ // Finish Block
+ break;
+ } else {
+ // blockHeader.level < node.level
+ // Begin child block
+ var childBlock = this.convertNodesToHeaderTree(nodes, i + 1, node);
+ childBlocks.push(childBlock);
+ i = childBlock.nextIndex;
+ }
+ }
+
+ // Finish block
+ return {
+ header: blockHeader,
+ childNodes: childNodes,
+ nextIndex: i,
+ childBlocks: childBlocks
+ };
+ },
+
+ convertNodes: function (nodes, recordHeader, insideCodeElement) {
+ return this.convertNodesInternal(nodes, recordHeader, insideCodeElement);
+ },
+
+ combineNodesTexts: function (nodesTexts) {
+ return nodesTexts.join("");
+ },
+
+ getNodeTextContent: function (node) {
+ if (node.type === Node.types.text)
+ return this.escapeSpecialChars(node.value);
+ else
+ return node.children ? node.children.map(this.getNodeTextContent, this).join("") : "";
+ },
+
+ // @Override
+ escapeSpecialChars: function (text) {
+ throw Error("Implement escapeSpecialChars");
+ },
+
+ // http://daringfireball.net/2010/07/improved_regex_for_matching_urls
+ urlPattern: /\b(?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])/ig,
+
+ // @Override
+ linkURL: function (text) {
+ var self = this;
+ return text.replace(this.urlPattern, function (matched) {
+ if (matched.indexOf("://") < 0)
+ matched = "http://" + matched;
+ return self.makeLink(matched);
+ });
+ },
+
+ makeLink: function (url) {
+ throw Error("Implement makeLink");
+ },
+
+ makeSubscripts: function (text) {
+ if (this.documentOptions["^"] === "{}")
+ return text.replace(/\b([^_ \t]*)_{([^}]*)}/g,
+ this.makeSubscript);
+ else if (this.documentOptions["^"])
+ return text.replace(/\b([^_ \t]*)_([^_]*)\b/g,
+ this.makeSubscript);
+ else
+ return text;
+ },
+
+ makeSubscript: function (match, body, subscript) {
+ throw Error("Implement makeSubscript");
+ },
+
+ stripParametersFromURL: function (url) {
+ return url.replace(/\?.*$/, "");
+ },
+
+ imageExtensionPattern: new RegExp("(" + [
+ "bmp", "png", "jpeg", "jpg", "gif", "tiff",
+ "tif", "xbm", "xpm", "pbm", "pgm", "ppm", "svg"
+ ].join("|") + ")$", "i")
+ };
+
+ if (typeof exports !== "undefined")
+ exports.Converter = Converter;
+
+ // var Converter = require("./converter.js").Converter;
+ // var Node = require("../node.js").Node;
+
+ function ConverterHTML(orgDocument, exportOptions) {
+ this.initialize(orgDocument, exportOptions);
+ this.result = this.convert();
+ }
+
+ ConverterHTML.prototype = {
+ __proto__: Converter.prototype,
+
+ convert: function () {
+ var contentHTML = this.convertNodes(this.orgDocument.nodes, false /* record headers */);
+
+ return {
+ contentHTML: contentHTML,
+ toString: function () {
+ return contentHTML;
+ }
+ };
+ },
+
+ tocToHTML: function (toc) {
+ function tocToHTMLFunction(tocList) {
+ var html = "";
+ for (var i = 0; i < tocList.length; ++i) {
+ var tocItem = tocList[i];
+ var sectionNumberText = tocItem.headerNode.sectionNumberText;
+ var sectionNumber = this.documentOptions.num ?
+ this.inlineTag("span", sectionNumberText, {
+ "class": "section-number"
+ }) : "";
+ var header = this.getNodeTextContent(tocItem.headerNode);
+ var headerLink = this.inlineTag("a", sectionNumber + header, {
+ href: "#header-" + sectionNumberText.replace(/\./g, "-")
+ });
+ var subList = tocItem.childTocs.length ? tocToHTMLFunction.call(this, tocItem.childTocs) : "";
+ html += this.tag("li", headerLink + subList);
+ }
+ return this.tag("ul", html);
+ }
+
+ return tocToHTMLFunction.call(this, toc);
+ },
+
+ computeAuxDataForNode: function (node) {
+ while (node.parent &&
+ node.parent.type === Node.types.inlineContainer) {
+ node = node.parent;
+ }
+ var attributesNode = node.previousSibling;
+ var attributesText = "";
+ while (attributesNode &&
+ attributesNode.type === Node.types.directive &&
+ attributesNode.directiveName === "attr_html:") {
+ attributesText += attributesNode.directiveRawValue + " ";
+ attributesNode = attributesNode.previousSibling;
+ }
+ return attributesText;
+ },
+
+ // Method to construct org-js generated class
+ orgClassName: function (className) {
+ return this.exportOptions.htmlClassPrefix ?
+ this.exportOptions.htmlClassPrefix + className
+ : className;
+ },
+
+ // Method to construct org-js generated id
+ orgId: function (id) {
+ return this.exportOptions.htmlIdPrefix ?
+ this.exportOptions.htmlIdPrefix + id
+ : id;
+ },
+
+ // ----------------------------------------------------
+ // Node conversion
+ // ----------------------------------------------------
+
+ convertHeader: function (node, childText, auxData, sectionNumberText) {
+ var headerAttributes = {};
+
+ // Parse task status
+ taskStatusRegex = /^\s*([A-Z]+) /
+ taskStatusMatch = childText.match(taskStatusRegex);
+ taskStatus = taskStatusMatch && taskStatusMatch[1];
+ childText = childText.replace(taskStatusRegex, "");
+
+ if (taskStatus) {
+ childText = this.inlineTag("span", taskStatus, {
+ "class": "task-status " + taskStatus
+ }) + childText;
+ }
+
+ // Parse task tags
+ taskTagsRegex = /:([\w:]+):/g
+ taskTagsMatch = childText.match(taskTagsRegex);
+ taskTags = taskTagsMatch && taskTagsMatch[0].split(":").slice(1,-1);
+ childText = childText.replace(taskTagsRegex, "");
+
+ if (taskTags) {
+ taskTags.forEach(tag => {
+ childText += this.inlineTag("span", tag, { "class": "task-tag" })
+ });
+ }
+
+ if (sectionNumberText) {
+ childText = this.inlineTag("span", sectionNumberText, {
+ "class": "section-number"
+ }) + childText;
+ headerAttributes["id"] = "header-" + sectionNumberText.replace(/\./g, "-");
+ }
+
+ if (taskStatus)
+ headerAttributes["class"] = "task-status " + taskStatus;
+
+ return this.tag("h" + (this.headerOffset + node.level),
+ childText, headerAttributes, auxData);
+ },
+
+ convertOrderedList: function (node, childText, auxData) {
+ return this.tag("ol", childText, null, auxData);
+ },
+
+ convertUnorderedList: function (node, childText, auxData) {
+ return this.tag("ul", childText, null, auxData);
+ },
+
+ convertDefinitionList: function (node, childText, auxData) {
+ return this.tag("dl", childText, null, auxData);
+ },
+
+ convertDefinitionItem: function (node, childText, auxData,
+ term, definition) {
+ return this.tag("dt", term) + this.tag("dd", definition);
+ },
+
+ convertListItem: function (node, childText, auxData) {
+ if (this.exportOptions.suppressCheckboxHandling) {
+ return this.tag("li", childText, null, auxData);
+ } else {
+ var listItemAttributes = {};
+ var listItemText = childText;
+ // Embed checkbox
+ if (/^\s*\[(X| |-)\]([\s\S]*)/.exec(listItemText)) {
+ listItemText = RegExp.$2 ;
+ var checkboxIndicator = RegExp.$1;
+
+ var checkboxAttributes = { type: "checkbox" };
+ switch (checkboxIndicator) {
+ case "X":
+ checkboxAttributes["checked"] = "true";
+ listItemAttributes["data-checkbox-status"] = "done";
+ break;
+ case "-":
+ listItemAttributes["data-checkbox-status"] = "intermediate";
+ break;
+ default:
+ listItemAttributes["data-checkbox-status"] = "undone";
+ break;
+ }
+
+ listItemText = this.inlineTag("input", null, checkboxAttributes) + listItemText;
+ }
+
+ return this.tag("li", listItemText, listItemAttributes, auxData);
+ }
+ },
+
+ convertParagraph: function (node, childText, auxData) {
+ return this.tag("p", childText, null, auxData);
+ },
+
+ convertPreformatted: function (node, childText, auxData) {
+ return this.tag("pre", childText, null, auxData);
+ },
+
+ convertTable: function (node, childText, auxData) {
+ return this.tag("table", this.tag("tbody", childText), null, auxData);
+ },
+
+ convertTableRow: function (node, childText, auxData) {
+ return this.tag("tr", childText);
+ },
+
+ convertTableHeader: function (node, childText, auxData) {
+ return this.tag("th", childText);
+ },
+
+ convertTableCell: function (node, childText, auxData) {
+ return this.tag("td", childText);
+ },
+
+ convertHorizontalRule: function (node, childText, auxData) {
+ return this.tag("hr", null, null, auxData);
+ },
+
+ convertInlineContainer: function (node, childText, auxData) {
+ return childText;
+ },
+
+ convertBold: function (node, childText, auxData) {
+ return this.inlineTag("b", childText);
+ },
+
+ convertItalic: function (node, childText, auxData) {
+ return this.inlineTag("i", childText);
+ },
+
+ convertUnderline: function (node, childText, auxData) {
+ return this.inlineTag("span", childText, {
+ style: "text-decoration:underline;"
+ });
+ },
+
+ convertCode: function (node, childText, auxData) {
+ return this.inlineTag("code", childText);
+ },
+
+ convertDashed: function (node, childText, auxData) {
+ return this.inlineTag("del", childText);
+ },
+
+ convertLink: function (node, childText, auxData) {
+ var srcParameterStripped = this.stripParametersFromURL(node.src);
+ if (this.imageExtensionPattern.exec(srcParameterStripped)) {
+ var imgText = this.getNodeTextContent(node);
+ return this.inlineTag("img", null, {
+ src: node.src,
+ alt: imgText,
+ title: imgText
+ }, auxData);
+ } else {
+ return this.inlineTag("a", childText, { href: node.src });
+ }
+ },
+
+ convertQuote: function (node, childText, auxData) {
+ return this.tag("blockquote", childText, null, auxData);
+ },
+
+ convertExample: function (node, childText, auxData) {
+ return this.tag("pre", childText, null, auxData);
+ },
+
+ convertSrc: function (node, childText, auxData) {
+ var codeLanguage = node.directiveArguments.length
+ ? node.directiveArguments[0]
+ : "unknown";
+ childText = this.tag("code", childText, {
+ "class": "language-" + codeLanguage
+ }, auxData);
+ return this.tag("pre", childText, {
+ "class": "prettyprint"
+ });
+ },
+
+ // @override
+ convertHTML: function (node, childText, auxData) {
+ if (node.directiveName === "html:") {
+ return node.directiveRawValue;
+ } else if (node.directiveName === "html") {
+ return node.children.map(function (textNode) {
+ return textNode.value;
+ }).join("\n");
+ } else {
+ return childText;
+ }
+ },
+
+ // @implement
+ convertHeaderBlock: function (headerBlock, level, index) {
+ level = level || 0;
+ index = index || 0;
+
+ var contents = [];
+
+ var headerNode = headerBlock.header;
+ if (headerNode) {
+ contents.push(this.convertNode(headerNode));
+ }
+
+ var blockContent = this.convertNodes(headerBlock.childNodes);
+ contents.push(blockContent);
+
+ var childBlockContent = headerBlock.childBlocks
+ .map(function (block, idx) {
+ return this.convertHeaderBlock(block, level + 1, idx);
+ }, this)
+ .join("\n");
+ contents.push(childBlockContent);
+
+ var contentsText = contents.join("\n");
+
+ if (headerNode) {
+ return this.tag("section", "\n" + contents.join("\n"), {
+ "class": "block block-level-" + level
+ });
+ } else {
+ return contentsText;
+ }
+ },
+
+ // ----------------------------------------------------
+ // Supplemental methods
+ // ----------------------------------------------------
+
+ replaceMap: {
+ // [replacing pattern, predicate]
+ "&": ["&", null],
+ "<": ["<", null],
+ ">": [">", null],
+ '"': [""", null],
+ "'": ["'", null],
+ "->": ["➔", function (text, insideCodeElement) {
+ return this.exportOptions.translateSymbolArrow && !insideCodeElement;
+ }]
+ },
+
+ replaceRegexp: null,
+
+ // @implement @override
+ escapeSpecialChars: function (text, insideCodeElement) {
+ if (!this.replaceRegexp) {
+ this.replaceRegexp = new RegExp(Object.keys(this.replaceMap).join("|"), "g");
+ }
+
+ var replaceMap = this.replaceMap;
+ var self = this;
+ return text.replace(this.replaceRegexp, function (matched) {
+ if (!replaceMap[matched]) {
+ throw Error("escapeSpecialChars: Invalid match");
+ }
+
+ var predicate = replaceMap[matched][1];
+ if (typeof predicate === "function" &&
+ !predicate.call(self, text, insideCodeElement)) {
+ // Not fullfill the predicate
+ return matched;
+ }
+
+ return replaceMap[matched][0];
+ });
+ },
+
+ // @implement
+ postProcess: function (node, currentText, insideCodeElement) {
+ if (this.exportOptions.exportFromLineNumber &&
+ typeof node.fromLineNumber === "number") {
+ // Wrap with line number information
+ currentText = this.inlineTag("div", currentText, {
+ "data-line-number": node.fromLineNumber
+ });
+ }
+ return currentText;
+ },
+
+ // @implement
+ makeLink: function (url) {
+ return "" + decodeURIComponent(url) + "";
+ },
+
+ // @implement
+ makeSubscript: function (match, body, subscript) {
+ return "" +
+ body +
+ "" +
+ subscript +
+ "";
+ },
+
+ // ----------------------------------------------------
+ // Specific methods
+ // ----------------------------------------------------
+
+ attributesObjectToString: function (attributesObject) {
+ var attributesString = "";
+ for (var attributeName in attributesObject) {
+ if (attributesObject.hasOwnProperty(attributeName)) {
+ var attributeValue = attributesObject[attributeName];
+ // To avoid id/class name conflicts with other frameworks,
+ // users can add arbitrary prefix to org-js generated
+ // ids/classes via exportOptions.
+ if (attributeName === "class") {
+ attributeValue = this.orgClassName(attributeValue);
+ } else if (attributeName === "id") {
+ attributeValue = this.orgId(attributeValue);
+ }
+ attributesString += " " + attributeName + "=\"" + attributeValue + "\"";
+ }
+ }
+ return attributesString;
+ },
+
+ inlineTag: function (name, innerText, attributesObject, auxAttributesText) {
+ attributesObject = attributesObject || {};
+
+ var htmlString = "<" + name;
+ // TODO: check duplicated attributes
+ if (auxAttributesText)
+ htmlString += " " + auxAttributesText;
+ htmlString += this.attributesObjectToString(attributesObject);
+
+ if (innerText === null)
+ return htmlString + "/>";
+
+ htmlString += ">" + innerText + "" + name + ">";
+
+ return htmlString;
+ },
+
+ tag: function (name, innerText, attributesObject, auxAttributesText) {
+ return this.inlineTag(name, innerText, attributesObject, auxAttributesText) + "\n";
+ }
+ };
+
+ if (typeof exports !== "undefined")
+ exports.ConverterHTML = ConverterHTML;
+
+ return exports;
+})();
diff --git a/src/interface/desktop/assets/pico.min.css b/src/interface/desktop/assets/pico.min.css
new file mode 100644
index 00000000..61caa585
--- /dev/null
+++ b/src/interface/desktop/assets/pico.min.css
@@ -0,0 +1,5 @@
+@charset "UTF-8";/*!
+ * Pico CSS v1.5.10 (https://picocss.com)
+ * Copyright 2019-2023 - Licensed under MIT
+ */:root{--font-family:system-ui,-apple-system,"Segoe UI","Roboto","Ubuntu","Cantarell","Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--line-height:1.5;--font-weight:400;--font-size:16px;--border-radius:0.25rem;--border-width:1px;--outline-width:3px;--spacing:1rem;--typography-spacing-vertical:1.5rem;--block-spacing-vertical:calc(var(--spacing) * 2);--block-spacing-horizontal:var(--spacing);--grid-spacing-vertical:0;--grid-spacing-horizontal:var(--spacing);--form-element-spacing-vertical:0.75rem;--form-element-spacing-horizontal:1rem;--nav-element-spacing-vertical:1rem;--nav-element-spacing-horizontal:0.5rem;--nav-link-spacing-vertical:0.5rem;--nav-link-spacing-horizontal:0.5rem;--form-label-font-weight:var(--font-weight);--transition:0.2s ease-in-out;--modal-overlay-backdrop-filter:blur(0.25rem)}@media (min-width:576px){:root{--font-size:17px}}@media (min-width:768px){:root{--font-size:18px}}@media (min-width:992px){:root{--font-size:19px}}@media (min-width:1200px){:root{--font-size:20px}}@media (min-width:576px){body>footer,body>header,body>main,section{--block-spacing-vertical:calc(var(--spacing) * 2.5)}}@media (min-width:768px){body>footer,body>header,body>main,section{--block-spacing-vertical:calc(var(--spacing) * 3)}}@media (min-width:992px){body>footer,body>header,body>main,section{--block-spacing-vertical:calc(var(--spacing) * 3.5)}}@media (min-width:1200px){body>footer,body>header,body>main,section{--block-spacing-vertical:calc(var(--spacing) * 4)}}@media (min-width:576px){article{--block-spacing-horizontal:calc(var(--spacing) * 1.25)}}@media (min-width:768px){article{--block-spacing-horizontal:calc(var(--spacing) * 1.5)}}@media (min-width:992px){article{--block-spacing-horizontal:calc(var(--spacing) * 1.75)}}@media (min-width:1200px){article{--block-spacing-horizontal:calc(var(--spacing) * 2)}}dialog>article{--block-spacing-vertical:calc(var(--spacing) * 2);--block-spacing-horizontal:var(--spacing)}@media (min-width:576px){dialog>article{--block-spacing-vertical:calc(var(--spacing) * 2.5);--block-spacing-horizontal:calc(var(--spacing) * 1.25)}}@media (min-width:768px){dialog>article{--block-spacing-vertical:calc(var(--spacing) * 3);--block-spacing-horizontal:calc(var(--spacing) * 1.5)}}a{--text-decoration:none}a.contrast,a.secondary{--text-decoration:underline}small{--font-size:0.875em}h1,h2,h3,h4,h5,h6{--font-weight:700}h1{--font-size:2rem;--typography-spacing-vertical:3rem}h2{--font-size:1.75rem;--typography-spacing-vertical:2.625rem}h3{--font-size:1.5rem;--typography-spacing-vertical:2.25rem}h4{--font-size:1.25rem;--typography-spacing-vertical:1.874rem}h5{--font-size:1.125rem;--typography-spacing-vertical:1.6875rem}[type=checkbox],[type=radio]{--border-width:2px}[type=checkbox][role=switch]{--border-width:3px}tfoot td,tfoot th,thead td,thead th{--border-width:3px}:not(thead,tfoot)>*>td{--font-size:0.875em}code,kbd,pre,samp{--font-family:"Menlo","Consolas","Roboto Mono","Ubuntu Monospace","Noto Mono","Oxygen Mono","Liberation Mono",monospace,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"}kbd{--font-weight:bolder}:root:not([data-theme=dark]),[data-theme=light]{--background-color:#fff;--color:hsl(205, 20%, 32%);--h1-color:hsl(205, 30%, 15%);--h2-color:#24333e;--h3-color:hsl(205, 25%, 23%);--h4-color:#374956;--h5-color:hsl(205, 20%, 32%);--h6-color:#4d606d;--muted-color:hsl(205, 10%, 50%);--muted-border-color:hsl(205, 20%, 94%);--primary:hsl(195, 85%, 41%);--primary-hover:hsl(195, 90%, 32%);--primary-focus:rgba(16, 149, 193, 0.125);--primary-inverse:#fff;--secondary:hsl(205, 15%, 41%);--secondary-hover:hsl(205, 20%, 32%);--secondary-focus:rgba(89, 107, 120, 0.125);--secondary-inverse:#fff;--contrast:hsl(205, 30%, 15%);--contrast-hover:#000;--contrast-focus:rgba(89, 107, 120, 0.125);--contrast-inverse:#fff;--mark-background-color:#fff2ca;--mark-color:#543a26;--ins-color:#388e3c;--del-color:#c62828;--blockquote-border-color:var(--muted-border-color);--blockquote-footer-color:var(--muted-color);--button-box-shadow:0 0 0 rgba(0, 0, 0, 0);--button-hover-box-shadow:0 0 0 rgba(0, 0, 0, 0);--form-element-background-color:transparent;--form-element-border-color:hsl(205, 14%, 68%);--form-element-color:var(--color);--form-element-placeholder-color:var(--muted-color);--form-element-active-background-color:transparent;--form-element-active-border-color:var(--primary);--form-element-focus-color:var(--primary-focus);--form-element-disabled-background-color:hsl(205, 18%, 86%);--form-element-disabled-border-color:hsl(205, 14%, 68%);--form-element-disabled-opacity:0.5;--form-element-invalid-border-color:#c62828;--form-element-invalid-active-border-color:#d32f2f;--form-element-invalid-focus-color:rgba(211, 47, 47, 0.125);--form-element-valid-border-color:#388e3c;--form-element-valid-active-border-color:#43a047;--form-element-valid-focus-color:rgba(67, 160, 71, 0.125);--switch-background-color:hsl(205, 16%, 77%);--switch-color:var(--primary-inverse);--switch-checked-background-color:var(--primary);--range-border-color:hsl(205, 18%, 86%);--range-active-border-color:hsl(205, 16%, 77%);--range-thumb-border-color:var(--background-color);--range-thumb-color:var(--secondary);--range-thumb-hover-color:var(--secondary-hover);--range-thumb-active-color:var(--primary);--table-border-color:var(--muted-border-color);--table-row-stripped-background-color:#f6f8f9;--code-background-color:hsl(205, 20%, 94%);--code-color:var(--muted-color);--code-kbd-background-color:var(--contrast);--code-kbd-color:var(--contrast-inverse);--code-tag-color:hsl(330, 40%, 50%);--code-property-color:hsl(185, 40%, 40%);--code-value-color:hsl(40, 20%, 50%);--code-comment-color:hsl(205, 14%, 68%);--accordion-border-color:var(--muted-border-color);--accordion-close-summary-color:var(--color);--accordion-open-summary-color:var(--muted-color);--card-background-color:var(--background-color);--card-border-color:var(--muted-border-color);--card-box-shadow:0.0145rem 0.029rem 0.174rem rgba(27, 40, 50, 0.01698),0.0335rem 0.067rem 0.402rem rgba(27, 40, 50, 0.024),0.0625rem 0.125rem 0.75rem rgba(27, 40, 50, 0.03),0.1125rem 0.225rem 1.35rem rgba(27, 40, 50, 0.036),0.2085rem 0.417rem 2.502rem rgba(27, 40, 50, 0.04302),0.5rem 1rem 6rem rgba(27, 40, 50, 0.06),0 0 0 0.0625rem rgba(27, 40, 50, 0.015);--card-sectionning-background-color:#fbfbfc;--dropdown-background-color:#fbfbfc;--dropdown-border-color:#e1e6eb;--dropdown-box-shadow:var(--card-box-shadow);--dropdown-color:var(--color);--dropdown-hover-background-color:hsl(205, 20%, 94%);--modal-overlay-background-color:rgba(213, 220, 226, 0.7);--progress-background-color:hsl(205, 18%, 86%);--progress-color:var(--primary);--loading-spinner-opacity:0.5;--tooltip-background-color:var(--contrast);--tooltip-color:var(--contrast-inverse);--icon-checkbox:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button-inverse:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-close:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 130, 140)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");--icon-date:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");--icon-invalid:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(198, 40, 40)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");--icon-minus:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");--icon-search:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");--icon-time:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65, 84, 98)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");--icon-valid:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(56, 142, 60)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");color-scheme:light}@media only screen and (prefers-color-scheme:dark){:root:not([data-theme]){--background-color:#11191f;--color:hsl(205, 16%, 77%);--h1-color:hsl(205, 20%, 94%);--h2-color:#e1e6eb;--h3-color:hsl(205, 18%, 86%);--h4-color:#c8d1d8;--h5-color:hsl(205, 16%, 77%);--h6-color:#afbbc4;--muted-color:hsl(205, 10%, 50%);--muted-border-color:#1f2d38;--primary:hsl(195, 85%, 41%);--primary-hover:hsl(195, 80%, 50%);--primary-focus:rgba(16, 149, 193, 0.25);--primary-inverse:#fff;--secondary:hsl(205, 15%, 41%);--secondary-hover:hsl(205, 10%, 50%);--secondary-focus:rgba(115, 130, 140, 0.25);--secondary-inverse:#fff;--contrast:hsl(205, 20%, 94%);--contrast-hover:#fff;--contrast-focus:rgba(115, 130, 140, 0.25);--contrast-inverse:#000;--mark-background-color:#d1c284;--mark-color:#11191f;--ins-color:#388e3c;--del-color:#c62828;--blockquote-border-color:var(--muted-border-color);--blockquote-footer-color:var(--muted-color);--button-box-shadow:0 0 0 rgba(0, 0, 0, 0);--button-hover-box-shadow:0 0 0 rgba(0, 0, 0, 0);--form-element-background-color:#11191f;--form-element-border-color:#374956;--form-element-color:var(--color);--form-element-placeholder-color:var(--muted-color);--form-element-active-background-color:var(--form-element-background-color);--form-element-active-border-color:var(--primary);--form-element-focus-color:var(--primary-focus);--form-element-disabled-background-color:hsl(205, 25%, 23%);--form-element-disabled-border-color:hsl(205, 20%, 32%);--form-element-disabled-opacity:0.5;--form-element-invalid-border-color:#b71c1c;--form-element-invalid-active-border-color:#c62828;--form-element-invalid-focus-color:rgba(198, 40, 40, 0.25);--form-element-valid-border-color:#2e7d32;--form-element-valid-active-border-color:#388e3c;--form-element-valid-focus-color:rgba(56, 142, 60, 0.25);--switch-background-color:#374956;--switch-color:var(--primary-inverse);--switch-checked-background-color:var(--primary);--range-border-color:#24333e;--range-active-border-color:hsl(205, 25%, 23%);--range-thumb-border-color:var(--background-color);--range-thumb-color:var(--secondary);--range-thumb-hover-color:var(--secondary-hover);--range-thumb-active-color:var(--primary);--table-border-color:var(--muted-border-color);--table-row-stripped-background-color:rgba(115, 130, 140, 0.05);--code-background-color:#18232c;--code-color:var(--muted-color);--code-kbd-background-color:var(--contrast);--code-kbd-color:var(--contrast-inverse);--code-tag-color:hsl(330, 30%, 50%);--code-property-color:hsl(185, 30%, 50%);--code-value-color:hsl(40, 10%, 50%);--code-comment-color:#4d606d;--accordion-border-color:var(--muted-border-color);--accordion-active-summary-color:var(--primary);--accordion-close-summary-color:var(--color);--accordion-open-summary-color:var(--muted-color);--card-background-color:#141e26;--card-border-color:var(--card-background-color);--card-box-shadow:0.0145rem 0.029rem 0.174rem rgba(0, 0, 0, 0.01698),0.0335rem 0.067rem 0.402rem rgba(0, 0, 0, 0.024),0.0625rem 0.125rem 0.75rem rgba(0, 0, 0, 0.03),0.1125rem 0.225rem 1.35rem rgba(0, 0, 0, 0.036),0.2085rem 0.417rem 2.502rem rgba(0, 0, 0, 0.04302),0.5rem 1rem 6rem rgba(0, 0, 0, 0.06),0 0 0 0.0625rem rgba(0, 0, 0, 0.015);--card-sectionning-background-color:#18232c;--dropdown-background-color:hsl(205, 30%, 15%);--dropdown-border-color:#24333e;--dropdown-box-shadow:var(--card-box-shadow);--dropdown-color:var(--color);--dropdown-hover-background-color:rgba(36, 51, 62, 0.75);--modal-overlay-background-color:rgba(36, 51, 62, 0.8);--progress-background-color:#24333e;--progress-color:var(--primary);--loading-spinner-opacity:0.5;--tooltip-background-color:var(--contrast);--tooltip-color:var(--contrast-inverse);--icon-checkbox:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button-inverse:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(0, 0, 0)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-close:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 130, 140)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");--icon-date:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");--icon-invalid:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(183, 28, 28)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");--icon-minus:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");--icon-search:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");--icon-time:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");--icon-valid:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(46, 125, 50)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");color-scheme:dark}}[data-theme=dark]{--background-color:#11191f;--color:hsl(205, 16%, 77%);--h1-color:hsl(205, 20%, 94%);--h2-color:#e1e6eb;--h3-color:hsl(205, 18%, 86%);--h4-color:#c8d1d8;--h5-color:hsl(205, 16%, 77%);--h6-color:#afbbc4;--muted-color:hsl(205, 10%, 50%);--muted-border-color:#1f2d38;--primary:hsl(195, 85%, 41%);--primary-hover:hsl(195, 80%, 50%);--primary-focus:rgba(16, 149, 193, 0.25);--primary-inverse:#fff;--secondary:hsl(205, 15%, 41%);--secondary-hover:hsl(205, 10%, 50%);--secondary-focus:rgba(115, 130, 140, 0.25);--secondary-inverse:#fff;--contrast:hsl(205, 20%, 94%);--contrast-hover:#fff;--contrast-focus:rgba(115, 130, 140, 0.25);--contrast-inverse:#000;--mark-background-color:#d1c284;--mark-color:#11191f;--ins-color:#388e3c;--del-color:#c62828;--blockquote-border-color:var(--muted-border-color);--blockquote-footer-color:var(--muted-color);--button-box-shadow:0 0 0 rgba(0, 0, 0, 0);--button-hover-box-shadow:0 0 0 rgba(0, 0, 0, 0);--form-element-background-color:#11191f;--form-element-border-color:#374956;--form-element-color:var(--color);--form-element-placeholder-color:var(--muted-color);--form-element-active-background-color:var(--form-element-background-color);--form-element-active-border-color:var(--primary);--form-element-focus-color:var(--primary-focus);--form-element-disabled-background-color:hsl(205, 25%, 23%);--form-element-disabled-border-color:hsl(205, 20%, 32%);--form-element-disabled-opacity:0.5;--form-element-invalid-border-color:#b71c1c;--form-element-invalid-active-border-color:#c62828;--form-element-invalid-focus-color:rgba(198, 40, 40, 0.25);--form-element-valid-border-color:#2e7d32;--form-element-valid-active-border-color:#388e3c;--form-element-valid-focus-color:rgba(56, 142, 60, 0.25);--switch-background-color:#374956;--switch-color:var(--primary-inverse);--switch-checked-background-color:var(--primary);--range-border-color:#24333e;--range-active-border-color:hsl(205, 25%, 23%);--range-thumb-border-color:var(--background-color);--range-thumb-color:var(--secondary);--range-thumb-hover-color:var(--secondary-hover);--range-thumb-active-color:var(--primary);--table-border-color:var(--muted-border-color);--table-row-stripped-background-color:rgba(115, 130, 140, 0.05);--code-background-color:#18232c;--code-color:var(--muted-color);--code-kbd-background-color:var(--contrast);--code-kbd-color:var(--contrast-inverse);--code-tag-color:hsl(330, 30%, 50%);--code-property-color:hsl(185, 30%, 50%);--code-value-color:hsl(40, 10%, 50%);--code-comment-color:#4d606d;--accordion-border-color:var(--muted-border-color);--accordion-active-summary-color:var(--primary);--accordion-close-summary-color:var(--color);--accordion-open-summary-color:var(--muted-color);--card-background-color:#141e26;--card-border-color:var(--card-background-color);--card-box-shadow:0.0145rem 0.029rem 0.174rem rgba(0, 0, 0, 0.01698),0.0335rem 0.067rem 0.402rem rgba(0, 0, 0, 0.024),0.0625rem 0.125rem 0.75rem rgba(0, 0, 0, 0.03),0.1125rem 0.225rem 1.35rem rgba(0, 0, 0, 0.036),0.2085rem 0.417rem 2.502rem rgba(0, 0, 0, 0.04302),0.5rem 1rem 6rem rgba(0, 0, 0, 0.06),0 0 0 0.0625rem rgba(0, 0, 0, 0.015);--card-sectionning-background-color:#18232c;--dropdown-background-color:hsl(205, 30%, 15%);--dropdown-border-color:#24333e;--dropdown-box-shadow:var(--card-box-shadow);--dropdown-color:var(--color);--dropdown-hover-background-color:rgba(36, 51, 62, 0.75);--modal-overlay-background-color:rgba(36, 51, 62, 0.8);--progress-background-color:#24333e;--progress-color:var(--primary);--loading-spinner-opacity:0.5;--tooltip-background-color:var(--contrast);--tooltip-color:var(--contrast-inverse);--icon-checkbox:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button-inverse:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(0, 0, 0)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-close:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(115, 130, 140)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");--icon-date:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");--icon-invalid:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(183, 28, 28)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");--icon-minus:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");--icon-search:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");--icon-time:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(162, 175, 185)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");--icon-valid:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(46, 125, 50)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");color-scheme:dark}[type=checkbox],[type=radio],[type=range],progress{accent-color:var(--primary)}*,::after,::before{box-sizing:border-box;background-repeat:no-repeat}::after,::before{text-decoration:inherit;vertical-align:inherit}:where(:root){-webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--background-color);color:var(--color);font-weight:var(--font-weight);font-size:var(--font-size);line-height:var(--line-height);font-family:var(--font-family);text-rendering:optimizeLegibility;overflow-wrap:break-word;cursor:default;-moz-tab-size:4;-o-tab-size:4;tab-size:4}main{display:block}body{width:100%;margin:0}body>footer,body>header,body>main{width:100%;margin-right:auto;margin-left:auto;padding:var(--block-spacing-vertical) 0}.container,.container-fluid{width:100%;margin-right:auto;margin-left:auto;padding-right:var(--spacing);padding-left:var(--spacing)}@media (min-width:576px){.container{max-width:510px;padding-right:0;padding-left:0}}@media (min-width:768px){.container{max-width:700px}}@media (min-width:992px){.container{max-width:920px}}@media (min-width:1200px){.container{max-width:1130px}}section{margin-bottom:var(--block-spacing-vertical)}.grid{grid-column-gap:var(--grid-spacing-horizontal);grid-row-gap:var(--grid-spacing-vertical);display:grid;grid-template-columns:1fr;margin:0}@media (min-width:992px){.grid{grid-template-columns:repeat(auto-fit,minmax(0%,1fr))}}.grid>*{min-width:0}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:calc(var(--spacing) * .5) 0;color:var(--muted-color)}b,strong{font-weight:bolder}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin-top:0;margin-bottom:var(--typography-spacing-vertical);color:var(--color);font-style:normal;font-weight:var(--font-weight);font-size:var(--font-size)}[role=link],a{--color:var(--primary);--background-color:transparent;outline:0;background-color:var(--background-color);color:var(--color);-webkit-text-decoration:var(--text-decoration);text-decoration:var(--text-decoration);transition:background-color var(--transition),color var(--transition),box-shadow var(--transition),-webkit-text-decoration var(--transition);transition:background-color var(--transition),color var(--transition),text-decoration var(--transition),box-shadow var(--transition);transition:background-color var(--transition),color var(--transition),text-decoration var(--transition),box-shadow var(--transition),-webkit-text-decoration var(--transition)}[role=link]:is([aria-current],:hover,:active,:focus),a:is([aria-current],:hover,:active,:focus){--color:var(--primary-hover);--text-decoration:underline}[role=link]:focus,a:focus{--background-color:var(--primary-focus)}[role=link].secondary,a.secondary{--color:var(--secondary)}[role=link].secondary:is([aria-current],:hover,:active,:focus),a.secondary:is([aria-current],:hover,:active,:focus){--color:var(--secondary-hover)}[role=link].secondary:focus,a.secondary:focus{--background-color:var(--secondary-focus)}[role=link].contrast,a.contrast{--color:var(--contrast)}[role=link].contrast:is([aria-current],:hover,:active,:focus),a.contrast:is([aria-current],:hover,:active,:focus){--color:var(--contrast-hover)}[role=link].contrast:focus,a.contrast:focus{--background-color:var(--contrast-focus)}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:var(--typography-spacing-vertical);color:var(--color);font-weight:var(--font-weight);font-size:var(--font-size);font-family:var(--font-family)}h1{--color:var(--h1-color)}h2{--color:var(--h2-color)}h3{--color:var(--h3-color)}h4{--color:var(--h4-color)}h5{--color:var(--h5-color)}h6{--color:var(--h6-color)}:where(address,blockquote,dl,figure,form,ol,p,pre,table,ul)~:is(h1,h2,h3,h4,h5,h6){margin-top:var(--typography-spacing-vertical)}.headings,hgroup{margin-bottom:var(--typography-spacing-vertical)}.headings>*,hgroup>*{margin-bottom:0}.headings>:last-child,hgroup>:last-child{--color:var(--muted-color);--font-weight:unset;font-size:1rem;font-family:unset}p{margin-bottom:var(--typography-spacing-vertical)}small{font-size:var(--font-size)}:where(dl,ol,ul){padding-right:0;padding-left:var(--spacing);-webkit-padding-start:var(--spacing);padding-inline-start:var(--spacing);-webkit-padding-end:0;padding-inline-end:0}:where(dl,ol,ul) li{margin-bottom:calc(var(--typography-spacing-vertical) * .25)}:where(dl,ol,ul) :is(dl,ol,ul){margin:0;margin-top:calc(var(--typography-spacing-vertical) * .25)}ul li{list-style:square}mark{padding:.125rem .25rem;background-color:var(--mark-background-color);color:var(--mark-color);vertical-align:baseline}blockquote{display:block;margin:var(--typography-spacing-vertical) 0;padding:var(--spacing);border-right:none;border-left:.25rem solid var(--blockquote-border-color);-webkit-border-start:0.25rem solid var(--blockquote-border-color);border-inline-start:0.25rem solid var(--blockquote-border-color);-webkit-border-end:none;border-inline-end:none}blockquote footer{margin-top:calc(var(--typography-spacing-vertical) * .5);color:var(--blockquote-footer-color)}abbr[title]{border-bottom:1px dotted;text-decoration:none;cursor:help}ins{color:var(--ins-color);text-decoration:none}del{color:var(--del-color)}::-moz-selection{background-color:var(--primary-focus)}::selection{background-color:var(--primary-focus)}:where(audio,canvas,iframe,img,svg,video){vertical-align:middle}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}:where(iframe){border-style:none}img{max-width:100%;height:auto;border-style:none}:where(svg:not([fill])){fill:currentColor}svg:not(:root){overflow:hidden}button{margin:0;overflow:visible;font-family:inherit;text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}button{display:block;width:100%;margin-bottom:var(--spacing)}[role=button]{display:inline-block;text-decoration:none}[role=button],button,input[type=button],input[type=reset],input[type=submit]{--background-color:var(--primary);--border-color:var(--primary);--color:var(--primary-inverse);--box-shadow:var(--button-box-shadow, 0 0 0 rgba(0, 0, 0, 0));padding:var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:0;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);font-size:1rem;line-height:var(--line-height);text-align:center;cursor:pointer;transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}[role=button]:is([aria-current],:hover,:active,:focus),button:is([aria-current],:hover,:active,:focus),input[type=button]:is([aria-current],:hover,:active,:focus),input[type=reset]:is([aria-current],:hover,:active,:focus),input[type=submit]:is([aria-current],:hover,:active,:focus){--background-color:var(--primary-hover);--border-color:var(--primary-hover);--box-shadow:var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0));--color:var(--primary-inverse)}[role=button]:focus,button:focus,input[type=button]:focus,input[type=reset]:focus,input[type=submit]:focus{--box-shadow:var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),0 0 0 var(--outline-width) var(--primary-focus)}:is(button,input[type=submit],input[type=button],[role=button]).secondary,input[type=reset]{--background-color:var(--secondary);--border-color:var(--secondary);--color:var(--secondary-inverse);cursor:pointer}:is(button,input[type=submit],input[type=button],[role=button]).secondary:is([aria-current],:hover,:active,:focus),input[type=reset]:is([aria-current],:hover,:active,:focus){--background-color:var(--secondary-hover);--border-color:var(--secondary-hover);--color:var(--secondary-inverse)}:is(button,input[type=submit],input[type=button],[role=button]).secondary:focus,input[type=reset]:focus{--box-shadow:var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),0 0 0 var(--outline-width) var(--secondary-focus)}:is(button,input[type=submit],input[type=button],[role=button]).contrast{--background-color:var(--contrast);--border-color:var(--contrast);--color:var(--contrast-inverse)}:is(button,input[type=submit],input[type=button],[role=button]).contrast:is([aria-current],:hover,:active,:focus){--background-color:var(--contrast-hover);--border-color:var(--contrast-hover);--color:var(--contrast-inverse)}:is(button,input[type=submit],input[type=button],[role=button]).contrast:focus{--box-shadow:var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)),0 0 0 var(--outline-width) var(--contrast-focus)}:is(button,input[type=submit],input[type=button],[role=button]).outline,input[type=reset].outline{--background-color:transparent;--color:var(--primary)}:is(button,input[type=submit],input[type=button],[role=button]).outline:is([aria-current],:hover,:active,:focus),input[type=reset].outline:is([aria-current],:hover,:active,:focus){--background-color:transparent;--color:var(--primary-hover)}:is(button,input[type=submit],input[type=button],[role=button]).outline.secondary,input[type=reset].outline{--color:var(--secondary)}:is(button,input[type=submit],input[type=button],[role=button]).outline.secondary:is([aria-current],:hover,:active,:focus),input[type=reset].outline:is([aria-current],:hover,:active,:focus){--color:var(--secondary-hover)}:is(button,input[type=submit],input[type=button],[role=button]).outline.contrast{--color:var(--contrast)}:is(button,input[type=submit],input[type=button],[role=button]).outline.contrast:is([aria-current],:hover,:active,:focus){--color:var(--contrast-hover)}:where(button,[type=submit],[type=button],[type=reset],[role=button])[disabled],:where(fieldset[disabled]) :is(button,[type=submit],[type=button],[type=reset],[role=button]),a[role=button]:not([href]){opacity:.5;pointer-events:none}input,optgroup,select,textarea{margin:0;font-size:1rem;line-height:var(--line-height);font-family:inherit;letter-spacing:inherit}input{overflow:visible}select{text-transform:none}legend{max-width:100%;padding:0;color:inherit;white-space:normal}textarea{overflow:auto}[type=checkbox],[type=radio]{padding:0}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}::-moz-focus-inner{padding:0;border-style:none}:-moz-focusring{outline:0}:-moz-ui-invalid{box-shadow:none}::-ms-expand{display:none}[type=file],[type=range]{padding:0;border-width:0}input:not([type=checkbox],[type=radio],[type=range]){height:calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2)}fieldset{margin:0;margin-bottom:var(--spacing);padding:0;border:0}fieldset legend,label{display:block;margin-bottom:calc(var(--spacing) * .25);font-weight:var(--form-label-font-weight,var(--font-weight))}input:not([type=checkbox],[type=radio]),select,textarea{width:100%}input:not([type=checkbox],[type=radio],[type=range],[type=file]),select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal)}input,select,textarea{--background-color:var(--form-element-background-color);--border-color:var(--form-element-border-color);--color:var(--form-element-color);--box-shadow:none;border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:0;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}:where(select,textarea):is(:active,:focus),input:not([type=submit],[type=button],[type=reset],[type=checkbox],[type=radio],[readonly]):is(:active,:focus){--background-color:var(--form-element-active-background-color)}:where(select,textarea):is(:active,:focus),input:not([type=submit],[type=button],[type=reset],[role=switch],[readonly]):is(:active,:focus){--border-color:var(--form-element-active-border-color)}input:not([type=submit],[type=button],[type=reset],[type=range],[type=file],[readonly]):focus,select:focus,textarea:focus{--box-shadow:0 0 0 var(--outline-width) var(--form-element-focus-color)}:where(fieldset[disabled]) :is(input:not([type=submit],[type=button],[type=reset]),select,textarea),input:not([type=submit],[type=button],[type=reset])[disabled],select[disabled],textarea[disabled]{--background-color:var(--form-element-disabled-background-color);--border-color:var(--form-element-disabled-border-color);opacity:var(--form-element-disabled-opacity);pointer-events:none}:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week])[aria-invalid]{padding-right:calc(var(--form-element-spacing-horizontal) + 1.5rem)!important;padding-left:var(--form-element-spacing-horizontal);-webkit-padding-start:var(--form-element-spacing-horizontal)!important;padding-inline-start:var(--form-element-spacing-horizontal)!important;-webkit-padding-end:calc(var(--form-element-spacing-horizontal) + 1.5rem)!important;padding-inline-end:calc(var(--form-element-spacing-horizontal) + 1.5rem)!important;background-position:center right .75rem;background-size:1rem auto;background-repeat:no-repeat}:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week])[aria-invalid=false]{background-image:var(--icon-valid)}:where(input,select,textarea):not([type=checkbox],[type=radio],[type=date],[type=datetime-local],[type=month],[type=time],[type=week])[aria-invalid=true]{background-image:var(--icon-invalid)}:where(input,select,textarea)[aria-invalid=false]{--border-color:var(--form-element-valid-border-color)}:where(input,select,textarea)[aria-invalid=false]:is(:active,:focus){--border-color:var(--form-element-valid-active-border-color)!important;--box-shadow:0 0 0 var(--outline-width) var(--form-element-valid-focus-color)!important}:where(input,select,textarea)[aria-invalid=true]{--border-color:var(--form-element-invalid-border-color)}:where(input,select,textarea)[aria-invalid=true]:is(:active,:focus){--border-color:var(--form-element-invalid-active-border-color)!important;--box-shadow:0 0 0 var(--outline-width) var(--form-element-invalid-focus-color)!important}[dir=rtl] :where(input,select,textarea):not([type=checkbox],[type=radio]):is([aria-invalid],[aria-invalid=true],[aria-invalid=false]){background-position:center left .75rem}input::-webkit-input-placeholder,input::placeholder,select:invalid,textarea::-webkit-input-placeholder,textarea::placeholder{color:var(--form-element-placeholder-color);opacity:1}input:not([type=checkbox],[type=radio]),select,textarea{margin-bottom:var(--spacing)}select::-ms-expand{border:0;background-color:transparent}select:not([multiple],[size]){padding-right:calc(var(--form-element-spacing-horizontal) + 1.5rem);padding-left:var(--form-element-spacing-horizontal);-webkit-padding-start:var(--form-element-spacing-horizontal);padding-inline-start:var(--form-element-spacing-horizontal);-webkit-padding-end:calc(var(--form-element-spacing-horizontal) + 1.5rem);padding-inline-end:calc(var(--form-element-spacing-horizontal) + 1.5rem);background-image:var(--icon-chevron);background-position:center right .75rem;background-size:1rem auto;background-repeat:no-repeat}[dir=rtl] select:not([multiple],[size]){background-position:center left .75rem}:where(input,select,textarea,.grid)+small{display:block;width:100%;margin-top:calc(var(--spacing) * -.75);margin-bottom:var(--spacing);color:var(--muted-color)}label>:where(input,select,textarea){margin-top:calc(var(--spacing) * .25)}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:1.25em;height:1.25em;margin-top:-.125em;margin-right:.375em;margin-left:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:.375em;margin-inline-end:.375em;border-width:var(--border-width);font-size:inherit;vertical-align:middle;cursor:pointer}[type=checkbox]::-ms-check,[type=radio]::-ms-check{display:none}[type=checkbox]:checked,[type=checkbox]:checked:active,[type=checkbox]:checked:focus,[type=radio]:checked,[type=radio]:checked:active,[type=radio]:checked:focus{--background-color:var(--primary);--border-color:var(--primary);background-image:var(--icon-checkbox);background-position:center;background-size:.75em auto;background-repeat:no-repeat}[type=checkbox]~label,[type=radio]~label{display:inline-block;margin-right:.375em;margin-bottom:0;cursor:pointer}[type=checkbox]:indeterminate{--background-color:var(--primary);--border-color:var(--primary);background-image:var(--icon-minus);background-position:center;background-size:.75em auto;background-repeat:no-repeat}[type=radio]{border-radius:50%}[type=radio]:checked,[type=radio]:checked:active,[type=radio]:checked:focus{--background-color:var(--primary-inverse);border-width:.35em;background-image:none}[type=checkbox][role=switch]{--background-color:var(--switch-background-color);--border-color:var(--switch-background-color);--color:var(--switch-color);width:2.25em;height:1.25em;border:var(--border-width) solid var(--border-color);border-radius:1.25em;background-color:var(--background-color);line-height:1.25em}[type=checkbox][role=switch]:focus{--background-color:var(--switch-background-color);--border-color:var(--switch-background-color)}[type=checkbox][role=switch]:checked{--background-color:var(--switch-checked-background-color);--border-color:var(--switch-checked-background-color)}[type=checkbox][role=switch]:before{display:block;width:calc(1.25em - (var(--border-width) * 2));height:100%;border-radius:50%;background-color:var(--color);content:"";transition:margin .1s ease-in-out}[type=checkbox][role=switch]:checked{background-image:none}[type=checkbox][role=switch]:checked::before{margin-left:calc(1.125em - var(--border-width));-webkit-margin-start:calc(1.125em - var(--border-width));margin-inline-start:calc(1.125em - var(--border-width))}[type=checkbox]:checked[aria-invalid=false],[type=checkbox][aria-invalid=false],[type=checkbox][role=switch]:checked[aria-invalid=false],[type=checkbox][role=switch][aria-invalid=false],[type=radio]:checked[aria-invalid=false],[type=radio][aria-invalid=false]{--border-color:var(--form-element-valid-border-color)}[type=checkbox]:checked[aria-invalid=true],[type=checkbox][aria-invalid=true],[type=checkbox][role=switch]:checked[aria-invalid=true],[type=checkbox][role=switch][aria-invalid=true],[type=radio]:checked[aria-invalid=true],[type=radio][aria-invalid=true]{--border-color:var(--form-element-invalid-border-color)}[type=color]::-webkit-color-swatch-wrapper{padding:0}[type=color]::-moz-focus-inner{padding:0}[type=color]::-webkit-color-swatch{border:0;border-radius:calc(var(--border-radius) * .5)}[type=color]::-moz-color-swatch{border:0;border-radius:calc(var(--border-radius) * .5)}input:not([type=checkbox],[type=radio],[type=range],[type=file]):is([type=date],[type=datetime-local],[type=month],[type=time],[type=week]){--icon-position:0.75rem;--icon-width:1rem;padding-right:calc(var(--icon-width) + var(--icon-position));background-image:var(--icon-date);background-position:center right var(--icon-position);background-size:var(--icon-width) auto;background-repeat:no-repeat}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=time]{background-image:var(--icon-time)}[type=date]::-webkit-calendar-picker-indicator,[type=datetime-local]::-webkit-calendar-picker-indicator,[type=month]::-webkit-calendar-picker-indicator,[type=time]::-webkit-calendar-picker-indicator,[type=week]::-webkit-calendar-picker-indicator{width:var(--icon-width);margin-right:calc(var(--icon-width) * -1);margin-left:var(--icon-position);opacity:0}[dir=rtl] :is([type=date],[type=datetime-local],[type=month],[type=time],[type=week]){text-align:right}@-moz-document url-prefix(){[type=date],[type=datetime-local],[type=month],[type=time],[type=week]{padding-right:var(--form-element-spacing-horizontal)!important;background-image:none!important}}[type=file]{--color:var(--muted-color);padding:calc(var(--form-element-spacing-vertical) * .5) 0;border:0;border-radius:0;background:0 0}[type=file]::file-selector-button{--background-color:var(--secondary);--border-color:var(--secondary);--color:var(--secondary-inverse);margin-right:calc(var(--spacing)/ 2);margin-left:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:calc(var(--spacing)/ 2);margin-inline-end:calc(var(--spacing)/ 2);padding:calc(var(--form-element-spacing-vertical) * .5) calc(var(--form-element-spacing-horizontal) * .5);border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:0;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);font-size:1rem;line-height:var(--line-height);text-align:center;cursor:pointer;transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}[type=file]::file-selector-button:is(:hover,:active,:focus){--background-color:var(--secondary-hover);--border-color:var(--secondary-hover)}[type=file]::-webkit-file-upload-button{--background-color:var(--secondary);--border-color:var(--secondary);--color:var(--secondary-inverse);margin-right:calc(var(--spacing)/ 2);margin-left:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:calc(var(--spacing)/ 2);margin-inline-end:calc(var(--spacing)/ 2);padding:calc(var(--form-element-spacing-vertical) * .5) calc(var(--form-element-spacing-horizontal) * .5);border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:0;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);font-size:1rem;line-height:var(--line-height);text-align:center;cursor:pointer;-webkit-transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition);transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}[type=file]::-webkit-file-upload-button:is(:hover,:active,:focus){--background-color:var(--secondary-hover);--border-color:var(--secondary-hover)}[type=file]::-ms-browse{--background-color:var(--secondary);--border-color:var(--secondary);--color:var(--secondary-inverse);margin-right:calc(var(--spacing)/ 2);margin-left:0;margin-inline-start:0;margin-inline-end:calc(var(--spacing)/ 2);padding:calc(var(--form-element-spacing-vertical) * .5) calc(var(--form-element-spacing-horizontal) * .5);border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:0;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);font-size:1rem;line-height:var(--line-height);text-align:center;cursor:pointer;-ms-transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition);transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}[type=file]::-ms-browse:is(:hover,:active,:focus){--background-color:var(--secondary-hover);--border-color:var(--secondary-hover)}[type=range]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:1.25rem;background:0 0}[type=range]::-webkit-slider-runnable-track{width:100%;height:.25rem;border-radius:var(--border-radius);background-color:var(--range-border-color);-webkit-transition:background-color var(--transition),box-shadow var(--transition);transition:background-color var(--transition),box-shadow var(--transition)}[type=range]::-moz-range-track{width:100%;height:.25rem;border-radius:var(--border-radius);background-color:var(--range-border-color);-moz-transition:background-color var(--transition),box-shadow var(--transition);transition:background-color var(--transition),box-shadow var(--transition)}[type=range]::-ms-track{width:100%;height:.25rem;border-radius:var(--border-radius);background-color:var(--range-border-color);-ms-transition:background-color var(--transition),box-shadow var(--transition);transition:background-color var(--transition),box-shadow var(--transition)}[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.5rem;border:2px solid var(--range-thumb-border-color);border-radius:50%;background-color:var(--range-thumb-color);cursor:pointer;-webkit-transition:background-color var(--transition),transform var(--transition);transition:background-color var(--transition),transform var(--transition)}[type=range]::-moz-range-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.5rem;border:2px solid var(--range-thumb-border-color);border-radius:50%;background-color:var(--range-thumb-color);cursor:pointer;-moz-transition:background-color var(--transition),transform var(--transition);transition:background-color var(--transition),transform var(--transition)}[type=range]::-ms-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.5rem;border:2px solid var(--range-thumb-border-color);border-radius:50%;background-color:var(--range-thumb-color);cursor:pointer;-ms-transition:background-color var(--transition),transform var(--transition);transition:background-color var(--transition),transform var(--transition)}[type=range]:focus,[type=range]:hover{--range-border-color:var(--range-active-border-color);--range-thumb-color:var(--range-thumb-hover-color)}[type=range]:active{--range-thumb-color:var(--range-thumb-active-color)}[type=range]:active::-webkit-slider-thumb{transform:scale(1.25)}[type=range]:active::-moz-range-thumb{transform:scale(1.25)}[type=range]:active::-ms-thumb{transform:scale(1.25)}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search]{-webkit-padding-start:calc(var(--form-element-spacing-horizontal) + 1.75rem);padding-inline-start:calc(var(--form-element-spacing-horizontal) + 1.75rem);border-radius:5rem;background-image:var(--icon-search);background-position:center left 1.125rem;background-size:1rem auto;background-repeat:no-repeat}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid]{-webkit-padding-start:calc(var(--form-element-spacing-horizontal) + 1.75rem)!important;padding-inline-start:calc(var(--form-element-spacing-horizontal) + 1.75rem)!important;background-position:center left 1.125rem,center right .75rem}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid=false]{background-image:var(--icon-search),var(--icon-valid)}input:not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid=true]{background-image:var(--icon-search),var(--icon-invalid)}[type=search]::-webkit-search-cancel-button{-webkit-appearance:none;display:none}[dir=rtl] :where(input):not([type=checkbox],[type=radio],[type=range],[type=file])[type=search]{background-position:center right 1.125rem}[dir=rtl] :where(input):not([type=checkbox],[type=radio],[type=range],[type=file])[type=search][aria-invalid]{background-position:center right 1.125rem,center left .75rem}:where(table){width:100%;border-collapse:collapse;border-spacing:0;text-indent:0}td,th{padding:calc(var(--spacing)/ 2) var(--spacing);border-bottom:var(--border-width) solid var(--table-border-color);color:var(--color);font-weight:var(--font-weight);font-size:var(--font-size);text-align:left;text-align:start}tfoot td,tfoot th{border-top:var(--border-width) solid var(--table-border-color);border-bottom:0}table[role=grid] tbody tr:nth-child(odd){background-color:var(--table-row-stripped-background-color)}code,kbd,pre,samp{font-size:.875em;font-family:var(--font-family)}pre{-ms-overflow-style:scrollbar;overflow:auto}code,kbd,pre{border-radius:var(--border-radius);background:var(--code-background-color);color:var(--code-color);font-weight:var(--font-weight);line-height:initial}code,kbd{display:inline-block;padding:.375rem .5rem}pre{display:block;margin-bottom:var(--spacing);overflow-x:auto}pre>code{display:block;padding:var(--spacing);background:0 0;font-size:14px;line-height:var(--line-height)}code b{color:var(--code-tag-color);font-weight:var(--font-weight)}code i{color:var(--code-property-color);font-style:normal}code u{color:var(--code-value-color);text-decoration:none}code em{color:var(--code-comment-color);font-style:normal}kbd{background-color:var(--code-kbd-background-color);color:var(--code-kbd-color);vertical-align:baseline}hr{height:0;border:0;border-top:1px solid var(--muted-border-color);color:inherit}[hidden],template{display:none!important}canvas{display:inline-block}details{display:block;margin-bottom:var(--spacing);padding-bottom:var(--spacing);border-bottom:var(--border-width) solid var(--accordion-border-color)}details summary{line-height:1rem;list-style-type:none;cursor:pointer;transition:color var(--transition)}details summary:not([role]){color:var(--accordion-close-summary-color)}details summary::-webkit-details-marker{display:none}details summary::marker{display:none}details summary::-moz-list-bullet{list-style-type:none}details summary::after{display:block;width:1rem;height:1rem;-webkit-margin-start:calc(var(--spacing,1rem) * 0.5);margin-inline-start:calc(var(--spacing,1rem) * .5);float:right;transform:rotate(-90deg);background-image:var(--icon-chevron);background-position:right center;background-size:1rem auto;background-repeat:no-repeat;content:"";transition:transform var(--transition)}details summary:focus{outline:0}details summary:focus:not([role=button]){color:var(--accordion-active-summary-color)}details summary[role=button]{width:100%;text-align:left}details summary[role=button]::after{height:calc(1rem * var(--line-height,1.5));background-image:var(--icon-chevron-button)}details summary[role=button]:not(.outline).contrast::after{background-image:var(--icon-chevron-button-inverse)}details[open]>summary{margin-bottom:calc(var(--spacing))}details[open]>summary:not([role]):not(:focus){color:var(--accordion-open-summary-color)}details[open]>summary::after{transform:rotate(0)}[dir=rtl] details summary{text-align:right}[dir=rtl] details summary::after{float:left;background-position:left center}article{margin:var(--block-spacing-vertical) 0;padding:var(--block-spacing-vertical) var(--block-spacing-horizontal);border-radius:var(--border-radius);background:var(--card-background-color);box-shadow:var(--card-box-shadow)}article>footer,article>header{margin-right:calc(var(--block-spacing-horizontal) * -1);margin-left:calc(var(--block-spacing-horizontal) * -1);padding:calc(var(--block-spacing-vertical) * .66) var(--block-spacing-horizontal);background-color:var(--card-sectionning-background-color)}article>header{margin-top:calc(var(--block-spacing-vertical) * -1);margin-bottom:var(--block-spacing-vertical);border-bottom:var(--border-width) solid var(--card-border-color);border-top-right-radius:var(--border-radius);border-top-left-radius:var(--border-radius)}article>footer{margin-top:var(--block-spacing-vertical);margin-bottom:calc(var(--block-spacing-vertical) * -1);border-top:var(--border-width) solid var(--card-border-color);border-bottom-right-radius:var(--border-radius);border-bottom-left-radius:var(--border-radius)}:root{--scrollbar-width:0px}dialog{display:flex;z-index:999;position:fixed;top:0;right:0;bottom:0;left:0;align-items:center;justify-content:center;width:inherit;min-width:100%;height:inherit;min-height:100%;padding:var(--spacing);border:0;-webkit-backdrop-filter:var(--modal-overlay-backdrop-filter);backdrop-filter:var(--modal-overlay-backdrop-filter);background-color:var(--modal-overlay-background-color);color:var(--color)}dialog article{max-height:calc(100vh - var(--spacing) * 2);overflow:auto}@media (min-width:576px){dialog article{max-width:510px}}@media (min-width:768px){dialog article{max-width:700px}}dialog article>footer,dialog article>header{padding:calc(var(--block-spacing-vertical) * .5) var(--block-spacing-horizontal)}dialog article>header .close{margin:0;margin-left:var(--spacing);float:right}dialog article>footer{text-align:right}dialog article>footer [role=button]{margin-bottom:0}dialog article>footer [role=button]:not(:first-of-type){margin-left:calc(var(--spacing) * .5)}dialog article p:last-of-type{margin:0}dialog article .close{display:block;width:1rem;height:1rem;margin-top:calc(var(--block-spacing-vertical) * -.5);margin-bottom:var(--typography-spacing-vertical);margin-left:auto;background-image:var(--icon-close);background-position:center;background-size:auto 1rem;background-repeat:no-repeat;opacity:.5;transition:opacity var(--transition)}dialog article .close:is([aria-current],:hover,:active,:focus){opacity:1}dialog:not([open]),dialog[open=false]{display:none}.modal-is-open{padding-right:var(--scrollbar-width,0);overflow:hidden;pointer-events:none;touch-action:none}.modal-is-open dialog{pointer-events:auto}:where(.modal-is-opening,.modal-is-closing) dialog,:where(.modal-is-opening,.modal-is-closing) dialog>article{animation-duration:.2s;animation-timing-function:ease-in-out;animation-fill-mode:both}:where(.modal-is-opening,.modal-is-closing) dialog{animation-duration:.8s;animation-name:modal-overlay}:where(.modal-is-opening,.modal-is-closing) dialog>article{animation-delay:.2s;animation-name:modal}.modal-is-closing dialog,.modal-is-closing dialog>article{animation-delay:0s;animation-direction:reverse}@keyframes modal-overlay{from{-webkit-backdrop-filter:none;backdrop-filter:none;background-color:transparent}}@keyframes modal{from{transform:translateY(-100%);opacity:0}}:where(nav li)::before{float:left;content:""}nav,nav ul{display:flex}nav{justify-content:space-between}nav ol,nav ul{align-items:center;margin-bottom:0;padding:0;list-style:none}nav ol:first-of-type,nav ul:first-of-type{margin-left:calc(var(--nav-element-spacing-horizontal) * -1)}nav ol:last-of-type,nav ul:last-of-type{margin-right:calc(var(--nav-element-spacing-horizontal) * -1)}nav li{display:inline-block;margin:0;padding:var(--nav-element-spacing-vertical) var(--nav-element-spacing-horizontal)}nav li>*{--spacing:0}nav :where(a,[role=link]){display:inline-block;margin:calc(var(--nav-link-spacing-vertical) * -1) calc(var(--nav-link-spacing-horizontal) * -1);padding:var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal);border-radius:var(--border-radius);text-decoration:none}nav :where(a,[role=link]):is([aria-current],:hover,:active,:focus){text-decoration:none}nav[aria-label=breadcrumb]{align-items:center;justify-content:start}nav[aria-label=breadcrumb] ul li:not(:first-child){-webkit-margin-start:var(--nav-link-spacing-horizontal);margin-inline-start:var(--nav-link-spacing-horizontal)}nav[aria-label=breadcrumb] ul li:not(:last-child) ::after{position:absolute;width:calc(var(--nav-link-spacing-horizontal) * 2);-webkit-margin-start:calc(var(--nav-link-spacing-horizontal)/ 2);margin-inline-start:calc(var(--nav-link-spacing-horizontal)/ 2);content:"/";color:var(--muted-color);text-align:center}nav[aria-label=breadcrumb] a[aria-current]{background-color:transparent;color:inherit;text-decoration:none;pointer-events:none}nav [role=button]{margin-right:inherit;margin-left:inherit;padding:var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal)}aside li,aside nav,aside ol,aside ul{display:block}aside li{padding:calc(var(--nav-element-spacing-vertical) * .5) var(--nav-element-spacing-horizontal)}aside li a{display:block}aside li [role=button]{margin:inherit}[dir=rtl] nav[aria-label=breadcrumb] ul li:not(:last-child) ::after{content:"\\"}progress{display:inline-block;vertical-align:baseline}progress{-webkit-appearance:none;-moz-appearance:none;display:inline-block;appearance:none;width:100%;height:.5rem;margin-bottom:calc(var(--spacing) * .5);overflow:hidden;border:0;border-radius:var(--border-radius);background-color:var(--progress-background-color);color:var(--progress-color)}progress::-webkit-progress-bar{border-radius:var(--border-radius);background:0 0}progress[value]::-webkit-progress-value{background-color:var(--progress-color)}progress::-moz-progress-bar{background-color:var(--progress-color)}@media (prefers-reduced-motion:no-preference){progress:indeterminate{background:var(--progress-background-color) linear-gradient(to right,var(--progress-color) 30%,var(--progress-background-color) 30%) top left/150% 150% no-repeat;animation:progress-indeterminate 1s linear infinite}progress:indeterminate[value]::-webkit-progress-value{background-color:transparent}progress:indeterminate::-moz-progress-bar{background-color:transparent}}@media (prefers-reduced-motion:no-preference){[dir=rtl] progress:indeterminate{animation-direction:reverse}}@keyframes progress-indeterminate{0%{background-position:200% 0}100%{background-position:-200% 0}}details[role=list],li[role=list]{position:relative}details[role=list] summary+ul,li[role=list]>ul{display:flex;z-index:99;position:absolute;top:auto;right:0;left:0;flex-direction:column;margin:0;padding:0;border:var(--border-width) solid var(--dropdown-border-color);border-radius:var(--border-radius);border-top-right-radius:0;border-top-left-radius:0;background-color:var(--dropdown-background-color);box-shadow:var(--card-box-shadow);color:var(--dropdown-color);white-space:nowrap}details[role=list] summary+ul li,li[role=list]>ul li{width:100%;margin-bottom:0;padding:calc(var(--form-element-spacing-vertical) * .5) var(--form-element-spacing-horizontal);list-style:none}details[role=list] summary+ul li:first-of-type,li[role=list]>ul li:first-of-type{margin-top:calc(var(--form-element-spacing-vertical) * .5)}details[role=list] summary+ul li:last-of-type,li[role=list]>ul li:last-of-type{margin-bottom:calc(var(--form-element-spacing-vertical) * .5)}details[role=list] summary+ul li a,li[role=list]>ul li a{display:block;margin:calc(var(--form-element-spacing-vertical) * -.5) calc(var(--form-element-spacing-horizontal) * -1);padding:calc(var(--form-element-spacing-vertical) * .5) var(--form-element-spacing-horizontal);overflow:hidden;color:var(--dropdown-color);text-decoration:none;text-overflow:ellipsis}details[role=list] summary+ul li a:hover,li[role=list]>ul li a:hover{background-color:var(--dropdown-hover-background-color)}details[role=list] summary::after,li[role=list]>a::after{display:block;width:1rem;height:calc(1rem * var(--line-height,1.5));-webkit-margin-start:0.5rem;margin-inline-start:.5rem;float:right;transform:rotate(0);background-position:right center;background-size:1rem auto;background-repeat:no-repeat;content:""}details[role=list]{padding:0;border-bottom:none}details[role=list] summary{margin-bottom:0}details[role=list] summary:not([role]){height:calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2);padding:var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);border:var(--border-width) solid var(--form-element-border-color);border-radius:var(--border-radius);background-color:var(--form-element-background-color);color:var(--form-element-placeholder-color);line-height:inherit;cursor:pointer;transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}details[role=list] summary:not([role]):active,details[role=list] summary:not([role]):focus{border-color:var(--form-element-active-border-color);background-color:var(--form-element-active-background-color)}details[role=list] summary:not([role]):focus{box-shadow:0 0 0 var(--outline-width) var(--form-element-focus-color)}details[role=list][open] summary{border-bottom-right-radius:0;border-bottom-left-radius:0}details[role=list][open] summary::before{display:block;z-index:1;position:fixed;top:0;right:0;bottom:0;left:0;background:0 0;content:"";cursor:default}nav details[role=list] summary,nav li[role=list] a{display:flex;direction:ltr}nav details[role=list] summary+ul,nav li[role=list]>ul{min-width:-moz-fit-content;min-width:fit-content;border-radius:var(--border-radius)}nav details[role=list] summary+ul li a,nav li[role=list]>ul li a{border-radius:0}nav details[role=list] summary,nav details[role=list] summary:not([role]){height:auto;padding:var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal)}nav details[role=list][open] summary{border-radius:var(--border-radius)}nav details[role=list] summary+ul{margin-top:var(--outline-width);-webkit-margin-start:0;margin-inline-start:0}nav details[role=list] summary[role=link]{margin-bottom:calc(var(--nav-link-spacing-vertical) * -1);line-height:var(--line-height)}nav details[role=list] summary[role=link]+ul{margin-top:calc(var(--nav-link-spacing-vertical) + var(--outline-width));-webkit-margin-start:calc(var(--nav-link-spacing-horizontal) * -1);margin-inline-start:calc(var(--nav-link-spacing-horizontal) * -1)}li[role=list] a:active~ul,li[role=list] a:focus~ul,li[role=list]:hover>ul{display:flex}li[role=list]>ul{display:none;margin-top:calc(var(--nav-link-spacing-vertical) + var(--outline-width));-webkit-margin-start:calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal));margin-inline-start:calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal))}li[role=list]>a::after{background-image:var(--icon-chevron)}label>details[role=list]{margin-top:calc(var(--spacing) * .25);margin-bottom:var(--spacing)}[aria-busy=true]{cursor:progress}[aria-busy=true]:not(input,select,textarea,html)::before{display:inline-block;width:1em;height:1em;border:.1875em solid currentColor;border-radius:1em;border-right-color:transparent;content:"";vertical-align:text-bottom;vertical-align:-.125em;animation:spinner .75s linear infinite;opacity:var(--loading-spinner-opacity)}[aria-busy=true]:not(input,select,textarea,html):not(:empty)::before{margin-right:calc(var(--spacing) * .5);margin-left:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:calc(var(--spacing) * .5);margin-inline-end:calc(var(--spacing) * .5)}[aria-busy=true]:not(input,select,textarea,html):empty{text-align:center}a[aria-busy=true],button[aria-busy=true],input[type=button][aria-busy=true],input[type=reset][aria-busy=true],input[type=submit][aria-busy=true]{pointer-events:none}@keyframes spinner{to{transform:rotate(360deg)}}[data-tooltip]{position:relative}[data-tooltip]:not(a,button,input){border-bottom:1px dotted;text-decoration:none;cursor:help}[data-tooltip]::after,[data-tooltip]::before,[data-tooltip][data-placement=top]::after,[data-tooltip][data-placement=top]::before{display:block;z-index:99;position:absolute;bottom:100%;left:50%;padding:.25rem .5rem;overflow:hidden;transform:translate(-50%,-.25rem);border-radius:var(--border-radius);background:var(--tooltip-background-color);content:attr(data-tooltip);color:var(--tooltip-color);font-style:normal;font-weight:var(--font-weight);font-size:.875rem;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;opacity:0;pointer-events:none}[data-tooltip]::after,[data-tooltip][data-placement=top]::after{padding:0;transform:translate(-50%,0);border-top:.3rem solid;border-right:.3rem solid transparent;border-left:.3rem solid transparent;border-radius:0;background-color:transparent;content:"";color:var(--tooltip-background-color)}[data-tooltip][data-placement=bottom]::after,[data-tooltip][data-placement=bottom]::before{top:100%;bottom:auto;transform:translate(-50%,.25rem)}[data-tooltip][data-placement=bottom]:after{transform:translate(-50%,-.3rem);border:.3rem solid transparent;border-bottom:.3rem solid}[data-tooltip][data-placement=left]::after,[data-tooltip][data-placement=left]::before{top:50%;right:100%;bottom:auto;left:auto;transform:translate(-.25rem,-50%)}[data-tooltip][data-placement=left]:after{transform:translate(.3rem,-50%);border:.3rem solid transparent;border-left:.3rem solid}[data-tooltip][data-placement=right]::after,[data-tooltip][data-placement=right]::before{top:50%;right:auto;bottom:auto;left:100%;transform:translate(.25rem,-50%)}[data-tooltip][data-placement=right]:after{transform:translate(-.3rem,-50%);border:.3rem solid transparent;border-right:.3rem solid}[data-tooltip]:focus::after,[data-tooltip]:focus::before,[data-tooltip]:hover::after,[data-tooltip]:hover::before{opacity:1}@media (hover:hover) and (pointer:fine){[data-tooltip]:hover::after,[data-tooltip]:hover::before,[data-tooltip][data-placement=bottom]:focus::after,[data-tooltip][data-placement=bottom]:focus::before,[data-tooltip][data-placement=bottom]:hover [data-tooltip]:focus::after,[data-tooltip][data-placement=bottom]:hover [data-tooltip]:focus::before{animation-duration:.2s;animation-name:tooltip-slide-top}[data-tooltip]:hover::after,[data-tooltip][data-placement=bottom]:focus::after,[data-tooltip][data-placement=bottom]:hover [data-tooltip]:focus::after{animation-name:tooltip-caret-slide-top}[data-tooltip][data-placement=bottom]:focus::after,[data-tooltip][data-placement=bottom]:focus::before,[data-tooltip][data-placement=bottom]:hover::after,[data-tooltip][data-placement=bottom]:hover::before{animation-duration:.2s;animation-name:tooltip-slide-bottom}[data-tooltip][data-placement=bottom]:focus::after,[data-tooltip][data-placement=bottom]:hover::after{animation-name:tooltip-caret-slide-bottom}[data-tooltip][data-placement=left]:focus::after,[data-tooltip][data-placement=left]:focus::before,[data-tooltip][data-placement=left]:hover::after,[data-tooltip][data-placement=left]:hover::before{animation-duration:.2s;animation-name:tooltip-slide-left}[data-tooltip][data-placement=left]:focus::after,[data-tooltip][data-placement=left]:hover::after{animation-name:tooltip-caret-slide-left}[data-tooltip][data-placement=right]:focus::after,[data-tooltip][data-placement=right]:focus::before,[data-tooltip][data-placement=right]:hover::after,[data-tooltip][data-placement=right]:hover::before{animation-duration:.2s;animation-name:tooltip-slide-right}[data-tooltip][data-placement=right]:focus::after,[data-tooltip][data-placement=right]:hover::after{animation-name:tooltip-caret-slide-right}}@keyframes tooltip-slide-top{from{transform:translate(-50%,.75rem);opacity:0}to{transform:translate(-50%,-.25rem);opacity:1}}@keyframes tooltip-caret-slide-top{from{opacity:0}50%{transform:translate(-50%,-.25rem);opacity:0}to{transform:translate(-50%,0);opacity:1}}@keyframes tooltip-slide-bottom{from{transform:translate(-50%,-.75rem);opacity:0}to{transform:translate(-50%,.25rem);opacity:1}}@keyframes tooltip-caret-slide-bottom{from{opacity:0}50%{transform:translate(-50%,-.5rem);opacity:0}to{transform:translate(-50%,-.3rem);opacity:1}}@keyframes tooltip-slide-left{from{transform:translate(.75rem,-50%);opacity:0}to{transform:translate(-.25rem,-50%);opacity:1}}@keyframes tooltip-caret-slide-left{from{opacity:0}50%{transform:translate(.05rem,-50%);opacity:0}to{transform:translate(.3rem,-50%);opacity:1}}@keyframes tooltip-slide-right{from{transform:translate(-.75rem,-50%);opacity:0}to{transform:translate(.25rem,-50%);opacity:1}}@keyframes tooltip-caret-slide-right{from{opacity:0}50%{transform:translate(-.05rem,-50%);opacity:0}to{transform:translate(-.3rem,-50%);opacity:1}}[aria-controls]{cursor:pointer}[aria-disabled=true],[disabled]{cursor:not-allowed}[aria-hidden=false][hidden]{display:initial}[aria-hidden=false][hidden]:not(:focus){clip:rect(0,0,0,0);position:absolute}[tabindex],a,area,button,input,label,select,summary,textarea{-ms-touch-action:manipulation}[dir=rtl]{direction:rtl}@media (prefers-reduced-motion:reduce){:not([aria-busy=true]),:not([aria-busy=true])::after,:not([aria-busy=true])::before{background-attachment:initial!important;animation-duration:1ms!important;animation-delay:-1ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-delay:0s!important;transition-duration:0s!important}}
+/*# sourceMappingURL=pico.min.css.map */
diff --git a/src/interface/desktop/chat.html b/src/interface/desktop/chat.html
new file mode 100644
index 00000000..21a1a416
--- /dev/null
+++ b/src/interface/desktop/chat.html
@@ -0,0 +1,559 @@
+
+
+
+
+ Khoj - Chat
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/interface/desktop/config.html b/src/interface/desktop/config.html
new file mode 100644
index 00000000..09610296
--- /dev/null
+++ b/src/interface/desktop/config.html
@@ -0,0 +1,342 @@
+
+
+
+
+ Khoj - Search
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Host
+
+
+
+
+
+
+
+
+ Files
+
+
+
+
+
+
+
+ Folders
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/interface/desktop/index.html b/src/interface/desktop/index.html
new file mode 100644
index 00000000..6b3c7e32
--- /dev/null
+++ b/src/interface/desktop/index.html
@@ -0,0 +1,499 @@
+
+
+
+
+ Khoj - Search
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/interface/desktop/main.js b/src/interface/desktop/main.js
new file mode 100644
index 00000000..097b799c
--- /dev/null
+++ b/src/interface/desktop/main.js
@@ -0,0 +1,359 @@
+const { app, BrowserWindow, ipcMain } = require('electron');
+const todesktop = require("@todesktop/runtime");
+
+todesktop.init();
+
+const fs = require('fs');
+const {dialog} = require('electron');
+
+const cron = require('cron').CronJob;
+const axios = require('axios');
+const { Readable } = require('stream');
+
+const KHOJ_URL = 'http://127.0.0.1:42110'
+
+const Store = require('electron-store');
+
+const validFileTypes = ['org', 'md', 'markdown', 'txt', 'html', 'xml', 'pdf']
+
+const binaryFileTypes = ['pdf', 'png', 'jpg', 'jpeg']
+
+const schema = {
+ files: {
+ type: 'array',
+ items: {
+ type: 'object',
+ properties: {
+ path: {
+ type: 'string'
+ }
+ }
+ },
+ default: []
+ },
+ folders: {
+ type: 'array',
+ items: {
+ type: 'object',
+ properties: {
+ path: {
+ type: 'string'
+ }
+ }
+ },
+ default: []
+ },
+ hostURL: {
+ type: 'string',
+ default: KHOJ_URL
+ },
+ lastSync: {
+ type: 'array',
+ items: {
+ type: 'object',
+ properties: {
+ path: {
+ type: 'string'
+ },
+ datetime: {
+ type: 'string'
+ }
+ }
+ }
+ }
+};
+
+var state = {}
+
+const store = new Store({schema});
+
+console.log(store);
+
+// include the Node.js 'path' module at the top of your file
+const path = require('path');
+
+function handleSetTitle (event, title) {
+ const webContents = event.sender
+ const win = BrowserWindow.fromWebContents(webContents)
+ win.setTitle(title)
+ dialog.showOpenDialog({properties: ['openFile', 'openDirectory'] }).then(function (response) {
+ if (!response.canceled) {
+ // handle fully qualified file name
+ console.log(response.filePaths[0]);
+ } else {
+ console.log("no file selected");
+ }
+ });
+}
+
+function pushDataToKhoj () {
+ let filesToPush = [];
+ const files = store.get('files');
+ const folders = store.get('folders');
+ state = {
+ completed: true
+ }
+
+ if (files) {
+ for (file of files) {
+ filesToPush.push(file.path);
+ }
+ }
+ if (folders) {
+ for (folder of folders) {
+ const files = fs.readdirSync(folder.path, { withFileTypes: true });
+ for (file of files) {
+ if (file.isFile() && validFileTypes.includes(file.name.split('.').pop())) {
+ filesToPush.push(path.join(folder.path, file.name));
+ }
+ }
+ }
+ }
+
+ let data = {
+ files: []
+ }
+
+ const lastSync = store.get('lastSync') || [];
+
+ for (file of filesToPush) {
+ const stats = fs.statSync(file);
+ if (stats.mtime.toISOString() < lastSync.find((syncedFile) => syncedFile.path === file)?.datetime) {
+ continue;
+ }
+ try {
+ let rawData;
+ // If the file is a PDF or IMG file, read it as a binary file
+ if (binaryFileTypes.includes(file.split('.').pop())) {
+ rawData = fs.readFileSync(file).toString('base64');
+ } else {
+ rawData = fs.readFileSync(file, 'utf8');
+ }
+
+ data.files.push({
+ path: file,
+ content: rawData
+ });
+ state[file] = {
+ success: true,
+ }
+ } catch (err) {
+ console.error(err);
+ state[file] = {
+ success: false,
+ error: err
+ }
+ }
+ }
+
+ for (const syncedFile of lastSync) {
+ if (!filesToPush.includes(syncedFile.path)) {
+ data.files.push({
+ path: syncedFile.path,
+ content: ""
+ });
+ }
+ }
+
+ const headers = { 'x-api-key': 'secret', 'Content-Type': 'application/json' };
+
+ const stream = new Readable({
+ read() {
+ this.push(JSON.stringify(data));
+ this.push(null);
+ }
+ });
+
+ const hostURL = store.get('hostURL') || KHOJ_URL;
+
+ axios.post(`${hostURL}/v1/indexer/batch`, stream, { headers })
+ .then(response => {
+ console.log(response.data);
+ const win = BrowserWindow.getAllWindows()[0];
+ win.webContents.send('update-state', state);
+ let lastSync = [];
+ for (const file of filesToPush) {
+ lastSync.push({
+ path: file,
+ datetime: new Date().toISOString()
+ });
+ }
+ store.set('lastSync', lastSync);
+ })
+ .catch(error => {
+ console.error(error);
+ state['completed'] = false
+ const win = BrowserWindow.getAllWindows()[0];
+ win.webContents.send('update-state', state);
+ });
+
+}
+
+pushDataToKhoj();
+
+async function handleFileOpen (event, key) {
+ const { canceled, filePaths } = await dialog.showOpenDialog({properties: ['openFile', 'openDirectory'], filters: [{ name: "Valid Khoj Files", extensions: validFileTypes}] });
+ if (!canceled) {
+ const files = store.get('files') || [];
+ const folders = store.get('folders') || [];
+
+ for (const filePath of filePaths) {
+ console.log(filePath);
+ if (fs.existsSync(filePath)) {
+ const stats = fs.statSync(filePath);
+ if (stats.isFile()) {
+ console.log(`${filePath} is a file.`);
+
+ if (files.find((file) => file.path === filePath)) {
+ continue;
+ }
+
+ files.push({path: filePath});
+ store.set('files', files);
+ } else if (stats.isDirectory()) {
+ console.log(`${filePath} is a directory.`);
+
+ if (folders.find((folder) => folder.path === filePath)) {
+ continue;
+ }
+
+ folders.push({path: filePath});
+ store.set('folders', folders);
+ }
+
+ } else {
+ console.log(`${filePath} does not exist.`);
+ }
+ }
+ return {
+ files: store.get('files'),
+ folders: store.get('folders')
+ }
+ }
+}
+
+async function getFiles () {
+ return store.get('files');
+}
+
+async function getFolders () {
+ return store.get('folders');
+}
+
+async function setURL (event, url) {
+ store.set('hostURL', url);
+ return store.get('hostURL');
+}
+
+async function getURL () {
+ return store.get('hostURL');
+}
+
+async function removeFile (event, filePath) {
+ const files = store.get('files');
+ const newFiles = files.filter((file) => file.path !== filePath);
+ store.set('files', newFiles);
+ return newFiles;
+}
+
+async function removeFolder (event, folderPath) {
+ const folders = store.get('folders');
+ const newFolders = folders.filter((folder) => folder.path !== folderPath);
+ store.set('folders', newFolders);
+ return newFolders;
+}
+
+async function syncData () {
+ try {
+ pushDataToKhoj();
+ const date = new Date();
+ console.log('Pushing data to Khoj at: ', date);
+ } catch (err) {
+ console.error(err);
+ }
+}
+
+const createWindow = () => {
+ const win = new BrowserWindow({
+ width: 800,
+ height: 800,
+ // titleBarStyle: 'hidden',
+ webPreferences: {
+ preload: path.join(__dirname, 'preload.js'),
+ nodeIntegration: true,
+ }
+ })
+
+ const job = new cron('0 */10 * * * *', function() {
+ try {
+ pushDataToKhoj();
+ const date = new Date();
+ console.log('Pushing data to Khoj at: ', date);
+ win.webContents.send('update-state', state);
+ } catch (err) {
+ console.error(err);
+ }
+ });
+
+ win.setResizable(true);
+ win.setOpacity(0.95);
+ win.setBackgroundColor('#FFFFFF');
+ win.setHasShadow(true);
+
+ job.start();
+
+ win.loadFile('index.html')
+}
+
+app.whenReady().then(() => {
+ ipcMain.on('set-title', handleSetTitle);
+
+ ipcMain.handle('getStoreValue', handleFileOpen);
+
+ ipcMain.on('update-state', (event, arg) => {
+ console.log(arg);
+ event.reply('update-state', arg);
+ });
+
+ ipcMain.handle('getFiles', getFiles);
+ ipcMain.handle('getFolders', getFolders);
+
+ ipcMain.handle('removeFile', removeFile);
+ ipcMain.handle('removeFolder', removeFolder);
+
+ ipcMain.handle('setURL', setURL);
+ ipcMain.handle('getURL', getURL);
+
+ ipcMain.handle('syncData', syncData);
+
+ createWindow()
+
+ app.setAboutPanelOptions({
+ applicationName: "Khoj",
+ applicationVersion: "0.0.1",
+ version: "0.0.1",
+ authors: "Khoj Team",
+ website: "https://khoj.dev",
+ iconPath: path.join(__dirname, 'assets', 'khoj.png')
+ });
+
+ app.on('ready', async() => {
+ try {
+ const result = await todesktop.autoUpdater.checkForUpdates();
+ if (result.updateInfo) {
+ console.log("Update found:", result.updateInfo.version);
+ todesktop.autoUpdater.restartAndInstall();
+ }
+ } catch (e) {
+ console.log("Update check failed:", e);
+ }
+ })
+
+ app.on('activate', () => {
+ if (BrowserWindow.getAllWindows().length === 0) createWindow()
+ })
+})
+
+app.on('window-all-closed', () => {
+ if (process.platform !== 'darwin') app.quit()
+})
diff --git a/src/interface/desktop/package.json b/src/interface/desktop/package.json
new file mode 100644
index 00000000..34e27d09
--- /dev/null
+++ b/src/interface/desktop/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "Khoj",
+ "homepage": ".",
+ "productName": "Khoj",
+ "version": "1.0.0",
+ "description": "Scaffolding for the desktop entrypoint to Khoj",
+ "main": "main.js",
+ "repository": "\"https://github.com/khoj-ai/khoj\"",
+ "author": "Khoj ",
+ "license": "MIT",
+ "private": false,
+ "devDependencies": {
+ "electron": "26.1.0"
+ },
+ "scripts": {
+ "start": "yarn electron ."
+ },
+ "dependencies": {
+ "@todesktop/runtime": "^1.3.0",
+ "axios": "^1.5.0",
+ "cron": "^2.4.3",
+ "electron-store": "^8.1.0",
+ "fs": "^0.0.1-security"
+ }
+}
diff --git a/src/interface/desktop/preload.js b/src/interface/desktop/preload.js
new file mode 100644
index 00000000..8b4ec59e
--- /dev/null
+++ b/src/interface/desktop/preload.js
@@ -0,0 +1,49 @@
+window.addEventListener('DOMContentLoaded', () => {
+ const replaceText = (selector, text) => {
+ const element = document.getElementById(selector)
+ if (element) element.innerText = text
+ }
+
+ for (const dependency of ['chrome', 'node', 'electron']) {
+ replaceText(`${dependency}-version`, process.versions[dependency])
+ }
+})
+
+const { contextBridge, ipcRenderer } = require('electron');
+
+contextBridge.exposeInMainWorld('electronAPI', {
+ setTitle: (title) => ipcRenderer.send('set-title', title)
+})
+
+contextBridge.exposeInMainWorld('storeValueAPI', {
+ getStoreValue: (key) => ipcRenderer.invoke('getStoreValue', key)
+})
+
+contextBridge.exposeInMainWorld('getFilesAPI', {
+ getFiles: () => ipcRenderer.invoke('getFiles')
+})
+
+contextBridge.exposeInMainWorld('getFoldersAPI', {
+ getFolders: () => ipcRenderer.invoke('getFolders')
+})
+
+contextBridge.exposeInMainWorld('updateStateAPI', {
+ onUpdateState: (callback) => ipcRenderer.on('update-state', callback)
+})
+
+contextBridge.exposeInMainWorld('removeFileAPI', {
+ removeFile: (filePath) => ipcRenderer.invoke('removeFile', filePath)
+})
+
+contextBridge.exposeInMainWorld('removeFolderAPI', {
+ removeFolder: (folderPath) => ipcRenderer.invoke('removeFolder', folderPath)
+})
+
+contextBridge.exposeInMainWorld('hostURLAPI', {
+ setURL: (url) => ipcRenderer.invoke('setURL', url),
+ getURL: () => ipcRenderer.invoke('getURL')
+})
+
+contextBridge.exposeInMainWorld('syncDataAPI', {
+ syncData: () => ipcRenderer.invoke('syncData')
+})
diff --git a/src/interface/desktop/renderer.js b/src/interface/desktop/renderer.js
new file mode 100644
index 00000000..a60805cb
--- /dev/null
+++ b/src/interface/desktop/renderer.js
@@ -0,0 +1,177 @@
+const getButton = document.getElementById('update-data')
+const showKey = document.getElementById('show-key');
+
+async function removeFile(filePath) {
+ const updatedFiles = await window.removeFileAPI.removeFile(filePath);
+
+ let currentFilesElement = document.getElementById("current-files");
+ currentFilesElement.innerHTML = '';
+ for (const file of updatedFiles) {
+ console.log(file);
+ let fileElement = makeFileElement(file);
+ currentFilesElement.appendChild(fileElement);
+ }
+}
+
+async function removeFolder(folderPath) {
+ const updatedFolders = await window.removeFolderAPI.removeFolder(folderPath);
+
+ let currentFoldersElement = document.getElementById("current-folders");
+ currentFoldersElement.innerHTML = '';
+ for (const folder of updatedFolders) {
+ console.log(folder);
+ let folderElement = makeFolderElement(folder);
+ currentFoldersElement.appendChild(folderElement);
+ }
+}
+
+const toggleFilesButton = document.getElementById('toggle-files');
+const currentFiles = document.getElementById('current-files');
+
+const toggleFilesSVG = document.getElementById('toggle-files-svg');
+
+toggleFilesButton.addEventListener('click', () => {
+ if (currentFiles.style.display === 'none') {
+ currentFiles.style.display = 'block';
+ toggleFilesSVG.style.transform = 'rotate(0deg)';
+ } else {
+ currentFiles.style.display = 'none';
+ toggleFilesSVG.style.transform = 'rotate(180deg)';
+ }
+});
+
+const toggleFoldersButton = document.getElementById('toggle-folders');
+const currentFolders = document.getElementById('current-folders');
+
+const toggleFoldersSVG = document.getElementById('toggle-folders-svg');
+
+
+toggleFoldersButton.addEventListener('click', () => {
+ if (currentFolders.style.display === 'none') {
+ currentFolders.style.display = 'block';
+ toggleFoldersSVG.style.transform = 'rotate(0deg)';
+ } else {
+ currentFolders.style.display = 'none';
+ toggleFoldersSVG.style.transform = 'rotate(180deg)';
+ }
+});
+
+function makeFileElement(file) {
+ let fileElement = document.createElement("div");
+ fileElement.classList.add("file-element");
+ let fileNameElement = document.createElement("div");
+ fileNameElement.classList.add("content-name");
+ fileNameElement.innerHTML = file.path;
+ fileElement.appendChild(fileNameElement);
+
+ let buttonContainer = document.createElement("div");
+ buttonContainer.classList.add("remove-button-container");
+ let removeFileButton = document.createElement("button");
+ removeFileButton.classList.add("remove-file-button");
+ removeFileButton.innerHTML = "🗑️";
+ removeFileButton.addEventListener("click", () => {
+ removeFile(file.path);
+ });
+ buttonContainer.appendChild(removeFileButton);
+ fileElement.appendChild(buttonContainer);
+ return fileElement;
+}
+
+function makeFolderElement(folder) {
+ let folderElement = document.createElement("div");
+ folderElement.classList.add("folder-element");
+ let folderNameElement = document.createElement("div");
+ folderNameElement.classList.add("content-name");
+ folderNameElement.innerHTML = folder.path;
+ folderElement.appendChild(folderNameElement);
+
+ let buttonContainer = document.createElement("div");
+ buttonContainer.classList.add("remove-button-container");
+ let removeFolderButton = document.createElement("button");
+ removeFolderButton.classList.add("remove-folder-button");
+ removeFolderButton.innerHTML = "🗑️";
+ removeFolderButton.addEventListener("click", () => {
+ removeFolder(folder.path);
+ });
+ buttonContainer.appendChild(removeFolderButton);
+ folderElement.appendChild(buttonContainer);
+ return folderElement;
+}
+
+(async function() {
+ const files = await window.getFilesAPI.getFiles();
+ let currentFilesElement = document.getElementById("current-files");
+ for (const file of files) {
+ console.log(file);
+ let fileElement = makeFileElement(file);
+ currentFilesElement.appendChild(fileElement);
+ }
+
+ const folders = await window.getFoldersAPI.getFolders();
+ let currentFoldersElement = document.getElementById("current-folders");
+ for (const folder of folders) {
+ let folderElement = makeFolderElement(folder);
+ currentFoldersElement.appendChild(folderElement);
+ }
+})();
+
+getButton.addEventListener('click', async () => {
+ const key = 'foo';
+ const value = await window.storeValueAPI.getStoreValue(key);
+ console.log(value);
+ let currentFilesElement = document.getElementById("current-files");
+ let currentFoldersElement = document.getElementById("current-folders");
+
+ if (value.files) {
+ currentFilesElement.innerHTML = '';
+ value.files.forEach((file) => {
+ let fileElement = makeFileElement(file);
+ currentFilesElement.appendChild(fileElement);
+ });
+ }
+
+ if (value.folders) {
+ currentFoldersElement.innerHTML = '';
+ value.folders.forEach((folder) => {
+ let folderElement = makeFolderElement(folder);
+ currentFoldersElement.appendChild(folderElement);
+ });
+ }
+});
+
+window.updateStateAPI.onUpdateState((event, state) => {
+ console.log("state was updated", state);
+ let syncStatusElement = document.getElementById("sync-status");
+ const currentTime = new Date();
+ if (state.completed == false) {
+ syncStatusElement.innerHTML = `Sync was unsuccessful at ${currentTime.toLocaleTimeString()}. Contact team@khoj.dev to report this issue.`;
+ return;
+ }
+ syncStatusElement.innerHTML = `Last synced at ${currentTime.toLocaleTimeString()}`;
+});
+
+const urlInput = document.getElementById('khoj-host-url');
+(async function() {
+ const url = await window.hostURLAPI.getURL();
+ urlInput.value = url;
+})();
+
+urlInput.addEventListener('blur', async () => {
+ const urlInputValue = urlInput.value;
+
+ // Check if it's a valid URL
+ try {
+ new URL(urlInputValue);
+ } catch (e) {
+ console.log(e);
+ return;
+ }
+
+ const url = await window.hostURLAPI.setURL(urlInput.value.trim());
+ urlInput.value = url;
+});
+
+const syncButton = document.getElementById('sync-data');
+syncButton.addEventListener('click', async () => {
+ await window.syncDataAPI.syncData();
+});
diff --git a/src/interface/desktop/todesktop.json b/src/interface/desktop/todesktop.json
new file mode 100644
index 00000000..3313a0f5
--- /dev/null
+++ b/src/interface/desktop/todesktop.json
@@ -0,0 +1,6 @@
+{
+ "id": "",
+ "icon": "./assets/icons/favicon-128x128.png",
+ "appPath": ".",
+ "schemaVersion": 1
+}
diff --git a/src/interface/desktop/yarn.lock b/src/interface/desktop/yarn.lock
new file mode 100644
index 00000000..9fe6be69
--- /dev/null
+++ b/src/interface/desktop/yarn.lock
@@ -0,0 +1,1205 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@electron/get@^2.0.0":
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/@electron/get/-/get-2.0.2.tgz#ae2a967b22075e9c25aaf00d5941cd79c21efd7e"
+ integrity sha512-eFZVFoRXb3GFGd7Ak7W4+6jBl9wBtiZ4AaYOse97ej6mKj5tkyO0dUnUChs1IhJZtx1BENo4/p4WUTXpi6vT+g==
+ dependencies:
+ debug "^4.1.1"
+ env-paths "^2.2.0"
+ fs-extra "^8.1.0"
+ got "^11.8.5"
+ progress "^2.0.3"
+ semver "^6.2.0"
+ sumchecker "^3.0.1"
+ optionalDependencies:
+ global-agent "^3.0.0"
+
+"@nodelib/fs.scandir@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.5"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.walk@^1.2.3":
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
+"@sindresorhus/is@^4.0.0":
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f"
+ integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==
+
+"@szmarczak/http-timer@^4.0.5":
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807"
+ integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==
+ dependencies:
+ defer-to-connect "^2.0.0"
+
+"@todesktop/runtime@^1.3.0":
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/@todesktop/runtime/-/runtime-1.3.0.tgz#7baa64fd5c2e4daa591bda96270a0e39947ec3c7"
+ integrity sha512-a5USs4VxnqvtNqFR6F3bCaQ56W6WFO4VOPPaXefCYiCxcsFMYb4IulXGkYjvcpkU/MFGWzmVnzba6UwK7eQMUQ==
+ dependencies:
+ del "^6.0.0"
+ electron-updater "^4.6.1"
+ eventemitter2 "^6.4.5"
+ execa "^5.0.0"
+ lodash.once "^4.1.1"
+ semver "^7.3.2"
+
+"@types/cacheable-request@^6.0.1":
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183"
+ integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==
+ dependencies:
+ "@types/http-cache-semantics" "*"
+ "@types/keyv" "^3.1.4"
+ "@types/node" "*"
+ "@types/responselike" "^1.0.0"
+
+"@types/http-cache-semantics@*":
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812"
+ integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==
+
+"@types/keyv@^3.1.4":
+ version "3.1.4"
+ resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6"
+ integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==
+ dependencies:
+ "@types/node" "*"
+
+"@types/luxon@~3.3.0":
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-3.3.1.tgz#08727da7d81ee6a6c702b9dc6c8f86be010eb4dc"
+ integrity sha512-XOS5nBcgEeP2PpcqJHjCWhUCAzGfXIU8ILOSLpx2FhxqMW9KdxgCGXNOEKGVBfveKtIpztHzKK5vSRVLyW/NqA==
+
+"@types/node@*":
+ version "20.5.7"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.7.tgz#4b8ecac87fbefbc92f431d09c30e176fc0a7c377"
+ integrity sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==
+
+"@types/node@^18.11.18":
+ version "18.17.12"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.17.12.tgz#c6bd7413a13e6ad9cfb7e97dd5c4e904c1821e50"
+ integrity sha512-d6xjC9fJ/nSnfDeU0AMDsaJyb1iHsqCSOdi84w4u+SlN/UgQdY5tRhpMzaFYsI4mnpvgTivEaQd0yOUhAtOnEQ==
+
+"@types/responselike@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29"
+ integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==
+ dependencies:
+ "@types/node" "*"
+
+"@types/semver@^7.3.6":
+ version "7.5.1"
+ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.1.tgz#0480eeb7221eb9bc398ad7432c9d7e14b1a5a367"
+ integrity sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==
+
+"@types/yauzl@^2.9.1":
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599"
+ integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==
+ dependencies:
+ "@types/node" "*"
+
+aggregate-error@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
+ integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==
+ dependencies:
+ clean-stack "^2.0.0"
+ indent-string "^4.0.0"
+
+ajv-formats@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
+ integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==
+ dependencies:
+ ajv "^8.0.0"
+
+ajv@^8.0.0, ajv@^8.6.3:
+ version "8.12.0"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1"
+ integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ json-schema-traverse "^1.0.0"
+ require-from-string "^2.0.2"
+ uri-js "^4.2.2"
+
+argparse@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
+ integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+
+array-union@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
+atomically@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/atomically/-/atomically-1.7.0.tgz#c07a0458432ea6dbc9a3506fffa424b48bccaafe"
+ integrity sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==
+
+axios@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.0.tgz#f02e4af823e2e46a9768cfc74691fdd0517ea267"
+ integrity sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==
+ dependencies:
+ follow-redirects "^1.15.0"
+ form-data "^4.0.0"
+ proxy-from-env "^1.1.0"
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+boolean@^3.0.1:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b"
+ integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+braces@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ dependencies:
+ fill-range "^7.0.1"
+
+buffer-crc32@~0.2.3:
+ version "0.2.13"
+ resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
+ integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
+
+builder-util-runtime@8.9.2:
+ version "8.9.2"
+ resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz#a9669ae5b5dcabfe411ded26678e7ae997246c28"
+ integrity sha512-rhuKm5vh7E0aAmT6i8aoSfEjxzdYEFX7zDApK+eNgOhjofnWb74d9SRJv0H/8nsgOkos0TZ4zxW0P8J4N7xQ2A==
+ dependencies:
+ debug "^4.3.2"
+ sax "^1.2.4"
+
+cacheable-lookup@^5.0.3:
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005"
+ integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==
+
+cacheable-request@^7.0.2:
+ version "7.0.4"
+ resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817"
+ integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==
+ dependencies:
+ clone-response "^1.0.2"
+ get-stream "^5.1.0"
+ http-cache-semantics "^4.0.0"
+ keyv "^4.0.0"
+ lowercase-keys "^2.0.0"
+ normalize-url "^6.0.1"
+ responselike "^2.0.0"
+
+clean-stack@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
+ integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
+
+clone-response@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3"
+ integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==
+ dependencies:
+ mimic-response "^1.0.0"
+
+combined-stream@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
+conf@^10.2.0:
+ version "10.2.0"
+ resolved "https://registry.yarnpkg.com/conf/-/conf-10.2.0.tgz#838e757be963f1a2386dfe048a98f8f69f7b55d6"
+ integrity sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg==
+ dependencies:
+ ajv "^8.6.3"
+ ajv-formats "^2.1.1"
+ atomically "^1.7.0"
+ debounce-fn "^4.0.0"
+ dot-prop "^6.0.1"
+ env-paths "^2.2.1"
+ json-schema-typed "^7.0.3"
+ onetime "^5.1.2"
+ pkg-up "^3.1.0"
+ semver "^7.3.5"
+
+cron@^2.4.3:
+ version "2.4.3"
+ resolved "https://registry.yarnpkg.com/cron/-/cron-2.4.3.tgz#4e43d8d9a6373b8f28d876c4e9a47c14422d8652"
+ integrity sha512-YBvExkQYF7w0PxyeFLRyr817YVDhGxaCi5/uRRMqa4aWD3IFKRd+uNbpW1VWMdqQy8PZ7CElc+accXJcauPKzQ==
+ dependencies:
+ "@types/luxon" "~3.3.0"
+ luxon "~3.3.0"
+
+cross-spawn@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
+ integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+debounce-fn@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/debounce-fn/-/debounce-fn-4.0.0.tgz#ed76d206d8a50e60de0dd66d494d82835ffe61c7"
+ integrity sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==
+ dependencies:
+ mimic-fn "^3.0.0"
+
+debug@^4.1.0, debug@^4.1.1, debug@^4.3.2:
+ version "4.3.4"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
+decompress-response@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
+ integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==
+ dependencies:
+ mimic-response "^3.1.0"
+
+defer-to-connect@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587"
+ integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==
+
+define-properties@^1.1.3:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5"
+ integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==
+ dependencies:
+ has-property-descriptors "^1.0.0"
+ object-keys "^1.1.1"
+
+del@^6.0.0:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a"
+ integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==
+ dependencies:
+ globby "^11.0.1"
+ graceful-fs "^4.2.4"
+ is-glob "^4.0.1"
+ is-path-cwd "^2.2.0"
+ is-path-inside "^3.0.2"
+ p-map "^4.0.0"
+ rimraf "^3.0.2"
+ slash "^3.0.0"
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
+detect-node@^2.0.4:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
+ integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==
+
+dir-glob@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+ dependencies:
+ path-type "^4.0.0"
+
+dot-prop@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083"
+ integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==
+ dependencies:
+ is-obj "^2.0.0"
+
+electron-store@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-8.1.0.tgz#46a398f2bd9aa83c4a9daaae28380e2b3b9c7597"
+ integrity sha512-2clHg/juMjOH0GT9cQ6qtmIvK183B39ZXR0bUoPwKwYHJsEF3quqyDzMFUAu+0OP8ijmN2CbPRAelhNbWUbzwA==
+ dependencies:
+ conf "^10.2.0"
+ type-fest "^2.17.0"
+
+electron-updater@^4.6.1:
+ version "4.6.5"
+ resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.6.5.tgz#e9a75458bbfd6bb41a58a829839e150ad2eb2d3d"
+ integrity sha512-kdTly8O9mSZfm9fslc1mnCY+mYOeaYRy7ERa2Fed240u01BKll3aiupzkd07qKw69KvhBSzuHroIW3mF0D8DWA==
+ dependencies:
+ "@types/semver" "^7.3.6"
+ builder-util-runtime "8.9.2"
+ fs-extra "^10.0.0"
+ js-yaml "^4.1.0"
+ lazy-val "^1.0.5"
+ lodash.escaperegexp "^4.1.2"
+ lodash.isequal "^4.5.0"
+ semver "^7.3.5"
+
+electron@^26.1.0:
+ version "26.1.0"
+ resolved "https://registry.yarnpkg.com/electron/-/electron-26.1.0.tgz#d26fefba5a5c68069b07a117d87aee1c4e5d172d"
+ integrity sha512-qEh19H09Pysn3ibms5nZ0haIh5pFoOd7/5Ww7gzmAwDQOulRi8Sa2naeueOyIb1GKpf+6L4ix3iceYRAuA5r5Q==
+ dependencies:
+ "@electron/get" "^2.0.0"
+ "@types/node" "^18.11.18"
+ extract-zip "^2.0.1"
+
+end-of-stream@^1.1.0:
+ version "1.4.4"
+ resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
+ integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
+ dependencies:
+ once "^1.4.0"
+
+env-paths@^2.2.0, env-paths@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
+ integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
+
+es6-error@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d"
+ integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==
+
+escape-string-regexp@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
+ integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+
+eventemitter2@^6.4.5:
+ version "6.4.9"
+ resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.9.tgz#41f2750781b4230ed58827bc119d293471ecb125"
+ integrity sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==
+
+execa@^5.0.0:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
+ integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
+ dependencies:
+ cross-spawn "^7.0.3"
+ get-stream "^6.0.0"
+ human-signals "^2.1.0"
+ is-stream "^2.0.0"
+ merge-stream "^2.0.0"
+ npm-run-path "^4.0.1"
+ onetime "^5.1.2"
+ signal-exit "^3.0.3"
+ strip-final-newline "^2.0.0"
+
+extract-zip@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
+ integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
+ dependencies:
+ debug "^4.1.1"
+ get-stream "^5.1.0"
+ yauzl "^2.10.0"
+ optionalDependencies:
+ "@types/yauzl" "^2.9.1"
+
+fast-deep-equal@^3.1.1:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-glob@^3.2.9:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4"
+ integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==
+ 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"
+
+fastq@^1.6.0:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
+ integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==
+ dependencies:
+ reusify "^1.0.4"
+
+fd-slicer@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
+ integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==
+ dependencies:
+ pend "~1.2.0"
+
+fill-range@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+find-up@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
+ integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+ dependencies:
+ locate-path "^3.0.0"
+
+follow-redirects@^1.15.0:
+ version "1.15.2"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
+ integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
+
+form-data@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
+ integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
+fs-extra@^10.0.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
+ integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
+ dependencies:
+ graceful-fs "^4.2.0"
+ jsonfile "^6.0.1"
+ universalify "^2.0.0"
+
+fs-extra@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0"
+ integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==
+ dependencies:
+ graceful-fs "^4.2.0"
+ jsonfile "^4.0.0"
+ universalify "^0.1.0"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+
+fs@^0.0.1-security:
+ version "0.0.1-security"
+ resolved "https://registry.yarnpkg.com/fs/-/fs-0.0.1-security.tgz#8a7bd37186b6dddf3813f23858b57ecaaf5e41d4"
+ integrity sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==
+
+function-bind@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+get-intrinsic@^1.1.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82"
+ integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==
+ dependencies:
+ function-bind "^1.1.1"
+ has "^1.0.3"
+ has-proto "^1.0.1"
+ has-symbols "^1.0.3"
+
+get-stream@^5.1.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
+ integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
+ dependencies:
+ pump "^3.0.0"
+
+get-stream@^6.0.0:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
+ integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
+
+glob-parent@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+glob@^7.1.3:
+ version "7.2.3"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
+ integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.1.1"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+global-agent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-3.0.0.tgz#ae7cd31bd3583b93c5a16437a1afe27cc33a1ab6"
+ integrity sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==
+ dependencies:
+ boolean "^3.0.1"
+ es6-error "^4.1.1"
+ matcher "^3.0.0"
+ roarr "^2.15.3"
+ semver "^7.3.2"
+ serialize-error "^7.0.1"
+
+globalthis@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf"
+ integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==
+ dependencies:
+ define-properties "^1.1.3"
+
+globby@^11.0.1:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
+ integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+ dependencies:
+ array-union "^2.1.0"
+ dir-glob "^3.0.1"
+ fast-glob "^3.2.9"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
+ slash "^3.0.0"
+
+got@^11.8.5:
+ version "11.8.6"
+ resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a"
+ integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==
+ dependencies:
+ "@sindresorhus/is" "^4.0.0"
+ "@szmarczak/http-timer" "^4.0.5"
+ "@types/cacheable-request" "^6.0.1"
+ "@types/responselike" "^1.0.0"
+ cacheable-lookup "^5.0.3"
+ cacheable-request "^7.0.2"
+ decompress-response "^6.0.0"
+ http2-wrapper "^1.0.0-beta.5.2"
+ lowercase-keys "^2.0.0"
+ p-cancelable "^2.0.0"
+ responselike "^2.0.0"
+
+graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
+ version "4.2.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+ integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+has-property-descriptors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861"
+ integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==
+ dependencies:
+ get-intrinsic "^1.1.1"
+
+has-proto@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0"
+ integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==
+
+has-symbols@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
+ integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
+
+has@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+ dependencies:
+ function-bind "^1.1.1"
+
+http-cache-semantics@^4.0.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
+ integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
+
+http2-wrapper@^1.0.0-beta.5.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d"
+ integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==
+ dependencies:
+ quick-lru "^5.1.1"
+ resolve-alpn "^1.0.0"
+
+human-signals@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
+ integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
+
+ignore@^5.2.0:
+ version "5.2.4"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
+ integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
+
+indent-string@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
+ integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-glob@^4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-obj@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
+ integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
+
+is-path-cwd@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb"
+ integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==
+
+is-path-inside@^3.0.2:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
+ integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
+
+is-stream@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
+ integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+js-yaml@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
+ integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
+ dependencies:
+ argparse "^2.0.1"
+
+json-buffer@3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
+ integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
+
+json-schema-traverse@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
+ integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+
+json-schema-typed@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/json-schema-typed/-/json-schema-typed-7.0.3.tgz#23ff481b8b4eebcd2ca123b4fa0409e66469a2d9"
+ integrity sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==
+
+json-stringify-safe@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+ integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==
+
+jsonfile@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+ integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
+jsonfile@^6.0.1:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
+ integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
+ dependencies:
+ universalify "^2.0.0"
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
+keyv@^4.0.0:
+ version "4.5.3"
+ resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25"
+ integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==
+ dependencies:
+ json-buffer "3.0.1"
+
+lazy-val@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.5.tgz#6cf3b9f5bc31cee7ee3e369c0832b7583dcd923d"
+ integrity sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==
+
+locate-path@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
+ integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+ dependencies:
+ p-locate "^3.0.0"
+ path-exists "^3.0.0"
+
+lodash.escaperegexp@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
+ integrity sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==
+
+lodash.isequal@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
+ integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
+
+lodash.once@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
+ integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==
+
+lowercase-keys@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
+ integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
+
+lru-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ dependencies:
+ yallist "^4.0.0"
+
+luxon@~3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.3.0.tgz#d73ab5b5d2b49a461c47cedbc7e73309b4805b48"
+ integrity sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==
+
+matcher@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca"
+ integrity sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==
+ dependencies:
+ escape-string-regexp "^4.0.0"
+
+merge-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
+ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+
+merge2@^1.3.0, merge2@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+micromatch@^4.0.4:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
+ integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
+ dependencies:
+ braces "^3.0.2"
+ picomatch "^2.3.1"
+
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.12:
+ version "2.1.35"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
+mimic-fn@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+ integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+
+mimic-fn@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74"
+ integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==
+
+mimic-response@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
+ integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
+
+mimic-response@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
+ integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
+
+minimatch@^3.1.1:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+ms@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+normalize-url@^6.0.1:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
+ integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
+
+npm-run-path@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
+ integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
+ dependencies:
+ path-key "^3.0.0"
+
+object-keys@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
+ integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
+
+once@^1.3.0, once@^1.3.1, once@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+ dependencies:
+ wrappy "1"
+
+onetime@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
+ integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
+ dependencies:
+ mimic-fn "^2.1.0"
+
+p-cancelable@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf"
+ integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==
+
+p-limit@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+ dependencies:
+ p-try "^2.0.0"
+
+p-locate@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
+ integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+ dependencies:
+ p-limit "^2.0.0"
+
+p-map@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
+ integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
+ dependencies:
+ aggregate-error "^3.0.0"
+
+p-try@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+path-exists@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+ integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
+
+path-key@^3.0.0, path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+path-type@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
+pend@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
+ integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==
+
+picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+pkg-up@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5"
+ integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==
+ dependencies:
+ find-up "^3.0.0"
+
+progress@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
+ integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
+
+proxy-from-env@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
+ integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
+
+pump@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
+ integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
+ dependencies:
+ end-of-stream "^1.1.0"
+ once "^1.3.1"
+
+punycode@^2.1.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
+ integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
+
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+quick-lru@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
+ integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
+
+require-from-string@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
+ integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+
+resolve-alpn@^1.0.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9"
+ integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==
+
+responselike@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc"
+ integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==
+ dependencies:
+ lowercase-keys "^2.0.0"
+
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+rimraf@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
+ integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
+ dependencies:
+ glob "^7.1.3"
+
+roarr@^2.15.3:
+ version "2.15.4"
+ resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.4.tgz#f5fe795b7b838ccfe35dc608e0282b9eba2e7afd"
+ integrity sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==
+ dependencies:
+ boolean "^3.0.1"
+ detect-node "^2.0.4"
+ globalthis "^1.0.1"
+ json-stringify-safe "^5.0.1"
+ semver-compare "^1.0.0"
+ sprintf-js "^1.1.2"
+
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
+sax@^1.2.4:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+ integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
+
+semver-compare@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
+ integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==
+
+semver@^6.2.0:
+ version "6.3.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
+ integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
+
+semver@^7.3.2, semver@^7.3.5:
+ version "7.5.4"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
+ integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
+ dependencies:
+ lru-cache "^6.0.0"
+
+serialize-error@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18"
+ integrity sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==
+ dependencies:
+ type-fest "^0.13.1"
+
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+signal-exit@^3.0.3:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
+ integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
+
+slash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+sprintf-js@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
+ integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
+
+strip-final-newline@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
+ integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
+
+sumchecker@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42"
+ integrity sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==
+ dependencies:
+ debug "^4.1.0"
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+type-fest@^0.13.1:
+ version "0.13.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
+ integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==
+
+type-fest@^2.17.0:
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b"
+ integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==
+
+universalify@^0.1.0:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+ integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+
+universalify@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
+ integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
+
+uri-js@^4.2.2:
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+ integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+ dependencies:
+ punycode "^2.1.0"
+
+which@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+
+yallist@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
+yauzl@^2.10.0:
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
+ integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==
+ dependencies:
+ buffer-crc32 "~0.2.3"
+ fd-slicer "~1.1.0"
diff --git a/src/khoj/configure.py b/src/khoj/configure.py
index d35b04f8..6a358c1f 100644
--- a/src/khoj/configure.py
+++ b/src/khoj/configure.py
@@ -105,7 +105,7 @@ def configure_routes(app):
app.mount("/static", StaticFiles(directory=constants.web_directory), name="static")
app.include_router(api, prefix="/api")
app.include_router(api_beta, prefix="/api/beta")
- app.include_router(indexer, prefix="/indexer")
+ app.include_router(indexer, prefix="/v1/indexer")
app.include_router(web_client)
diff --git a/src/khoj/processor/github/github_to_jsonl.py b/src/khoj/processor/github/github_to_jsonl.py
index 6abc137f..bcd2e530 100644
--- a/src/khoj/processor/github/github_to_jsonl.py
+++ b/src/khoj/processor/github/github_to_jsonl.py
@@ -37,7 +37,7 @@ class GithubToJsonl(TextToJsonl):
else:
return
- def process(self, previous_entries=[], files=None):
+ def process(self, previous_entries=[], files=None, full_corpus=True):
if self.config.pat_token is None or self.config.pat_token == "":
logger.error(f"Github PAT token is not set. Skipping github content")
raise ValueError("Github PAT token is not set. Skipping github content")
diff --git a/src/khoj/processor/jsonl/jsonl_to_jsonl.py b/src/khoj/processor/jsonl/jsonl_to_jsonl.py
index 1ace9b8a..4a6fab99 100644
--- a/src/khoj/processor/jsonl/jsonl_to_jsonl.py
+++ b/src/khoj/processor/jsonl/jsonl_to_jsonl.py
@@ -16,7 +16,7 @@ logger = logging.getLogger(__name__)
class JsonlToJsonl(TextToJsonl):
# Define Functions
- def process(self, previous_entries=[], files: dict[str, str] = {}):
+ def process(self, previous_entries=[], files: dict[str, str] = {}, full_corpus: bool = True):
# Extract required fields from config
input_jsonl_files, input_jsonl_filter, output_file = (
self.config.input_files,
diff --git a/src/khoj/processor/markdown/markdown_to_jsonl.py b/src/khoj/processor/markdown/markdown_to_jsonl.py
index 4cb5a525..c2f0f0bf 100644
--- a/src/khoj/processor/markdown/markdown_to_jsonl.py
+++ b/src/khoj/processor/markdown/markdown_to_jsonl.py
@@ -22,10 +22,17 @@ class MarkdownToJsonl(TextToJsonl):
self.config = config
# Define Functions
- def process(self, previous_entries=[], files=None):
+ def process(self, previous_entries=[], files=None, full_corpus: bool = True):
# Extract required fields from config
output_file = self.config.compressed_jsonl
+ if not full_corpus:
+ deletion_file_names = set([file for file in files if files[file] == ""])
+ files_to_process = set(files) - deletion_file_names
+ files = {file: files[file] for file in files_to_process}
+ else:
+ deletion_file_names = None
+
# Extract Entries from specified Markdown files
with timer("Parse entries from Markdown files into dictionaries", logger):
current_entries = MarkdownToJsonl.convert_markdown_entries_to_maps(
@@ -39,7 +46,7 @@ class MarkdownToJsonl(TextToJsonl):
# Identify, mark and merge any new entries with previous entries
with timer("Identify new or updated entries", logger):
entries_with_ids = TextToJsonl.mark_entries_for_update(
- current_entries, previous_entries, key="compiled", logger=logger
+ current_entries, previous_entries, key="compiled", logger=logger, deletion_filenames=deletion_file_names
)
with timer("Write markdown entries to JSONL file", logger):
diff --git a/src/khoj/processor/notion/notion_to_jsonl.py b/src/khoj/processor/notion/notion_to_jsonl.py
index ab53c974..0df56c37 100644
--- a/src/khoj/processor/notion/notion_to_jsonl.py
+++ b/src/khoj/processor/notion/notion_to_jsonl.py
@@ -80,7 +80,7 @@ class NotionToJsonl(TextToJsonl):
self.body_params = {"page_size": 100}
- def process(self, previous_entries=[], files=None):
+ def process(self, previous_entries=[], files=None, full_corpus=True):
current_entries = []
# Get all pages
diff --git a/src/khoj/processor/org_mode/org_to_jsonl.py b/src/khoj/processor/org_mode/org_to_jsonl.py
index 34db4798..2f22add4 100644
--- a/src/khoj/processor/org_mode/org_to_jsonl.py
+++ b/src/khoj/processor/org_mode/org_to_jsonl.py
@@ -21,11 +21,20 @@ class OrgToJsonl(TextToJsonl):
self.config = config
# Define Functions
- def process(self, previous_entries: List[Entry] = [], files: dict[str, str] = None) -> List[Tuple[int, Entry]]:
+ def process(
+ self, previous_entries: List[Entry] = [], files: dict[str, str] = None, full_corpus: bool = True
+ ) -> List[Tuple[int, Entry]]:
# Extract required fields from config
output_file = self.config.compressed_jsonl
index_heading_entries = self.config.index_heading_entries
+ if not full_corpus:
+ deletion_file_names = set([file for file in files if files[file] == ""])
+ files_to_process = set(files) - deletion_file_names
+ files = {file: files[file] for file in files_to_process}
+ else:
+ deletion_file_names = None
+
# Extract Entries from specified Org files
with timer("Parse entries from org files into OrgNode objects", logger):
entry_nodes, file_to_entries = self.extract_org_entries(files)
@@ -39,7 +48,7 @@ class OrgToJsonl(TextToJsonl):
# Identify, mark and merge any new entries with previous entries
with timer("Identify new or updated entries", logger):
entries_with_ids = TextToJsonl.mark_entries_for_update(
- current_entries, previous_entries, key="compiled", logger=logger
+ current_entries, previous_entries, key="compiled", logger=logger, deletion_filenames=deletion_file_names
)
# Process Each Entry from All Notes Files
diff --git a/src/khoj/processor/pdf/pdf_to_jsonl.py b/src/khoj/processor/pdf/pdf_to_jsonl.py
index ad52637e..77c34617 100644
--- a/src/khoj/processor/pdf/pdf_to_jsonl.py
+++ b/src/khoj/processor/pdf/pdf_to_jsonl.py
@@ -2,9 +2,10 @@
import os
import logging
from typing import List
+import base64
# External Packages
-from langchain.document_loaders import PyPDFLoader
+from langchain.document_loaders import PyMuPDFLoader
# Internal Packages
from khoj.processor.text_to_jsonl import TextToJsonl
@@ -18,10 +19,17 @@ logger = logging.getLogger(__name__)
class PdfToJsonl(TextToJsonl):
# Define Functions
- def process(self, previous_entries=[], files=dict[str, str]):
+ def process(self, previous_entries=[], files: dict[str, str] = None, full_corpus: bool = True):
# Extract required fields from config
output_file = self.config.compressed_jsonl
+ if not full_corpus:
+ deletion_file_names = set([file for file in files if files[file] == ""])
+ files_to_process = set(files) - deletion_file_names
+ files = {file: files[file] for file in files_to_process}
+ else:
+ deletion_file_names = None
+
# Extract Entries from specified Pdf files
with timer("Parse entries from PDF files into dictionaries", logger):
current_entries = PdfToJsonl.convert_pdf_entries_to_maps(*PdfToJsonl.extract_pdf_entries(files))
@@ -33,7 +41,7 @@ class PdfToJsonl(TextToJsonl):
# Identify, mark and merge any new entries with previous entries
with timer("Identify new or updated entries", logger):
entries_with_ids = TextToJsonl.mark_entries_for_update(
- current_entries, previous_entries, key="compiled", logger=logger
+ current_entries, previous_entries, key="compiled", logger=logger, deletion_filenames=deletion_file_names
)
with timer("Write PDF entries to JSONL file", logger):
@@ -55,9 +63,11 @@ class PdfToJsonl(TextToJsonl):
for pdf_file in pdf_files:
try:
# Write the PDF file to a temporary file, as it is stored in byte format in the pdf_file object and the PyPDFLoader expects a file path
- with open(f"{pdf_file}.pdf", "wb") as f:
- f.write(pdf_files[pdf_file])
- loader = PyPDFLoader(f"{pdf_file}.pdf")
+ tmp_file = f"tmp_pdf_file.pdf"
+ with open(f"{tmp_file}", "wb") as f:
+ bytes = base64.b64decode(pdf_files[pdf_file])
+ f.write(bytes)
+ loader = PyMuPDFLoader(f"{tmp_file}")
pdf_entries_per_file = [page.page_content for page in loader.load()]
entry_to_location_map += zip(pdf_entries_per_file, [pdf_file] * len(pdf_entries_per_file))
entries.extend(pdf_entries_per_file)
@@ -65,8 +75,8 @@ class PdfToJsonl(TextToJsonl):
logger.warning(f"Unable to process file: {pdf_file}. This file will not be indexed.")
logger.warning(e)
finally:
- if os.path.exists(f"{pdf_file}.pdf"):
- os.remove(f"{pdf_file}.pdf")
+ if os.path.exists(f"{tmp_file}"):
+ os.remove(f"{tmp_file}")
return entries, dict(entry_to_location_map)
diff --git a/src/khoj/processor/plaintext/plaintext_to_jsonl.py b/src/khoj/processor/plaintext/plaintext_to_jsonl.py
index f488faed..3acb656e 100644
--- a/src/khoj/processor/plaintext/plaintext_to_jsonl.py
+++ b/src/khoj/processor/plaintext/plaintext_to_jsonl.py
@@ -15,9 +15,18 @@ logger = logging.getLogger(__name__)
class PlaintextToJsonl(TextToJsonl):
# Define Functions
- def process(self, previous_entries: List[Entry] = [], files: dict[str, str] = None) -> List[Tuple[int, Entry]]:
+ def process(
+ self, previous_entries: List[Entry] = [], files: dict[str, str] = None, full_corpus: bool = True
+ ) -> List[Tuple[int, Entry]]:
output_file = self.config.compressed_jsonl
+ if not full_corpus:
+ deletion_file_names = set([file for file in files if files[file] == ""])
+ files_to_process = set(files) - deletion_file_names
+ files = {file: files[file] for file in files_to_process}
+ else:
+ deletion_file_names = None
+
# Extract Entries from specified plaintext files
with timer("Parse entries from plaintext files", logger):
current_entries = PlaintextToJsonl.convert_plaintext_entries_to_maps(files)
@@ -29,7 +38,7 @@ class PlaintextToJsonl(TextToJsonl):
# Identify, mark and merge any new entries with previous entries
with timer("Identify new or updated entries", logger):
entries_with_ids = TextToJsonl.mark_entries_for_update(
- current_entries, previous_entries, key="compiled", logger=logger
+ current_entries, previous_entries, key="compiled", logger=logger, deletion_filenames=deletion_file_names
)
with timer("Write entries to JSONL file", logger):
diff --git a/src/khoj/processor/text_to_jsonl.py b/src/khoj/processor/text_to_jsonl.py
index 09371994..98f5986f 100644
--- a/src/khoj/processor/text_to_jsonl.py
+++ b/src/khoj/processor/text_to_jsonl.py
@@ -2,7 +2,7 @@
from abc import ABC, abstractmethod
import hashlib
import logging
-from typing import Callable, List, Tuple
+from typing import Callable, List, Tuple, Set
from khoj.utils.helpers import timer
# Internal Packages
@@ -17,7 +17,9 @@ class TextToJsonl(ABC):
self.config = config
@abstractmethod
- def process(self, previous_entries: List[Entry] = [], files: dict[str, str] = None) -> List[Tuple[int, Entry]]:
+ def process(
+ self, previous_entries: List[Entry] = [], files: dict[str, str] = None, full_corpus: bool = True
+ ) -> List[Tuple[int, Entry]]:
...
@staticmethod
@@ -62,12 +64,21 @@ class TextToJsonl(ABC):
@staticmethod
def mark_entries_for_update(
- current_entries: List[Entry], previous_entries: List[Entry], key="compiled", logger: logging.Logger = None
- ) -> List[Tuple[int, Entry]]:
+ current_entries: List[Entry],
+ previous_entries: List[Entry],
+ key="compiled",
+ logger: logging.Logger = None,
+ deletion_filenames: Set[str] = None,
+ ):
# Hash all current and previous entries to identify new entries
with timer("Hash previous, current entries", logger):
current_entry_hashes = list(map(TextToJsonl.hash_func(key), current_entries))
previous_entry_hashes = list(map(TextToJsonl.hash_func(key), previous_entries))
+ if deletion_filenames is not None:
+ deletion_entries = [entry for entry in previous_entries if entry.file in deletion_filenames]
+ deletion_entry_hashes = list(map(TextToJsonl.hash_func(key), deletion_entries))
+ else:
+ deletion_entry_hashes = []
with timer("Identify, Mark, Combine new, existing entries", logger):
hash_to_current_entries = dict(zip(current_entry_hashes, current_entries))
@@ -77,6 +88,19 @@ class TextToJsonl(ABC):
new_entry_hashes = set(current_entry_hashes) - set(previous_entry_hashes)
# All entries that exist in both current and previous sets are kept
existing_entry_hashes = set(current_entry_hashes) & set(previous_entry_hashes)
+ # All entries that exist in the previous set but not in the current set should be preserved
+ remaining_entry_hashes = set(previous_entry_hashes) - set(current_entry_hashes)
+ # All entries that exist in the previous set and also in the deletions set should be removed
+ to_delete_entry_hashes = set(previous_entry_hashes) & set(deletion_entry_hashes)
+
+ preserving_entry_hashes = existing_entry_hashes
+
+ if deletion_filenames is not None:
+ preserving_entry_hashes = (
+ (existing_entry_hashes | remaining_entry_hashes)
+ if len(deletion_entry_hashes) == 0
+ else (set(previous_entry_hashes) - to_delete_entry_hashes)
+ )
# load new entries in the order in which they are processed for a stable sort
new_entries = [
@@ -90,7 +114,7 @@ class TextToJsonl(ABC):
# Set id of existing entries to their previous ids to reuse their existing encoded embeddings
existing_entries = [
(previous_entry_hashes.index(entry_hash), hash_to_previous_entries[entry_hash])
- for entry_hash in existing_entry_hashes
+ for entry_hash in preserving_entry_hashes
]
existing_entries_sorted = sorted(existing_entries, key=lambda e: e[0])
diff --git a/src/khoj/routers/indexer.py b/src/khoj/routers/indexer.py
index eaff7bf8..ca2d884e 100644
--- a/src/khoj/routers/indexer.py
+++ b/src/khoj/routers/indexer.py
@@ -1,6 +1,7 @@
# Standard Packages
import logging
-from typing import Optional, Union
+import sys
+from typing import Optional, Union, Dict
# External Packages
from fastapi import APIRouter, HTTPException, Header, Request, Body, Response
@@ -15,10 +16,11 @@ from khoj.processor.pdf.pdf_to_jsonl import PdfToJsonl
from khoj.processor.github.github_to_jsonl import GithubToJsonl
from khoj.processor.notion.notion_to_jsonl import NotionToJsonl
from khoj.processor.plaintext.plaintext_to_jsonl import PlaintextToJsonl
-from khoj.utils.rawconfig import ContentConfig
+from khoj.utils.rawconfig import ContentConfig, TextContentConfig
from khoj.search_type import text_search, image_search
from khoj.utils.config import SearchModels
-from khoj.utils.helpers import LRU
+from khoj.utils.constants import default_config
+from khoj.utils.helpers import LRU, get_file_type
from khoj.utils.rawconfig import (
ContentConfig,
)
@@ -35,11 +37,20 @@ logger = logging.getLogger(__name__)
indexer = APIRouter()
+class File(BaseModel):
+ path: str
+ content: Union[str, bytes]
+
+
class IndexBatchRequest(BaseModel):
- org: Optional[dict[str, str]]
- pdf: Optional[dict[str, str]]
- plaintext: Optional[dict[str, str]]
- markdown: Optional[dict[str, str]]
+ files: list[File]
+
+
+class IndexerInput(BaseModel):
+ org: Optional[dict[str, str]] = None
+ markdown: Optional[dict[str, str]] = None
+ pdf: Optional[dict[str, bytes]] = None
+ plaintext: Optional[dict[str, str]] = None
@indexer.post("/batch")
@@ -54,24 +65,65 @@ async def index_batch(
state.config_lock.acquire()
try:
logger.info(f"Received batch indexing request")
- index_batch_request_acc = ""
+ index_batch_request_acc = b""
async for chunk in request.stream():
- index_batch_request_acc += chunk.decode()
+ index_batch_request_acc += chunk
+ data_bytes = sys.getsizeof(index_batch_request_acc)
+ unit = "KB"
+ data_size = data_bytes / 1024
+ if data_size > 1000:
+ unit = "MB"
+ data_size = data_size / 1024
+ if data_size > 1000:
+ unit = "GB"
+ data_size = data_size / 1024
+ data_size_metric = f"{data_size:.2f} {unit}"
+ logger.info(f"Received {data_size_metric} of data")
index_batch_request = IndexBatchRequest.parse_raw(index_batch_request_acc)
- logger.info(f"Received batch indexing request size: {len(index_batch_request.dict())}")
+ logger.info(f"Received {len(index_batch_request.files)} files")
+
+ org_files: Dict[str, str] = {}
+ markdown_files: Dict[str, str] = {}
+ pdf_files: Dict[str, str] = {}
+ plaintext_files: Dict[str, str] = {}
+
+ for file in index_batch_request.files:
+ file_type = get_file_type(file.path)
+ dict_to_update = None
+ if file_type == "org":
+ dict_to_update = org_files
+ elif file_type == "markdown":
+ dict_to_update = markdown_files
+ elif file_type == "pdf":
+ dict_to_update = pdf_files
+ elif file_type == "plaintext":
+ dict_to_update = plaintext_files
+
+ if dict_to_update is not None:
+ dict_to_update[file.path] = file.content
+ else:
+ logger.info(f"Skipping unsupported streamed file: {file.path}")
+
+ indexer_input = IndexerInput(
+ org=org_files,
+ markdown=markdown_files,
+ pdf=pdf_files,
+ plaintext=plaintext_files,
+ )
# Extract required fields from config
state.content_index = configure_content(
state.content_index,
state.config.content_type,
- index_batch_request.dict(),
+ indexer_input.dict(),
state.search_models,
regenerate=regenerate,
t=search_type,
+ full_corpus=False,
)
except Exception as e:
- logger.error(f"Failed to process batch indexing request: {e}")
+ logger.error(f"Failed to process batch indexing request: {e}", exc_info=True)
finally:
state.config_lock.release()
return Response(content="OK", status_code=200)
@@ -84,6 +136,7 @@ def configure_content(
search_models: SearchModels,
regenerate: bool = False,
t: Optional[Union[state.SearchType, str]] = None,
+ full_corpus: bool = True,
) -> Optional[ContentIndex]:
# Run Validation Checks
if content_config is None:
@@ -105,10 +158,17 @@ def configure_content(
# Initialize Org Notes Search
if (
(t == None or t == state.SearchType.Org.value)
- and content_config.org
+ and (content_config.org or files["org"])
and search_models.text_search
- and files["org"]
):
+ if content_config.org == None:
+ logger.info("🦄 No configuration for orgmode notes. Using default configuration.")
+ default_configuration = default_config["content-type"]["org"] # type: ignore
+ content_config.org = TextContentConfig(
+ compressed_jsonl=default_configuration["compressed-jsonl"],
+ embeddings_file=default_configuration["embeddings-file"],
+ )
+
logger.info("🦄 Setting up search for orgmode notes")
# Extract Entries, Generate Notes Embeddings
content_index.org = text_search.setup(
@@ -118,15 +178,27 @@ def configure_content(
search_models.text_search.bi_encoder,
regenerate=regenerate,
filters=[DateFilter(), WordFilter(), FileFilter()],
+ full_corpus=full_corpus,
)
+ except Exception as e:
+ logger.error(f"🚨 Failed to setup org: {e}", exc_info=True)
+ try:
# Initialize Markdown Search
if (
(t == None or t == state.SearchType.Markdown.value)
- and content_config.markdown
+ and (content_config.markdown or files["markdown"])
and search_models.text_search
and files["markdown"]
):
+ if content_config.markdown == None:
+ logger.info("💎 No configuration for markdown notes. Using default configuration.")
+ default_configuration = default_config["content-type"]["markdown"] # type: ignore
+ content_config.markdown = TextContentConfig(
+ compressed_jsonl=default_configuration["compressed-jsonl"],
+ embeddings_file=default_configuration["embeddings-file"],
+ )
+
logger.info("💎 Setting up search for markdown notes")
# Extract Entries, Generate Markdown Embeddings
content_index.markdown = text_search.setup(
@@ -136,15 +208,28 @@ def configure_content(
search_models.text_search.bi_encoder,
regenerate=regenerate,
filters=[DateFilter(), WordFilter(), FileFilter()],
+ full_corpus=full_corpus,
)
+ except Exception as e:
+ logger.error(f"🚨 Failed to setup markdown: {e}", exc_info=True)
+
+ try:
# Initialize PDF Search
if (
(t == None or t == state.SearchType.Pdf.value)
- and content_config.pdf
+ and (content_config.pdf or files["pdf"])
and search_models.text_search
and files["pdf"]
):
+ if content_config.pdf == None:
+ logger.info("🖨️ No configuration for pdf notes. Using default configuration.")
+ default_configuration = default_config["content-type"]["pdf"] # type: ignore
+ content_config.pdf = TextContentConfig(
+ compressed_jsonl=default_configuration["compressed-jsonl"],
+ embeddings_file=default_configuration["embeddings-file"],
+ )
+
logger.info("🖨️ Setting up search for pdf")
# Extract Entries, Generate PDF Embeddings
content_index.pdf = text_search.setup(
@@ -154,15 +239,28 @@ def configure_content(
search_models.text_search.bi_encoder,
regenerate=regenerate,
filters=[DateFilter(), WordFilter(), FileFilter()],
+ full_corpus=full_corpus,
)
+ except Exception as e:
+ logger.error(f"🚨 Failed to setup PDF: {e}", exc_info=True)
+
+ try:
# Initialize Plaintext Search
if (
(t == None or t == state.SearchType.Plaintext.value)
- and content_config.plaintext
+ and (content_config.plaintext or files["plaintext"])
and search_models.text_search
and files["plaintext"]
):
+ if content_config.plaintext == None:
+ logger.info("📄 No configuration for plaintext notes. Using default configuration.")
+ default_configuration = default_config["content-type"]["plaintext"] # type: ignore
+ content_config.plaintext = TextContentConfig(
+ compressed_jsonl=default_configuration["compressed-jsonl"],
+ embeddings_file=default_configuration["embeddings-file"],
+ )
+
logger.info("📄 Setting up search for plaintext")
# Extract Entries, Generate Plaintext Embeddings
content_index.plaintext = text_search.setup(
@@ -172,8 +270,13 @@ def configure_content(
search_models.text_search.bi_encoder,
regenerate=regenerate,
filters=[DateFilter(), WordFilter(), FileFilter()],
+ full_corpus=full_corpus,
)
+ except Exception as e:
+ logger.error(f"🚨 Failed to setup plaintext: {e}", exc_info=True)
+
+ try:
# Initialize Image Search
if (t == None or t == state.SearchType.Image.value) and content_config.image and search_models.image_search:
logger.info("🌄 Setting up search for images")
@@ -182,6 +285,10 @@ def configure_content(
content_config.image, search_models.image_search.image_encoder, regenerate=regenerate
)
+ except Exception as e:
+ logger.error(f"🚨 Failed to setup images: {e}", exc_info=True)
+
+ try:
if (t == None or t == state.SearchType.Github.value) and content_config.github and search_models.text_search:
logger.info("🐙 Setting up search for github")
# Extract Entries, Generate Github Embeddings
@@ -192,8 +299,13 @@ def configure_content(
search_models.text_search.bi_encoder,
regenerate=regenerate,
filters=[DateFilter(), WordFilter(), FileFilter()],
+ full_corpus=full_corpus,
)
+ except Exception as e:
+ logger.error(f"🚨 Failed to setup GitHub: {e}", exc_info=True)
+
+ try:
# Initialize Notion Search
if (t == None or t in state.SearchType.Notion.value) and content_config.notion and search_models.text_search:
logger.info("🔌 Setting up search for notion")
@@ -204,8 +316,13 @@ def configure_content(
search_models.text_search.bi_encoder,
regenerate=regenerate,
filters=[DateFilter(), WordFilter(), FileFilter()],
+ full_corpus=full_corpus,
)
+ except Exception as e:
+ logger.error(f"🚨 Failed to setup GitHub: {e}", exc_info=True)
+
+ try:
# Initialize External Plugin Search
if (t == None or t in state.SearchType) and content_config.plugins and search_models.text_search:
logger.info("🔌 Setting up search for plugins")
@@ -218,11 +335,11 @@ def configure_content(
search_models.text_search.bi_encoder,
regenerate=regenerate,
filters=[DateFilter(), WordFilter(), FileFilter()],
+ full_corpus=full_corpus,
)
except Exception as e:
- logger.error(f"🚨 Failed to setup search: {e}", exc_info=True)
- raise e
+ logger.error(f"🚨 Failed to setup Plugin: {e}", exc_info=True)
# Invalidate Query Cache
state.query_cache = LRU()
diff --git a/src/khoj/search_type/text_search.py b/src/khoj/search_type/text_search.py
index 468a7584..b790b000 100644
--- a/src/khoj/search_type/text_search.py
+++ b/src/khoj/search_type/text_search.py
@@ -192,19 +192,24 @@ def setup(
regenerate: bool,
filters: List[BaseFilter] = [],
normalize: bool = True,
+ full_corpus: bool = True,
) -> TextContent:
# Map notes in text files to (compressed) JSONL formatted file
config.compressed_jsonl = resolve_absolute_path(config.compressed_jsonl)
previous_entries = []
if config.compressed_jsonl.exists() and not regenerate:
previous_entries = extract_entries(config.compressed_jsonl)
- entries_with_indices = text_to_jsonl(config).process(previous_entries=previous_entries, files=files)
+ entries_with_indices = text_to_jsonl(config).process(
+ previous_entries=previous_entries, files=files, full_corpus=full_corpus
+ )
# Extract Updated Entries
entries = extract_entries(config.compressed_jsonl)
if is_none_or_empty(entries):
config_params = ", ".join([f"{key}={value}" for key, value in config.dict().items()])
- raise ValueError(f"No valid entries found in specified files: {config_params}")
+ raise ValueError(
+ f"No valid entries found in specified configuration: {config_params}, with files: {files.keys()}"
+ )
# Compute or Load Embeddings
config.embeddings_file = resolve_absolute_path(config.embeddings_file)
diff --git a/src/khoj/utils/fs_syncer.py b/src/khoj/utils/fs_syncer.py
index 7aa5af2b..d303d39b 100644
--- a/src/khoj/utils/fs_syncer.py
+++ b/src/khoj/utils/fs_syncer.py
@@ -1,5 +1,6 @@
import logging
import glob
+import base64
from typing import Optional
from bs4 import BeautifulSoup
@@ -209,7 +210,7 @@ def get_pdf_files(config: TextContentConfig):
for file in all_pdf_files:
with open(file, "rb") as f:
try:
- filename_to_content_map[file] = f.read()
+ filename_to_content_map[file] = base64.b64encode(f.read()).decode("utf-8")
except Exception as e:
logger.warning(f"Unable to read file: {file} as PDF. Skipping file.")
logger.warning(e, exc_info=True)
diff --git a/src/khoj/utils/helpers.py b/src/khoj/utils/helpers.py
index 9bd139d4..fcdca7cb 100644
--- a/src/khoj/utils/helpers.py
+++ b/src/khoj/utils/helpers.py
@@ -66,6 +66,22 @@ def merge_dicts(priority_dict: dict, default_dict: dict):
return merged_dict
+def get_file_type(filepath: str) -> str:
+ "Get file type from file path"
+ file_type = Path(filepath).suffix[1:]
+
+ if file_type in ["md", "markdown"]:
+ return "markdown"
+ elif file_type in ["org", "orgmode"]:
+ return "org"
+ elif file_type in ["txt", "text", "html", "xml", "htm", "rst"]:
+ return "plaintext"
+ elif file_type in ["pdf"]:
+ return "pdf"
+
+ return file_type
+
+
def load_model(
model_name: str, model_type, model_dir=None, device: str = None
) -> Union[BaseEncoder, SentenceTransformer, CrossEncoder]:
diff --git a/src/khoj/utils/rawconfig.py b/src/khoj/utils/rawconfig.py
index 13c9b1cf..0a916db4 100644
--- a/src/khoj/utils/rawconfig.py
+++ b/src/khoj/utils/rawconfig.py
@@ -32,14 +32,6 @@ class TextContentConfig(TextConfigBase):
input_filter: Optional[List[str]]
index_heading_entries: Optional[bool] = False
- @validator("input_filter")
- def input_filter_or_files_required(cls, input_filter, values, **kwargs):
- if is_none_or_empty(input_filter) and ("input_files" not in values or values["input_files"] is None):
- raise ValueError(
- "Either input_filter or input_files required in all content-type. section of Khoj config file"
- )
- return input_filter
-
class GithubRepoConfig(ConfigBase):
name: str
@@ -63,16 +55,6 @@ class ImageContentConfig(ConfigBase):
use_xmp_metadata: bool
batch_size: int
- @validator("input_filter")
- def input_filter_or_directories_required(cls, input_filter, values, **kwargs):
- if is_none_or_empty(input_filter) and (
- "input_directories" not in values or values["input_directories"] is None
- ):
- raise ValueError(
- "Either input_filter or input_directories required in all content-type.image section of Khoj config file"
- )
- return input_filter
-
class ContentConfig(ConfigBase):
org: Optional[TextContentConfig]
diff --git a/tests/test_client.py b/tests/test_client.py
index b2fad8b1..d2497f73 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -66,7 +66,7 @@ def test_index_batch(client):
headers = {"x-api-key": "secret"}
# Act
- response = client.post("/indexer/batch", json=request_body, headers=headers)
+ response = client.post("/v1/indexer/batch", json=request_body, headers=headers)
# Assert
assert response.status_code == 200
@@ -81,7 +81,7 @@ def test_regenerate_with_valid_content_type(client):
headers = {"x-api-key": "secret"}
# Act
- response = client.post(f"/indexer/batch?search_type={content_type}", json=request_body, headers=headers)
+ response = client.post(f"/v1/indexer/batch?search_type={content_type}", json=request_body, headers=headers)
# Assert
assert response.status_code == 200, f"Returned status: {response.status_code} for content type: {content_type}"
@@ -97,7 +97,7 @@ def test_regenerate_with_github_fails_without_pat(client):
headers = {"x-api-key": "secret"}
# Act
- response = client.post(f"/indexer/batch?search_type=github", json=request_body, headers=headers)
+ response = client.post(f"/v1/indexer/batch?search_type=github", json=request_body, headers=headers)
# Assert
assert response.status_code == 200, f"Returned status: {response.status_code} for content type: github"
diff --git a/tests/test_pdf_to_jsonl.py b/tests/test_pdf_to_jsonl.py
index b9b26986..bacce37c 100644
--- a/tests/test_pdf_to_jsonl.py
+++ b/tests/test_pdf_to_jsonl.py
@@ -1,6 +1,7 @@
# Standard Packages
import json
import os
+import base64
# Internal Packages
from khoj.processor.pdf.pdf_to_jsonl import PdfToJsonl
@@ -15,7 +16,7 @@ def test_single_page_pdf_to_jsonl():
# Extract Entries from specified Pdf files
# Read singlepage.pdf into memory as bytes
with open("tests/data/pdf/singlepage.pdf", "rb") as f:
- pdf_bytes = f.read()
+ pdf_bytes = base64.b64encode(f.read()).decode("utf-8")
data = {"tests/data/pdf/singlepage.pdf": pdf_bytes}
entries, entry_to_file_map = PdfToJsonl.extract_pdf_entries(pdf_files=data)
@@ -35,7 +36,7 @@ def test_multi_page_pdf_to_jsonl():
# Act
# Extract Entries from specified Pdf files
with open("tests/data/pdf/multipage.pdf", "rb") as f:
- pdf_bytes = f.read()
+ pdf_bytes = base64.b64encode(f.read()).decode("utf-8")
data = {"tests/data/pdf/multipage.pdf": pdf_bytes}
entries, entry_to_file_map = PdfToJsonl.extract_pdf_entries(pdf_files=data)
diff --git a/tests/test_rawconfig.py b/tests/test_rawconfig.py
index 50baa92a..3f3028b5 100644
--- a/tests/test_rawconfig.py
+++ b/tests/test_rawconfig.py
@@ -6,18 +6,6 @@ from khoj.utils.rawconfig import TextContentConfig, ImageContentConfig
# Test
-# ----------------------------------------------------------------------------------------------------
-def test_input_file_or_filter_required_in_text_content_config():
- # Act
- with pytest.raises(ValueError):
- TextContentConfig(
- input_files=None,
- input_filter=None,
- compressed_jsonl="notes.jsonl",
- embeddings_file="note_embeddings.pt",
- )
-
-
# ----------------------------------------------------------------------------------------------------
def test_input_filter_or_directories_required_in_image_content_config():
# Act
diff --git a/tests/test_text_search.py b/tests/test_text_search.py
index f8c0b688..b1a9aa4d 100644
--- a/tests/test_text_search.py
+++ b/tests/test_text_search.py
@@ -131,6 +131,65 @@ def test_entry_chunking_by_max_tokens(org_config_with_only_new_file: TextContent
assert len(initial_notes_model.corpus_embeddings) == 2
+# ----------------------------------------------------------------------------------------------------
+# @pytest.mark.skip(reason="Flaky due to compressed_jsonl file being rewritten by other tests")
+def test_entry_chunking_by_max_tokens_not_full_corpus(
+ org_config_with_only_new_file: TextContentConfig, search_models: SearchModels
+):
+ # Arrange
+ # Insert org-mode entry with size exceeding max token limit to new org file
+ data = {
+ "readme.org": """
+* Khoj
+ /Allow natural language search on user content like notes, images using transformer based models/
+
+ All data is processed locally. User can interface with khoj app via [[./interface/emacs/khoj.el][Emacs]], API or Commandline
+
+** Dependencies
+ - Python3
+ - [[https://docs.conda.io/en/latest/miniconda.html#latest-miniconda-installer-links][Miniconda]]
+
+** Install
+ #+begin_src shell
+ git clone https://github.com/khoj-ai/khoj && cd khoj
+ conda env create -f environment.yml
+ conda activate khoj
+ #+end_src"""
+ }
+ text_search.setup(
+ OrgToJsonl,
+ data,
+ org_config_with_only_new_file,
+ search_models.text_search.bi_encoder,
+ regenerate=False,
+ )
+
+ max_tokens = 256
+ new_file_to_index = Path(org_config_with_only_new_file.input_files[0])
+ with open(new_file_to_index, "w") as f:
+ f.write(f"* Entry more than {max_tokens} words\n")
+ for index in range(max_tokens + 1):
+ f.write(f"{index} ")
+
+ data = get_org_files(org_config_with_only_new_file)
+
+ # Act
+ # reload embeddings, entries, notes model after adding new org-mode file
+ initial_notes_model = text_search.setup(
+ OrgToJsonl,
+ data,
+ org_config_with_only_new_file,
+ search_models.text_search.bi_encoder,
+ regenerate=False,
+ full_corpus=False,
+ )
+
+ # Assert
+ # verify newly added org-mode entry is split by max tokens
+ assert len(initial_notes_model.entries) == 5
+ assert len(initial_notes_model.corpus_embeddings) == 5
+
+
# ----------------------------------------------------------------------------------------------------
def test_regenerate_index_with_new_entry(
content_config: ContentConfig, search_models: SearchModels, new_org_file: Path