From 37338b13e4392cc053e3670a2dbb5f09bc2db901 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 13 Jun 2024 01:23:31 +0800 Subject: [PATCH 01/98] refactor: extract a new $tw.wiki.getParser --- core/modules/wiki.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/core/modules/wiki.js b/core/modules/wiki.js index 2850dec5f..e53b0d387 100755 --- a/core/modules/wiki.js +++ b/core/modules/wiki.js @@ -1035,6 +1035,18 @@ Options include: exports.parseText = function(type,text,options) { text = text || ""; options = options || {}; + var Parser = this.getParser(type,options) + // Return the parser instance + return new Parser(type,text,{ + parseAsInline: options.parseAsInline, + wiki: this, + _canonical_uri: options._canonical_uri, + configTrimWhiteSpace: options.configTrimWhiteSpace + }); +}; + +exports.getParser = function(type,options) { + options = $tw.utils.extend({},options); // Select a parser var Parser = $tw.Wiki.parsers[type]; if(!Parser && $tw.utils.getFileExtensionInfo(type)) { @@ -1046,13 +1058,7 @@ exports.parseText = function(type,text,options) { if(!Parser) { return null; } - // Return the parser instance - return new Parser(type,text,{ - parseAsInline: options.parseAsInline, - wiki: this, - _canonical_uri: options._canonical_uri, - configTrimWhiteSpace: options.configTrimWhiteSpace - }); + return Parser; }; /* From 8a12498fa96aa76973a6dbd8d28698bd3ef4418e Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 13 Jun 2024 01:23:59 +0800 Subject: [PATCH 02/98] feat: allow $tw.utils.getParseTreeText to render other rules' text --- core/modules/utils/parsetree.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index a74b8f3f8..7e7542d34 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -106,7 +106,7 @@ exports.findParseTreeNode = function(nodeArray,search) { /* Helper to get the text of a parse tree node or array of nodes */ -exports.getParseTreeText = function getParseTreeText(tree) { +exports.getParseTreeText = function getParseTreeText(tree, tiddlerType) { var output = []; if($tw.utils.isArray(tree)) { $tw.utils.each(tree,function(node) { @@ -115,6 +115,14 @@ exports.getParseTreeText = function getParseTreeText(tree) { } else { if(tree.type === "text") { output.push(tree.text); + } else { + var Parser = $tw.wiki.getParser(tiddlerType); + var Rule = Parser.prototype.blockRuleClasses[tree.type] || + Parser.prototype.inlineRuleClasses[tree.type] || + Parser.prototype.pragmaRuleClasses[tree.type]; + if(Rule && Rule.prototype.getText) { + output.push(Rule.prototype.getText(tree)); + } } if(tree.children) { return getParseTreeText(tree.children); From 09c2e71e228dbe8b6d0e30364dd8d9244f6e1f4e Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 13 Jun 2024 01:25:23 +0800 Subject: [PATCH 03/98] feat: two example getText handler --- core/modules/parsers/wikiparser/rules/codeblock.js | 4 ++++ core/modules/parsers/wikiparser/rules/horizrule.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/core/modules/parsers/wikiparser/rules/codeblock.js b/core/modules/parsers/wikiparser/rules/codeblock.js index 6c3480566..71efe2dfd 100644 --- a/core/modules/parsers/wikiparser/rules/codeblock.js +++ b/core/modules/parsers/wikiparser/rules/codeblock.js @@ -57,4 +57,8 @@ exports.parse = function() { }]; }; +exports.getText = function(tree) { + return "\n```" + tree.attributes.language.value + "\n" + tree.attributes.code.value + "\n```\n"; +} + })(); diff --git a/core/modules/parsers/wikiparser/rules/horizrule.js b/core/modules/parsers/wikiparser/rules/horizrule.js index bacad06ed..2e69e1986 100644 --- a/core/modules/parsers/wikiparser/rules/horizrule.js +++ b/core/modules/parsers/wikiparser/rules/horizrule.js @@ -31,4 +31,8 @@ exports.parse = function() { return [{type: "element", tag: "hr"}]; }; +exports.getText = function() { + return "---"; +} + })(); From a0708a17cb9c3f43e26752e0a3233f69bbf6baf1 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 13 Jun 2024 01:29:22 +0800 Subject: [PATCH 04/98] Revert "feat: allow $tw.utils.getParseTreeText to render other rules' text" This reverts commit 8a12498fa96aa76973a6dbd8d28698bd3ef4418e. --- core/modules/utils/parsetree.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index 7e7542d34..a74b8f3f8 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -106,7 +106,7 @@ exports.findParseTreeNode = function(nodeArray,search) { /* Helper to get the text of a parse tree node or array of nodes */ -exports.getParseTreeText = function getParseTreeText(tree, tiddlerType) { +exports.getParseTreeText = function getParseTreeText(tree) { var output = []; if($tw.utils.isArray(tree)) { $tw.utils.each(tree,function(node) { @@ -115,14 +115,6 @@ exports.getParseTreeText = function getParseTreeText(tree, tiddlerType) { } else { if(tree.type === "text") { output.push(tree.text); - } else { - var Parser = $tw.wiki.getParser(tiddlerType); - var Rule = Parser.prototype.blockRuleClasses[tree.type] || - Parser.prototype.inlineRuleClasses[tree.type] || - Parser.prototype.pragmaRuleClasses[tree.type]; - if(Rule && Rule.prototype.getText) { - output.push(Rule.prototype.getText(tree)); - } } if(tree.children) { return getParseTreeText(tree.children); From f882cbd7af6f0fd2796b39c6c7b0870396baf674 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 13 Jun 2024 01:31:13 +0800 Subject: [PATCH 05/98] refactor: keep original getParseTreeText not touched --- core/modules/utils/parsetree.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index a74b8f3f8..d553ec4f0 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -123,4 +123,32 @@ exports.getParseTreeText = function getParseTreeText(tree) { return output.join(""); }; +/* +Utility to get the (similarly but not 1:1 equal) original wikitext of a parse tree node or array of nodes +*/ +exports.serializeParseTree = function serializeParseTree(tree, tiddlerType) { + var output = []; + if($tw.utils.isArray(tree)) { + $tw.utils.each(tree,function(node) { + output.push(serializeParseTree(node)); + }); + } else { + if(tree.type === "text") { + output.push(tree.text); + } else { + var Parser = $tw.wiki.getParser(tiddlerType); + var Rule = Parser.prototype.blockRuleClasses[tree.type] || + Parser.prototype.inlineRuleClasses[tree.type] || + Parser.prototype.pragmaRuleClasses[tree.type]; + if(Rule && Rule.prototype.getText) { + output.push(Rule.prototype.getText(tree)); + } + } + if(tree.children) { + return getParseTreeText(tree.children); + } + } + return output.join(""); +}; + })(); From be3f037a57217fc2131f34ae8e967d3aad9bb989 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 13 Jun 2024 01:34:18 +0800 Subject: [PATCH 06/98] refactor: use serialize in rules --- core/modules/parsers/wikiparser/rules/codeblock.js | 2 +- core/modules/parsers/wikiparser/rules/horizrule.js | 4 ++-- core/modules/utils/parsetree.js | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/codeblock.js b/core/modules/parsers/wikiparser/rules/codeblock.js index 71efe2dfd..11681261b 100644 --- a/core/modules/parsers/wikiparser/rules/codeblock.js +++ b/core/modules/parsers/wikiparser/rules/codeblock.js @@ -57,7 +57,7 @@ exports.parse = function() { }]; }; -exports.getText = function(tree) { +exports.serialize = function(tree) { return "\n```" + tree.attributes.language.value + "\n" + tree.attributes.code.value + "\n```\n"; } diff --git a/core/modules/parsers/wikiparser/rules/horizrule.js b/core/modules/parsers/wikiparser/rules/horizrule.js index 2e69e1986..697bd65a5 100644 --- a/core/modules/parsers/wikiparser/rules/horizrule.js +++ b/core/modules/parsers/wikiparser/rules/horizrule.js @@ -31,8 +31,8 @@ exports.parse = function() { return [{type: "element", tag: "hr"}]; }; -exports.getText = function() { - return "---"; +exports.serialize = function() { + return "\n---\n"; } })(); diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index d553ec4f0..ae548de0e 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -137,15 +137,15 @@ exports.serializeParseTree = function serializeParseTree(tree, tiddlerType) { output.push(tree.text); } else { var Parser = $tw.wiki.getParser(tiddlerType); - var Rule = Parser.prototype.blockRuleClasses[tree.type] || - Parser.prototype.inlineRuleClasses[tree.type] || - Parser.prototype.pragmaRuleClasses[tree.type]; - if(Rule && Rule.prototype.getText) { - output.push(Rule.prototype.getText(tree)); + var Rule = Parser.prototype.blockRuleClasses[tree.rule] || + Parser.prototype.inlineRuleClasses[tree.rule] || + Parser.prototype.pragmaRuleClasses[tree.rule]; + if(Rule && Rule.prototype.serialize) { + output.push(Rule.prototype.serialize(tree)); } } if(tree.children) { - return getParseTreeText(tree.children); + return serializeParseTree(tree.children); } } return output.join(""); From 4e896d18a018fd2af70b331ce82e985b7ca79cc4 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 29 Jul 2024 23:23:39 +0800 Subject: [PATCH 07/98] refactor: $tw.utils.extend({},options) -> options || {} --- core/modules/wiki.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/modules/wiki.js b/core/modules/wiki.js index 0baf1bdcf..516751a1a 100755 --- a/core/modules/wiki.js +++ b/core/modules/wiki.js @@ -1064,7 +1064,7 @@ exports.parseText = function(type,text,options) { }; exports.getParser = function(type,options) { - options = $tw.utils.extend({},options); + options = options || {}; // Select a parser var Parser = $tw.Wiki.parsers[type]; if(!Parser && $tw.utils.getFileExtensionInfo(type)) { @@ -1083,7 +1083,7 @@ exports.getParser = function(type,options) { Parse a tiddler according to its MIME type */ exports.parseTiddler = function(title,options) { - options = $tw.utils.extend({},options); + options = options || {}; var cacheType = options.parseAsInline ? "inlineParseTree" : "blockParseTree", tiddler = this.getTiddler(title), self = this; From 179651a189c4be09891a6af189f1214738353a94 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 29 Jul 2024 23:23:47 +0800 Subject: [PATCH 08/98] Update codeinline.js --- core/modules/parsers/wikiparser/rules/codeinline.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/modules/parsers/wikiparser/rules/codeinline.js b/core/modules/parsers/wikiparser/rules/codeinline.js index 048fc051c..015c325c5 100644 --- a/core/modules/parsers/wikiparser/rules/codeinline.js +++ b/core/modules/parsers/wikiparser/rules/codeinline.js @@ -55,4 +55,8 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree) { + return "`" + tree.children.text + "`"; +} + })(); From 8cbf85592d554537fbf239d2235044e31f20c839 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 29 Jul 2024 23:23:53 +0800 Subject: [PATCH 09/98] Create test-wikitext-serialize.js --- .../tiddlers/tests/test-wikitext-serialize.js | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 editions/test/tiddlers/tests/test-wikitext-serialize.js diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js new file mode 100644 index 000000000..d8747ef48 --- /dev/null +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -0,0 +1,40 @@ +/*\ +title: test-wikitext-serialize.js +type: application/javascript +tags: [[$:/tags/test-spec]] + +Tests the wikitext inverse-rendering from Wiki AST. + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +describe("WikiAST serialization tests", function() { + + // Create a wiki + var wiki = new $tw.Wiki(); + // Add a couple of tiddlers + wiki.addTiddler({title: "TiddlerOne", text: "The quick brown fox"}); + wiki.addTiddler({title: "TiddlerTwo", text: "The rain in Spain\nfalls mainly on the plain"}); + wiki.addTiddler({title: "TiddlerThree", text: "The speed of sound\n\nThe light of speed"}); + wiki.addTiddler({title: "TiddlerFour", text: "Simple `JS` and complex\n\n---\n\n```js\nvar match = reEnd.exec(this.parser.source)\n```\nend"}); + + it("should render tiddlers with no special markup as-is", function() { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerOne').tree)).toBe(wiki.getTiddlerText('TiddlerOne')); + }); + it("should preserve single new lines", function() { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerTwo').tree)).toBe(wiki.getTiddlerText('TiddlerTwo')); + }); + it("should preserve double new lines to create paragraphs", function() { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerThree').tree)).toBe(wiki.getTiddlerText('TiddlerThree')); + }); + + it("should render inline code and block code", function() { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerFour').tree)).toBe(wiki.getTiddlerText('TiddlerFour')); + }); +}); + +})(); From a075303932914502118f3f1e7fcce1704913a005 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 29 Jul 2024 23:24:32 +0800 Subject: [PATCH 10/98] DEBUG: only run my tests for development, remove before PR merge --- plugins/tiddlywiki/jasmine/jasmine-plugin.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/tiddlywiki/jasmine/jasmine-plugin.js b/plugins/tiddlywiki/jasmine/jasmine-plugin.js index 8dbf6568e..488377b44 100644 --- a/plugins/tiddlywiki/jasmine/jasmine-plugin.js +++ b/plugins/tiddlywiki/jasmine/jasmine-plugin.js @@ -12,7 +12,8 @@ The main module of the Jasmine test plugin for TiddlyWiki5 /*global $tw: true */ "use strict"; -var TEST_TIDDLER_FILTER = "[all[tiddlers+shadows]type[application/javascript]tag[$:/tags/test-spec]]"; +// DEBUG: only run my tests for development, remove before PR merge +var TEST_TIDDLER_FILTER = "[[test-wikitext-serialize.js]]"; var TESTS_DONE = false; exports.testsWereRun = function() { From 05dec729a0f7a266ebc69afac6777cf64003c031 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Tue, 30 Jul 2024 00:43:40 +0800 Subject: [PATCH 11/98] lint: if --- core/modules/parsers/wikiparser/wikiparser.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js index 854171d19..09866b064 100644 --- a/core/modules/parsers/wikiparser/wikiparser.js +++ b/core/modules/parsers/wikiparser/wikiparser.js @@ -218,8 +218,8 @@ WikiParser.prototype.parsePragmas = function() { var subTree = nextMatch.rule.parse(); if(subTree.length > 0) { // Set the start and end positions of the pragma rule if - if (subTree[0].start === undefined) subTree[0].start = start; - if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; + if(subTree[0].start === undefined) subTree[0].start = start; + if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; $tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; }); // Quick hack; we only cope with a single parse tree node being returned, which is true at the moment currentTreeBranch.push.apply(currentTreeBranch,subTree); @@ -248,9 +248,9 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) { var start = this.pos; var subTree = nextMatch.rule.parse(); // Set the start and end positions of the first and last blocks if they're not already set - if (subTree.length > 0) { - if (subTree[0].start === undefined) subTree[0].start = start; - if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; + if(subTree.length > 0) { + if(subTree[0].start === undefined) subTree[0].start = start; + if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; } $tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; }); return subTree; @@ -353,10 +353,10 @@ WikiParser.prototype.parseInlineRunUnterminated = function(options) { var start = this.pos; var subTree = nextMatch.rule.parse(); // Set the start and end positions of the first and last child if they're not already set - if (subTree.length > 0) { + if(subTree.length > 0) { // Set the start and end positions of the first and last child if they're not already set - if (subTree[0].start === undefined) subTree[0].start = start; - if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; + if(subTree[0].start === undefined) subTree[0].start = start; + if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; } $tw.utils.each(subTree, function (node) { node.rule = nextMatch.rule.name; }); tree.push.apply(tree,subTree); @@ -413,9 +413,9 @@ WikiParser.prototype.parseInlineRunTerminatedExtended = function(terminatorRegEx var start = this.pos; var subTree = inlineRuleMatch.rule.parse(); // Set the start and end positions of the first and last child if they're not already set - if (subTree.length > 0) { - if (subTree[0].start === undefined) subTree[0].start = start; - if (subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; + if(subTree.length > 0) { + if(subTree[0].start === undefined) subTree[0].start = start; + if(subTree[subTree.length - 1].end === undefined) subTree[subTree.length - 1].end = this.pos; } $tw.utils.each(subTree, function (node) { node.rule = inlineRuleMatch.rule.name; }); tree.push.apply(tree,subTree); From 1a6a071a29336dadfe0dfde0dba0cc2373568d1a Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Tue, 30 Jul 2024 00:43:55 +0800 Subject: [PATCH 12/98] feat: add rule: 'parseBlock' metadata --- core/modules/parsers/wikiparser/wikiparser.js | 2 +- core/modules/utils/parsetree.js | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js index 09866b064..10acf91ec 100644 --- a/core/modules/parsers/wikiparser/wikiparser.js +++ b/core/modules/parsers/wikiparser/wikiparser.js @@ -259,7 +259,7 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) { var start = this.pos; var children = this.parseInlineRun(terminatorRegExp); var end = this.pos; - return [{type: "element", tag: "p", children: children, start: start, end: end }]; + return [{type: "element", tag: "p", children: children, start: start, end: end, rule: 'parseBlock' }]; }; /* diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index ae548de0e..f5b2c12d0 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -124,9 +124,10 @@ exports.getParseTreeText = function getParseTreeText(tree) { }; /* -Utility to get the (similarly but not 1:1 equal) original wikitext of a parse tree node or array of nodes +Utility to get the (similarly but not 1:1 equal) original wikitext of a parse tree node or array of nodes. +Based on `node.rule` metadata added in `wikiparser.js`. */ -exports.serializeParseTree = function serializeParseTree(tree, tiddlerType) { +exports.serializeParseTree = function serializeParseTree(tree,tiddlerType) { var output = []; if($tw.utils.isArray(tree)) { $tw.utils.each(tree,function(node) { @@ -141,12 +142,11 @@ exports.serializeParseTree = function serializeParseTree(tree, tiddlerType) { Parser.prototype.inlineRuleClasses[tree.rule] || Parser.prototype.pragmaRuleClasses[tree.rule]; if(Rule && Rule.prototype.serialize) { - output.push(Rule.prototype.serialize(tree)); + output.push(Rule.prototype.serialize(tree,serializeParseTree)); + } else if(tree.rule === "parseBlock") { + output.push(serializeParseTree(tree.children,tiddlerType),"\n\n"); } } - if(tree.children) { - return serializeParseTree(tree.children); - } } return output.join(""); }; From 84e27c05b91e536daa82f933f7f14d460cdd4bc1 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Tue, 30 Jul 2024 00:46:16 +0800 Subject: [PATCH 13/98] feat: handle tailing \n that may be missing --- core/modules/parsers/wikiparser/rules/codeinline.js | 2 +- core/modules/parsers/wikiparser/rules/horizrule.js | 2 +- editions/test/tiddlers/tests/test-wikitext-serialize.js | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/codeinline.js b/core/modules/parsers/wikiparser/rules/codeinline.js index 015c325c5..a78b56e6b 100644 --- a/core/modules/parsers/wikiparser/rules/codeinline.js +++ b/core/modules/parsers/wikiparser/rules/codeinline.js @@ -56,7 +56,7 @@ exports.parse = function() { }; exports.serialize = function(tree) { - return "`" + tree.children.text + "`"; + return "`" + tree.children[0].text + "`"; } })(); diff --git a/core/modules/parsers/wikiparser/rules/horizrule.js b/core/modules/parsers/wikiparser/rules/horizrule.js index 697bd65a5..e9279a4d7 100644 --- a/core/modules/parsers/wikiparser/rules/horizrule.js +++ b/core/modules/parsers/wikiparser/rules/horizrule.js @@ -32,7 +32,7 @@ exports.parse = function() { }; exports.serialize = function() { - return "\n---\n"; + return "---\n"; } })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index d8747ef48..03e330b43 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -23,17 +23,18 @@ describe("WikiAST serialization tests", function() { wiki.addTiddler({title: "TiddlerFour", text: "Simple `JS` and complex\n\n---\n\n```js\nvar match = reEnd.exec(this.parser.source)\n```\nend"}); it("should render tiddlers with no special markup as-is", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerOne').tree)).toBe(wiki.getTiddlerText('TiddlerOne')); + // `trimEnd` because when we handle `p` element when parsing block rules, we always add a newline. But original text that may not have a trailing newline, will still be recognized as a block. + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerOne').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerOne')); }); it("should preserve single new lines", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerTwo').tree)).toBe(wiki.getTiddlerText('TiddlerTwo')); + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerTwo').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerTwo')); }); it("should preserve double new lines to create paragraphs", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerThree').tree)).toBe(wiki.getTiddlerText('TiddlerThree')); + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerThree').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerThree')); }); it("should render inline code and block code", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerFour').tree)).toBe(wiki.getTiddlerText('TiddlerFour')); + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerFour').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerFour')); }); }); From 078967c830ad26a145c01bb41808f8fc24787f38 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Tue, 30 Jul 2024 00:56:28 +0800 Subject: [PATCH 14/98] feat: allow recursive --- core/modules/parsers/wikiparser/rules/codeblock.js | 2 +- core/modules/parsers/wikiparser/rules/codeinline.js | 4 ++-- core/modules/parsers/wikiparser/rules/horizrule.js | 2 +- core/modules/utils/parsetree.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/codeblock.js b/core/modules/parsers/wikiparser/rules/codeblock.js index 11681261b..99e25af55 100644 --- a/core/modules/parsers/wikiparser/rules/codeblock.js +++ b/core/modules/parsers/wikiparser/rules/codeblock.js @@ -57,7 +57,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { return "\n```" + tree.attributes.language.value + "\n" + tree.attributes.code.value + "\n```\n"; } diff --git a/core/modules/parsers/wikiparser/rules/codeinline.js b/core/modules/parsers/wikiparser/rules/codeinline.js index a78b56e6b..4d32089ab 100644 --- a/core/modules/parsers/wikiparser/rules/codeinline.js +++ b/core/modules/parsers/wikiparser/rules/codeinline.js @@ -55,8 +55,8 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree) { - return "`" + tree.children[0].text + "`"; +exports.serialize = function(tree,serialize) { + return "`" + serialize(tree.children) + "`"; } })(); diff --git a/core/modules/parsers/wikiparser/rules/horizrule.js b/core/modules/parsers/wikiparser/rules/horizrule.js index e9279a4d7..4fd66de41 100644 --- a/core/modules/parsers/wikiparser/rules/horizrule.js +++ b/core/modules/parsers/wikiparser/rules/horizrule.js @@ -31,7 +31,7 @@ exports.parse = function() { return [{type: "element", tag: "hr"}]; }; -exports.serialize = function() { +exports.serialize = function(tree,serialize) { return "---\n"; } diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index f5b2c12d0..e825cd747 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -131,7 +131,7 @@ exports.serializeParseTree = function serializeParseTree(tree,tiddlerType) { var output = []; if($tw.utils.isArray(tree)) { $tw.utils.each(tree,function(node) { - output.push(serializeParseTree(node)); + output.push(serializeParseTree(node,tiddlerType)); }); } else { if(tree.type === "text") { From 2aff9fecf19bc2ff918a3d2d85c94402be55121c Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 1 Aug 2024 23:29:48 +0800 Subject: [PATCH 15/98] feat: generate more rule and tests --- .../parsers/wikiparser/rules/commentblock.js | 17 +- .../parsers/wikiparser/rules/commentinline.js | 16 +- .../parsers/wikiparser/rules/conditional.js | 12 + core/modules/parsers/wikiparser/rules/dash.js | 5 + .../parsers/wikiparser/rules/entity.js | 5 + .../parsers/wikiparser/rules/extlink.js | 9 + .../rules/filteredtranscludeblock.js | 15 + .../rules/filteredtranscludeinline.js | 15 + .../parsers/wikiparser/rules/fnprocdef.js | 15 + .../wikiparser/rules/hardlinebreaks.js | 15 + .../parsers/wikiparser/rules/heading.js | 12 + core/modules/parsers/wikiparser/rules/html.js | 15 + .../modules/parsers/wikiparser/rules/image.js | 13 + .../parsers/wikiparser/rules/import.js | 7 + core/modules/parsers/wikiparser/rules/list.js | 24 ++ .../wikiparser/rules/macrocallblock.js | 11 + .../wikiparser/rules/macrocallinline.js | 11 + .../parsers/wikiparser/rules/macrodef.js | 13 + .../parsers/wikiparser/rules/parameters.js | 9 + .../parsers/wikiparser/rules/parsermode.js | 7 + .../parsers/wikiparser/rules/prettyextlink.js | 9 + .../parsers/wikiparser/rules/prettylink.js | 11 +- .../tiddlers/tests/test-wikitext-serialize.js | 279 ++++++++++++++++-- 23 files changed, 512 insertions(+), 33 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 1c303f38f..62bbd4088 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -46,11 +46,24 @@ exports.findNextMatch = function(startPos) { return undefined; }; + exports.parse = function() { // Move past the match this.parser.pos = this.endMatchRegExp.lastIndex; - // Don't return any elements - return []; + // Return a node representing the comment that is not rendered + var commentStart = this.match.index; + var commentEnd = this.endMatch.index + this.endMatch[0].length; + var commentText = this.parser.source.slice(commentStart, commentEnd); + return [{ + type: "commentblock", + text: commentText, + start: commentStart, + end: commentEnd + }]; +}; + +exports.serialize = function(tree) { + return tree.text; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/commentinline.js b/core/modules/parsers/wikiparser/rules/commentinline.js index 671bd79d6..50e861fe4 100644 --- a/core/modules/parsers/wikiparser/rules/commentinline.js +++ b/core/modules/parsers/wikiparser/rules/commentinline.js @@ -43,8 +43,20 @@ exports.findNextMatch = function(startPos) { exports.parse = function() { // Move past the match this.parser.pos = this.endMatchRegExp.lastIndex; - // Don't return any elements - return []; + // Return a node representing the inline comment + var commentStart = this.match.index; + var commentEnd = this.endMatch.index + this.endMatch[0].length; + var commentText = this.parser.source.slice(commentStart, commentEnd); + return [{ + type: "commentinline", + text: commentText, + start: commentStart, + end: commentEnd + }]; +}; + +exports.serialize = function(tree) { + return tree.text; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js index 23940fd88..ead7fc0af 100644 --- a/core/modules/parsers/wikiparser/rules/conditional.js +++ b/core/modules/parsers/wikiparser/rules/conditional.js @@ -117,4 +117,16 @@ exports.parseIfClause = function(filterCondition) { return [listWidget]; }; +exports.serialize = function(tree, serialize) { + var filterCondition = tree.attributes.filter.value; + var ifClause = serialize(tree.children[0].children); + var elseClause = serialize(tree.children[1].children); + var serialized = '<% if ' + filterCondition + ' %>' + ifClause; + if(elseClause) { + serialized += '<% else %>' + elseClause; + } + serialized += '<% endif %>'; + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/dash.js b/core/modules/parsers/wikiparser/rules/dash.js index 45481bf07..60c82f0a7 100644 --- a/core/modules/parsers/wikiparser/rules/dash.js +++ b/core/modules/parsers/wikiparser/rules/dash.js @@ -37,4 +37,9 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree) { + var dash = tree.entity === "–" ? "--" : "---"; + return dash; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/entity.js b/core/modules/parsers/wikiparser/rules/entity.js index dc3917daf..7f15c8a95 100644 --- a/core/modules/parsers/wikiparser/rules/entity.js +++ b/core/modules/parsers/wikiparser/rules/entity.js @@ -37,4 +37,9 @@ exports.parse = function() { return [{type: "entity", entity: this.match[0]}]; }; +// Serialize method for the entity rule +exports.serialize = function(tree, serialize) { + return tree.entity; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/extlink.js b/core/modules/parsers/wikiparser/rules/extlink.js index 5b9f57adf..58b7e772e 100644 --- a/core/modules/parsers/wikiparser/rules/extlink.js +++ b/core/modules/parsers/wikiparser/rules/extlink.js @@ -53,4 +53,13 @@ exports.parse = function() { } }; +// Serialize method for the extlink rule +exports.serialize = function(tree, serialize) { + if(tree.type === "text") { + return tree.text; + } else if(tree.type === "element" && tree.tag === "a") { + return tree.attributes.href.value; + } +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js index 73bdff813..c66009f85 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js @@ -71,4 +71,19 @@ exports.parse = function() { return [node]; }; +exports.serialize = function(tree) { + // Filter expression + var serialized = "{{{" + tree.attributes.filter.value; + // Tooltip text + if(tree.attributes.tooltip) serialized += "|" + tree.attributes.tooltip.value; + // Template title + if(tree.attributes.template) serialized += "||" + tree.attributes.template.value; + serialized += "}}}"; + // Inline styles + if(tree.attributes.style) serialized += tree.attributes.style.value; + // CSS classes + if(tree.attributes.itemClass) serialized += "." + tree.attributes.itemClass.value.split(" ").join("."); + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js index c0b19a941..cb992dbed 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js @@ -70,4 +70,19 @@ exports.parse = function() { return [node]; }; +exports.serialize = function(tree) { + // Filter expression + var serialized = "{{{" + tree.attributes.filter.value; + // Tooltip text + if(tree.attributes.tooltip) serialized += "|" + tree.attributes.tooltip.value; + // Template title + if(tree.attributes.template) serialized += "||" + tree.attributes.template.value; + serialized += "}}}"; + // Inline styles + if(tree.attributes.style) serialized += tree.attributes.style.value; + // CSS classes + if(tree.attributes.itemClass) serialized += "." + tree.attributes.itemClass.value.split(" ").join("."); + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/fnprocdef.js b/core/modules/parsers/wikiparser/rules/fnprocdef.js index 85bd14d5c..a4259e574 100644 --- a/core/modules/parsers/wikiparser/rules/fnprocdef.js +++ b/core/modules/parsers/wikiparser/rules/fnprocdef.js @@ -93,5 +93,20 @@ exports.parse = function() { return parseTreeNodes; }; +exports.serialize = function(tree, serialize) { + // Type of definition: "function", "procedure", or "widget" + var type = tree.isFunctionDefinition ? "function" : (tree.isProcedureDefinition ? "procedure" : "widget"); + // Name of the function, procedure, or widget + var name = tree.attributes.name.value; + // Parameters with default values + var params = tree.params.map(function(param) { + return param.name + (param.default ? ":" + param.default : ""); + }).join(","); + // Definition text + var definition = tree.attributes.value.value; + // Construct the serialized string + return "\\" + type + " " + name + "(" + params + ")\n" + definition + "\n\\end"; +}; + })(); \ No newline at end of file diff --git a/core/modules/parsers/wikiparser/rules/hardlinebreaks.js b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js index 94f517cd4..39ef6fc5c 100644 --- a/core/modules/parsers/wikiparser/rules/hardlinebreaks.js +++ b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js @@ -57,4 +57,19 @@ exports.parse = function() { return tree; }; +exports.serialize = function(tree,serialize) { + // Serialized text with hard line breaks + var serialized = '"""\n'; + // Serialize each node in the tree + tree.forEach(function(node) { + if(node.type === "element" && node.tag === "br") { + serialized += "\n"; + } else { + serialized += serialize([node]).join(''); + } + }); + serialized += '\n"""'; + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/heading.js b/core/modules/parsers/wikiparser/rules/heading.js index 7a0ecb9db..79df971e5 100644 --- a/core/modules/parsers/wikiparser/rules/heading.js +++ b/core/modules/parsers/wikiparser/rules/heading.js @@ -45,4 +45,16 @@ exports.parse = function() { children: tree }]; }; + +exports.serialize = function(tree, serialize) { + // Heading level + var headingLevel = tree.tag.length - 1; + // Classes + var classes = tree.attributes.class ? tree.attributes.class.value.split(" ").join(".") : ""; + // Serialized heading text + var headingText = serialize(tree.children).join(''); + // Construct the serialized string + return Array(headingLevel + 1).join("!") + (classes ? "." + classes : "") + " " + headingText; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index 61c4ad9e1..911099b37 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -195,4 +195,19 @@ exports.isLegalTag = function(tag) { } }; +exports.serialize = function(tree, serialize) { + var tag = tree.tag; + var attributes = Object.keys(tree.attributes).map(function(key) { + return key + '="' + tree.attributes[key].value + '"'; + }).join(" "); + // Children + var children = tree.children ? serialize(tree.children).join('') : ''; + // Self-closing tag + if(tree.isSelfClosing) { + return "<" + tag + (attributes ? " " + attributes : "") + " />"; + } + // Opening and closing tags + return "<" + tag + (attributes ? " " + attributes : "") + ">" + children + ""; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/image.js b/core/modules/parsers/wikiparser/rules/image.js index 6f58225e0..8591e544e 100644 --- a/core/modules/parsers/wikiparser/rules/image.js +++ b/core/modules/parsers/wikiparser/rules/image.js @@ -130,4 +130,17 @@ exports.parseImage = function(source,pos) { return node; }; +exports.serialize = function(tree) { + // Width attribute + var width = tree.attributes.width ? " width=" + tree.attributes.width.value : ""; + // Height attribute + var height = tree.attributes.height ? " height=" + tree.attributes.height.value : ""; + // Tooltip attribute + var tooltip = tree.attributes.tooltip ? tree.attributes.tooltip.value + "|" : ""; + // Source attribute + var source = tree.attributes.source.value; + // Construct the serialized string + return "[img" + width + height + " [" + tooltip + source + "]]"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/import.js b/core/modules/parsers/wikiparser/rules/import.js index bb1832255..7025d20f2 100644 --- a/core/modules/parsers/wikiparser/rules/import.js +++ b/core/modules/parsers/wikiparser/rules/import.js @@ -51,4 +51,11 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree) { + // Filter attribute + var filter = tree.attributes.filter.value; + // Construct the serialized string + return "\\import " + filter; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js index d89c201b9..8dc8411aa 100644 --- a/core/modules/parsers/wikiparser/rules/list.js +++ b/core/modules/parsers/wikiparser/rules/list.js @@ -153,4 +153,28 @@ exports.parse = function() { return [listStack[0]]; }; +exports.serialize = function(tree, serialize) { + // Serialize the list recursively + return serializeList(tree, serialize, 0); +}; + +// utility to handle recursion of list +function serializeList(node, serialize, depth) { + // List tag + var listTag = node.tag; + // List item tag + var itemTag = listTypes[listTag[0]].itemTag; + // Serialized list items + var items = node.children.map(function(child) { + // Classes + var classes = child.attributes && child.attributes.class ? child.attributes.class.value.split(" ").join(".") : ""; + // Serialized children + var children = serialize(child.children).join(''); + // Construct the serialized list item + return Array(depth + 1).join(listTag[0]) + (classes ? "." + classes : "") + " " + children; + }).join("\n"); + // Return the serialized list + return items; +} + })(); diff --git a/core/modules/parsers/wikiparser/rules/macrocallblock.js b/core/modules/parsers/wikiparser/rules/macrocallblock.js index a2c10e04a..c3b0e92e9 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallblock.js +++ b/core/modules/parsers/wikiparser/rules/macrocallblock.js @@ -53,4 +53,15 @@ exports.parse = function() { return [call]; }; +exports.serialize = function(tree) { + // Macro name + var name = tree.name; + // Macro parameters + var params = tree.params.map(function(param) { + return param.value; + }).join(" "); + // Construct the serialized string + return "<<" + name + " " + params + ">>"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/macrocallinline.js b/core/modules/parsers/wikiparser/rules/macrocallinline.js index e9f79f09e..a62596414 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallinline.js +++ b/core/modules/parsers/wikiparser/rules/macrocallinline.js @@ -46,4 +46,15 @@ exports.parse = function() { return [call]; }; +exports.serialize = function(tree) { + // Macro name + var name = tree.name; + // Macro parameters + var params = tree.params.map(function(param) { + return param.value; + }).join(" "); + // Construct the serialized string + return "<<" + name + " " + params + ">>"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js index 2001f70d5..31a93f27b 100644 --- a/core/modules/parsers/wikiparser/rules/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/macrodef.js @@ -89,4 +89,17 @@ exports.parse = function() { return parseTreeNodes; }; +exports.serialize = function(tree) { + // Macro name + var name = tree.attributes.name.value; + // Parameters + var params = tree.params.map(function(param) { + return param.name + (param.default ? ":" + param.default : ""); + }).join(","); + // Definition text + var definition = tree.attributes.value.value; + // Construct the serialized string + return "\\define " + name + "(" + params + ")\n" + definition + "\n\\end"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/parameters.js b/core/modules/parsers/wikiparser/rules/parameters.js index 60bbd8901..692f03ea7 100644 --- a/core/modules/parsers/wikiparser/rules/parameters.js +++ b/core/modules/parsers/wikiparser/rules/parameters.js @@ -57,4 +57,13 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree) { + // Parameters + var params = tree.orderedAttributes.map(function(param) { + return param.name + (param.value ? ":" + param.value : ""); + }).join(","); + // Construct the serialized string + return "\\parameters(" + params + ")"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/parsermode.js b/core/modules/parsers/wikiparser/rules/parsermode.js index 72a6de067..4814a4ba1 100644 --- a/core/modules/parsers/wikiparser/rules/parsermode.js +++ b/core/modules/parsers/wikiparser/rules/parsermode.js @@ -65,4 +65,11 @@ exports.parse = function() { return []; }; +exports.serialize = function(tree) { + // Parser mode + var mode = tree.parser.parseAsInline ? "inline" : "block"; + // Construct the serialized string + return "\\parsermode " + mode; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/prettyextlink.js b/core/modules/parsers/wikiparser/rules/prettyextlink.js index 4707fa0d0..e2cc48a7e 100644 --- a/core/modules/parsers/wikiparser/rules/prettyextlink.js +++ b/core/modules/parsers/wikiparser/rules/prettyextlink.js @@ -117,4 +117,13 @@ exports.parseLink = function(source,pos) { return node; }; +exports.serialize = function(tree) { + // Tooltip text + var tooltip = tree.children[0].text; + // URL + var url = tree.attributes.href.value; + // Construct the serialized string + return "[ext[" + (tooltip !== url ? tooltip + "|" : "") + url + "]]"; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/prettylink.js b/core/modules/parsers/wikiparser/rules/prettylink.js index 66c19dc88..74a275e42 100644 --- a/core/modules/parsers/wikiparser/rules/prettylink.js +++ b/core/modules/parsers/wikiparser/rules/prettylink.js @@ -35,7 +35,7 @@ exports.parse = function() { var text = this.match[1], link = this.match[2] || text, textEndPos = this.parser.source.indexOf("|", start); - if (textEndPos < 0 || textEndPos > this.matchRegExp.lastIndex) { + if(textEndPos < 0 || textEndPos > this.matchRegExp.lastIndex) { textEndPos = this.matchRegExp.lastIndex - 2; } var linkStart = this.match[2] ? (start + this.match[1].length + 1) : start; @@ -67,4 +67,13 @@ exports.parse = function() { } }; +exports.serialize = function(tree) { + // Link text + var text = tree.children[0].text; + // Link target + var target = tree.attributes.to ? tree.attributes.to.value : tree.attributes.href.value; + // Construct the serialized string + return "[[" + text + (text !== target ? "|" + target : "") + "]]"; +}; + })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 03e330b43..b21627564 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -6,36 +6,259 @@ tags: [[$:/tags/test-spec]] Tests the wikitext inverse-rendering from Wiki AST. \*/ -(function(){ -/*jslint node: true, browser: true */ -/*global $tw: false */ -"use strict"; +describe('WikiAST serialization tests', function () { + var wiki = new $tw.Wiki(); -describe("WikiAST serialization tests", function() { + wiki.addTiddler({ title: 'TiddlerOne', text: 'The quick brown fox' }); + it('should render tiddlers with no special markup as-is', function () { + // `trimEnd` because when we handle `p` element when parsing block rules, we always add a newline. But original text that may not have a trailing newline, will still be recognized as a block. + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerOne').tree).trimEnd()).toBe( + wiki.getTiddlerText('TiddlerOne') + ); + }); - // Create a wiki - var wiki = new $tw.Wiki(); - // Add a couple of tiddlers - wiki.addTiddler({title: "TiddlerOne", text: "The quick brown fox"}); - wiki.addTiddler({title: "TiddlerTwo", text: "The rain in Spain\nfalls mainly on the plain"}); - wiki.addTiddler({title: "TiddlerThree", text: "The speed of sound\n\nThe light of speed"}); - wiki.addTiddler({title: "TiddlerFour", text: "Simple `JS` and complex\n\n---\n\n```js\nvar match = reEnd.exec(this.parser.source)\n```\nend"}); + wiki.addTiddler({ title: 'TiddlerTwo', text: 'The rain in Spain\nfalls mainly on the plain' }); + it('should preserve single new lines', function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerTwo').tree).trimEnd()).toBe( + wiki.getTiddlerText('TiddlerTwo') + ); + }); - it("should render tiddlers with no special markup as-is", function() { - // `trimEnd` because when we handle `p` element when parsing block rules, we always add a newline. But original text that may not have a trailing newline, will still be recognized as a block. - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerOne').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerOne')); - }); - it("should preserve single new lines", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerTwo').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerTwo')); - }); - it("should preserve double new lines to create paragraphs", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerThree').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerThree')); - }); - - it("should render inline code and block code", function() { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerFour').tree).trimEnd()).toBe(wiki.getTiddlerText('TiddlerFour')); - }); + wiki.addTiddler({ title: 'TiddlerThree', text: 'The speed of sound\n\nThe light of speed' }); + it('should preserve double new lines to create paragraphs', function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerThree').tree).trimEnd()).toBe( + wiki.getTiddlerText('TiddlerThree') + ); + }); + + wiki.addTiddler({ + title: 'TiddlerFour', + text: 'Simple `JS` and complex\n\n---\n\n```js\nvar match = reEnd.exec(this.parser.source)\n```\nend', + }); + it('should render inline code and block code', function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerFour').tree).trimEnd()).toBe( + wiki.getTiddlerText('TiddlerFour') + ); + }); + + // Test case for commentblock rule + wiki.addTiddler({ + title: 'CommentBlockTest', + text: '\n\nSome text\n\n\n\nMore text', + }); + it('should serialize block comments correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('CommentBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('CommentBlockTest').trimEnd()); + }); + + // Test case for commentinline rule + wiki.addTiddler({ + title: 'CommentInlineTest', + text: 'This is some text with an inline comment and some more text.', + }); + it('should serialize inline comments correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('CommentInlineTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('CommentInlineTest').trimEnd()); + }); + + // Test case for conditional rule + wiki.addTiddler({ + title: 'ConditionalTest', + text: 'This is a <% if [{something}] %>Elephant<% elseif [{else}] %>Pelican<% else %>Crocodile<% endif %>', + }); + it('should serialize conditional statements correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ConditionalTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ConditionalTest').trimEnd()); + }); + + // Test case for dash rule + wiki.addTiddler({ + title: 'DashTest', + text: 'This is an en-dash: --\n\nThis is an em-dash: ---', + }); + it('should serialize dashes correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('DashTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('DashTest').trimEnd()); + }); + + // Test case for entity rule + wiki.addTiddler({ + title: 'EntityTest', + text: 'This is a copyright symbol: ©', + }); + it('should serialize HTML entities correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('EntityTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('EntityTest').trimEnd()); + }); + + // Test case for extlink rule + wiki.addTiddler({ + title: 'ExtLinkTest', + text: 'An external link: https://www.tiddlywiki.com/\n\nA suppressed external link: ~http://www.tiddlyspace.com/', + }); + it('should serialize external links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ExtLinkTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ExtLinkTest').trimEnd()); + }); + + // Test case for filteredtranscludeblock rule + wiki.addTiddler({ + title: 'FilteredTranscludeBlockTest', + text: '{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class', + }); + it('should serialize block-level filtered transclusion correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FilteredTranscludeBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('FilteredTranscludeBlockTest').trimEnd()); + }); + + // Test case for filteredtranscludeinline rule + wiki.addTiddler({ + title: 'FilteredTranscludeInlineTest', + text: '{{{ [tag[docs]] }}} {{{ [tag[docs]] |tooltip}}} {{{ [tag[docs]] ||TemplateTitle}}} {{{ [tag[docs]] |tooltip||TemplateTitle}}} {{{ [tag[docs]] }}width:40;height:50;}.class.class', + }); + it('should serialize inline filtered transclusion correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FilteredTranscludeInlineTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('FilteredTranscludeInlineTest').trimEnd()); + }); + + // Test case based on the rule code's comment + wiki.addTiddler({ + title: 'FunctionDefinition', + text: '\\function name(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end\n\n\\procedure name(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end\n\n\\widget $mywidget(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end', + }); + it('should serialize function, procedure, and widget definitions correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FunctionDefinition').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('FunctionDefinition').trimEnd()); + }); + + // Test case for hardlinebreaks rule + wiki.addTiddler({ + title: 'HardLineBreaksTest', + text: '"""\nThis is some text\nThat is set like\nIt is a Poem\nWhen it is\nClearly\nNot\n"""\n', + }); + it('should serialize hard line breaks correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('HardLineBreaksTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('HardLineBreaksTest').trimEnd()); + }); + + // Test case for heading rule + wiki.addTiddler({ + title: 'HeadingTest', + text: '! Heading 1\n!! Heading 2\n!!! Heading 3\n!!!! Heading 4\n!!!!! Heading 5\n!!!!!! Heading 6', + }); + it('should serialize headings correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('HeadingTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('HeadingTest').trimEnd()); + }); + + // Test case for html rule + wiki.addTiddler({ + title: 'HtmlTest', + text: '\n\n<$slider target="MyTiddler">\nThis is a widget invocation\n', + }); + it('should serialize HTML elements and widgets correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('HtmlTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('HtmlTest').trimEnd()); + }); + + // Test case for image rule + wiki.addTiddler({ + title: 'ImageTest', + text: '[img[https://tiddlywiki.com/fractalveg.jpg]]\n[img width=23 height=24 [https://tiddlywiki.com/fractalveg.jpg]]\n[img width={{!!width}} height={{!!height}} [https://tiddlywiki.com/fractalveg.jpg]]\n[img[Description of image|https://tiddlywiki.com/fractalveg.jpg]]\n[img[TiddlerTitle]]\n[img[Description of image|TiddlerTitle]]', + }); + it('should serialize image tags correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImageTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ImageTest').trimEnd()); + }); + + // Test case for import rule + wiki.addTiddler({ + title: 'ImportTest', + text: '\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]', + }); + it('should serialize import pragma correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImportTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ImportTest').trimEnd()); + }); + + // Test case for list rule + wiki.addTiddler({ + title: 'ListTest', + text: '* This is an unordered list\n* It has two items\n\n# This is a numbered list\n## With a subitem\n# And a third item\n\n; This is a term that is being defined\n: This is the definition of that term\n\n#** One\n#* Two\n#** Three\n#**** Four\n#**# Five\n#**## Six\n## Seven\n### Eight\n## Nine\n\n* List item one\n*.active List item two has the class `active`\n* List item three', + }); + it('should serialize lists correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ListTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ListTest').trimEnd()); + }); + + // Test case for macrocallblock rule + wiki.addTiddler({ + title: 'MacroCallBlockTest', + text: '<>', + }); + it('should serialize block macro calls correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroCallBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('MacroCallBlockTest').trimEnd()); + }); + + // Test case for macrocallinline rule + wiki.addTiddler({ + title: 'MacroCallInlineTest', + text: 'This is a macro call: <>', + }); + it('should serialize inline macro calls correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroCallInlineTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('MacroCallInlineTest').trimEnd()); + }); + + // Test case for macrodef rule + wiki.addTiddler({ + title: 'MacroDefTest', + text: '\\define name(param:defaultvalue,param2:defaultvalue)\ndefinition text, including $param$ markers\n\\end', + }); + it('should serialize macro definitions correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroDefTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('MacroDefTest').trimEnd()); + }); + + // Test case for parameters rule + wiki.addTiddler({ + title: 'ParametersTest', + text: '\\parameters(param:defaultvalue,param2:defaultvalue)', + }); + it('should serialize parameter definitions correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ParametersTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ParametersTest').trimEnd()); + }); + + // Test case for parsermode rule + wiki.addTiddler({ + title: 'ParserModeTest', + text: '\\parsermode block\n\\parsermode inline', + }); + it('should serialize parser mode specifications correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ParserModeTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ParserModeTest').trimEnd()); + }); + + // Test case for prettyextlink rule + wiki.addTiddler({ + title: 'PrettyExtLinkTest', + text: '[ext[https://tiddlywiki.com/fractalveg.jpg]]\n[ext[Tooltip|https://tiddlywiki.com/fractalveg.jpg]]', + }); + it('should serialize pretty external links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('PrettyExtLinkTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('PrettyExtLinkTest').trimEnd()); + }); + + // Test case for prettylink rule + wiki.addTiddler({ + title: 'PrettyLinkTest', + text: '[[Introduction]]\n[[Link description|TiddlerTitle]]', + }); + it('should serialize pretty links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('PrettyLinkTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('PrettyLinkTest').trimEnd()); + }); }); - -})(); From bfd116a438a61f790928e77a4cbb8a079c75ccfa Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Fri, 2 Aug 2024 22:54:45 +0800 Subject: [PATCH 16/98] feat: generate more rule and tests --- .../parsers/wikiparser/rules/emphasis/bold.js | 13 ++ .../wikiparser/rules/emphasis/italic.js | 13 ++ .../rules/emphasis/strikethrough.js | 13 ++ .../wikiparser/rules/emphasis/subscript.js | 13 ++ .../wikiparser/rules/emphasis/superscript.js | 13 ++ .../wikiparser/rules/emphasis/underscore.js | 13 ++ core/modules/parsers/wikiparser/rules/html.js | 14 +- .../parsers/wikiparser/rules/quoteblock.js | 13 ++ .../modules/parsers/wikiparser/rules/rules.js | 13 ++ .../parsers/wikiparser/rules/styleblock.js | 22 +++ .../parsers/wikiparser/rules/styleinline.js | 22 +++ .../parsers/wikiparser/rules/syslink.js | 13 ++ .../modules/parsers/wikiparser/rules/table.js | 29 ++++ .../wikiparser/rules/transcludeblock.js | 37 +++++ .../wikiparser/rules/transcludeinline.js | 37 +++++ .../parsers/wikiparser/rules/typedblock.js | 15 ++ .../parsers/wikiparser/rules/wikilink.js | 13 ++ .../wikiparser/rules/wikilinkprefix.js | 11 ++ .../tiddlers/tests/test-wikitext-serialize.js | 153 ++++++++++++++++++ 19 files changed, 463 insertions(+), 7 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/emphasis/bold.js b/core/modules/parsers/wikiparser/rules/emphasis/bold.js index 3799feeb5..946fff7cf 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/bold.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/bold.js @@ -47,4 +47,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'strong', children: [{ type: 'text', text: 'bold' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter + var serialized = "''"; + // Serialize the children of the bold element + serialized += serialize(tree.children); + // Close the serialized string with the closing delimiter + serialized += "''"; + // Return the complete serialized string + return serialized; +}; + })(); \ No newline at end of file diff --git a/core/modules/parsers/wikiparser/rules/emphasis/italic.js b/core/modules/parsers/wikiparser/rules/emphasis/italic.js index 3e0744c4d..798429ed2 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/italic.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/italic.js @@ -47,4 +47,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'em', children: [{ type: 'text', text: 'italic' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter + var serialized = "//"; + // Serialize the children of the italic element + serialized += serialize(tree.children); + // Close the serialized string with the closing delimiter + serialized += "//"; + // Return the complete serialized string + return serialized; +}; + })(); \ No newline at end of file diff --git a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js index 0fb34fc52..572217052 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js @@ -47,4 +47,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'strike', children: [{ type: 'text', text: 'strikethrough' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter + var serialized = "~~"; + // Serialize the children of the strikethrough element + serialized += serialize(tree.children); + // Close the serialized string with the closing delimiter + serialized += "~~"; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js index 12be0fbbc..f4d9ecc5d 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js @@ -47,4 +47,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'sub', children: [{ type: 'text', text: 'subscript' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter + var serialized = ",,"; + // Serialize the children of the subscript element + serialized += serialize(tree.children); + // Close the serialized string with the closing delimiter + serialized += ",,"; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js index 5a5330d8c..e33e75ac4 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js @@ -47,4 +47,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'sup', children: [{ type: 'text', text: 'superscript' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter + var serialized = "^^"; + // Serialize the children of the superscript element + serialized += serialize(tree.children); + // Close the serialized string with the closing delimiter + serialized += "^^"; + // Return the complete serialized string + return serialized; +}; + })(); \ No newline at end of file diff --git a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js index d36bd242d..640b36e02 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js @@ -47,4 +47,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'u', children: [{ type: 'text', text: 'underscore' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter + var serialized = "__"; + // Serialize the children of the underscore element + serialized += serialize(tree.children); + // Close the serialized string with the closing delimiter + serialized += "__"; + // Return the complete serialized string + return serialized; +}; + })(); \ No newline at end of file diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index 911099b37..305f037de 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -44,7 +44,7 @@ Parse the most recent match exports.parse = function() { // Retrieve the most recent match so that recursive calls don't overwrite it var tag = this.nextTag; - if (!tag.isSelfClosing) { + if(!tag.isSelfClosing) { tag.openTagStart = tag.start; tag.openTagEnd = tag.end; } @@ -66,22 +66,22 @@ exports.parse = function() { } tag.end = this.parser.pos; tag.closeTagEnd = tag.end; - if (tag.closeTagEnd === tag.openTagEnd || this.parser.source[tag.closeTagEnd - 1] !== '>') { + if(tag.closeTagEnd === tag.openTagEnd || this.parser.source[tag.closeTagEnd - 1] !== '>') { tag.closeTagStart = tag.end; } else { tag.closeTagStart = tag.closeTagEnd - 2; var closeTagMinPos = tag.children.length > 0 ? tag.children[tag.children.length-1].end : tag.openTagEnd; - if (!Number.isSafeInteger(closeTagMinPos)) closeTagMinPos = tag.openTagEnd; - while (tag.closeTagStart >= closeTagMinPos) { + if(!Number.isSafeInteger(closeTagMinPos)) closeTagMinPos = tag.openTagEnd; + while(tag.closeTagStart >= closeTagMinPos) { var char = this.parser.source[tag.closeTagStart]; - if (char === '>') { + if(char === '>') { tag.closeTagStart = -1; break; } - if (char === '<') break; + if(char === '<') break; tag.closeTagStart -= 1; } - if (tag.closeTagStart < closeTagMinPos) { + if(tag.closeTagStart < closeTagMinPos) { tag.closeTagStart = tag.end; } } diff --git a/core/modules/parsers/wikiparser/rules/quoteblock.js b/core/modules/parsers/wikiparser/rules/quoteblock.js index fdd6c860b..3f946cf13 100644 --- a/core/modules/parsers/wikiparser/rules/quoteblock.js +++ b/core/modules/parsers/wikiparser/rules/quoteblock.js @@ -73,4 +73,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'element', tag: 'blockquote', attributes: { class: { type: 'string', value: 'tc-quote' } }, children: [{ type: 'text', text: 'Quote text' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Split the class attribute value into an array of classes, classes: ['tc-quote'] + var classes = tree.attributes.class.value.split(" "); + // Start the serialized string with the opening delimiter and classes, serialized: '<< 0) { + serialized += "|" + params.join("|"); + } + // Close the serialized string + serialized += "}}"; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/transcludeinline.js b/core/modules/parsers/wikiparser/rules/transcludeinline.js index 3ce9dc78e..78839f925 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeinline.js +++ b/core/modules/parsers/wikiparser/rules/transcludeinline.js @@ -84,4 +84,41 @@ exports.parse = function() { } }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'transclude', attributes: { $tiddler: { name: '$tiddler', type: 'string', value: 'MyTiddler' }, $field: { name: '$field', type: 'string', value: 'text' } } } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string + var serialized = "{{"; + // Check for tiddler attribute + if(tree.attributes.$tiddler) { + serialized += tree.attributes.$tiddler.value; + // Check for field attribute + if(tree.attributes.$field) { + serialized += "##" + tree.attributes.$field.value; + } + // Check for index attribute + if(tree.attributes.$index) { + serialized += "!!" + tree.attributes.$index.value; + } + } + // Check for template attribute + if(tree.attributes.$template) { + serialized += "||" + tree.attributes.$template.value; + } + // Check for parameters + var params = []; + for(var key in tree.attributes) { + if(key !== "$tiddler" && key !== "$field" && key !== "$index" && key !== "$template") { + params.push(tree.attributes[key].value); + } + } + if(params.length > 0) { + serialized += "|" + params.join("|"); + } + // Close the serialized string + serialized += "}}"; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/typedblock.js b/core/modules/parsers/wikiparser/rules/typedblock.js index 07c88be15..daaefb7b7 100644 --- a/core/modules/parsers/wikiparser/rules/typedblock.js +++ b/core/modules/parsers/wikiparser/rules/typedblock.js @@ -83,4 +83,19 @@ exports.parse = function() { } }; +exports.serialize = function (tree, serialize) { + // tree: { type: 'element', tag: 'pre', children: [{ type: 'text', text: 'This will be rendered as JavaScript' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the opening delimiter and type + var serialized = '$$$'; // Extract the type from the tree node (assuming it's stored in a specific attribute) + if(tree.attributes && tree.attributes.type) { + serialized += tree.attributes.type.value; + } + serialized += '\n'; // Serialize the children of the block + serialized += serialize(tree.children); // Close the serialized string + serialized += "\n$$$"; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/wikilink.js b/core/modules/parsers/wikiparser/rules/wikilink.js index 6b195f9ff..5762aeee4 100644 --- a/core/modules/parsers/wikiparser/rules/wikilink.js +++ b/core/modules/parsers/wikiparser/rules/wikilink.js @@ -65,4 +65,17 @@ exports.parse = function() { }]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'link', attributes: { to: { type: 'string', value: 'AWikiLink' } }, children: [{ type: 'text', text: 'AWikiLink' }] } + // serialize: function that accepts array of nodes or a node and returns a string + // Check if the link is suppressed + var isSuppressed = tree.children[0].text.substr(0,1) === $tw.config.textPrimitives.unWikiLink; + // Initialize the serialized string + var serialized = isSuppressed ? $tw.config.textPrimitives.unWikiLink : ""; + // Append the link text + serialized += tree.attributes.to.value; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js index 60cb3d992..be902edc8 100644 --- a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js +++ b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js @@ -37,4 +37,15 @@ exports.parse = function() { return [{type: "text", text: linkText.substr(1)}]; }; +exports.serialize = function(tree, serialize) { + // tree: { type: 'text', text: 'SuppressedLink' } + // serialize: function that accepts array of nodes or a node and returns a string + // Initialize the serialized string with the unwikilink character + var serialized = $tw.config.textPrimitives.unWikiLink; + // Append the text + serialized += tree.text; + // Return the complete serialized string + return serialized; +}; + })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index b21627564..1ab851226 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -10,6 +10,60 @@ Tests the wikitext inverse-rendering from Wiki AST. describe('WikiAST serialization tests', function () { var wiki = new $tw.Wiki(); + wiki.addTiddler({ + title: 'BoldEmphasisTest', + text: "This is ''bold'' text" + }); + it('should serialize bold emphasis correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('BoldEmphasisTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('BoldEmphasisTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'ItalicEmphasisTest', + text: "This is //italic// text" + }); + it('should serialize italic emphasis correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ItalicEmphasisTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('ItalicEmphasisTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'StrikethroughEmphasisTest', + text: "This is ~~strikethrough~~ text" + }); + it('should serialize strikethrough emphasis correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('StrikethroughEmphasisTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('StrikethroughEmphasisTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'SubscriptEmphasisTest', + text: "This is ,,subscript,, text" + }); + it('should serialize subscript emphasis correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('SubscriptEmphasisTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('SubscriptEmphasisTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'SuperscriptEmphasisTest', + text: "This is ^^superscript^^ text" + }); + it('should serialize superscript emphasis correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('SuperscriptEmphasisTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('SuperscriptEmphasisTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'UnderscoreEmphasisTest', + text: "This is __underscore__ text" + }); + it('should serialize underscore emphasis correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('UnderscoreEmphasisTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('UnderscoreEmphasisTest').trimEnd()); + }); + wiki.addTiddler({ title: 'TiddlerOne', text: 'The quick brown fox' }); it('should render tiddlers with no special markup as-is', function () { // `trimEnd` because when we handle `p` element when parsing block rules, we always add a newline. But original text that may not have a trailing newline, will still be recognized as a block. @@ -261,4 +315,103 @@ describe('WikiAST serialization tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('PrettyLinkTest').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('PrettyLinkTest').trimEnd()); }); + + wiki.addTiddler({ + title: 'QuoteBlockTest', + text: '<<` around this list will also have the class `myClass`\n* List item 2\n@@', + }); + it('should serialize style blocks correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('StyleBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('StyleBlockTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'StyleInlineTest', + text: '@@.myClass This is some text with a class@@\n@@background-color:red;This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@', + }); + it('should serialize style inlines correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('StyleInlineTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('StyleInlineTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'SysLinkTest', + text: '$:TiddlerTitle\n~$:TiddlerTitle' + }); + it('should serialize system links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('SysLinkTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('SysLinkTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'TableTest', + text: '|! |!Alpha |!Beta |!Gamma |!Delta |\n|!One | | | | |\n|!Two | | | | |\n|!Three | | | | |' + }); + it('should serialize tables correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TableTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('TableTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'TranscludeBlockTest', + text: '{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}' + }); + it('should serialize block-level transclusions correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TranscludeBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('TranscludeBlockTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'TranscludeInlineTest', + text: '{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}' + }); + it('should serialize inline-level transclusions correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TranscludeInlineTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('TranscludeInlineTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'TypedBlockTest', + text: '$$$.js\nThis will be rendered as JavaScript\n$$$\n$$$.svg\n\n \n\n$$$\n$$$text/vnd.tiddlywiki>text/html\nThis will be rendered as an //HTML representation// of WikiText\n$$$' + }); + it('should serialize typed blocks correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TypedBlockTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('TypedBlockTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'WikiLinkTest', + text: 'AWikiLink\nAnotherLink\n~SuppressedLink' + }); + it('should serialize wiki links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('WikiLinkTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('WikiLinkTest').trimEnd()); + }); + + wiki.addTiddler({ + title: 'WikiLinkPrefixTest', + text: '~SuppressedLink' + }); + it('should serialize suppressed wiki links correctly', function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('WikiLinkPrefixTest').tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText('WikiLinkPrefixTest').trimEnd()); + }); }); From d0678716aa21a4938d10ba99f669f86b5af09d0f Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 3 Aug 2024 00:10:38 +0800 Subject: [PATCH 17/98] fix: remove pragma:true, otherwise following text will become children of it --- core/modules/parsers/wikiparser/rules/commentblock.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 62bbd4088..0fc3c0422 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -25,7 +25,7 @@ Note that the syntax for comments is simplified to an opening "\n\nSome text\n\n\n\nMore text', @@ -106,7 +105,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('CommentBlockTest').trimEnd()); }); - // Test case for commentinline rule wiki.addTiddler({ title: 'CommentInlineTest', text: 'This is some text with an inline comment and some more text.', @@ -116,7 +114,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('CommentInlineTest').trimEnd()); }); - // Test case for conditional rule wiki.addTiddler({ title: 'ConditionalTest', text: 'This is a <% if [{something}] %>Elephant<% elseif [{else}] %>Pelican<% else %>Crocodile<% endif %>', @@ -126,7 +123,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('ConditionalTest').trimEnd()); }); - // Test case for dash rule wiki.addTiddler({ title: 'DashTest', text: 'This is an en-dash: --\n\nThis is an em-dash: ---', @@ -136,7 +132,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('DashTest').trimEnd()); }); - // Test case for entity rule wiki.addTiddler({ title: 'EntityTest', text: 'This is a copyright symbol: ©', @@ -146,7 +141,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('EntityTest').trimEnd()); }); - // Test case for extlink rule wiki.addTiddler({ title: 'ExtLinkTest', text: 'An external link: https://www.tiddlywiki.com/\n\nA suppressed external link: ~http://www.tiddlyspace.com/', @@ -156,7 +150,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('ExtLinkTest').trimEnd()); }); - // Test case for filteredtranscludeblock rule wiki.addTiddler({ title: 'FilteredTranscludeBlockTest', text: '{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class', @@ -166,7 +159,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('FilteredTranscludeBlockTest').trimEnd()); }); - // Test case for filteredtranscludeinline rule wiki.addTiddler({ title: 'FilteredTranscludeInlineTest', text: '{{{ [tag[docs]] }}} {{{ [tag[docs]] |tooltip}}} {{{ [tag[docs]] ||TemplateTitle}}} {{{ [tag[docs]] |tooltip||TemplateTitle}}} {{{ [tag[docs]] }}width:40;height:50;}.class.class', @@ -185,8 +177,8 @@ describe('WikiAST serialization tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FunctionDefinition').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('FunctionDefinition').trimEnd()); }); + return; - // Test case for hardlinebreaks rule wiki.addTiddler({ title: 'HardLineBreaksTest', text: '"""\nThis is some text\nThat is set like\nIt is a Poem\nWhen it is\nClearly\nNot\n"""\n', @@ -196,7 +188,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('HardLineBreaksTest').trimEnd()); }); - // Test case for heading rule wiki.addTiddler({ title: 'HeadingTest', text: '! Heading 1\n!! Heading 2\n!!! Heading 3\n!!!! Heading 4\n!!!!! Heading 5\n!!!!!! Heading 6', @@ -206,7 +197,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('HeadingTest').trimEnd()); }); - // Test case for html rule wiki.addTiddler({ title: 'HtmlTest', text: '\n\n<$slider target="MyTiddler">\nThis is a widget invocation\n', @@ -216,7 +206,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('HtmlTest').trimEnd()); }); - // Test case for image rule wiki.addTiddler({ title: 'ImageTest', text: '[img[https://tiddlywiki.com/fractalveg.jpg]]\n[img width=23 height=24 [https://tiddlywiki.com/fractalveg.jpg]]\n[img width={{!!width}} height={{!!height}} [https://tiddlywiki.com/fractalveg.jpg]]\n[img[Description of image|https://tiddlywiki.com/fractalveg.jpg]]\n[img[TiddlerTitle]]\n[img[Description of image|TiddlerTitle]]', @@ -226,7 +215,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('ImageTest').trimEnd()); }); - // Test case for import rule wiki.addTiddler({ title: 'ImportTest', text: '\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]', @@ -236,7 +224,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('ImportTest').trimEnd()); }); - // Test case for list rule wiki.addTiddler({ title: 'ListTest', text: '* This is an unordered list\n* It has two items\n\n# This is a numbered list\n## With a subitem\n# And a third item\n\n; This is a term that is being defined\n: This is the definition of that term\n\n#** One\n#* Two\n#** Three\n#**** Four\n#**# Five\n#**## Six\n## Seven\n### Eight\n## Nine\n\n* List item one\n*.active List item two has the class `active`\n* List item three', @@ -246,7 +233,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('ListTest').trimEnd()); }); - // Test case for macrocallblock rule wiki.addTiddler({ title: 'MacroCallBlockTest', text: '<>', @@ -256,7 +242,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('MacroCallBlockTest').trimEnd()); }); - // Test case for macrocallinline rule wiki.addTiddler({ title: 'MacroCallInlineTest', text: 'This is a macro call: <>', @@ -266,7 +251,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('MacroCallInlineTest').trimEnd()); }); - // Test case for macrodef rule wiki.addTiddler({ title: 'MacroDefTest', text: '\\define name(param:defaultvalue,param2:defaultvalue)\ndefinition text, including $param$ markers\n\\end', @@ -276,7 +260,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('MacroDefTest').trimEnd()); }); - // Test case for parameters rule wiki.addTiddler({ title: 'ParametersTest', text: '\\parameters(param:defaultvalue,param2:defaultvalue)', @@ -286,7 +269,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('ParametersTest').trimEnd()); }); - // Test case for parsermode rule wiki.addTiddler({ title: 'ParserModeTest', text: '\\parsermode block\n\\parsermode inline', @@ -296,7 +278,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('ParserModeTest').trimEnd()); }); - // Test case for prettyextlink rule wiki.addTiddler({ title: 'PrettyExtLinkTest', text: '[ext[https://tiddlywiki.com/fractalveg.jpg]]\n[ext[Tooltip|https://tiddlywiki.com/fractalveg.jpg]]', @@ -306,7 +287,6 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('PrettyExtLinkTest').trimEnd()); }); - // Test case for prettylink rule wiki.addTiddler({ title: 'PrettyLinkTest', text: '[[Introduction]]\n[[Link description|TiddlerTitle]]', From 383e1b68b5d790c7594879c66dd630032446d133 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 3 Aug 2024 02:04:26 +0800 Subject: [PATCH 20/98] fix: some test --- .../parsers/wikiparser/rules/fnprocdef.js | 4 +-- .../wikiparser/rules/hardlinebreaks.js | 25 ++++++++--------- .../parsers/wikiparser/rules/heading.js | 11 +++----- core/modules/parsers/wikiparser/rules/html.js | 2 +- .../modules/parsers/wikiparser/rules/image.js | 10 +++---- .../tiddlers/tests/test-wikitext-serialize.js | 28 +++++++++---------- 6 files changed, 37 insertions(+), 43 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/fnprocdef.js b/core/modules/parsers/wikiparser/rules/fnprocdef.js index a4259e574..82c4b6217 100644 --- a/core/modules/parsers/wikiparser/rules/fnprocdef.js +++ b/core/modules/parsers/wikiparser/rules/fnprocdef.js @@ -104,8 +104,8 @@ exports.serialize = function(tree, serialize) { }).join(","); // Definition text var definition = tree.attributes.value.value; - // Construct the serialized string - return "\\" + type + " " + name + "(" + params + ")\n" + definition + "\n\\end"; + // Construct the serialized string, concat the children because pragma rule wrap everything below it as children + return "\\" + type + " " + name + "(" + params + ")\n" + definition + "\n\\end\n\n" + serialize(tree.children) + "\n"; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/hardlinebreaks.js b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js index 39ef6fc5c..9f26c3d95 100644 --- a/core/modules/parsers/wikiparser/rules/hardlinebreaks.js +++ b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js @@ -53,23 +53,22 @@ exports.parse = function() { } } } while(match && !match[1]); - // Return the nodes + // Mark first and last node, and return the nodes + if(tree[0]) tree[0].isRuleStart = true; + if(tree[tree.length-1]) tree[tree.length-1].isRuleEnd = true; return tree; }; exports.serialize = function(tree,serialize) { - // Serialized text with hard line breaks - var serialized = '"""\n'; - // Serialize each node in the tree - tree.forEach(function(node) { - if(node.type === "element" && node.tag === "br") { - serialized += "\n"; - } else { - serialized += serialize([node]).join(''); - } - }); - serialized += '\n"""'; - return serialized; + // we get each of element on tree from `parse` one by one here. + var text = tree.tag === 'br' ? '\n' : tree.text; + if(tree.isRuleStart) { + return '"""\n' + text; + } + if(tree.isRuleEnd) { + return text + '"""'; + } + return text; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/heading.js b/core/modules/parsers/wikiparser/rules/heading.js index 79df971e5..67470c9c5 100644 --- a/core/modules/parsers/wikiparser/rules/heading.js +++ b/core/modules/parsers/wikiparser/rules/heading.js @@ -47,14 +47,11 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // Heading level - var headingLevel = tree.tag.length - 1; - // Classes + // Get heading level from number after `h` + var headingLevel = parseInt(tree.tag.substr(1),10); var classes = tree.attributes.class ? tree.attributes.class.value.split(" ").join(".") : ""; - // Serialized heading text - var headingText = serialize(tree.children).join(''); - // Construct the serialized string - return Array(headingLevel + 1).join("!") + (classes ? "." + classes : "") + " " + headingText; + var headingText = serialize(tree.children); + return Array(headingLevel + 1).join("!") + (classes ? "." + classes : "") + " " + headingText + "\n"; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index 656759ed8..1e3f9865b 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -199,7 +199,7 @@ exports.serialize = function(tree, serialize) { var tag = tree.tag; var attributes = Object.keys(tree.attributes).map(function(key) { return key + '="' + tree.attributes[key].value + '"'; - }); + }).join(''); // Children var children = tree.children ? serialize(tree.children) : ''; // Self-closing tag diff --git a/core/modules/parsers/wikiparser/rules/image.js b/core/modules/parsers/wikiparser/rules/image.js index 8591e544e..33454f46e 100644 --- a/core/modules/parsers/wikiparser/rules/image.js +++ b/core/modules/parsers/wikiparser/rules/image.js @@ -131,16 +131,14 @@ exports.parseImage = function(source,pos) { }; exports.serialize = function(tree) { - // Width attribute + // DEBUG: console tree + console.warn(`tree`, JSON.stringify(tree, null, ' ')); var width = tree.attributes.width ? " width=" + tree.attributes.width.value : ""; - // Height attribute var height = tree.attributes.height ? " height=" + tree.attributes.height.value : ""; - // Tooltip attribute + var padSpace = width || height ? " " : ""; var tooltip = tree.attributes.tooltip ? tree.attributes.tooltip.value + "|" : ""; - // Source attribute var source = tree.attributes.source.value; - // Construct the serialized string - return "[img" + width + height + " [" + tooltip + source + "]]"; + return "[img" + width + height + padSpace + "[" + tooltip + source + "]]"; }; })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index d3ab4dc04..69800a81f 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -7,7 +7,7 @@ Tests the wikitext inverse-rendering from Wiki AST. \*/ -describe('WikiAST serialization tests', function () { +describe('WikiAST serialization unit tests', function () { var wiki = new $tw.Wiki(); wiki.addTiddler({ @@ -64,35 +64,35 @@ describe('WikiAST serialization tests', function () { expect(serialized).toBe(wiki.getTiddlerText('UnderscoreEmphasisTest').trimEnd()); }); - wiki.addTiddler({ title: 'TiddlerOne', text: 'The quick brown fox' }); + wiki.addTiddler({ title: 'SimpleTextTest', text: 'The quick brown fox' }); it('should render tiddlers with no special markup as-is', function () { // `trimEnd` because when we handle `p` element when parsing block rules, we always add a newline. But original text that may not have a trailing newline, will still be recognized as a block. - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerOne').tree).trimEnd()).toBe( - wiki.getTiddlerText('TiddlerOne') + expect($tw.utils.serializeParseTree(wiki.parseTiddler('SimpleTextTest').tree).trimEnd()).toBe( + wiki.getTiddlerText('SimpleTextTest') ); }); - wiki.addTiddler({ title: 'TiddlerTwo', text: 'The rain in Spain\nfalls mainly on the plain' }); + wiki.addTiddler({ title: 'SoftLineBreakTest', text: 'The rain in Spain\nfalls mainly on the plain' }); it('should preserve single new lines', function () { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerTwo').tree).trimEnd()).toBe( - wiki.getTiddlerText('TiddlerTwo') + expect($tw.utils.serializeParseTree(wiki.parseTiddler('SoftLineBreakTest').tree).trimEnd()).toBe( + wiki.getTiddlerText('SoftLineBreakTest') ); }); - wiki.addTiddler({ title: 'TiddlerThree', text: 'The speed of sound\n\nThe light of speed' }); + wiki.addTiddler({ title: 'BlockRule', text: 'The speed of sound\n\nThe light of speed' }); it('should preserve double new lines to create paragraphs', function () { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerThree').tree).trimEnd()).toBe( - wiki.getTiddlerText('TiddlerThree') + expect($tw.utils.serializeParseTree(wiki.parseTiddler('BlockRule').tree).trimEnd()).toBe( + wiki.getTiddlerText('BlockRule') ); }); wiki.addTiddler({ - title: 'TiddlerFour', + title: 'CodeBlockTest', text: 'Simple `JS` and complex\n\n---\n\n```js\nvar match = reEnd.exec(this.parser.source)\n```\nend', }); it('should render inline code and block code', function () { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('TiddlerFour').tree).trimEnd()).toBe( - wiki.getTiddlerText('TiddlerFour') + expect($tw.utils.serializeParseTree(wiki.parseTiddler('CodeBlockTest').tree).trimEnd()).toBe( + wiki.getTiddlerText('CodeBlockTest') ); }); @@ -177,7 +177,6 @@ describe('WikiAST serialization tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FunctionDefinition').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('FunctionDefinition').trimEnd()); }); - return; wiki.addTiddler({ title: 'HardLineBreaksTest', @@ -214,6 +213,7 @@ describe('WikiAST serialization tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImageTest').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('ImageTest').trimEnd()); }); + return; wiki.addTiddler({ title: 'ImportTest', From 63613ceec04b20e9355e839cf3620150c62ab8b9 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 3 Aug 2024 16:21:55 +0800 Subject: [PATCH 21/98] feat: $tw.utils.serializeAttribute --- core/modules/parsers/parseutils.js | 31 +++++++++++++++++++ .../test/tiddlers/tests/test-html-parser.js | 31 +++++++++++++++++++ plugins/tiddlywiki/jasmine/jasmine-plugin.js | 2 +- 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js index 2a2e36309..b11300bfe 100644 --- a/core/modules/parsers/parseutils.js +++ b/core/modules/parsers/parseutils.js @@ -385,4 +385,35 @@ exports.parseAttribute = function(source,pos) { return node; }; +/* +Given a parsed attribute node, serialize it back into its source string representation. +*/ +exports.serializeAttribute = function(node) { + if(!node || typeof node !== 'object' || !node.name || !node.type) { + return null; + } + + var attributeString = node.name; + + if(node.type === 'string') { + if(node.value === 'true') { + return attributeString; + } + attributeString += '="' + node.value + '"'; + } else if(node.type === 'filtered') { + attributeString += '={{{' + node.filter + '}}}'; + } else if(node.type === 'indirect') { + attributeString += '={{' + node.textReference + '}}'; + } else if(node.type === 'substituted') { + attributeString += '=`' + node.rawValue + '`'; + } else if(node.type === 'macro') { + // Assuming macro serialization is complex and handled elsewhere + attributeString += '=' + node.value.serialize(); + } else { + return null; // Unsupported type + } + + return attributeString; +}; + })(); diff --git a/editions/test/tiddlers/tests/test-html-parser.js b/editions/test/tiddlers/tests/test-html-parser.js index d2266ca5e..4d07bc4f9 100644 --- a/editions/test/tiddlers/tests/test-html-parser.js +++ b/editions/test/tiddlers/tests/test-html-parser.js @@ -173,6 +173,37 @@ describe("HTML tag new parser tests", function() { ); }); + + describe('serializeAttribute', function () { + it('should serialize string attributes', function () { + expect($tw.utils.serializeAttribute({ type: 'string', name: 'p', value: 'blah' })).toBe('p="blah"'); + expect($tw.utils.serializeAttribute({ type: 'string', name: 'p', value: 'true' })).toBe('p'); + }); + + it('should serialize filtered attributes', function () { + expect($tw.utils.serializeAttribute({ type: 'filtered', name: 'p', filter: 'blah' })).toBe('p={{{blah}}}'); + }); + + it('should serialize indirect attributes', function () { + expect($tw.utils.serializeAttribute({ type: 'indirect', name: 'p', textReference: 'blah' })).toBe('p={{blah}}'); + }); + + it('should serialize substituted attributes', function () { + expect($tw.utils.serializeAttribute({ type: 'substituted', name: 'p', rawValue: 'blah' })).toBe('p=`blah`'); + }); + + it('should return null for unsupported types', function () { + expect($tw.utils.serializeAttribute({ type: 'unknown', name: 'p', value: 'blah' })).toBeNull(); + }); + + it('should return null for invalid input', function () { + expect($tw.utils.serializeAttribute(null)).toBeNull(); + expect($tw.utils.serializeAttribute({})).toBeNull(); + expect($tw.utils.serializeAttribute({ type: 'string' })).toBeNull(); + expect($tw.utils.serializeAttribute({ name: 'p' })).toBeNull(); + }); + }); + it("should parse HTML tags", function() { expect(parser.parseTag("",1)).toEqual( null diff --git a/plugins/tiddlywiki/jasmine/jasmine-plugin.js b/plugins/tiddlywiki/jasmine/jasmine-plugin.js index 488377b44..73d5b55d5 100644 --- a/plugins/tiddlywiki/jasmine/jasmine-plugin.js +++ b/plugins/tiddlywiki/jasmine/jasmine-plugin.js @@ -13,7 +13,7 @@ The main module of the Jasmine test plugin for TiddlyWiki5 "use strict"; // DEBUG: only run my tests for development, remove before PR merge -var TEST_TIDDLER_FILTER = "[[test-wikitext-serialize.js]]"; +var TEST_TIDDLER_FILTER = "[[test-wikitext-serialize.js]] [[test-html-parser.js]]"; var TESTS_DONE = false; exports.testsWereRun = function() { From 7b4ea476f35974eb933d44e4d5836e817f10b7f5 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 3 Aug 2024 20:29:55 +0800 Subject: [PATCH 22/98] fix: use "" for string param --- core/modules/parsers/wikiparser/rules/image.js | 6 ++---- editions/test/tiddlers/tests/test-wikitext-serialize.js | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/image.js b/core/modules/parsers/wikiparser/rules/image.js index 33454f46e..f046c59f1 100644 --- a/core/modules/parsers/wikiparser/rules/image.js +++ b/core/modules/parsers/wikiparser/rules/image.js @@ -131,10 +131,8 @@ exports.parseImage = function(source,pos) { }; exports.serialize = function(tree) { - // DEBUG: console tree - console.warn(`tree`, JSON.stringify(tree, null, ' ')); - var width = tree.attributes.width ? " width=" + tree.attributes.width.value : ""; - var height = tree.attributes.height ? " height=" + tree.attributes.height.value : ""; + var width = tree.attributes.width ? " " + $tw.utils.serializeAttribute(tree.attributes.width) : ""; + var height = tree.attributes.height ? " " + $tw.utils.serializeAttribute(tree.attributes.height) : ""; var padSpace = width || height ? " " : ""; var tooltip = tree.attributes.tooltip ? tree.attributes.tooltip.value + "|" : ""; var source = tree.attributes.source.value; diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 69800a81f..8e73c8ef9 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -207,7 +207,7 @@ describe('WikiAST serialization unit tests', function () { wiki.addTiddler({ title: 'ImageTest', - text: '[img[https://tiddlywiki.com/fractalveg.jpg]]\n[img width=23 height=24 [https://tiddlywiki.com/fractalveg.jpg]]\n[img width={{!!width}} height={{!!height}} [https://tiddlywiki.com/fractalveg.jpg]]\n[img[Description of image|https://tiddlywiki.com/fractalveg.jpg]]\n[img[TiddlerTitle]]\n[img[Description of image|TiddlerTitle]]', + text: '[img[https://tiddlywiki.com/fractalveg.jpg]]\n[img width="23" height="24" [https://tiddlywiki.com/fractalveg.jpg]]\n[img width={{!!width}} height={{!!height}} [https://tiddlywiki.com/fractalveg.jpg]]\n[img[Description of image|https://tiddlywiki.com/fractalveg.jpg]]\n[img[TiddlerTitle]]\n[img[Description of image|TiddlerTitle]]', }); it('should serialize image tags correctly', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImageTest').tree).trimEnd(); From f69795c62e9c25533141b975836cc91e486d21cc Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 3 Aug 2024 22:41:58 +0800 Subject: [PATCH 23/98] feat: list --- .../parsers/wikiparser/rules/import.js | 6 +- core/modules/parsers/wikiparser/rules/list.js | 70 +++++++++++++------ .../tiddlers/tests/test-wikitext-serialize.js | 4 +- 3 files changed, 53 insertions(+), 27 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/import.js b/core/modules/parsers/wikiparser/rules/import.js index 7025d20f2..2142f7a58 100644 --- a/core/modules/parsers/wikiparser/rules/import.js +++ b/core/modules/parsers/wikiparser/rules/import.js @@ -51,11 +51,11 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { // Filter attribute var filter = tree.attributes.filter.value; - // Construct the serialized string - return "\\import " + filter; + // Construct the serialized string with children that is actually the sibling below the pragma. + return "\\import " + filter + "\n" + serialize(tree.children); }; })(); diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js index fbda16711..704ad60ae 100644 --- a/core/modules/parsers/wikiparser/rules/list.js +++ b/core/modules/parsers/wikiparser/rules/list.js @@ -153,28 +153,54 @@ exports.parse = function() { return [listStack[0]]; }; -exports.serialize = function(tree, serialize) { - // Serialize the list recursively - return serializeList(tree, serialize, 0); +exports.serialize = function (tree, serialize) { + // Helper function to find the marker for a given list container tag and item tag + function findMarker(listTag, itemTag) { + for(var key in listTypes) { + if(listTypes[key].listTag === listTag && listTypes[key].itemTag === itemTag) { + return key; // Return the marker associated with the list tag and item tag + } + } + return ''; // Return empty string if no matching marker is found + } + + // Recursive function to serialize list nodes, handling nested lists and formatting output + function serializeList(node, markerPrefix) { + var result = []; + if(node.type === 'element' && ['ul', 'ol', 'dl', 'blockquote'].includes(node.tag)) { + node.children.forEach(function (child) { + if(['li', 'dt', 'dd', 'div'].includes(child.tag)) { + var currentMarker = findMarker(node.tag, child.tag); + // Handle class attributes + var classAttr = child.attributes && child.attributes.class ? '.' + child.attributes.class.value : ''; + // same level text nodes may be split into multiple children, and separated by deeper list sub-tree. We collect same level text nodes into this list, and concat then submit them before enter deeper list. + var content = []; + $tw.utils.each(child.children,function (subNode) { + // Check if the child is a nested list or a simple line of list item + if(['ul', 'ol', 'dl', 'blockquote'].includes(subNode.tag)) { + // Recursive call for nested lists + if(content.length > 0) { + result.push(markerPrefix + currentMarker + classAttr + ' ' + content.join('').trim()); + content = [] + } + result.push(serializeList(subNode, markerPrefix + currentMarker).trim()) + } else { + content.push(serialize(subNode)) ; + } + return ''; // Default return for unhandled node types + }); + if(content.length > 0) { + result.push(markerPrefix + currentMarker + classAttr + ' ' + content.join('').trim()); + content = [] + } + } + }); + } + return result.join('\n'); + } + + // Begin serialization from the root node, with an empty string as the initial marker prefix + return serializeList(tree, '') + '\n\n'; }; -// utility to handle recursion of list -function serializeList(node, serialize, depth) { - // List tag - var listTag = node.tag; - // List item tag - var itemTag = listTypes[listTag[0]].itemTag; - // Serialized list items - var items = node.children.map(function(child) { - // Classes - var classes = child.attributes && child.attributes.class ? child.attributes.class.value.split(" ").join(".") : ""; - // Serialized children - var children = serialize(child.children); - // Construct the serialized list item - return Array(depth + 1).join(listTag[0]) + (classes ? "." + classes : "") + " " + children; - }).join("\n"); - // Return the serialized list - return items; -} - })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 8e73c8ef9..e19a2d922 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -213,11 +213,10 @@ describe('WikiAST serialization unit tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImageTest').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('ImageTest').trimEnd()); }); - return; wiki.addTiddler({ title: 'ImportTest', - text: '\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]', + text: '\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\\import [[$:/core/ui/PageMacros]]', }); it('should serialize import pragma correctly', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImportTest').tree).trimEnd(); @@ -232,6 +231,7 @@ describe('WikiAST serialization unit tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ListTest').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('ListTest').trimEnd()); }); + return; wiki.addTiddler({ title: 'MacroCallBlockTest', From 9df36a2b15a5f1c66a647819e96dea4b273d0b1c Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 00:29:33 +0800 Subject: [PATCH 24/98] refactor: ' -> " --- .../parsers/wikiparser/rules/conditional.js | 10 +++---- core/modules/parsers/wikiparser/rules/list.js | 27 ++++++++++------- .../wikiparser/rules/macrocallblock.js | 30 ++++++++++++------- .../wikiparser/rules/macrocallinline.js | 28 +++++++++++------ .../parsers/wikiparser/rules/macrodef.js | 2 +- .../parsers/wikiparser/rules/parameters.js | 2 +- .../tiddlers/tests/test-wikitext-serialize.js | 8 ++--- plugins/tiddlywiki/jasmine/jasmine-plugin.js | 2 +- 8 files changed, 68 insertions(+), 41 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js index 88d243d0e..3a4486cf2 100644 --- a/core/modules/parsers/wikiparser/rules/conditional.js +++ b/core/modules/parsers/wikiparser/rules/conditional.js @@ -121,24 +121,24 @@ exports.serialize = function(tree, serialize) { var filterCondition = tree.attributes.filter.value; var ifClause = serialize(tree.children[0].children); var elseClause = tree.children[1].children; - var serialized = '<% if ' + filterCondition + '%>' + ifClause; + var serialized = "<% if " + filterCondition + "%>" + ifClause; if(elseClause && elseClause.length > 0) { for(var i = 0; i < elseClause.length; i++) { - if(elseClause[i].type === 'list' && elseClause[i].attributes.filter) { + if(elseClause[i].type === "list" && elseClause[i].attributes.filter) { // Handle elseif clause var elseifCondition = elseClause[i].attributes.filter.value; var elseifClause = serialize(elseClause[i].children[0]); - serialized += '<% elseif ' + elseifCondition + '%>' + elseifClause; + serialized += "<% elseif " + elseifCondition + "%>" + elseifClause; } if(elseClause[i].children[1]) { var elseClauseText = serialize(elseClause[i].children[1]); - serialized += '<% else %>' + elseClauseText; + serialized += "<% else %>" + elseClauseText; } } } - serialized += '<% endif %>'; + serialized += "<% endif %>"; return serialized; }; diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js index 704ad60ae..71a7cab5e 100644 --- a/core/modules/parsers/wikiparser/rules/list.js +++ b/core/modules/parsers/wikiparser/rules/list.js @@ -63,6 +63,13 @@ var listTypes = { ">": {listTag: "blockquote", itemTag: "div"} }; +var listTags = Object.values(listTypes).map(function(type) { + return type.listTag; +}); +var itemTags = Object.values(listTypes).map(function(type) { + return type.itemTag; +}); + /* Parse the most recent match */ @@ -161,46 +168,46 @@ exports.serialize = function (tree, serialize) { return key; // Return the marker associated with the list tag and item tag } } - return ''; // Return empty string if no matching marker is found + return ""; // Return empty string if no matching marker is found } // Recursive function to serialize list nodes, handling nested lists and formatting output function serializeList(node, markerPrefix) { var result = []; - if(node.type === 'element' && ['ul', 'ol', 'dl', 'blockquote'].includes(node.tag)) { + if(node.type === "element" && listTags.includes(node.tag)) { node.children.forEach(function (child) { - if(['li', 'dt', 'dd', 'div'].includes(child.tag)) { + if(itemTags.includes(child.tag)) { var currentMarker = findMarker(node.tag, child.tag); // Handle class attributes - var classAttr = child.attributes && child.attributes.class ? '.' + child.attributes.class.value : ''; + var classAttr = child.attributes && child.attributes.class ? "." + child.attributes.class.value : ""; // same level text nodes may be split into multiple children, and separated by deeper list sub-tree. We collect same level text nodes into this list, and concat then submit them before enter deeper list. var content = []; $tw.utils.each(child.children,function (subNode) { // Check if the child is a nested list or a simple line of list item - if(['ul', 'ol', 'dl', 'blockquote'].includes(subNode.tag)) { + if(listTags.includes(subNode.tag)) { // Recursive call for nested lists if(content.length > 0) { - result.push(markerPrefix + currentMarker + classAttr + ' ' + content.join('').trim()); + result.push(markerPrefix + currentMarker + classAttr + " " + content.join("").trim()); content = [] } result.push(serializeList(subNode, markerPrefix + currentMarker).trim()) } else { content.push(serialize(subNode)) ; } - return ''; // Default return for unhandled node types + return ""; // Default return for unhandled node types }); if(content.length > 0) { - result.push(markerPrefix + currentMarker + classAttr + ' ' + content.join('').trim()); + result.push(markerPrefix + currentMarker + classAttr + " " + content.join("").trim()); content = [] } } }); } - return result.join('\n'); + return result.join("\n"); } // Begin serialization from the root node, with an empty string as the initial marker prefix - return serializeList(tree, '') + '\n\n'; + return serializeList(tree, "") + "\n\n"; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/macrocallblock.js b/core/modules/parsers/wikiparser/rules/macrocallblock.js index c3b0e92e9..923484bae 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallblock.js +++ b/core/modules/parsers/wikiparser/rules/macrocallblock.js @@ -32,7 +32,7 @@ exports.findNextMatch = function(startPos) { var c = this.parser.source.charAt(nextCall.end); // Ensure EOL after parsed macro // If we didn't need to support IE, we'd just use /(?:\r?\n|$)/ym - if ((c === "") || (c === "\n") || ((c === "\r") && this.parser.source.charAt(nextCall.end+1) === "\n")) { + if((c === "") || (c === "\n") || ((c === "\r") && this.parser.source.charAt(nextCall.end+1) === "\n")) { this.nextCall = nextCall; return nextStart; } @@ -53,15 +53,25 @@ exports.parse = function() { return [call]; }; -exports.serialize = function(tree) { - // Macro name - var name = tree.name; - // Macro parameters - var params = tree.params.map(function(param) { - return param.value; - }).join(" "); - // Construct the serialized string - return "<<" + name + " " + params + ">>"; +/* +Serialize a macro call node to wikitext +*/ +exports.serialize = function (node) { + // Start with macro opener + var result = "<<"; + if(node.attributes && node.attributes["$variable"]) { + result += node.attributes["$variable"].value; // Add macro name + } + // Append ordered arguments if any + if(node.orderedAttributes) { + node.orderedAttributes.forEach(function (attr) { + if(attr.name !== "$variable") { + result += " " + '"' + attr.value + '"'; // Add each additional value + } + }); + } + result += ">>\n\n"; + return result; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/macrocallinline.js b/core/modules/parsers/wikiparser/rules/macrocallinline.js index a62596414..bc0ac7f22 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallinline.js +++ b/core/modules/parsers/wikiparser/rules/macrocallinline.js @@ -46,15 +46,25 @@ exports.parse = function() { return [call]; }; -exports.serialize = function(tree) { - // Macro name - var name = tree.name; - // Macro parameters - var params = tree.params.map(function(param) { - return param.value; - }).join(" "); - // Construct the serialized string - return "<<" + name + " " + params + ">>"; +/* +Same as macrocallblock but without \n\n +*/ +exports.serialize = function (node) { + // Start with macro opener + var result = "<<"; + if(node.attributes && node.attributes["$variable"]) { + result += node.attributes["$variable"].value; // Add macro name + } + // Append ordered arguments if any + if(node.orderedAttributes) { + node.orderedAttributes.forEach(function (attr) { + if(attr.name !== "$variable") { + result += " " + '"' + attr.value + '"'; // Add each additional value + } + }); + } + result += ">>"; + return result; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js index 31a93f27b..735c7958a 100644 --- a/core/modules/parsers/wikiparser/rules/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/macrodef.js @@ -99,7 +99,7 @@ exports.serialize = function(tree) { // Definition text var definition = tree.attributes.value.value; // Construct the serialized string - return "\\define " + name + "(" + params + ")\n" + definition + "\n\\end"; + return "\\define " + name + "(" + params + ")\n" + definition + "\n\\end\n\n" + serialize(tree.children); }; })(); diff --git a/core/modules/parsers/wikiparser/rules/parameters.js b/core/modules/parsers/wikiparser/rules/parameters.js index 692f03ea7..ddb3a65ab 100644 --- a/core/modules/parsers/wikiparser/rules/parameters.js +++ b/core/modules/parsers/wikiparser/rules/parameters.js @@ -63,7 +63,7 @@ exports.serialize = function(tree) { return param.name + (param.value ? ":" + param.value : ""); }).join(","); // Construct the serialized string - return "\\parameters(" + params + ")"; + return "\\parameters(" + params + ")\n\n" + serialize(tree.children); }; })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index e19a2d922..032417549 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -231,11 +231,10 @@ describe('WikiAST serialization unit tests', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ListTest').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('ListTest').trimEnd()); }); - return; wiki.addTiddler({ title: 'MacroCallBlockTest', - text: '<>', + text: '<>\n\n<<.def "macro calls">>', }); it('should serialize block macro calls correctly', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroCallBlockTest').tree).trimEnd(); @@ -244,7 +243,7 @@ describe('WikiAST serialization unit tests', function () { wiki.addTiddler({ title: 'MacroCallInlineTest', - text: 'This is a macro call: <>', + text: 'These are macro calls in a line: <> and <<.def "macro calls">>', }); it('should serialize inline macro calls correctly', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroCallInlineTest').tree).trimEnd(); @@ -271,12 +270,13 @@ describe('WikiAST serialization unit tests', function () { wiki.addTiddler({ title: 'ParserModeTest', - text: '\\parsermode block\n\\parsermode inline', + text: '\\parsermode block\n\n\\parsermode inline\n\nTest.', }); it('should serialize parser mode specifications correctly', function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ParserModeTest').tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText('ParserModeTest').trimEnd()); }); + return; wiki.addTiddler({ title: 'PrettyExtLinkTest', diff --git a/plugins/tiddlywiki/jasmine/jasmine-plugin.js b/plugins/tiddlywiki/jasmine/jasmine-plugin.js index 73d5b55d5..488377b44 100644 --- a/plugins/tiddlywiki/jasmine/jasmine-plugin.js +++ b/plugins/tiddlywiki/jasmine/jasmine-plugin.js @@ -13,7 +13,7 @@ The main module of the Jasmine test plugin for TiddlyWiki5 "use strict"; // DEBUG: only run my tests for development, remove before PR merge -var TEST_TIDDLER_FILTER = "[[test-wikitext-serialize.js]] [[test-html-parser.js]]"; +var TEST_TIDDLER_FILTER = "[[test-wikitext-serialize.js]]"; var TESTS_DONE = false; exports.testsWereRun = function() { From 2a75077747a979125cfe3dee35cc09c913c30864 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 00:35:16 +0800 Subject: [PATCH 25/98] fix: parsemode don't have node --- .../parsers/wikiparser/rules/parsermode.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/parsermode.js b/core/modules/parsers/wikiparser/rules/parsermode.js index 4814a4ba1..c5ec0fdd1 100644 --- a/core/modules/parsers/wikiparser/rules/parsermode.js +++ b/core/modules/parsers/wikiparser/rules/parsermode.js @@ -34,6 +34,7 @@ Parse the most recent match */ exports.parse = function() { // Move past the pragma invocation + var start = this.parser.pos; this.parser.pos = this.matchRegExp.lastIndex; // Parse whitespace delimited tokens terminated by a line break var reMatch = /[^\S\n]*(\S+)|(\r?\n)/mg, @@ -61,15 +62,17 @@ exports.parse = function() { this.parser.parseAsInline = true; } } - // No parse tree nodes to return - return []; + return [{ + type: "parsermode", + parseAsInline: this.parser.parseAsInline, + start: start, + end: this.parser.pos + }]; }; -exports.serialize = function(tree) { - // Parser mode - var mode = tree.parser.parseAsInline ? "inline" : "block"; - // Construct the serialized string - return "\\parsermode " + mode; +exports.serialize = function(tree,serialize) { + var mode = tree.parseAsInline ? "inline" : "block"; + return "\\parsermode " + mode + "\n\n" + serialize(tree.children); }; })(); From c39297698f995798d96809a23270ef665bd2c34f Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 00:48:29 +0800 Subject: [PATCH 26/98] fix: render invisible comment and parsemode as data element --- core/modules/parsers/wikiparser/rules/commentblock.js | 3 ++- core/modules/parsers/wikiparser/rules/commentinline.js | 3 ++- core/modules/parsers/wikiparser/rules/macrodef.js | 2 +- core/modules/parsers/wikiparser/rules/parameters.js | 2 +- core/modules/parsers/wikiparser/rules/parsermode.js | 3 ++- core/modules/utils/parsetree.js | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 0fc3c0422..56a0857dd 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -55,7 +55,8 @@ exports.parse = function() { var commentEnd = this.endMatch.index + this.endMatch[0].length; var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ - type: "commentblock", + type: "element", + tag: "data", text: commentText, start: commentStart, end: commentEnd diff --git a/core/modules/parsers/wikiparser/rules/commentinline.js b/core/modules/parsers/wikiparser/rules/commentinline.js index 50e861fe4..5ddcd8c82 100644 --- a/core/modules/parsers/wikiparser/rules/commentinline.js +++ b/core/modules/parsers/wikiparser/rules/commentinline.js @@ -48,7 +48,8 @@ exports.parse = function() { var commentEnd = this.endMatch.index + this.endMatch[0].length; var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ - type: "commentinline", + type: "element", + tag: "data", text: commentText, start: commentStart, end: commentEnd diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js index 735c7958a..9dec07682 100644 --- a/core/modules/parsers/wikiparser/rules/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/macrodef.js @@ -89,7 +89,7 @@ exports.parse = function() { return parseTreeNodes; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { // Macro name var name = tree.attributes.name.value; // Parameters diff --git a/core/modules/parsers/wikiparser/rules/parameters.js b/core/modules/parsers/wikiparser/rules/parameters.js index ddb3a65ab..6be51c24b 100644 --- a/core/modules/parsers/wikiparser/rules/parameters.js +++ b/core/modules/parsers/wikiparser/rules/parameters.js @@ -57,7 +57,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { // Parameters var params = tree.orderedAttributes.map(function(param) { return param.name + (param.value ? ":" + param.value : ""); diff --git a/core/modules/parsers/wikiparser/rules/parsermode.js b/core/modules/parsers/wikiparser/rules/parsermode.js index c5ec0fdd1..713bb36ed 100644 --- a/core/modules/parsers/wikiparser/rules/parsermode.js +++ b/core/modules/parsers/wikiparser/rules/parsermode.js @@ -63,7 +63,8 @@ exports.parse = function() { } } return [{ - type: "parsermode", + type: "element", + tag: "data", parseAsInline: this.parser.parseAsInline, start: start, end: this.parser.pos diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index 76ff385f0..670d6307b 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -133,7 +133,7 @@ exports.serializeParseTree = function serializeParseTree(tree,tiddlerType) { $tw.utils.each(tree,function(node) { output.push(serializeParseTree(node,tiddlerType)); }); - } else { + } else if(tree) { if(tree.type === "text" && !tree.rule) { output.push(tree.text); } else { From b22ca2b3df081123062b01486490d8f89cd5d433 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 18:54:15 +0800 Subject: [PATCH 27/98] feat: add void: true, in ast node to prevent render --- core/modules/parsers/wikiparser/rules/commentblock.js | 6 +++--- core/modules/parsers/wikiparser/rules/commentinline.js | 4 ++-- core/modules/parsers/wikiparser/rules/parsermode.js | 4 ++-- core/modules/widgets/widget.js | 3 ++- plugins/tiddlywiki/jasmine/jasmine-plugin.js | 3 +-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 56a0857dd..1e9b2c622 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -55,8 +55,8 @@ exports.parse = function() { var commentEnd = this.endMatch.index + this.endMatch[0].length; var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ - type: "element", - tag: "data", + type: "comment", + void: true, text: commentText, start: commentStart, end: commentEnd @@ -64,7 +64,7 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - return tree.text + "\n\n"; + return tree.text + "\n\n" + serialize(tree.children); }; })(); diff --git a/core/modules/parsers/wikiparser/rules/commentinline.js b/core/modules/parsers/wikiparser/rules/commentinline.js index 5ddcd8c82..01f76c1c6 100644 --- a/core/modules/parsers/wikiparser/rules/commentinline.js +++ b/core/modules/parsers/wikiparser/rules/commentinline.js @@ -48,8 +48,8 @@ exports.parse = function() { var commentEnd = this.endMatch.index + this.endMatch[0].length; var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ - type: "element", - tag: "data", + type: "comment", + void: true, text: commentText, start: commentStart, end: commentEnd diff --git a/core/modules/parsers/wikiparser/rules/parsermode.js b/core/modules/parsers/wikiparser/rules/parsermode.js index 713bb36ed..9aea958d2 100644 --- a/core/modules/parsers/wikiparser/rules/parsermode.js +++ b/core/modules/parsers/wikiparser/rules/parsermode.js @@ -63,8 +63,8 @@ exports.parse = function() { } } return [{ - type: "element", - tag: "data", + type: "parsermode", + void: true, parseAsInline: this.parser.parseAsInline, start: start, end: this.parser.pos diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index eb84fab4a..73c299d69 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -553,7 +553,8 @@ Widget.prototype.makeChildWidget = function(parseTreeNode,options) { var WidgetClass = this.widgetClasses[parseTreeNode.type]; if(!WidgetClass) { WidgetClass = this.widgetClasses.text; - parseTreeNode = {type: "text", text: "Undefined widget '" + parseTreeNode.type + "'"}; + // Skip void node that is not intended for render. Show error for missing widgets. + parseTreeNode = {type: "text", text: parseTreeNode.void ? "" : "Undefined widget '" + parseTreeNode.type + "'"}; } // Create set variable widgets for each variable $tw.utils.each(options.variables,function(value,name) { diff --git a/plugins/tiddlywiki/jasmine/jasmine-plugin.js b/plugins/tiddlywiki/jasmine/jasmine-plugin.js index 488377b44..8dbf6568e 100644 --- a/plugins/tiddlywiki/jasmine/jasmine-plugin.js +++ b/plugins/tiddlywiki/jasmine/jasmine-plugin.js @@ -12,8 +12,7 @@ The main module of the Jasmine test plugin for TiddlyWiki5 /*global $tw: true */ "use strict"; -// DEBUG: only run my tests for development, remove before PR merge -var TEST_TIDDLER_FILTER = "[[test-wikitext-serialize.js]]"; +var TEST_TIDDLER_FILTER = "[all[tiddlers+shadows]type[application/javascript]tag[$:/tags/test-spec]]"; var TESTS_DONE = false; exports.testsWereRun = function() { From 5b2c3dbace13f78e4fc253fc84388d13301d94c5 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 14:18:01 +0000 Subject: [PATCH 28/98] feat: use void widget, so methods always return a widget --- core/modules/widgets/void.js | 49 ++++++++++++++++++++++++++++++++++ core/modules/widgets/widget.js | 2 +- 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100755 core/modules/widgets/void.js diff --git a/core/modules/widgets/void.js b/core/modules/widgets/void.js new file mode 100755 index 000000000..e7b982a35 --- /dev/null +++ b/core/modules/widgets/void.js @@ -0,0 +1,49 @@ +/*\ +title: $:/core/modules/widgets/Void.js +type: application/javascript +module-type: widget + +Void widget that is not intended for render. + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget; + +var VoidNodeWidget = function(parseTreeNode,options) { + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +VoidNodeWidget.prototype = new Widget(); + +/* +Render this widget into the DOM +*/ +VoidNodeWidget.prototype.render = function(parent,nextSibling) { + // Nothing to do for a void node +}; + +/* +Compute the internal state of the widget +*/ +VoidNodeWidget.prototype.execute = function() { + // Nothing to do for a void node +}; + +/* +Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering +*/ +VoidNodeWidget.prototype.refresh = function(changedTiddlers) { + return false; +}; + +exports.void = VoidNodeWidget; + +})(); diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index 73c299d69..6f2842d19 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -554,7 +554,7 @@ Widget.prototype.makeChildWidget = function(parseTreeNode,options) { if(!WidgetClass) { WidgetClass = this.widgetClasses.text; // Skip void node that is not intended for render. Show error for missing widgets. - parseTreeNode = {type: "text", text: parseTreeNode.void ? "" : "Undefined widget '" + parseTreeNode.type + "'"}; + parseTreeNode = {type: "text", text: "Undefined widget '" + parseTreeNode.type + "'"}; } // Create set variable widgets for each variable $tw.utils.each(options.variables,function(value,name) { From 7bc408b3b0f9f0e1dc705a9dc85df3de94a5d555 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 14:38:54 +0000 Subject: [PATCH 29/98] feat: ast to use new widget type void --- core/modules/parsers/wikiparser/rules/commentblock.js | 3 +-- core/modules/parsers/wikiparser/rules/commentinline.js | 3 +-- core/modules/parsers/wikiparser/rules/parsermode.js | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 1e9b2c622..a1510b8bc 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -55,8 +55,7 @@ exports.parse = function() { var commentEnd = this.endMatch.index + this.endMatch[0].length; var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ - type: "comment", - void: true, + type: "void", text: commentText, start: commentStart, end: commentEnd diff --git a/core/modules/parsers/wikiparser/rules/commentinline.js b/core/modules/parsers/wikiparser/rules/commentinline.js index 01f76c1c6..183eea447 100644 --- a/core/modules/parsers/wikiparser/rules/commentinline.js +++ b/core/modules/parsers/wikiparser/rules/commentinline.js @@ -48,8 +48,7 @@ exports.parse = function() { var commentEnd = this.endMatch.index + this.endMatch[0].length; var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ - type: "comment", - void: true, + type: "void", text: commentText, start: commentStart, end: commentEnd diff --git a/core/modules/parsers/wikiparser/rules/parsermode.js b/core/modules/parsers/wikiparser/rules/parsermode.js index 9aea958d2..ba165a283 100644 --- a/core/modules/parsers/wikiparser/rules/parsermode.js +++ b/core/modules/parsers/wikiparser/rules/parsermode.js @@ -63,8 +63,7 @@ exports.parse = function() { } } return [{ - type: "parsermode", - void: true, + type: "void", parseAsInline: this.parser.parseAsInline, start: start, end: this.parser.pos From 82ae7678a720b15c9f135e5ee6f21951c46af69a Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 4 Aug 2024 14:39:20 +0000 Subject: [PATCH 30/98] test: add rule: 'parseBlock' and isRuleEnd: true --- .../Parameterised-ParseTreeNodes.tid | 2 +- .../tiddlers/tests/test-wikitext-parser.js | 60 +++++++++---------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid index 916e2abfb..6db3f8be2 100644 --- a/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid @@ -26,4 +26,4 @@ title: TiddlerOne + title: ExpectedResult -

[{"type":"element","tag":"p","children":[{"type":"text","text":"This is a block","start":68,"end":83}],"start":68,"end":83}]

[{"type":"text","text":"This is inline","start":136,"end":152}]

\ No newline at end of file +

[{"type":"element","tag":"p","children":[{"type":"text","text":"This is a block","start":68,"end":83}],"start":68,"end":83,"rule":"parseBlock"}]

[{"type":"text","text":"This is inline","start":136,"end":152}]

\ No newline at end of file diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index 04d041ec9..0cb1a9f55 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -26,87 +26,87 @@ describe("WikiText parser tests", function() { it("should parse tags", function() { expect(parse("
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 4, children : [ { type : 'element', tag : 'br', start : 0, end : 4, openTagStart: 0, openTagEnd: 4, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 4, children : [ { type : 'element', tag : 'br', start : 0, end : 4, openTagStart: 0, openTagEnd: 4, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ] } ] } ] ); expect(parse("
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 5, children : [ { type : 'text', text : '
', start : 0, end : 5 } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 5, children : [ { type : 'text', text : '
', start : 0, end : 5 } ] } ] ); expect(parse("
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 5, children : [ { type : 'element', tag : 'div', start : 0, end : 5, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 5, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 5, children : [ { type : 'element', tag : 'div', start : 0, end : 5, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 5, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ] } ] } ] ); expect(parse("
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 6, children : [ { type : 'element', tag : 'div', isSelfClosing : true, isBlock : false, attributes : { }, orderedAttributes: [ ], start : 0, end : 6, rule: 'html' } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 6, children : [ { type : 'element', tag : 'div', isSelfClosing : true, isBlock : false, attributes : { }, orderedAttributes: [ ], start : 0, end : 6, rule: 'html' } ] } ] ); expect(parse("
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 11, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ], start : 0, end : 11, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 11, rule: 'html' } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 11, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ], start : 0, end : 11, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 11, rule: 'html' } ] } ] ); expect(parse("
some text
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 20, children : [ { type : 'element', tag : 'div', openTagStart: 0, openTagEnd: 5, closeTagStart: 14, closeTagEnd: 20, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ { type : 'text', text : 'some text', start : 5, end : 14 } ], start : 0, end : 20 } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 20, children : [ { type : 'element', tag : 'div', openTagStart: 0, openTagEnd: 5, closeTagStart: 14, closeTagEnd: 20, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ { type : 'text', text : 'some text', start : 5, end : 14 } ], start : 0, end : 20 } ] } ] ); expect(parse("
some text
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 30, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { attribute : { type : 'string', value : 'true', start : 4, end : 14, name: 'attribute' } }, orderedAttributes: [ { type : 'string', value : 'true', start : 4, end : 14, name: 'attribute' } ], children : [ { type : 'text', text : 'some text', start : 15, end : 24 } ], start : 0, end : 30, openTagStart: 0, openTagEnd: 15, closeTagStart: 24, closeTagEnd: 30, rule: 'html' } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 30, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { attribute : { type : 'string', value : 'true', start : 4, end : 14, name: 'attribute' } }, orderedAttributes: [ { type : 'string', value : 'true', start : 4, end : 14, name: 'attribute' } ], children : [ { type : 'text', text : 'some text', start : 15, end : 24 } ], start : 0, end : 30, openTagStart: 0, openTagEnd: 15, closeTagStart: 24, closeTagEnd: 30, rule: 'html' } ] } ] ); expect(parse("
some text
")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 38, children : [ { type : 'element', tag : 'div', openTagStart: 0, openTagEnd: 23, closeTagStart: 32, closeTagEnd: 38, rule: 'html', isBlock : false, attributes : { attribute : { type : 'string', name: 'attribute', value : 'value', start: 4, end: 22 } }, orderedAttributes: [ { type: 'string', name: 'attribute', value : 'value', start: 4, end: 22 } ], children : [ { type : 'text', text : 'some text', start : 23, end : 32 } ], start : 0, end : 38 } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 38, children : [ { type : 'element', tag : 'div', openTagStart: 0, openTagEnd: 23, closeTagStart: 32, closeTagEnd: 38, rule: 'html', isBlock : false, attributes : { attribute : { type : 'string', name: 'attribute', value : 'value', start: 4, end: 22 } }, orderedAttributes: [ { type: 'string', name: 'attribute', value : 'value', start: 4, end: 22 } ], children : [ { type : 'text', text : 'some text', start : 23, end : 32 } ], start : 0, end : 38 } ] } ] ); expect(parse("
some text
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 47, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { attribute : { type : 'indirect', name: 'attribute', textReference : 'TiddlerTitle', start : 4, end : 31 } }, orderedAttributes: [ { type : 'indirect', name: 'attribute', textReference : 'TiddlerTitle', start : 4, end : 31 } ], children : [ { type : 'text', text : 'some text', start : 32, end : 41 } ], start : 0, end : 47, openTagStart: 0, openTagEnd: 32, closeTagStart: 41, closeTagEnd: 47, rule: 'html' } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 47, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { attribute : { type : 'indirect', name: 'attribute', textReference : 'TiddlerTitle', start : 4, end : 31 } }, orderedAttributes: [ { type : 'indirect', name: 'attribute', textReference : 'TiddlerTitle', start : 4, end : 31 } ], children : [ { type : 'text', text : 'some text', start : 32, end : 41 } ], start : 0, end : 47, openTagStart: 0, openTagEnd: 32, closeTagStart: 41, closeTagEnd: 47, rule: 'html' } ] } ] ); expect(parse("<$reveal state='$:/temp/search' type='nomatch' text=''>")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 55, children : [ { type : 'reveal', tag: '$reveal', rule: 'html', attributes : { state : { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, type : { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, text : { start : 46, name : 'text', type : 'string', value : '', end : 54 } }, orderedAttributes: [ { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, { start : 46, name : 'text', type : 'string', value : '', end : 54 } ], start: 0, end : 55, openTagStart: 0, openTagEnd: 55, closeTagStart: 55, closeTagEnd: 55, isBlock : false, children : [ ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 55, children : [ { type : 'reveal', tag: '$reveal', rule: 'html', attributes : { state : { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, type : { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, text : { start : 46, name : 'text', type : 'string', value : '', end : 54 } }, orderedAttributes: [ { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, { start : 46, name : 'text', type : 'string', value : '', end : 54 } ], start: 0, end : 55, openTagStart: 0, openTagEnd: 55, closeTagStart: 55, closeTagEnd: 55, isBlock : false, children : [ ] } ] } ] ); expect(parse("
some text
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 54, children : [ { type : 'element', tag : 'div', rule: 'html', isBlock : false, attributes : { attribute : { type : 'indirect', name : 'attribute', textReference : 'TiddlerTitle!!field', start : 4, end : 38 } }, orderedAttributes: [ { type : 'indirect', name : 'attribute', textReference : 'TiddlerTitle!!field', start : 4, end : 38 } ], children : [ { type : 'text', text : 'some text', start : 39, end : 48 } ], start : 0, end : 54, openTagStart: 0, openTagEnd: 39, closeTagStart: 48, closeTagEnd: 54 } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 54, children : [ { type : 'element', tag : 'div', rule: 'html', isBlock : false, attributes : { attribute : { type : 'indirect', name : 'attribute', textReference : 'TiddlerTitle!!field', start : 4, end : 38 } }, orderedAttributes: [ { type : 'indirect', name : 'attribute', textReference : 'TiddlerTitle!!field', start : 4, end : 38 } ], children : [ { type : 'text', text : 'some text', start : 39, end : 48 } ], start : 0, end : 54, openTagStart: 0, openTagEnd: 39, closeTagStart: 48, closeTagEnd: 54 } ] } ] ); expect(parse("
some text
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 55, children : [ { type : 'element', tag : 'div', rule: 'html', isBlock : false, attributes : { attribute : { type : 'indirect', name : 'attribute', textReference : 'Tiddler Title!!field', start : 4, end : 39 } }, orderedAttributes: [ { type : 'indirect', name : 'attribute', textReference : 'Tiddler Title!!field', start : 4, end : 39 } ], children : [ { type : 'text', text : 'some text', start : 40, end : 49 } ], start : 0, end : 55, openTagStart: 0, openTagEnd: 40, closeTagStart: 49, closeTagEnd: 55 } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 55, children : [ { type : 'element', tag : 'div', rule: 'html', isBlock : false, attributes : { attribute : { type : 'indirect', name : 'attribute', textReference : 'Tiddler Title!!field', start : 4, end : 39 } }, orderedAttributes: [ { type : 'indirect', name : 'attribute', textReference : 'Tiddler Title!!field', start : 4, end : 39 } ], children : [ { type : 'text', text : 'some text', start : 40, end : 49 } ], start : 0, end : 55, openTagStart: 0, openTagEnd: 40, closeTagStart: 49, closeTagEnd: 55 } ] } ] ); expect(parse("
\n\nsome text
")).toEqual( - [ { type : 'element', start : 0, attributes : { attribute : { start : 4, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 38 } }, orderedAttributes: [ { start : 4, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 38 } ], tag : 'div', rule: 'html', end : 56, openTagStart: 0, openTagEnd: 39, closeTagStart: 50, closeTagEnd: 56, isBlock : true, children : [ { type : 'element', tag : 'p', start : 41, end : 50, children : [ { type : 'text', text : 'some text', start : 41, end : 50 } ] } ] } ] + [ { type : 'element', start : 0, attributes : { attribute : { start : 4, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 38 } }, orderedAttributes: [ { start : 4, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 38 } ], tag : 'div', rule: 'html', end : 56, openTagStart: 0, openTagEnd: 39, closeTagStart: 50, closeTagEnd: 56, isBlock : true, children : [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 41, end : 50, children : [ { type : 'text', text : 'some text', start : 41, end : 50 } ] } ] } ] ); expect(parse("
\n\nsome text
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 67, children : [ { type : 'element', start : 0, end: 67, openTagStart: 0, openTagEnd: 5, closeTagStart: 61, closeTagEnd: 67, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 61, openTagStart: 5, openTagEnd: 44, closeTagStart: 55, closeTagEnd: 61, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'p', start : 46, end : 55, children : [ { type : 'text', text : 'some text', start : 46, end : 55 } ] } ] } ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 67, children : [ { type : 'element', start : 0, end: 67, openTagStart: 0, openTagEnd: 5, closeTagStart: 61, closeTagEnd: 67, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 61, openTagStart: 5, openTagEnd: 44, closeTagStart: 55, closeTagEnd: 61, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 46, end : 55, children : [ { type : 'text', text : 'some text', start : 46, end : 55 } ] } ] } ] } ] } ] ); expect(parse("
\n\n!some heading
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 71, children : [ { type : 'element', start : 0, end: 71, openTagStart: 0, openTagEnd: 5, closeTagStart: 71, closeTagEnd: 71, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 71, openTagStart: 5, openTagEnd: 44, closeTagStart: 71, closeTagEnd: 71, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'h1', start: 46, end: 71, rule: 'heading', attributes : { class : { type : 'string', value : '', start: 47, end: 47 } }, children : [ { type : 'text', text : 'some heading
', start : 47, end : 71 } ] } ] } ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 71, children : [ { type : 'element', start : 0, end: 71, openTagStart: 0, openTagEnd: 5, closeTagStart: 71, closeTagEnd: 71, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 71, openTagStart: 5, openTagEnd: 44, closeTagStart: 71, closeTagEnd: 71, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'h1', start: 46, end: 71, rule: 'heading', attributes : { class : { type : 'string', value : '', start: 47, end: 47 } }, children : [ { type : 'text', text : 'some heading', start : 47, end : 71 } ] } ] } ] } ] } ] ); expect(parse("
\n!some heading
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 70, children : [ { type : 'element', start : 0, end: 70, openTagStart: 0, openTagEnd: 5, closeTagStart: 64, closeTagEnd: 70, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 64, openTagStart: 5, openTagEnd: 44, closeTagStart: 58, closeTagEnd: 64, rule: 'html', isBlock : false, children : [ { type : 'text', text : '\n!some heading', start : 44, end : 58 } ] } ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 70, children : [ { type : 'element', start : 0, end: 70, openTagStart: 0, openTagEnd: 5, closeTagStart: 64, closeTagEnd: 70, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 64, openTagStart: 5, openTagEnd: 44, closeTagStart: 58, closeTagEnd: 64, rule: 'html', isBlock : false, children : [ { type : 'text', text : '\n!some heading', start : 44, end : 58 } ] } ] } ] } ] ); // Regression test for issue (#3306) expect(parse("
\n\nSome text
")).toEqual( - [ { type : 'element', tag : 'p', start: 0, end: 48, children : [ { type : 'element', start : 0, end: 48, openTagStart: 0, openTagEnd: 5, closeTagStart: 42, closeTagEnd: 48, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { }, orderedAttributes: [ ], tag : 'span', end : 42, openTagStart: 5, openTagEnd: 11, closeTagStart: 35, closeTagEnd: 42, rule: 'html', isBlock : false, children : [ { type : 'element', start : 11, attributes : { }, orderedAttributes: [ ], tag : 'span', end : 35, openTagStart: 11, openTagEnd: 17, closeTagStart: 28, closeTagEnd: 35, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'p', start : 19, end : 28, children : [ { type : 'text', text : 'Some text', start : 19, end : 28 } ] } ] } ] } ] } ] } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 48, children : [ { type : 'element', start : 0, end: 48, openTagStart: 0, openTagEnd: 5, closeTagStart: 42, closeTagEnd: 48, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { }, orderedAttributes: [ ], tag : 'span', end : 42, openTagStart: 5, openTagEnd: 11, closeTagStart: 35, closeTagEnd: 42, rule: 'html', isBlock : false, children : [ { type : 'element', start : 11, attributes : { }, orderedAttributes: [ ], tag : 'span', end : 35, openTagStart: 11, openTagEnd: 17, closeTagStart: 28, closeTagEnd: 35, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 19, end : 28, children : [ { type : 'text', text : 'Some text', start : 19, end : 28 } ] } ] } ] } ] } ] } ] ); }); @@ -206,38 +206,38 @@ describe("WikiText parser tests", function() { it("should parse inline macro calls", function() { expect(parse("<><><><>")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"transclude","start":8,"end":16,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"paul"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"paul"}]},{"type":"transclude","start":16,"end":26,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"george"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"george"}]},{"type":"transclude","start":26,"end":35,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"ringo"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"ringo"}]}],"start":0,"end":35}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"transclude","start":8,"end":16,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"paul"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"paul"}]},{"type":"transclude","start":16,"end":26,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"george"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"george"}]},{"type":"transclude","start":26,"end":35,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"ringo"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"ringo"}]}],"start":0,"end":35}] ); expect(parse("text <>")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},"three":{"name":"three","type":"string","value":"val '3'","start":35,"end":52},"four":{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},"five":{"name":"five","type":"string","value":"val 5","start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":11,"end":20},{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},{"name":"three","type":"string","value":"val '3'","start":35,"end":52},{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},{"name":"five","type":"string","value":"val 5","start":73,"end":89}]}],"start":0,"end":92}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},"three":{"name":"three","type":"string","value":"val '3'","start":35,"end":52},"four":{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},"five":{"name":"five","type":"string","value":"val 5","start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":11,"end":20},{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},{"name":"three","type":"string","value":"val '3'","start":35,"end":52},{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},{"name":"five","type":"string","value":"val 5","start":73,"end":89}]}],"start":0,"end":92}] ); expect(parse("ignored << carrots <>")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"text","text":"ignored << carrots ","start":0,"end":19},{"type":"transclude","start":19,"end":27,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":27}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"ignored << carrots ","start":0,"end":19},{"type":"transclude","start":19,"end":27,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":27}] ); expect(parse("text <<>")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":14,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":">")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"text","text":"before\n","start":0,"end":7},{"type":"transclude","start":7,"end":15,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":15}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"before\n","start":0,"end":7},{"type":"transclude","start":7,"end":15,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":15}] ); // A single space will cause it to be inline expect(parse("<> ")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"text","text":" ","start":8,"end":9}],"start":0,"end":9}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"text","text":" ","start":8,"end":9}],"start":0,"end":9}] ); expect(parse("text <>' >>")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","type":"string","value":"my <>","start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","type":"string","value":"my <>","start":12,"end":31}]}],"start":0,"end":34}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","type":"string","value":"my <>","start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","type":"string","value":"my <>","start":12,"end":31}]}],"start":0,"end":34}] ); @@ -256,17 +256,17 @@ describe("WikiText parser tests", function() { ); expect(parse("<< carrots\n\n<>")).toEqual( - [ { type: 'element', tag: 'p', start : 0, end : 10, children: [ { type: 'text', text: '<< carrots', start : 0, end : 10 } ] }, { type: 'transclude', start: 12, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 20, isBlock: true } ] + [ { type: 'element', tag: 'p', rule: 'parseBlock', start : 0, end : 10, children: [ { type: 'text', text: '<< carrots', start : 0, end : 10 } ] }, { type: 'transclude', start: 12, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 20, isBlock: true } ] ); expect(parse("before\n\n<>")).toEqual( - [ { type: 'element', tag: 'p', start : 0, end : 6, children: [ { type: 'text', text: 'before', start : 0, end : 6 } ] }, { type: 'transclude', start: 8, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 16, isBlock: true } ] + [ { type: 'element', tag: 'p', rule: 'parseBlock', start : 0, end : 6, children: [ { type: 'text', text: 'before', start : 0, end : 6 } ] }, { type: 'transclude', start: 8, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 16, isBlock: true } ] ); expect(parse("<>\nafter")).toEqual( - [ { type: 'transclude', start: 0, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 8, isBlock: true }, { type: 'element', tag: 'p', start: 9, end: 14, children: [ { type: 'text', text: 'after', start: 9, end: 14 } ] } ] + [ { type: 'transclude', start: 0, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 8, isBlock: true }, { type: 'element', tag: 'p', rule: 'parseBlock', start: 9, end: 14, children: [ { type: 'text', text: 'after', start: 9, end: 14 } ] } ] ); expect(parse("<>")).toEqual( @@ -294,7 +294,7 @@ describe("WikiText parser tests", function() { ); expect(parse("<>>")).toEqual( - [{"type":"element","tag":"p","children":[{"type":"transclude","start":0,"end":14,"rule":"macrocallinline","attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}] + [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"transclude","start":0,"end":14,"rule":"macrocallinline","attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}] ); // equals signs should be allowed @@ -309,7 +309,7 @@ describe("WikiText parser tests", function() { it("should parse horizontal rules", function() { expect(parse("---Not a rule\n\n----\n\nBetween\n\n---")).toEqual( - [ { type : 'element', tag : 'p', start : 0, end : 13, children : [ { type : 'entity', entity : '—', start: 0, end: 3, rule: 'dash' }, { type : 'text', text : 'Not a rule', start : 3, end : 13 } ] }, { type : 'element', tag : 'hr', start: 15, end: 20, rule: 'horizrule' }, { type : 'element', tag : 'p', start : 21, end : 28, children : [ { type : 'text', text : 'Between', start : 21, end : 28 } ] }, { type : 'element', tag : 'hr', start: 30, end: 33, rule: 'horizrule' } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 13, children : [ { type : 'entity', entity : '—', start: 0, end: 3, rule: 'dash' }, { type : 'text', text : 'Not a rule', start : 3, end : 13 } ] }, { type : 'element', tag : 'hr', start: 15, end: 20, rule: 'horizrule' }, { type : 'element', tag : 'p', rule: 'parseBlock', start : 21, end : 28, children : [ { type : 'text', text : 'Between', start : 21, end : 28 } ] }, { type : 'element', tag : 'hr', start: 30, end: 33, rule: 'horizrule' } ] ); @@ -318,7 +318,7 @@ describe("WikiText parser tests", function() { it("should parse hard linebreak areas", function() { expect(parse("\"\"\"Something\nin the\nway she moves\n\"\"\"\n\n")).toEqual( - [ { type : 'element', tag : 'p', children : [ { type : 'text', text : 'Something', start : 3, end : 12, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 12, end: 13 }, { type : 'text', text : 'in the', start : 13, end : 19, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 19, end: 20 }, { type : 'text', text : 'way she moves', start : 20, end : 33, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 33, end: 34 } ], start : 0, end : 37 } ] + [ { type : 'element', tag : 'p', rule: 'parseBlock', children : [ { type : 'text', text : 'Something', start : 3, end : 12, rule: 'hardlinebreaks', isRuleStart: true }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 12, end: 13 }, { type : 'text', text : 'in the', start : 13, end : 19, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 19, end: 20 }, { type : 'text', text : 'way she moves', start : 20, end : 33, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 33, end: 34, isRuleEnd: true } ], start : 0, end : 37 } ] ); From 893edf9ae3980794c093d3292ce457e868a6319f Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 5 Aug 2024 01:34:30 +0800 Subject: [PATCH 31/98] lint: quote --- .../tiddlers/tests/test-wikitext-serialize.js | 416 +++++++++--------- 1 file changed, 208 insertions(+), 208 deletions(-) diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 032417549..6b7ea72e0 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -7,391 +7,391 @@ Tests the wikitext inverse-rendering from Wiki AST. \*/ -describe('WikiAST serialization unit tests', function () { +describe("WikiAST serialization unit tests", function () { var wiki = new $tw.Wiki(); wiki.addTiddler({ - title: 'BoldEmphasisTest', - text: "This is ''bold'' text" + title: "BoldEmphasisTest", + text: "This is ''bold'' text", }); - it('should serialize bold emphasis correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('BoldEmphasisTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('BoldEmphasisTest').trimEnd()); + it("should serialize bold emphasis correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("BoldEmphasisTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("BoldEmphasisTest").trimEnd()); }); wiki.addTiddler({ - title: 'ItalicEmphasisTest', - text: "This is //italic// text" + title: "ItalicEmphasisTest", + text: "This is //italic// text", }); - it('should serialize italic emphasis correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ItalicEmphasisTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('ItalicEmphasisTest').trimEnd()); + it("should serialize italic emphasis correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ItalicEmphasisTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ItalicEmphasisTest").trimEnd()); }); wiki.addTiddler({ - title: 'StrikethroughEmphasisTest', - text: "This is ~~strikethrough~~ text" + title: "StrikethroughEmphasisTest", + text: "This is ~~strikethrough~~ text", }); - it('should serialize strikethrough emphasis correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('StrikethroughEmphasisTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('StrikethroughEmphasisTest').trimEnd()); + it("should serialize strikethrough emphasis correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StrikethroughEmphasisTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("StrikethroughEmphasisTest").trimEnd()); }); wiki.addTiddler({ - title: 'SubscriptEmphasisTest', - text: "This is ,,subscript,, text" + title: "SubscriptEmphasisTest", + text: "This is ,,subscript,, text", }); - it('should serialize subscript emphasis correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('SubscriptEmphasisTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('SubscriptEmphasisTest').trimEnd()); + it("should serialize subscript emphasis correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("SubscriptEmphasisTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("SubscriptEmphasisTest").trimEnd()); }); wiki.addTiddler({ - title: 'SuperscriptEmphasisTest', - text: "This is ^^superscript^^ text" + title: "SuperscriptEmphasisTest", + text: "This is ^^superscript^^ text", }); - it('should serialize superscript emphasis correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('SuperscriptEmphasisTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('SuperscriptEmphasisTest').trimEnd()); + it("should serialize superscript emphasis correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("SuperscriptEmphasisTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("SuperscriptEmphasisTest").trimEnd()); }); wiki.addTiddler({ - title: 'UnderscoreEmphasisTest', - text: "This is __underscore__ text" + title: "UnderscoreEmphasisTest", + text: "This is __underscore__ text", }); - it('should serialize underscore emphasis correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('UnderscoreEmphasisTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('UnderscoreEmphasisTest').trimEnd()); + it("should serialize underscore emphasis correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("UnderscoreEmphasisTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("UnderscoreEmphasisTest").trimEnd()); }); - wiki.addTiddler({ title: 'SimpleTextTest', text: 'The quick brown fox' }); - it('should render tiddlers with no special markup as-is', function () { + wiki.addTiddler({ title: "SimpleTextTest", text: "The quick brown fox" }); + it("should render tiddlers with no special markup as-is", function () { // `trimEnd` because when we handle `p` element when parsing block rules, we always add a newline. But original text that may not have a trailing newline, will still be recognized as a block. - expect($tw.utils.serializeParseTree(wiki.parseTiddler('SimpleTextTest').tree).trimEnd()).toBe( - wiki.getTiddlerText('SimpleTextTest') + expect($tw.utils.serializeParseTree(wiki.parseTiddler("SimpleTextTest").tree).trimEnd()).toBe( + wiki.getTiddlerText("SimpleTextTest") ); }); - wiki.addTiddler({ title: 'SoftLineBreakTest', text: 'The rain in Spain\nfalls mainly on the plain' }); - it('should preserve single new lines', function () { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('SoftLineBreakTest').tree).trimEnd()).toBe( - wiki.getTiddlerText('SoftLineBreakTest') + wiki.addTiddler({ title: "SoftLineBreakTest", text: "The rain in Spain\nfalls mainly on the plain" }); + it("should preserve single new lines", function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler("SoftLineBreakTest").tree).trimEnd()).toBe( + wiki.getTiddlerText("SoftLineBreakTest") ); }); - wiki.addTiddler({ title: 'BlockRule', text: 'The speed of sound\n\nThe light of speed' }); - it('should preserve double new lines to create paragraphs', function () { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('BlockRule').tree).trimEnd()).toBe( - wiki.getTiddlerText('BlockRule') + wiki.addTiddler({ title: "BlockRule", text: "The speed of sound\n\nThe light of speed" }); + it("should preserve double new lines to create paragraphs", function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler("BlockRule").tree).trimEnd()).toBe( + wiki.getTiddlerText("BlockRule") ); }); wiki.addTiddler({ - title: 'CodeBlockTest', - text: 'Simple `JS` and complex\n\n---\n\n```js\nvar match = reEnd.exec(this.parser.source)\n```\nend', + title: "CodeBlockTest", + text: "Simple `JS` and complex\n\n---\n\n```js\nvar match = reEnd.exec(this.parser.source)\n```\nend", }); - it('should render inline code and block code', function () { - expect($tw.utils.serializeParseTree(wiki.parseTiddler('CodeBlockTest').tree).trimEnd()).toBe( - wiki.getTiddlerText('CodeBlockTest') + it("should render inline code and block code", function () { + expect($tw.utils.serializeParseTree(wiki.parseTiddler("CodeBlockTest").tree).trimEnd()).toBe( + wiki.getTiddlerText("CodeBlockTest") ); }); wiki.addTiddler({ - title: 'CommentBlockTest', - text: '\n\nSome text\n\n\n\nMore text', + title: "CommentBlockTest", + text: "\n\nSome text\n\n\n\nMore text", }); - it('should serialize block comments correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('CommentBlockTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('CommentBlockTest').trimEnd()); + it("should serialize block comments correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("CommentBlockTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("CommentBlockTest").trimEnd()); }); wiki.addTiddler({ - title: 'CommentInlineTest', - text: 'This is some text with an inline comment and some more text.', + title: "CommentInlineTest", + text: "This is some text with an inline comment and some more text.", }); - it('should serialize inline comments correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('CommentInlineTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('CommentInlineTest').trimEnd()); + it("should serialize inline comments correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("CommentInlineTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("CommentInlineTest").trimEnd()); }); wiki.addTiddler({ - title: 'ConditionalTest', - text: 'This is a <% if [{something}] %>Elephant<% elseif [{else}] %>Pelican<% else %>Crocodile<% endif %>', + title: "ConditionalTest", + text: "This is a <% if [{something}] %>Elephant<% elseif [{else}] %>Pelican<% else %>Crocodile<% endif %>", }); - it('should serialize conditional statements correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ConditionalTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('ConditionalTest').trimEnd()); + it("should serialize conditional statements correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ConditionalTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ConditionalTest").trimEnd()); }); wiki.addTiddler({ - title: 'DashTest', - text: 'This is an en-dash: --\n\nThis is an em-dash: ---', + title: "DashTest", + text: "This is an en-dash: --\n\nThis is an em-dash: ---", }); - it('should serialize dashes correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('DashTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('DashTest').trimEnd()); + it("should serialize dashes correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("DashTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("DashTest").trimEnd()); }); wiki.addTiddler({ - title: 'EntityTest', - text: 'This is a copyright symbol: ©', + title: "EntityTest", + text: "This is a copyright symbol: ©", }); - it('should serialize HTML entities correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('EntityTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('EntityTest').trimEnd()); + it("should serialize HTML entities correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("EntityTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("EntityTest").trimEnd()); }); wiki.addTiddler({ - title: 'ExtLinkTest', - text: 'An external link: https://www.tiddlywiki.com/\n\nA suppressed external link: ~http://www.tiddlyspace.com/', + title: "ExtLinkTest", + text: "An external link: https://www.tiddlywiki.com/\n\nA suppressed external link: ~http://www.tiddlyspace.com/", }); - it('should serialize external links correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ExtLinkTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('ExtLinkTest').trimEnd()); + it("should serialize external links correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ExtLinkTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ExtLinkTest").trimEnd()); }); wiki.addTiddler({ - title: 'FilteredTranscludeBlockTest', - text: '{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class', + title: "FilteredTranscludeBlockTest", + text: "{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class", }); - it('should serialize block-level filtered transclusion correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FilteredTranscludeBlockTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('FilteredTranscludeBlockTest').trimEnd()); + it("should serialize block-level filtered transclusion correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("FilteredTranscludeBlockTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("FilteredTranscludeBlockTest").trimEnd()); }); wiki.addTiddler({ - title: 'FilteredTranscludeInlineTest', - text: '{{{ [tag[docs]] }}} {{{ [tag[docs]] |tooltip}}} {{{ [tag[docs]] ||TemplateTitle}}} {{{ [tag[docs]] |tooltip||TemplateTitle}}} {{{ [tag[docs]] }}width:40;height:50;}.class.class', + title: "FilteredTranscludeInlineTest", + text: "{{{ [tag[docs]] }}} {{{ [tag[docs]] |tooltip}}} {{{ [tag[docs]] ||TemplateTitle}}} {{{ [tag[docs]] |tooltip||TemplateTitle}}} {{{ [tag[docs]] }}width:40;height:50;}.class.class", }); - it('should serialize inline filtered transclusion correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FilteredTranscludeInlineTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('FilteredTranscludeInlineTest').trimEnd()); + it("should serialize inline filtered transclusion correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("FilteredTranscludeInlineTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("FilteredTranscludeInlineTest").trimEnd()); }); // Test case based on the rule code's comment wiki.addTiddler({ - title: 'FunctionDefinition', - text: '\\function name(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end\n\n\\procedure name(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end\n\n\\widget $mywidget(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end', + title: "FunctionDefinition", + text: "\\function name(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end\n\n\\procedure name(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end\n\n\\widget $mywidget(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end", }); - it('should serialize function, procedure, and widget definitions correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('FunctionDefinition').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('FunctionDefinition').trimEnd()); + it("should serialize function, procedure, and widget definitions correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("FunctionDefinition").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("FunctionDefinition").trimEnd()); }); wiki.addTiddler({ - title: 'HardLineBreaksTest', + title: "HardLineBreaksTest", text: '"""\nThis is some text\nThat is set like\nIt is a Poem\nWhen it is\nClearly\nNot\n"""\n', }); - it('should serialize hard line breaks correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('HardLineBreaksTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('HardLineBreaksTest').trimEnd()); + it("should serialize hard line breaks correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("HardLineBreaksTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("HardLineBreaksTest").trimEnd()); }); wiki.addTiddler({ - title: 'HeadingTest', - text: '! Heading 1\n!! Heading 2\n!!! Heading 3\n!!!! Heading 4\n!!!!! Heading 5\n!!!!!! Heading 6', + title: "HeadingTest", + text: "! Heading 1\n!! Heading 2\n!!! Heading 3\n!!!! Heading 4\n!!!!! Heading 5\n!!!!!! Heading 6", }); - it('should serialize headings correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('HeadingTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('HeadingTest').trimEnd()); + it("should serialize headings correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("HeadingTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("HeadingTest").trimEnd()); }); wiki.addTiddler({ - title: 'HtmlTest', + title: "HtmlTest", text: '\n\n<$slider target="MyTiddler">\nThis is a widget invocation\n', }); - it('should serialize HTML elements and widgets correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('HtmlTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('HtmlTest').trimEnd()); + it("should serialize HTML elements and widgets correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("HtmlTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("HtmlTest").trimEnd()); }); wiki.addTiddler({ - title: 'ImageTest', + title: "ImageTest", text: '[img[https://tiddlywiki.com/fractalveg.jpg]]\n[img width="23" height="24" [https://tiddlywiki.com/fractalveg.jpg]]\n[img width={{!!width}} height={{!!height}} [https://tiddlywiki.com/fractalveg.jpg]]\n[img[Description of image|https://tiddlywiki.com/fractalveg.jpg]]\n[img[TiddlerTitle]]\n[img[Description of image|TiddlerTitle]]', }); - it('should serialize image tags correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImageTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('ImageTest').trimEnd()); + it("should serialize image tags correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ImageTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ImageTest").trimEnd()); }); wiki.addTiddler({ - title: 'ImportTest', - text: '\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\\import [[$:/core/ui/PageMacros]]', + title: "ImportTest", + text: "\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\\import [[$:/core/ui/PageMacros]]", }); - it('should serialize import pragma correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ImportTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('ImportTest').trimEnd()); + it("should serialize import pragma correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ImportTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ImportTest").trimEnd()); }); wiki.addTiddler({ - title: 'ListTest', - text: '* This is an unordered list\n* It has two items\n\n# This is a numbered list\n## With a subitem\n# And a third item\n\n; This is a term that is being defined\n: This is the definition of that term\n\n#** One\n#* Two\n#** Three\n#**** Four\n#**# Five\n#**## Six\n## Seven\n### Eight\n## Nine\n\n* List item one\n*.active List item two has the class `active`\n* List item three', + title: "ListTest", + text: "* This is an unordered list\n* It has two items\n\n# This is a numbered list\n## With a subitem\n# And a third item\n\n; This is a term that is being defined\n: This is the definition of that term\n\n#** One\n#* Two\n#** Three\n#**** Four\n#**# Five\n#**## Six\n## Seven\n### Eight\n## Nine\n\n* List item one\n*.active List item two has the class `active`\n* List item three", }); - it('should serialize lists correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ListTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('ListTest').trimEnd()); + it("should serialize lists correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ListTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ListTest").trimEnd()); }); wiki.addTiddler({ - title: 'MacroCallBlockTest', + title: "MacroCallBlockTest", text: '<>\n\n<<.def "macro calls">>', }); - it('should serialize block macro calls correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroCallBlockTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('MacroCallBlockTest').trimEnd()); + it("should serialize block macro calls correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("MacroCallBlockTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("MacroCallBlockTest").trimEnd()); }); wiki.addTiddler({ - title: 'MacroCallInlineTest', + title: "MacroCallInlineTest", text: 'These are macro calls in a line: <> and <<.def "macro calls">>', }); - it('should serialize inline macro calls correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroCallInlineTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('MacroCallInlineTest').trimEnd()); + it("should serialize inline macro calls correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("MacroCallInlineTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("MacroCallInlineTest").trimEnd()); }); wiki.addTiddler({ - title: 'MacroDefTest', - text: '\\define name(param:defaultvalue,param2:defaultvalue)\ndefinition text, including $param$ markers\n\\end', + title: "MacroDefTest", + text: "\\define name(param:defaultvalue,param2:defaultvalue)\ndefinition text, including $param$ markers\n\\end", }); - it('should serialize macro definitions correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('MacroDefTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('MacroDefTest').trimEnd()); + it("should serialize macro definitions correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("MacroDefTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("MacroDefTest").trimEnd()); }); wiki.addTiddler({ - title: 'ParametersTest', - text: '\\parameters(param:defaultvalue,param2:defaultvalue)', + title: "ParametersTest", + text: "\\parameters(param:defaultvalue,param2:defaultvalue)", }); - it('should serialize parameter definitions correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ParametersTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('ParametersTest').trimEnd()); + it("should serialize parameter definitions correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ParametersTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ParametersTest").trimEnd()); }); wiki.addTiddler({ - title: 'ParserModeTest', - text: '\\parsermode block\n\n\\parsermode inline\n\nTest.', + title: "ParserModeTest", + text: "\\parsermode block\n\n\\parsermode inline\n\nTest.", }); - it('should serialize parser mode specifications correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('ParserModeTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('ParserModeTest').trimEnd()); + it("should serialize parser mode specifications correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ParserModeTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("ParserModeTest").trimEnd()); }); return; wiki.addTiddler({ - title: 'PrettyExtLinkTest', - text: '[ext[https://tiddlywiki.com/fractalveg.jpg]]\n[ext[Tooltip|https://tiddlywiki.com/fractalveg.jpg]]', + title: "PrettyExtLinkTest", + text: "[ext[https://tiddlywiki.com/fractalveg.jpg]]\n[ext[Tooltip|https://tiddlywiki.com/fractalveg.jpg]]", }); - it('should serialize pretty external links correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('PrettyExtLinkTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('PrettyExtLinkTest').trimEnd()); + it("should serialize pretty external links correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("PrettyExtLinkTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("PrettyExtLinkTest").trimEnd()); }); wiki.addTiddler({ - title: 'PrettyLinkTest', - text: '[[Introduction]]\n[[Link description|TiddlerTitle]]', + title: "PrettyLinkTest", + text: "[[Introduction]]\n[[Link description|TiddlerTitle]]", }); - it('should serialize pretty links correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('PrettyLinkTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('PrettyLinkTest').trimEnd()); + it("should serialize pretty links correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("PrettyLinkTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("PrettyLinkTest").trimEnd()); }); wiki.addTiddler({ - title: 'QuoteBlockTest', - text: '<<` around this list will also have the class `myClass`\n* List item 2\n@@', + title: "StyleBlockTest", + text: "@@.myClass\n@@background-color:red;\nThis paragraph will have the CSS class `myClass`.\n\n* The `
    ` around this list will also have the class `myClass`\n* List item 2\n@@", }); - it('should serialize style blocks correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('StyleBlockTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('StyleBlockTest').trimEnd()); + it("should serialize style blocks correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleBlockTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("StyleBlockTest").trimEnd()); }); wiki.addTiddler({ - title: 'StyleInlineTest', - text: '@@.myClass This is some text with a class@@\n@@background-color:red;This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@', + title: "StyleInlineTest", + text: "@@.myClass This is some text with a class@@\n@@background-color:red;This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@", }); - it('should serialize style inlines correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('StyleInlineTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('StyleInlineTest').trimEnd()); + it("should serialize style inlines correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleInlineTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("StyleInlineTest").trimEnd()); }); wiki.addTiddler({ - title: 'SysLinkTest', - text: '$:TiddlerTitle\n~$:TiddlerTitle' + title: "SysLinkTest", + text: "$:TiddlerTitle\n~$:TiddlerTitle", }); - it('should serialize system links correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('SysLinkTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('SysLinkTest').trimEnd()); + it("should serialize system links correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("SysLinkTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("SysLinkTest").trimEnd()); }); wiki.addTiddler({ - title: 'TableTest', - text: '|! |!Alpha |!Beta |!Gamma |!Delta |\n|!One | | | | |\n|!Two | | | | |\n|!Three | | | | |' + title: "TableTest", + text: "|! |!Alpha |!Beta |!Gamma |!Delta |\n|!One | | | | |\n|!Two | | | | |\n|!Three | | | | |", }); - it('should serialize tables correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TableTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('TableTest').trimEnd()); + it("should serialize tables correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TableTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("TableTest").trimEnd()); }); wiki.addTiddler({ - title: 'TranscludeBlockTest', - text: '{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}' + title: "TranscludeBlockTest", + text: "{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}", }); - it('should serialize block-level transclusions correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TranscludeBlockTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('TranscludeBlockTest').trimEnd()); + it("should serialize block-level transclusions correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TranscludeBlockTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("TranscludeBlockTest").trimEnd()); }); wiki.addTiddler({ - title: 'TranscludeInlineTest', - text: '{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}' + title: "TranscludeInlineTest", + text: "{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}", }); - it('should serialize inline-level transclusions correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TranscludeInlineTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('TranscludeInlineTest').trimEnd()); + it("should serialize inline-level transclusions correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TranscludeInlineTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("TranscludeInlineTest").trimEnd()); }); wiki.addTiddler({ - title: 'TypedBlockTest', - text: '$$$.js\nThis will be rendered as JavaScript\n$$$\n$$$.svg\n\n \n\n$$$\n$$$text/vnd.tiddlywiki>text/html\nThis will be rendered as an //HTML representation// of WikiText\n$$$' + title: "TypedBlockTest", + text: '$$$.js\nThis will be rendered as JavaScript\n$$$\n$$$.svg\n\n \n\n$$$\n$$$text/vnd.tiddlywiki>text/html\nThis will be rendered as an //HTML representation// of WikiText\n$$$', }); - it('should serialize typed blocks correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('TypedBlockTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('TypedBlockTest').trimEnd()); + it("should serialize typed blocks correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TypedBlockTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("TypedBlockTest").trimEnd()); }); wiki.addTiddler({ - title: 'WikiLinkTest', - text: 'AWikiLink\nAnotherLink\n~SuppressedLink' + title: "WikiLinkTest", + text: "AWikiLink\nAnotherLink\n~SuppressedLink", }); - it('should serialize wiki links correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('WikiLinkTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('WikiLinkTest').trimEnd()); + it("should serialize wiki links correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("WikiLinkTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("WikiLinkTest").trimEnd()); }); wiki.addTiddler({ - title: 'WikiLinkPrefixTest', - text: '~SuppressedLink' + title: "WikiLinkPrefixTest", + text: "~SuppressedLink", }); - it('should serialize suppressed wiki links correctly', function () { - var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler('WikiLinkPrefixTest').tree).trimEnd(); - expect(serialized).toBe(wiki.getTiddlerText('WikiLinkPrefixTest').trimEnd()); + it("should serialize suppressed wiki links correctly", function () { + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("WikiLinkPrefixTest").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("WikiLinkPrefixTest").trimEnd()); }); }); From d6b9d00ef794ef2bd85b30a349bae9066cb9bc8e Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 5 Aug 2024 01:34:33 +0800 Subject: [PATCH 32/98] Update widget.js --- core/modules/widgets/widget.js | 1 - 1 file changed, 1 deletion(-) diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index 6f2842d19..eb84fab4a 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -553,7 +553,6 @@ Widget.prototype.makeChildWidget = function(parseTreeNode,options) { var WidgetClass = this.widgetClasses[parseTreeNode.type]; if(!WidgetClass) { WidgetClass = this.widgetClasses.text; - // Skip void node that is not intended for render. Show error for missing widgets. parseTreeNode = {type: "text", text: "Undefined widget '" + parseTreeNode.type + "'"}; } // Create set variable widgets for each variable From 6ac9592bd7594d77a7c3488791d6361c5322f8cb Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 5 Aug 2024 02:31:16 +0800 Subject: [PATCH 33/98] fix: void node need to handle its children --- .../modules/parsers/wikiparser/rules/commentblock.js | 3 ++- core/modules/parsers/wikiparser/rules/parsermode.js | 1 + core/modules/widgets/void.js | 12 ++++++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index a1510b8bc..7d9a68f14 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -25,7 +25,7 @@ Note that the syntax for comments is simplified to an opening "\n\\define aMacro()\nnothing\n\\end\n")).toEqual( - [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}],"start":32,"end":61,"rule":"macrodef"}] + [{"type":"void","children":[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}],"start":31,"end":60,"rule":"macrodef"}],"text":"","start":0,"end":31,"rule":"commentblock"}] ); }); From e7d4819f0389a41b4bbe304d4c2b09db0a947235 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 5 Aug 2024 02:52:12 +0800 Subject: [PATCH 35/98] lint: quote --- .../tiddlers/tests/test-wikitext-parser.js | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index a0cb99c95..8a38ccc53 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -26,87 +26,87 @@ describe("WikiText parser tests", function() { it("should parse tags", function() { expect(parse("
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 4, children : [ { type : 'element', tag : 'br', start : 0, end : 4, openTagStart: 0, openTagEnd: 4, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 4, children : [ { type : "element", tag : "br", start : 0, end : 4, openTagStart: 0, openTagEnd: 4, rule: "html", isBlock : false, attributes : { }, orderedAttributes: [ ] } ] } ] ); expect(parse("
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 5, children : [ { type : 'text', text : '
    ', start : 0, end : 5 } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 5, children : [ { type : "text", text : "
    ", start : 0, end : 5 } ] } ] ); expect(parse("
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 5, children : [ { type : 'element', tag : 'div', start : 0, end : 5, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 5, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 5, children : [ { type : "element", tag : "div", start : 0, end : 5, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 5, rule: "html", isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ] } ] } ] ); expect(parse("
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 6, children : [ { type : 'element', tag : 'div', isSelfClosing : true, isBlock : false, attributes : { }, orderedAttributes: [ ], start : 0, end : 6, rule: 'html' } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 6, children : [ { type : "element", tag : "div", isSelfClosing : true, isBlock : false, attributes : { }, orderedAttributes: [ ], start : 0, end : 6, rule: "html" } ] } ] ); expect(parse("
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 11, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ], start : 0, end : 11, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 11, rule: 'html' } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 11, children : [ { type : "element", tag : "div", isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ], start : 0, end : 11, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 11, rule: "html" } ] } ] ); expect(parse("
    some text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 20, children : [ { type : 'element', tag : 'div', openTagStart: 0, openTagEnd: 5, closeTagStart: 14, closeTagEnd: 20, rule: 'html', isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ { type : 'text', text : 'some text', start : 5, end : 14 } ], start : 0, end : 20 } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 20, children : [ { type : "element", tag : "div", openTagStart: 0, openTagEnd: 5, closeTagStart: 14, closeTagEnd: 20, rule: "html", isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ { type : "text", text : "some text", start : 5, end : 14 } ], start : 0, end : 20 } ] } ] ); expect(parse("
    some text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 30, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { attribute : { type : 'string', value : 'true', start : 4, end : 14, name: 'attribute' } }, orderedAttributes: [ { type : 'string', value : 'true', start : 4, end : 14, name: 'attribute' } ], children : [ { type : 'text', text : 'some text', start : 15, end : 24 } ], start : 0, end : 30, openTagStart: 0, openTagEnd: 15, closeTagStart: 24, closeTagEnd: 30, rule: 'html' } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 30, children : [ { type : "element", tag : "div", isBlock : false, attributes : { attribute : { type : "string", value : "true", start : 4, end : 14, name: "attribute" } }, orderedAttributes: [ { type : "string", value : "true", start : 4, end : 14, name: "attribute" } ], children : [ { type : "text", text : "some text", start : 15, end : 24 } ], start : 0, end : 30, openTagStart: 0, openTagEnd: 15, closeTagStart: 24, closeTagEnd: 30, rule: "html" } ] } ] ); expect(parse("
    some text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 38, children : [ { type : 'element', tag : 'div', openTagStart: 0, openTagEnd: 23, closeTagStart: 32, closeTagEnd: 38, rule: 'html', isBlock : false, attributes : { attribute : { type : 'string', name: 'attribute', value : 'value', start: 4, end: 22 } }, orderedAttributes: [ { type: 'string', name: 'attribute', value : 'value', start: 4, end: 22 } ], children : [ { type : 'text', text : 'some text', start : 23, end : 32 } ], start : 0, end : 38 } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 38, children : [ { type : "element", tag : "div", openTagStart: 0, openTagEnd: 23, closeTagStart: 32, closeTagEnd: 38, rule: "html", isBlock : false, attributes : { attribute : { type : "string", name: "attribute", value : "value", start: 4, end: 22 } }, orderedAttributes: [ { type: "string", name: "attribute", value : "value", start: 4, end: 22 } ], children : [ { type : "text", text : "some text", start : 23, end : 32 } ], start : 0, end : 38 } ] } ] ); expect(parse("
    some text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 47, children : [ { type : 'element', tag : 'div', isBlock : false, attributes : { attribute : { type : 'indirect', name: 'attribute', textReference : 'TiddlerTitle', start : 4, end : 31 } }, orderedAttributes: [ { type : 'indirect', name: 'attribute', textReference : 'TiddlerTitle', start : 4, end : 31 } ], children : [ { type : 'text', text : 'some text', start : 32, end : 41 } ], start : 0, end : 47, openTagStart: 0, openTagEnd: 32, closeTagStart: 41, closeTagEnd: 47, rule: 'html' } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 47, children : [ { type : "element", tag : "div", isBlock : false, attributes : { attribute : { type : "indirect", name: "attribute", textReference : "TiddlerTitle", start : 4, end : 31 } }, orderedAttributes: [ { type : "indirect", name: "attribute", textReference : "TiddlerTitle", start : 4, end : 31 } ], children : [ { type : "text", text : "some text", start : 32, end : 41 } ], start : 0, end : 47, openTagStart: 0, openTagEnd: 32, closeTagStart: 41, closeTagEnd: 47, rule: "html" } ] } ] ); expect(parse("<$reveal state='$:/temp/search' type='nomatch' text=''>")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 55, children : [ { type : 'reveal', tag: '$reveal', rule: 'html', attributes : { state : { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, type : { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, text : { start : 46, name : 'text', type : 'string', value : '', end : 54 } }, orderedAttributes: [ { start : 8, name : 'state', type : 'string', value : '$:/temp/search', end : 31 }, { start : 31, name : 'type', type : 'string', value : 'nomatch', end : 46 }, { start : 46, name : 'text', type : 'string', value : '', end : 54 } ], start: 0, end : 55, openTagStart: 0, openTagEnd: 55, closeTagStart: 55, closeTagEnd: 55, isBlock : false, children : [ ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 55, children : [ { type : "reveal", tag: "$reveal", rule: "html", attributes : { state : { start : 8, name : "state", type : "string", value : "$:/temp/search", end : 31 }, type : { start : 31, name : "type", type : "string", value : "nomatch", end : 46 }, text : { start : 46, name : "text", type : "string", value : "", end : 54 } }, orderedAttributes: [ { start : 8, name : "state", type : "string", value : "$:/temp/search", end : 31 }, { start : 31, name : "type", type : "string", value : "nomatch", end : 46 }, { start : 46, name : "text", type : "string", value : "", end : 54 } ], start: 0, end : 55, openTagStart: 0, openTagEnd: 55, closeTagStart: 55, closeTagEnd: 55, isBlock : false, children : [ ] } ] } ] ); expect(parse("
    some text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 54, children : [ { type : 'element', tag : 'div', rule: 'html', isBlock : false, attributes : { attribute : { type : 'indirect', name : 'attribute', textReference : 'TiddlerTitle!!field', start : 4, end : 38 } }, orderedAttributes: [ { type : 'indirect', name : 'attribute', textReference : 'TiddlerTitle!!field', start : 4, end : 38 } ], children : [ { type : 'text', text : 'some text', start : 39, end : 48 } ], start : 0, end : 54, openTagStart: 0, openTagEnd: 39, closeTagStart: 48, closeTagEnd: 54 } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 54, children : [ { type : "element", tag : "div", rule: "html", isBlock : false, attributes : { attribute : { type : "indirect", name : "attribute", textReference : "TiddlerTitle!!field", start : 4, end : 38 } }, orderedAttributes: [ { type : "indirect", name : "attribute", textReference : "TiddlerTitle!!field", start : 4, end : 38 } ], children : [ { type : "text", text : "some text", start : 39, end : 48 } ], start : 0, end : 54, openTagStart: 0, openTagEnd: 39, closeTagStart: 48, closeTagEnd: 54 } ] } ] ); expect(parse("
    some text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 55, children : [ { type : 'element', tag : 'div', rule: 'html', isBlock : false, attributes : { attribute : { type : 'indirect', name : 'attribute', textReference : 'Tiddler Title!!field', start : 4, end : 39 } }, orderedAttributes: [ { type : 'indirect', name : 'attribute', textReference : 'Tiddler Title!!field', start : 4, end : 39 } ], children : [ { type : 'text', text : 'some text', start : 40, end : 49 } ], start : 0, end : 55, openTagStart: 0, openTagEnd: 40, closeTagStart: 49, closeTagEnd: 55 } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 55, children : [ { type : "element", tag : "div", rule: "html", isBlock : false, attributes : { attribute : { type : "indirect", name : "attribute", textReference : "Tiddler Title!!field", start : 4, end : 39 } }, orderedAttributes: [ { type : "indirect", name : "attribute", textReference : "Tiddler Title!!field", start : 4, end : 39 } ], children : [ { type : "text", text : "some text", start : 40, end : 49 } ], start : 0, end : 55, openTagStart: 0, openTagEnd: 40, closeTagStart: 49, closeTagEnd: 55 } ] } ] ); expect(parse("
    \n\nsome text
    ")).toEqual( - [ { type : 'element', start : 0, attributes : { attribute : { start : 4, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 38 } }, orderedAttributes: [ { start : 4, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 38 } ], tag : 'div', rule: 'html', end : 56, openTagStart: 0, openTagEnd: 39, closeTagStart: 50, closeTagEnd: 56, isBlock : true, children : [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 41, end : 50, children : [ { type : 'text', text : 'some text', start : 41, end : 50 } ] } ] } ] + [ { type : "element", start : 0, attributes : { attribute : { start : 4, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 38 } }, orderedAttributes: [ { start : 4, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 38 } ], tag : "div", rule: "html", end : 56, openTagStart: 0, openTagEnd: 39, closeTagStart: 50, closeTagEnd: 56, isBlock : true, children : [ { type : "element", tag : "p", rule: "parseBlock", start : 41, end : 50, children : [ { type : "text", text : "some text", start : 41, end : 50 } ] } ] } ] ); expect(parse("
    \n\nsome text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 67, children : [ { type : 'element', start : 0, end: 67, openTagStart: 0, openTagEnd: 5, closeTagStart: 61, closeTagEnd: 67, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 61, openTagStart: 5, openTagEnd: 44, closeTagStart: 55, closeTagEnd: 61, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 46, end : 55, children : [ { type : 'text', text : 'some text', start : 46, end : 55 } ] } ] } ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 67, children : [ { type : "element", start : 0, end: 67, openTagStart: 0, openTagEnd: 5, closeTagStart: 61, closeTagEnd: 67, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { attribute : { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } }, orderedAttributes: [ { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } ], tag : "div", end : 61, openTagStart: 5, openTagEnd: 44, closeTagStart: 55, closeTagEnd: 61, rule: "html", isBlock : true, children : [ { type : "element", tag : "p", rule: "parseBlock", start : 46, end : 55, children : [ { type : "text", text : "some text", start : 46, end : 55 } ] } ] } ] } ] } ] ); expect(parse("
    \n\n!some heading
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 71, children : [ { type : 'element', start : 0, end: 71, openTagStart: 0, openTagEnd: 5, closeTagStart: 71, closeTagEnd: 71, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 71, openTagStart: 5, openTagEnd: 44, closeTagStart: 71, closeTagEnd: 71, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'h1', start: 46, end: 71, rule: 'heading', attributes : { class : { type : 'string', value : '', start: 47, end: 47 } }, children : [ { type : 'text', text : 'some heading
    ', start : 47, end : 71 } ] } ] } ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 71, children : [ { type : "element", start : 0, end: 71, openTagStart: 0, openTagEnd: 5, closeTagStart: 71, closeTagEnd: 71, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { attribute : { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } }, orderedAttributes: [ { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } ], tag : "div", end : 71, openTagStart: 5, openTagEnd: 44, closeTagStart: 71, closeTagEnd: 71, rule: "html", isBlock : true, children : [ { type : "element", tag : "h1", start: 46, end: 71, rule: "heading", attributes : { class : { type : "string", value : "", start: 47, end: 47 } }, children : [ { type : "text", text : "some heading", start : 47, end : 71 } ] } ] } ] } ] } ] ); expect(parse("
    \n!some heading
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 70, children : [ { type : 'element', start : 0, end: 70, openTagStart: 0, openTagEnd: 5, closeTagStart: 64, closeTagEnd: 70, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { attribute : { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } }, orderedAttributes: [ { start : 9, name : 'attribute', type : 'indirect', textReference : 'TiddlerTitle!!field', end : 43 } ], tag : 'div', end : 64, openTagStart: 5, openTagEnd: 44, closeTagStart: 58, closeTagEnd: 64, rule: 'html', isBlock : false, children : [ { type : 'text', text : '\n!some heading', start : 44, end : 58 } ] } ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 70, children : [ { type : "element", start : 0, end: 70, openTagStart: 0, openTagEnd: 5, closeTagStart: 64, closeTagEnd: 70, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { attribute : { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } }, orderedAttributes: [ { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } ], tag : "div", end : 64, openTagStart: 5, openTagEnd: 44, closeTagStart: 58, closeTagEnd: 64, rule: "html", isBlock : false, children : [ { type : "text", text : "\n!some heading", start : 44, end : 58 } ] } ] } ] } ] ); // Regression test for issue (#3306) expect(parse("
    \n\nSome text
    ")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start: 0, end: 48, children : [ { type : 'element', start : 0, end: 48, openTagStart: 0, openTagEnd: 5, closeTagStart: 42, closeTagEnd: 48, attributes : { }, orderedAttributes: [ ], tag : 'div', rule: 'html', isBlock : false, children : [ { type : 'element', start : 5, attributes : { }, orderedAttributes: [ ], tag : 'span', end : 42, openTagStart: 5, openTagEnd: 11, closeTagStart: 35, closeTagEnd: 42, rule: 'html', isBlock : false, children : [ { type : 'element', start : 11, attributes : { }, orderedAttributes: [ ], tag : 'span', end : 35, openTagStart: 11, openTagEnd: 17, closeTagStart: 28, closeTagEnd: 35, rule: 'html', isBlock : true, children : [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 19, end : 28, children : [ { type : 'text', text : 'Some text', start : 19, end : 28 } ] } ] } ] } ] } ] } ] + [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 48, children : [ { type : "element", start : 0, end: 48, openTagStart: 0, openTagEnd: 5, closeTagStart: 42, closeTagEnd: 48, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { }, orderedAttributes: [ ], tag : "span", end : 42, openTagStart: 5, openTagEnd: 11, closeTagStart: 35, closeTagEnd: 42, rule: "html", isBlock : false, children : [ { type : "element", start : 11, attributes : { }, orderedAttributes: [ ], tag : "span", end : 35, openTagStart: 11, openTagEnd: 17, closeTagStart: 28, closeTagEnd: 35, rule: "html", isBlock : true, children : [ { type : "element", tag : "p", rule: "parseBlock", start : 19, end : 28, children : [ { type : "text", text : "Some text", start : 19, end : 28 } ] } ] } ] } ] } ] } ] ); }); @@ -193,12 +193,12 @@ describe("WikiText parser tests", function() { it("should block mode filtered transclusions", function() { expect(parse("{{{ filter }}}")).toEqual( - [ { type: 'list', attributes: { filter: { type: 'string', value: ' filter ', start: 3, end: 11 } }, isBlock: true, start: 0, end: 14, rule: "filteredtranscludeblock" } ] + [ { type: "list", attributes: { filter: { type: "string", value: " filter ", start: 3, end: 11 } }, isBlock: true, start: 0, end: 14, rule: "filteredtranscludeblock" } ] ); expect(parse("{{{ fil\nter }}}")).toEqual( - [ { type: 'list', attributes: { filter: { type: 'string', value: ' fil\nter ', start: 3, end: 12 } }, isBlock: true, start: 0, end: 15, rule: "filteredtranscludeblock" } ] + [ { type: "list", attributes: { filter: { type: "string", value: " fil\nter ", start: 3, end: 12 } }, isBlock: true, start: 0, end: 15, rule: "filteredtranscludeblock" } ] ); }); @@ -206,38 +206,38 @@ describe("WikiText parser tests", function() { it("should parse inline macro calls", function() { expect(parse("<><><><>")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"transclude","start":8,"end":16,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"paul"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"paul"}]},{"type":"transclude","start":16,"end":26,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"george"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"george"}]},{"type":"transclude","start":26,"end":35,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"ringo"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"ringo"}]}],"start":0,"end":35}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"transclude","start":8,"end":16,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"paul"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"paul"}]},{"type":"transclude","start":16,"end":26,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"george"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"george"}]},{"type":"transclude","start":26,"end":35,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"ringo"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"ringo"}]}],"start":0,"end":35}] ); expect(parse("text <>")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},"three":{"name":"three","type":"string","value":"val '3'","start":35,"end":52},"four":{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},"five":{"name":"five","type":"string","value":"val 5","start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":11,"end":20},{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},{"name":"three","type":"string","value":"val '3'","start":35,"end":52},{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},{"name":"five","type":"string","value":"val 5","start":73,"end":89}]}],"start":0,"end":92}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},"three":{"name":"three","type":"string","value":"val '3'","start":35,"end":52},"four":{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},"five":{"name":"five","type":"string","value":"val 5","start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":11,"end":20},{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},{"name":"three","type":"string","value":"val '3'","start":35,"end":52},{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},{"name":"five","type":"string","value":"val 5","start":73,"end":89}]}],"start":0,"end":92}] ); expect(parse("ignored << carrots <>")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"ignored << carrots ","start":0,"end":19},{"type":"transclude","start":19,"end":27,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":27}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"text","text":"ignored << carrots ","start":0,"end":19},{"type":"transclude","start":19,"end":27,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":27}] ); expect(parse("text <<>")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":14,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":">")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"before\n","start":0,"end":7},{"type":"transclude","start":7,"end":15,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":15}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"text","text":"before\n","start":0,"end":7},{"type":"transclude","start":7,"end":15,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":15}] ); // A single space will cause it to be inline expect(parse("<> ")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"text","text":" ","start":8,"end":9}],"start":0,"end":9}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"text","text":" ","start":8,"end":9}],"start":0,"end":9}] ); expect(parse("text <>' >>")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","type":"string","value":"my <>","start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","type":"string","value":"my <>","start":12,"end":31}]}],"start":0,"end":34}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","type":"string","value":"my <>","start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","type":"string","value":"my <>","start":12,"end":31}]}],"start":0,"end":34}] ); @@ -246,7 +246,7 @@ describe("WikiText parser tests", function() { it("should parse block macro calls", function() { expect(parse("<>\n<>\r\n<>\n<>")).toEqual( - [ { type: 'transclude', start: 0, rule: 'macrocallblock', attributes: { $variable: { name: "$variable", type: "string", value: "john" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "john" }], end: 8, isBlock: true }, { type: 'transclude', start: 9, rule: 'macrocallblock', attributes: { $variable: { name: "$variable", type: "string", value: "paul" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "paul" }], end: 17, isBlock: true }, { type: 'transclude', start: 19, rule: 'macrocallblock', attributes: { $variable: { name: "$variable", type: "string", value: "george" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "george" }], end: 29, isBlock: true }, { type: 'transclude', start: 30, rule: 'macrocallblock', attributes: { $variable: { name: "$variable", type: "string", value: "ringo" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "ringo" }], end: 39, isBlock: true } ] + [ { type: "transclude", start: 0, rule: "macrocallblock", attributes: { $variable: { name: "$variable", type: "string", value: "john" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "john" }], end: 8, isBlock: true }, { type: "transclude", start: 9, rule: "macrocallblock", attributes: { $variable: { name: "$variable", type: "string", value: "paul" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "paul" }], end: 17, isBlock: true }, { type: "transclude", start: 19, rule: "macrocallblock", attributes: { $variable: { name: "$variable", type: "string", value: "george" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "george" }], end: 29, isBlock: true }, { type: "transclude", start: 30, rule: "macrocallblock", attributes: { $variable: { name: "$variable", type: "string", value: "ringo" }}, orderedAttributes: [ { name: "$variable", type: "string", value: "ringo" }], end: 39, isBlock: true } ] ); expect(parse("<>")).toEqual( @@ -256,17 +256,17 @@ describe("WikiText parser tests", function() { ); expect(parse("<< carrots\n\n<>")).toEqual( - [ { type: 'element', tag: 'p', rule: 'parseBlock', start : 0, end : 10, children: [ { type: 'text', text: '<< carrots', start : 0, end : 10 } ] }, { type: 'transclude', start: 12, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 20, isBlock: true } ] + [ { type: "element", tag: "p", rule: "parseBlock", start : 0, end : 10, children: [ { type: "text", text: "<< carrots", start : 0, end : 10 } ] }, { type: "transclude", start: 12, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 20, isBlock: true } ] ); expect(parse("before\n\n<>")).toEqual( - [ { type: 'element', tag: 'p', rule: 'parseBlock', start : 0, end : 6, children: [ { type: 'text', text: 'before', start : 0, end : 6 } ] }, { type: 'transclude', start: 8, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 16, isBlock: true } ] + [ { type: "element", tag: "p", rule: "parseBlock", start : 0, end : 6, children: [ { type: "text", text: "before", start : 0, end : 6 } ] }, { type: "transclude", start: 8, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 16, isBlock: true } ] ); expect(parse("<>\nafter")).toEqual( - [ { type: 'transclude', start: 0, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 8, isBlock: true }, { type: 'element', tag: 'p', rule: 'parseBlock', start: 9, end: 14, children: [ { type: 'text', text: 'after', start: 9, end: 14 } ] } ] + [ { type: "transclude", start: 0, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 8, isBlock: true }, { type: "element", tag: "p", rule: "parseBlock", start: 9, end: 14, children: [ { type: "text", text: "after", start: 9, end: 14 } ] } ] ); expect(parse("<>")).toEqual( @@ -276,7 +276,7 @@ describe("WikiText parser tests", function() { ); expect(parse("<>' >>")).toEqual( - [ { type: 'transclude', start: 0, rule: 'macrocallblock', attributes: { $variable: {name: "$variable", type:"string", value: "outie"}, one: {name: "one", type:"string", value: "my <>", start: 7, end: 26} }, orderedAttributes: [ {name: "$variable", type:"string", value: "outie"}, {name: "one", type:"string", value: "my <>", start: 7, end: 26} ], end: 29, isBlock: true } ] + [ { type: "transclude", start: 0, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "outie"}, one: {name: "one", type:"string", value: "my <>", start: 7, end: 26} }, orderedAttributes: [ {name: "$variable", type:"string", value: "outie"}, {name: "one", type:"string", value: "my <>", start: 7, end: 26} ], end: 29, isBlock: true } ] ); }); @@ -294,7 +294,7 @@ describe("WikiText parser tests", function() { ); expect(parse("<>>")).toEqual( - [{"type":"element","tag":"p",rule:'parseBlock',"children":[{"type":"transclude","start":0,"end":14,"rule":"macrocallinline","attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}] + [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"transclude","start":0,"end":14,"rule":"macrocallinline","attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}] ); // equals signs should be allowed @@ -309,7 +309,7 @@ describe("WikiText parser tests", function() { it("should parse horizontal rules", function() { expect(parse("---Not a rule\n\n----\n\nBetween\n\n---")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', start : 0, end : 13, children : [ { type : 'entity', entity : '—', start: 0, end: 3, rule: 'dash' }, { type : 'text', text : 'Not a rule', start : 3, end : 13 } ] }, { type : 'element', tag : 'hr', start: 15, end: 20, rule: 'horizrule' }, { type : 'element', tag : 'p', rule: 'parseBlock', start : 21, end : 28, children : [ { type : 'text', text : 'Between', start : 21, end : 28 } ] }, { type : 'element', tag : 'hr', start: 30, end: 33, rule: 'horizrule' } ] + [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 13, children : [ { type : "entity", entity : "—", start: 0, end: 3, rule: "dash" }, { type : "text", text : "Not a rule", start : 3, end : 13 } ] }, { type : "element", tag : "hr", start: 15, end: 20, rule: "horizrule" }, { type : "element", tag : "p", rule: "parseBlock", start : 21, end : 28, children : [ { type : "text", text : "Between", start : 21, end : 28 } ] }, { type : "element", tag : "hr", start: 30, end: 33, rule: "horizrule" } ] ); @@ -318,7 +318,7 @@ describe("WikiText parser tests", function() { it("should parse hard linebreak areas", function() { expect(parse("\"\"\"Something\nin the\nway she moves\n\"\"\"\n\n")).toEqual( - [ { type : 'element', tag : 'p', rule: 'parseBlock', children : [ { type : 'text', text : 'Something', start : 3, end : 12, rule: 'hardlinebreaks', isRuleStart: true }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 12, end: 13 }, { type : 'text', text : 'in the', start : 13, end : 19, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 19, end: 20 }, { type : 'text', text : 'way she moves', start : 20, end : 33, rule: 'hardlinebreaks' }, { type : 'element', tag : 'br', rule: 'hardlinebreaks', start: 33, end: 34, isRuleEnd: true } ], start : 0, end : 37 } ] + [ { type : "element", tag : "p", rule: "parseBlock", children : [ { type : "text", text : "Something", start : 3, end : 12, rule: "hardlinebreaks", isRuleStart: true }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 12, end: 13 }, { type : "text", text : "in the", start : 13, end : 19, rule: "hardlinebreaks" }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 19, end: 20 }, { type : "text", text : "way she moves", start : 20, end : 33, rule: "hardlinebreaks" }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 33, end: 34, isRuleEnd: true } ], start : 0, end : 37 } ] ); From af2ddaa350778ba535ebb1e1a42cbe48ab50e9ad Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 5 Aug 2024 02:58:28 +0800 Subject: [PATCH 36/98] Update void.js --- core/modules/widgets/void.js | 1 + 1 file changed, 1 insertion(+) diff --git a/core/modules/widgets/void.js b/core/modules/widgets/void.js index cc8e803c0..d2b6445a7 100755 --- a/core/modules/widgets/void.js +++ b/core/modules/widgets/void.js @@ -29,6 +29,7 @@ Render this widget into the DOM VoidNodeWidget.prototype.render = function(parent,nextSibling) { // Nothing to do for a void node, but render the children. Nodes generated by pragma rules are holding everything below it in the children. this.parentDomNode = parent; + this.computeAttributes() this.execute(); this.renderChildren(parent,nextSibling); }; From b8125d13b8132adf21e1fe055eb96872177af220 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 5 Aug 2024 03:04:03 +0800 Subject: [PATCH 37/98] Update test-wikitext-parser.js --- editions/test/tiddlers/tests/test-wikitext-parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index 8a38ccc53..9c3ae78ce 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -185,7 +185,7 @@ describe("WikiText parser tests", function() { it("should parse comment in pragma area. Comment will be invisible", function() { expect(parse("\n\\define aMacro()\nnothing\n\\end\n")).toEqual( - [{"type":"void","children":[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}],"start":31,"end":60,"rule":"macrodef"}],"text":"","start":0,"end":31,"rule":"commentblock"}] + [{"type":"void","children":[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}],"start":32,"end":61,"rule":"macrodef"}],"text":"","start":0,"end":31,"rule":"commentblock"}] ); }); From 2fa454ad843827419ea5c908c6460f8ca4bd579f Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Wed, 7 Aug 2024 23:53:48 +0800 Subject: [PATCH 38/98] fix: macrodef with comment (void node) not working --- core/modules/widgets/importvariables.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/modules/widgets/importvariables.js b/core/modules/widgets/importvariables.js index 3e1ac3fc6..1ccd04003 100644 --- a/core/modules/widgets/importvariables.js +++ b/core/modules/widgets/importvariables.js @@ -52,7 +52,8 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) { var parser = widgetPointer.wiki.parseTiddler(title,{parseAsInline:true, configTrimWhiteSpace:false}); if(parser) { var parseTreeNode = parser.tree[0]; - while(parseTreeNode && ["setvariable","set","parameters"].indexOf(parseTreeNode.type) !== -1) { + // process AST nodes generated by pragma rules. + while(parseTreeNode && ["setvariable","set","parameters","void"].indexOf(parseTreeNode.type) !== -1) { var node = { type: "set", attributes: parseTreeNode.attributes, @@ -85,7 +86,7 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) { // this widget. If it needs to refresh, // it'll do so along with the the whole // importvariable tree. - if (widgetPointer != this) { + if(widgetPointer != this) { widgetPointer.makeChildWidgets = function(){}; } widgetPointer = widgetPointer.children[0]; @@ -96,7 +97,7 @@ ImportVariablesWidget.prototype.execute = function(tiddlerList) { } }); - if (widgetPointer != this) { + if(widgetPointer != this) { widgetPointer.parseTreeNode.children = this.parseTreeNode.children; } else { widgetPointer.makeChildWidgets(); From fb8732a0812c368165418a4bcf9f3499f8cd609a Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Wed, 7 Aug 2024 23:58:45 +0800 Subject: [PATCH 39/98] lint: ' -> " --- .../test/tiddlers/tests/test-html-parser.js | 128 +++++++++--------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/editions/test/tiddlers/tests/test-html-parser.js b/editions/test/tiddlers/tests/test-html-parser.js index 4d07bc4f9..36eeea321 100644 --- a/editions/test/tiddlers/tests/test-html-parser.js +++ b/editions/test/tiddlers/tests/test-html-parser.js @@ -27,7 +27,7 @@ describe("HTML tag new parser tests", function() { null ); expect($tw.utils.parseWhiteSpace("p ",1)).toEqual( - { type : 'whitespace', start : 1, end : 3 } + { type : "whitespace", start : 1, end : 3 } ); }); @@ -36,7 +36,7 @@ describe("HTML tag new parser tests", function() { null ); expect($tw.utils.parseTokenString("p= ",1,"=")).toEqual( - { type : 'token', value : '=', start : 1, end : 2 } + { type : "token", value : "=", start : 1, end : 2 } ); }); @@ -45,10 +45,10 @@ describe("HTML tag new parser tests", function() { null ); expect($tw.utils.parseTokenRegExp("p=' ",1,/(=(?:'|"))/g).match[0]).toEqual( - '=\'' + "='" ); expect($tw.utils.parseTokenRegExp("p=blah ",2,/([^\s>]+)/g).match[0]).toEqual( - 'blah' + "blah" ); }); @@ -57,40 +57,40 @@ describe("HTML tag new parser tests", function() { null ); expect($tw.utils.parseStringLiteral("p='blah' ",2)).toEqual( - { type : 'string', start : 2, value : 'blah', end : 8 } + { type : "string", start : 2, value : "blah", end : 8 } ); expect($tw.utils.parseStringLiteral("p='' ",2)).toEqual( - { type : 'string', start : 2, value : '', end : 4 } + { type : "string", start : 2, value : "", end : 4 } ); expect($tw.utils.parseStringLiteral("p=\"blah' ",2)).toEqual( null ); expect($tw.utils.parseStringLiteral("p=\"\" ",2)).toEqual( - { type : 'string', start : 2, value : '', end : 4 } + { type : "string", start : 2, value : "", end : 4 } ); }); it("should parse macro parameters", function() { expect($tw.utils.parseMacroParameter("me",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'me', end : 2 } + { type : "macro-parameter", start : 0, value : "me", end : 2 } ); expect($tw.utils.parseMacroParameter("me:one",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'one', name : 'me', end : 6 } + { type : "macro-parameter", start : 0, value : "one", name : "me", end : 6 } ); expect($tw.utils.parseMacroParameter("me:'one two three'",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'one two three', name : 'me', end : 18 } + { type : "macro-parameter", start : 0, value : "one two three", name : "me", end : 18 } ); expect($tw.utils.parseMacroParameter("'one two three'",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'one two three', end : 15 } + { type : "macro-parameter", start : 0, value : "one two three", end : 15 } ); expect($tw.utils.parseMacroParameter("me:[[one two three]]",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'one two three', name : 'me', end : 20 } + { type : "macro-parameter", start : 0, value : "one two three", name : "me", end : 20 } ); expect($tw.utils.parseMacroParameter("[[one two three]]",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'one two three', end : 17 } + { type : "macro-parameter", start : 0, value : "one two three", end : 17 } ); expect($tw.utils.parseMacroParameter("myparam>",0)).toEqual( - { type : 'macro-parameter', start : 0, value : 'myparam>', end : 8 } + { type : "macro-parameter", start : 0, value : "myparam>", end : 8 } ); }); @@ -99,22 +99,22 @@ describe("HTML tag new parser tests", function() { null ); expect($tw.utils.parseMacroInvocation("<>",0)).toEqual( - { type : 'macrocall', start : 0, params : [ ], name : 'mymacro', end : 11 } + { type : "macrocall", start : 0, params : [ ], name : "mymacro", end : 11 } ); expect($tw.utils.parseMacroInvocation("<>",0)).toEqual( - { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one', end : 13 }, { type : 'macro-parameter', start : 13, value : 'two', end : 17 }, { type : 'macro-parameter', start : 17, value : 'three', end : 23 } ], name : 'mymacro', end : 25 } + { type : "macrocall", start : 0, params : [ { type : "macro-parameter", start : 9, value : "one", end : 13 }, { type : "macro-parameter", start : 13, value : "two", end : 17 }, { type : "macro-parameter", start : 17, value : "three", end : 23 } ], name : "mymacro", end : 25 } ); expect($tw.utils.parseMacroInvocation("<>",0)).toEqual( - { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one', name : 'p', end : 15 }, { type : 'macro-parameter', start : 15, value : 'two', name : 'q', end : 21 }, { type : 'macro-parameter', start : 21, value : 'three', end : 27 } ], name : 'mymacro', end : 29 } + { type : "macrocall", start : 0, params : [ { type : "macro-parameter", start : 9, value : "one", name : "p", end : 15 }, { type : "macro-parameter", start : 15, value : "two", name : "q", end : 21 }, { type : "macro-parameter", start : 21, value : "three", end : 27 } ], name : "mymacro", end : 29 } ); expect($tw.utils.parseMacroInvocation("<>",0)).toEqual( - { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one two three', end : 25 } ], name : 'mymacro', end : 27 } + { type : "macrocall", start : 0, params : [ { type : "macro-parameter", start : 9, value : "one two three", end : 25 } ], name : "mymacro", end : 27 } ); expect($tw.utils.parseMacroInvocation("<>",0)).toEqual( - { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'one two three', name : 'r', end : 27 } ], name : 'mymacro', end : 29 } + { type : "macrocall", start : 0, params : [ { type : "macro-parameter", start : 9, value : "one two three", name : "r", end : 27 } ], name : "mymacro", end : 29 } ); expect($tw.utils.parseMacroInvocation("<>",0)).toEqual( - { type : 'macrocall', start : 0, params : [ { type : 'macro-parameter', start : 9, value : 'two', name : 'one', end : 17 }, { type : 'macro-parameter', start : 17, value : 'four and five', name : 'three', end : 39 } ], name : 'myMacro', end : 41 } + { type : "macrocall", start : 0, params : [ { type : "macro-parameter", start : 9, value : "two", name : "one", end : 17 }, { type : "macro-parameter", start : 17, value : "four and five", name : "three", end : 39 } ], name : "myMacro", end : 41 } ); }); @@ -123,84 +123,84 @@ describe("HTML tag new parser tests", function() { null ); expect($tw.utils.parseAttribute("p='blah' ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'blah', end : 8 } + { type : "string", start : 0, name : "p", value : "blah", end : 8 } ); expect($tw.utils.parseAttribute("p=\"blah\" ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'blah', end : 8 } + { type : "string", start : 0, name : "p", value : "blah", end : 8 } ); expect($tw.utils.parseAttribute("p=\"bl\nah\" ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'bl\nah', end : 9 } + { type : "string", start : 0, name : "p", value : "bl\nah", end : 9 } ); expect($tw.utils.parseAttribute("p={{{blah}}} ",0)).toEqual( - { type : 'filtered', start : 0, name : 'p', filter : 'blah', end : 12 } + { type : "filtered", start : 0, name : "p", filter : "blah", end : 12 } ); expect($tw.utils.parseAttribute("p={{{bl\nah}}} ",0)).toEqual( - { type : 'filtered', start : 0, name : 'p', filter : 'bl\nah', end : 13 } + { type : "filtered", start : 0, name : "p", filter : "bl\nah", end : 13 } ); expect($tw.utils.parseAttribute("p={{{ [{$:/layout}] }}} ",0)).toEqual( - { type : 'filtered', start : 0, name : 'p', filter : ' [{$:/layout}] ', end : 23 } + { type : "filtered", start : 0, name : "p", filter : " [{$:/layout}] ", end : 23 } ); expect($tw.utils.parseAttribute("p={{blah}} ",0)).toEqual( - { type : 'indirect', start : 0, name : 'p', textReference : 'blah', end : 10 } + { type : "indirect", start : 0, name : "p", textReference : "blah", end : 10 } ); expect($tw.utils.parseAttribute("p=blah ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'blah', end : 6 } + { type : "string", start : 0, name : "p", value : "blah", end : 6 } ); expect($tw.utils.parseAttribute("p =blah ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'blah', end : 7 } + { type : "string", start : 0, name : "p", value : "blah", end : 7 } ); expect($tw.utils.parseAttribute("p= blah ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'blah', end : 7 } + { type : "string", start : 0, name : "p", value : "blah", end : 7 } ); expect($tw.utils.parseAttribute("p = blah ",0)).toEqual( - { type : 'string', start : 0, name : 'p', value : 'blah', end : 8 } + { type : "string", start : 0, name : "p", value : "blah", end : 8 } ); expect($tw.utils.parseAttribute("p = >blah ",0)).toEqual( - { type : 'string', value : 'true', start : 0, name : 'p', end : 4 } + { type : "string", value : "true", start : 0, name : "p", end : 4 } ); expect($tw.utils.parseAttribute(" attrib1>",0)).toEqual( - { type : 'string', value : 'true', start : 0, name : 'attrib1', end : 8 } + { type : "string", value : "true", start : 0, name : "attrib1", end : 8 } ); expect($tw.utils.parseAttribute("p=`blah` ",1)).toEqual(null); expect($tw.utils.parseAttribute("p=`blah` ",0)).toEqual( - { start: 0, name: 'p', type: 'substituted', rawValue: 'blah', end: 8 } + { start: 0, name: "p", type: "substituted", rawValue: "blah", end: 8 } ); expect($tw.utils.parseAttribute("p=```blah``` ",0)).toEqual( - { start: 0, name: 'p', type: 'substituted', rawValue: 'blah', end: 12 } + { start: 0, name: "p", type: "substituted", rawValue: "blah", end: 12 } ); expect($tw.utils.parseAttribute("p=`Hello \"There\"`",0)).toEqual( - { start: 0, name: 'p', type: 'substituted', rawValue: 'Hello "There"', end: 17 } + { start: 0, name: "p", type: "substituted", rawValue: 'Hello "There"', end: 17 } ); }); - describe('serializeAttribute', function () { - it('should serialize string attributes', function () { - expect($tw.utils.serializeAttribute({ type: 'string', name: 'p', value: 'blah' })).toBe('p="blah"'); - expect($tw.utils.serializeAttribute({ type: 'string', name: 'p', value: 'true' })).toBe('p'); + describe("serializeAttribute", function () { + it("should serialize string attributes", function () { + expect($tw.utils.serializeAttribute({ type: "string", name: "p", value: "blah" })).toBe('p="blah"'); + expect($tw.utils.serializeAttribute({ type: "string", name: "p", value: "true" })).toBe("p"); }); - it('should serialize filtered attributes', function () { - expect($tw.utils.serializeAttribute({ type: 'filtered', name: 'p', filter: 'blah' })).toBe('p={{{blah}}}'); + it("should serialize filtered attributes", function () { + expect($tw.utils.serializeAttribute({ type: "filtered", name: "p", filter: "blah" })).toBe("p={{{blah}}}"); }); - it('should serialize indirect attributes', function () { - expect($tw.utils.serializeAttribute({ type: 'indirect', name: 'p', textReference: 'blah' })).toBe('p={{blah}}'); + it("should serialize indirect attributes", function () { + expect($tw.utils.serializeAttribute({ type: "indirect", name: "p", textReference: "blah" })).toBe("p={{blah}}"); }); - it('should serialize substituted attributes', function () { - expect($tw.utils.serializeAttribute({ type: 'substituted', name: 'p', rawValue: 'blah' })).toBe('p=`blah`'); + it("should serialize substituted attributes", function () { + expect($tw.utils.serializeAttribute({ type: "substituted", name: "p", rawValue: "blah" })).toBe("p=`blah`"); }); - it('should return null for unsupported types', function () { - expect($tw.utils.serializeAttribute({ type: 'unknown', name: 'p', value: 'blah' })).toBeNull(); + it("should return null for unsupported types", function () { + expect($tw.utils.serializeAttribute({ type: "unknown", name: "p", value: "blah" })).toBeNull(); }); - it('should return null for invalid input', function () { + it("should return null for invalid input", function () { expect($tw.utils.serializeAttribute(null)).toBeNull(); expect($tw.utils.serializeAttribute({})).toBeNull(); - expect($tw.utils.serializeAttribute({ type: 'string' })).toBeNull(); - expect($tw.utils.serializeAttribute({ name: 'p' })).toBeNull(); + expect($tw.utils.serializeAttribute({ type: "string" })).toBeNull(); + expect($tw.utils.serializeAttribute({ name: "p" })).toBeNull(); }); }); @@ -212,52 +212,52 @@ describe("HTML tag new parser tests", function() { null ); expect(parser.parseTag("",0)).toEqual( - { type : 'element', start : 0, attributes : { }, orderedAttributes: [ ], tag : 'mytag', end : 7 } + { type : "element", start : 0, attributes : { }, orderedAttributes: [ ], tag : "mytag", end : 7 } ); expect(parser.parseTag("",0)).toEqual( - { type : 'element', start : 0, attributes : { attrib1 : { type : 'string', value : 'true', start : 6, name : 'attrib1', end : 14 } }, orderedAttributes: [ { start: 6, name: 'attrib1', type: 'string', value: 'true', end: 14 } ], tag : 'mytag', end : 15 } + { type : "element", start : 0, attributes : { attrib1 : { type : "string", value : "true", start : 6, name : "attrib1", end : 14 } }, orderedAttributes: [ { start: 6, name: "attrib1", type: "string", value: "true", end: 14 } ], tag : "mytag", end : 15 } ); expect(parser.parseTag("",0)).toEqual( - { type : 'element', start : 0, attributes : { attrib1 : { type : 'string', value : 'true', start : 6, name : 'attrib1', end : 14 } }, orderedAttributes: [ { start: 6, name: 'attrib1', type: 'string', value: 'true', end: 14 } ], tag : 'mytag', isSelfClosing : true, end : 16 } + { type : "element", start : 0, attributes : { attrib1 : { type : "string", value : "true", start : 6, name : "attrib1", end : 14 } }, orderedAttributes: [ { start: 6, name: "attrib1", type: "string", value: "true", end: 14 } ], tag : "mytag", isSelfClosing : true, end : 16 } ); expect(parser.parseTag("<$view field=\"title\" format=\"link\"/>",0)).toEqual( - { type : 'view', start : 0, attributes : { field : { start : 6, name : 'field', type : 'string', value : 'title', end : 20 }, format : { start : 20, name : 'format', type : 'string', value : 'link', end : 34 } }, orderedAttributes: [ { start: 6, name: 'field', type: 'string', value: 'title', end: 20 }, { start: 20, name: 'format', type: 'string', value: 'link', end: 34 } ], tag : '$view', isSelfClosing : true, end : 36 } + { type : "view", start : 0, attributes : { field : { start : 6, name : "field", type : "string", value : "title", end : 20 }, format : { start : 20, name : "format", type : "string", value : "link", end : 34 } }, orderedAttributes: [ { start: 6, name: "field", type: "string", value: "title", end: 20 }, { start: 20, name: "format", type: "string", value: "link", end: 34 } ], tag : "$view", isSelfClosing : true, end : 36 } ); expect(parser.parseTag("",0)).toEqual( - { type : 'element', start : 0, attributes : { attrib1 : { type : 'string', start : 6, name : 'attrib1', value : 'something', end : 26 } }, orderedAttributes: [ { start: 6, name: 'attrib1', type: 'string', value: 'something', end: 26 } ], tag : 'mytag', end : 27 } + { type : "element", start : 0, attributes : { attrib1 : { type : "string", start : 6, name : "attrib1", value : "something", end : 26 } }, orderedAttributes: [ { start: 6, name: "attrib1", type: "string", value: "something", end: 26 } ], tag : "mytag", end : 27 } ); expect(parser.parseTag("",0)).toEqual( - { type : 'element', start : 0, attributes : { attrib1 : { type : 'string', start : 15, name : 'attrib1', value : 'something', end : 34 } }, orderedAttributes: [ { start: 6, name: 'attrib1', type: 'string', value: 'true', end: 15 }, { start: 15, name: 'attrib1', type: 'string', value: 'something', end: 34 } ], tag : 'mytag', end : 35 } + { type : "element", start : 0, attributes : { attrib1 : { type : "string", start : 15, name : "attrib1", value : "something", end : 34 } }, orderedAttributes: [ { start: 6, name: "attrib1", type: "string", value: "true", end: 15 }, { start: 15, name: "attrib1", type: "string", value: "something", end: 34 } ], tag : "mytag", end : 35 } ); expect(parser.parseTag("",0)).toEqual( - { type : 'element', start : 0, attributes : { attrib1 : { type : 'string', start : 34, name : 'attrib1', value : 'else', end : 49 } }, orderedAttributes: [ { start: 6, name: 'attrib1', type: 'string', value: 'true', end: 15 }, { start: 15, name: 'attrib1', type: 'string', value: 'something', end: 34 }, { start: 34, name: 'attrib1', type: 'string', value: 'else', end: 49 } ], tag : 'mytag', end : 50 } + { type : "element", start : 0, attributes : { attrib1 : { type : "string", start : 34, name : "attrib1", value : "else", end : 49 } }, orderedAttributes: [ { start: 6, name: "attrib1", type: "string", value: "true", end: 15 }, { start: 15, name: "attrib1", type: "string", value: "something", end: 34 }, { start: 34, name: "attrib1", type: "string", value: "else", end: 49 } ], tag : "mytag", end : 50 } ); expect(parser.parseTag("<$mytag attrib1='something' attrib2=else thing>",0)).toEqual( - { type : 'mytag', start : 0, attributes : { attrib1 : { type : 'string', start : 7, name : 'attrib1', value : 'something', end : 27 }, attrib2 : { type : 'string', start : 27, name : 'attrib2', value : 'else', end : 40 }, thing : { type : 'string', start : 40, name : 'thing', value : 'true', end : 46 } }, orderedAttributes: [ { start: 7, name: 'attrib1', type: 'string', value: 'something', end: 27 }, { start: 27, name: 'attrib2', type: 'string', value: 'else', end: 40 }, { start: 40, name: 'thing', type: 'string', value: 'true', end: 46 } ], tag : '$mytag', end : 47 } + { type : "mytag", start : 0, attributes : { attrib1 : { type : "string", start : 7, name : "attrib1", value : "something", end : 27 }, attrib2 : { type : "string", start : 27, name : "attrib2", value : "else", end : 40 }, thing : { type : "string", start : 40, name : "thing", value : "true", end : 46 } }, orderedAttributes: [ { start: 7, name: "attrib1", type: "string", value: "something", end: 27 }, { start: 27, name: "attrib2", type: "string", value: "else", end: 40 }, { start: 40, name: "thing", type: "string", value: "true", end: 46 } ], tag : "$mytag", end : 47 } ); expect(parser.parseTag("< $mytag attrib1='something' attrib2=else thing>",0)).toEqual( null ); expect(parser.parseTag("<$mytag attrib3=<>>",0)).toEqual( - { type : 'mytag', start : 0, attributes : { attrib3 : { type : 'macro', start : 7, name : 'attrib3', value : { type : 'macrocall', start : 16, params : [ { type : 'macro-parameter', start : 25, value : 'two', name : 'one', end : 33 }, { type : 'macro-parameter', start : 33, value : 'four and five', name : 'three', end : 55 } ], name : 'myMacro', end : 57 }, end : 57 } }, orderedAttributes: [ { type : 'macro', start : 7, name : 'attrib3', value : { type : 'macrocall', start : 16, params : [ { type : 'macro-parameter', start : 25, value : 'two', name : 'one', end : 33 }, { type : 'macro-parameter', start : 33, value : 'four and five', name : 'three', end : 55 } ], name : 'myMacro', end : 57 }, end : 57 } ], tag : '$mytag', end : 58 } + { type : "mytag", start : 0, attributes : { attrib3 : { type : "macro", start : 7, name : "attrib3", value : { type : "macrocall", start : 16, params : [ { type : "macro-parameter", start : 25, value : "two", name : "one", end : 33 }, { type : "macro-parameter", start : 33, value : "four and five", name : "three", end : 55 } ], name : "myMacro", end : 57 }, end : 57 } }, orderedAttributes: [ { type : "macro", start : 7, name : "attrib3", value : { type : "macrocall", start : 16, params : [ { type : "macro-parameter", start : 25, value : "two", name : "one", end : 33 }, { type : "macro-parameter", start : 33, value : "four and five", name : "three", end : 55 } ], name : "myMacro", end : 57 }, end : 57 } ], tag : "$mytag", end : 58 } ); expect(parser.parseTag("<$mytag attrib1='something' attrib2=else thing attrib3=<>>",0)).toEqual( - { type : 'mytag', start : 0, attributes : { attrib1 : { type : 'string', start : 7, name : 'attrib1', value : 'something', end : 27 }, attrib2 : { type : 'string', start : 27, name : 'attrib2', value : 'else', end : 40 }, thing : { type : 'string', start : 40, name : 'thing', value : 'true', end : 47 }, attrib3 : { type : 'macro', start : 47, name : 'attrib3', value : { type : 'macrocall', start : 55, params : [ { type : 'macro-parameter', start : 64, value : 'two', name : 'one', end : 72 }, { type : 'macro-parameter', start : 72, value : 'four and five', name : 'three', end : 94 } ], name : 'myMacro', end : 96 }, end : 96 } }, orderedAttributes: [ { type : 'string', start : 7, name : 'attrib1', value : 'something', end : 27 }, { type : 'string', start : 27, name : 'attrib2', value : 'else', end : 40 }, { type : 'string', start : 40, name : 'thing', value : 'true', end : 47 }, { type : 'macro', start : 47, name : 'attrib3', value : { type : 'macrocall', start : 55, params : [ { type : 'macro-parameter', start : 64, value : 'two', name : 'one', end : 72 }, { type : 'macro-parameter', start : 72, value : 'four and five', name : 'three', end : 94 } ], name : 'myMacro', end : 96 }, end : 96 } ], tag : '$mytag', end : 97 } + { type : "mytag", start : 0, attributes : { attrib1 : { type : "string", start : 7, name : "attrib1", value : "something", end : 27 }, attrib2 : { type : "string", start : 27, name : "attrib2", value : "else", end : 40 }, thing : { type : "string", start : 40, name : "thing", value : "true", end : 47 }, attrib3 : { type : "macro", start : 47, name : "attrib3", value : { type : "macrocall", start : 55, params : [ { type : "macro-parameter", start : 64, value : "two", name : "one", end : 72 }, { type : "macro-parameter", start : 72, value : "four and five", name : "three", end : 94 } ], name : "myMacro", end : 96 }, end : 96 } }, orderedAttributes: [ { type : "string", start : 7, name : "attrib1", value : "something", end : 27 }, { type : "string", start : 27, name : "attrib2", value : "else", end : 40 }, { type : "string", start : 40, name : "thing", value : "true", end : 47 }, { type : "macro", start : 47, name : "attrib3", value : { type : "macrocall", start : 55, params : [ { type : "macro-parameter", start : 64, value : "two", name : "one", end : 72 }, { type : "macro-parameter", start : 72, value : "four and five", name : "three", end : 94 } ], name : "myMacro", end : 96 }, end : 96 } ], tag : "$mytag", end : 97 } ); }); it("should find and parse HTML tags", function() { expect(parser.findNextTag("",1)).toEqual( - { type : 'element', start : 11, attributes : { }, orderedAttributes: [ ], tag : 'mytag', end : 18 } + { type : "element", start : 11, attributes : { }, orderedAttributes: [ ], tag : "mytag", end : 18 } ); expect(parser.findNextTag("something else ",0)).toEqual( null ); expect(parser.findNextTag("<> ",0)).toEqual( - { type : 'element', start : 1, attributes : { other : { type : 'string', value : 'true', start : 6, name : 'other', end : 13 }, stuff : { type : 'string', value : 'true', start : 13, name : 'stuff', end : 18 } }, orderedAttributes: [ { type : 'string', value : 'true', start : 6, name : 'other', end : 13 }, { type : 'string', value : 'true', start : 13, name : 'stuff', end : 18 } ], tag : 'some', end : 19 } + { type : "element", start : 1, attributes : { other : { type : "string", value : "true", start : 6, name : "other", end : 13 }, stuff : { type : "string", value : "true", start : 13, name : "stuff", end : 18 } }, orderedAttributes: [ { type : "string", value : "true", start : 6, name : "other", end : 13 }, { type : "string", value : "true", start : 13, name : "stuff", end : 18 } ], tag : "some", end : 19 } ); expect(parser.findNextTag("<> ",2)).toEqual( - { type : 'element', start : 21, attributes : { }, orderedAttributes: [ ], tag : 'mytag', end : 28 } + { type : "element", start : 21, attributes : { }, orderedAttributes: [ ], tag : "mytag", end : 28 } ); }); From 078cd5fba2ab35819f24d835463fc77c287205ca Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 8 Aug 2024 01:16:27 +0800 Subject: [PATCH 40/98] feat: add to styleblock --- .../parsers/wikiparser/rules/quoteblock.js | 25 ++++--- .../modules/parsers/wikiparser/rules/rules.js | 36 ++++++---- .../parsers/wikiparser/rules/styleblock.js | 69 ++++++++++++++----- .../tiddlers/tests/test-wikitext-serialize.js | 10 ++- 4 files changed, 97 insertions(+), 43 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/quoteblock.js b/core/modules/parsers/wikiparser/rules/quoteblock.js index 3f946cf13..329d881b0 100644 --- a/core/modules/parsers/wikiparser/rules/quoteblock.js +++ b/core/modules/parsers/wikiparser/rules/quoteblock.js @@ -73,17 +73,20 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'blockquote', attributes: { class: { type: 'string', value: 'tc-quote' } }, children: [{ type: 'text', text: 'Quote text' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Split the class attribute value into an array of classes, classes: ['tc-quote'] - var classes = tree.attributes.class.value.split(" "); - // Start the serialized string with the opening delimiter and classes, serialized: '<< 0) { this.parser.amendRules(tokens[0],tokens.slice(1)); } - // No parse tree nodes to return - return []; + // No widget to render, return void node. + return [{ + type: "void", + attributes: { + action: {type: "string", value: tokens[0]}, + rules: {type: "string", value: tokens.slice(1).join(" ")} + }, + children: [] + }]; }; -exports.serialize = function(tree, serialize) { - // tree: { type: 'pragma', name: 'rules', args: ['except', 'ruleone', 'ruletwo', 'rulethree'] } - // serialize: function that accepts array of nodes or a node and returns a string - // Start the serialized string with the pragma name - var serialized = "\\rules"; - // Iterate over the arguments and append them to the serialized string - for(var i = 0; i < tree.args.length; i++) { - serialized += " " + tree.args[i]; +exports.serialize = function (tree, serialize) { + // tree: { type: "void", attributes: { action: { type: "string", value: "except" }, rules: { type: "string", value: "ruleone ruletwo rulethree" } }, children: [{ type: "void", attributes: { action: { type: "string", value: "only" }, rules: { type: "string", value: "ruleone ruletwo rulethree" } }, children: [] }] } + var result = []; + if(tree.attributes.action && tree.attributes.rules) { + // tree.attributes.action.value: "except" + // tree.attributes.rules.value: "ruleone ruletwo rulethree" + result.push("\\rules " + tree.attributes.action.value + " " + tree.attributes.rules.value); + tree.children.forEach(function (child) { + if(child.type === "void" && child.attributes.action && child.attributes.rules) { + // child.attributes.action.value: "only" + // child.attributes.rules.value: "ruleone ruletwo rulethree" + result.push("\\rules " + child.attributes.action.value + " " + child.attributes.rules.value); + } + }); } - // Return the complete serialized string - return serialized; + return result.join("\n"); }; })(); diff --git a/core/modules/parsers/wikiparser/rules/styleblock.js b/core/modules/parsers/wikiparser/rules/styleblock.js index 6ea89b5df..e054b0916 100644 --- a/core/modules/parsers/wikiparser/rules/styleblock.js +++ b/core/modules/parsers/wikiparser/rules/styleblock.js @@ -67,29 +67,62 @@ exports.parse = function() { $tw.utils.addAttributeToParseTreeNode(tree[t],"style",styles.join("")); } } - return tree; + return [{ + type: "void", + children: tree + }] }; exports.serialize = function(tree, serialize) { - // tree: [{ type: 'element', tag: 'p', attributes: { class: { type: 'string', value: 'myClass' }, style: { type: 'string', value: 'background-color:red;' } }, children: [{ type: 'text', text: 'This paragraph will have the CSS class `myClass`.' }] }] - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter - var serialized = "@@"; - // Check for styles and append them to the serialized string - if(tree[0].attributes.style) { - serialized += tree[0].attributes.style.value; - } - // Check for classes and append them to the serialized string - if(tree[0].attributes.class) { - var classes = tree[0].attributes.class.value.split(" "); - for(var i = 0; i < classes.length; i++) { - serialized += "." + classes[i]; + // serialize: function that serializes an array of nodes or a single node to a string + var result = []; + var classes = []; + var styles = []; + + // Collect all unique classes and styles from child nodes + for(var i = 0; i < tree.children.length; i++) { + var node = tree.children[i]; + if(node.attributes && node.attributes.class) { + var nodeClasses = node.attributes.class.value.split(" "); + for(var j = 0; j < nodeClasses.length; j++) { + if(classes.indexOf(nodeClasses[j]) === -1) { + classes.push(nodeClasses[j]); + } + } + } + if(node.attributes && node.attributes.style) { + var nodeStyles = node.attributes.style.value.split(";"); + for(var k = 0; k < nodeStyles.length; k++) { + var style = nodeStyles[k].trim(); + if(style && styles.indexOf(style) === -1) { + styles.push(style); + } + } } } - // Append the serialized children and the closing delimiter - serialized += "\n" + serialize(tree) + "\n@@"; - // Return the complete serialized string - return serialized; + + // Add the style block header if there are any classes or styles + if(classes.length > 0 || styles.length > 0) { + if(styles.length > 0) { + result.push("@@"); + result.push(styles.join(";")); + result.push(";\n"); + } + if(classes.length > 0) { + result.push("@@."); + result.push(classes.join(".")); + result.push("\n"); + } + } + + // Serialize each child node and add to result + for(var i = 0; i < tree.children.length; i++) { + result.push(serialize(tree.children[i])); + } + + // Add the closing @@ for the style block + result.push("@@"); + return result.join(""); }; })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 6b7ea72e0..7978b354f 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -276,7 +276,6 @@ describe("WikiAST serialization unit tests", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ParserModeTest").tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText("ParserModeTest").trimEnd()); }); - return; wiki.addTiddler({ title: "PrettyExtLinkTest", @@ -316,12 +315,19 @@ describe("WikiAST serialization unit tests", function () { wiki.addTiddler({ title: "StyleBlockTest", - text: "@@.myClass\n@@background-color:red;\nThis paragraph will have the CSS class `myClass`.\n\n* The `
      ` around this list will also have the class `myClass`\n* List item 2\n@@", + text: "@@.myClass\n@@background-color:red;\nThis paragraph will have the CSS class `myClass`.\n\n* The `
        ` around this list will also have the class `myClass`\n* List item 2\n@@\n\n@@font-size:1.5em;\n@@.coloured-text\n@@.coloured-bg\n* Block content\n* With custom style and classes\n@@", + }); + wiki.addTiddler({ + title: "StyleBlockTest2", + text: "@@.myFirstClass.mySecondClass\n@@width:100px;.myThirdClass\nThis is a paragraph\n@@\n\n@@background-color:lightcyan;\n* Item one\n* Item two\n@@", }); it("should serialize style blocks correctly", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleBlockTest").tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText("StyleBlockTest").trimEnd()); + var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleBlockTest2").tree).trimEnd(); + expect(serialized).toBe(wiki.getTiddlerText("StyleBlockTest2").trimEnd()); }); + return; wiki.addTiddler({ title: "StyleInlineTest", From 7c73f1f9228dd95247474731b24a9967bf7296c4 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Thu, 8 Aug 2024 23:52:48 +0800 Subject: [PATCH 41/98] feat: styleblock --- .../parsers/wikiparser/rules/styleblock.js | 54 +++++++++---------- .../tiddlers/tests/test-wikitext-serialize.js | 4 +- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/styleblock.js b/core/modules/parsers/wikiparser/rules/styleblock.js index e054b0916..089c5f395 100644 --- a/core/modules/parsers/wikiparser/rules/styleblock.js +++ b/core/modules/parsers/wikiparser/rules/styleblock.js @@ -75,54 +75,52 @@ exports.parse = function() { exports.serialize = function(tree, serialize) { // serialize: function that serializes an array of nodes or a single node to a string - var result = []; + var lines = []; var classes = []; var styles = []; - // Collect all unique classes and styles from child nodes - for(var i = 0; i < tree.children.length; i++) { - var node = tree.children[i]; - if(node.attributes && node.attributes.class) { - var nodeClasses = node.attributes.class.value.split(" "); - for(var j = 0; j < nodeClasses.length; j++) { - if(classes.indexOf(nodeClasses[j]) === -1) { - classes.push(nodeClasses[j]); - } + // Same classes are set to each children. So only collect from first child. + var node = tree.children[0]; + if(node && node.attributes && node.attributes.class) { + var nodeClasses = node.attributes.class.value.split(" "); + for(var j = 0; j < nodeClasses.length; j++) { + if(classes.indexOf(nodeClasses[j]) === -1) { + classes.push(nodeClasses[j]); } } - if(node.attributes && node.attributes.style) { - var nodeStyles = node.attributes.style.value.split(";"); - for(var k = 0; k < nodeStyles.length; k++) { - var style = nodeStyles[k].trim(); - if(style && styles.indexOf(style) === -1) { - styles.push(style); - } + } + if(node && node.attributes && node.attributes.style) { + var nodeStyles = node.attributes.style.value.split(";"); + for(var k = 0; k < nodeStyles.length; k++) { + var style = nodeStyles[k].trim(); + if(style && styles.indexOf(style) === -1) { + styles.push(style); } } } - // Add the style block header if there are any classes or styles + // Add the style block header, sort styles first, and classes later. Original order is not preserved intentionally for simplicity. if(classes.length > 0 || styles.length > 0) { if(styles.length > 0) { - result.push("@@"); - result.push(styles.join(";")); - result.push(";\n"); + lines.push("@@"); + lines.push(styles.join(";")); + lines.push(";\n"); } if(classes.length > 0) { - result.push("@@."); - result.push(classes.join(".")); - result.push("\n"); + lines.push("@@."); + lines.push(classes.join(".")); + lines.push("\n"); } } // Serialize each child node and add to result for(var i = 0; i < tree.children.length; i++) { - result.push(serialize(tree.children[i])); + lines.push(serialize(tree.children[i])); } - + var result = lines.join("").trimEnd(); // Add the closing @@ for the style block - result.push("@@"); - return result.join(""); + result += "\n@@\n\n" + return result; }; })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 7978b354f..7ee728cf6 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -315,11 +315,11 @@ describe("WikiAST serialization unit tests", function () { wiki.addTiddler({ title: "StyleBlockTest", - text: "@@.myClass\n@@background-color:red;\nThis paragraph will have the CSS class `myClass`.\n\n* The `
          ` around this list will also have the class `myClass`\n* List item 2\n@@\n\n@@font-size:1.5em;\n@@.coloured-text\n@@.coloured-bg\n* Block content\n* With custom style and classes\n@@", + text: "@@background-color:red;\n@@.myClass\nThis paragraph will have the CSS class `myClass`.\n\n* The `
            ` around this list will also have the class `myClass`\n* List item 2\n@@\n\n@@font-size:1.5em;\n@@.coloured-text.coloured-bg\n* Block content\n* With custom style and classes\n@@", }); wiki.addTiddler({ title: "StyleBlockTest2", - text: "@@.myFirstClass.mySecondClass\n@@width:100px;.myThirdClass\nThis is a paragraph\n@@\n\n@@background-color:lightcyan;\n* Item one\n* Item two\n@@", + text: "@@width:100px;\n@@.myFirstClass.mySecondClass.myThirdClass\nThis is a paragraph\n@@\n\n@@background-color:lightcyan;\n* Item one\n* Item two\n@@", }); it("should serialize style blocks correctly", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleBlockTest").tree).trimEnd(); From 43f3f8b5ed5e39d116df225116e38da64a030384 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Fri, 9 Aug 2024 19:50:07 +0800 Subject: [PATCH 42/98] feat: styleinline --- .../parsers/wikiparser/rules/styleinline.js | 31 ++++++++----------- .../tiddlers/tests/test-wikitext-serialize.js | 4 +-- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/styleinline.js b/core/modules/parsers/wikiparser/rules/styleinline.js index 281c2bc8d..873226f03 100644 --- a/core/modules/parsers/wikiparser/rules/styleinline.js +++ b/core/modules/parsers/wikiparser/rules/styleinline.js @@ -25,7 +25,7 @@ exports.types = {inline: true}; exports.init = function(parser) { this.parser = parser; // Regexp to match - this.matchRegExp = /@@((?:[^\.\r\n\s:]+:[^\r\n;]+;)+)?(\.(?:[^\r\n\s]+)\s+)?/mg; + this.matchRegExp = /@@((?:[^\.\r\n\s:]+:[^\r\n;]+;)+)?\s*(\.(?:[^\r\n\s]+)\s+)?/mg; }; exports.parse = function() { @@ -56,25 +56,20 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'span', attributes: { class: { type: 'string', value: 'myClass' }, style: { type: 'string', value: 'background-color:red;' } }, children: [{ type: 'text', text: 'This is some text with a class and a background colour' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter - var serialized = "@@"; - // Check for styles and append them to the serialized string - if(tree.attributes.style) { - serialized += tree.attributes.style.value; + // tree: {type: "element", tag: "span", children: [...], attributes: {class: {name: "class", type: "string", value: " myClass "}, style: {name: "style", type: "string", value: "background-color:red;"}}, orderedAttributes: [...], start: 0, end: 43, rule: "styleinline"} + // serialize: function that accepts an array of nodes or a single node and returns a string + var result = "@@"; + // Add styles if present + if(tree.attributes && tree.attributes.style) { + result += tree.attributes.style.value.trim(); } - // Check for classes and append them to the serialized string - if(tree.attributes.class) { - var classes = tree.attributes.class.value.split(" "); - for(var i = 0; i < classes.length; i++) { - serialized += "." + classes[i] + " "; - } + // Add classes if present + if(tree.attributes && tree.attributes.class) { + result += "." + tree.attributes.class.value.trim().split(" ").join("."); } - // Append the serialized children and the closing delimiter - serialized += serialize(tree.children) + "@@"; - // Return the complete serialized string - return serialized; + // Serialize children and append to result + result += " " + serialize(tree.children) + "@@"; + return result; }; })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index 7ee728cf6..bfc4523ad 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -327,11 +327,10 @@ describe("WikiAST serialization unit tests", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleBlockTest2").tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText("StyleBlockTest2").trimEnd()); }); - return; wiki.addTiddler({ title: "StyleInlineTest", - text: "@@.myClass This is some text with a class@@\n@@background-color:red;This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@", + text: "@@.myClass This is some text with a class@@\n@@background-color:red; This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@", }); it("should serialize style inlines correctly", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleInlineTest").tree).trimEnd(); @@ -355,6 +354,7 @@ describe("WikiAST serialization unit tests", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TableTest").tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText("TableTest").trimEnd()); }); + return; wiki.addTiddler({ title: "TranscludeBlockTest", From 856cb42039382e1432239719fff2352e3156d300 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Fri, 9 Aug 2024 22:33:05 +0800 Subject: [PATCH 43/98] Update table.js --- core/modules/parsers/wikiparser/rules/table.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/table.js b/core/modules/parsers/wikiparser/rules/table.js index ed4c7c889..9b730922d 100644 --- a/core/modules/parsers/wikiparser/rules/table.js +++ b/core/modules/parsers/wikiparser/rules/table.js @@ -186,9 +186,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'table', children: [{ type: 'element', tag: 'thead', children: [{ type: 'element', tag: 'tr', children: [{ type: 'element', tag: 'th', children: [{ type: 'text', text: 'Alpha' }] }, { type: 'element', tag: 'th', children: [{ type: 'text', text: 'Beta' }] }, { type: 'element', tag: 'th', children: [{ type: 'text', text: 'Gamma' }] }, { type: 'element', tag: 'th', children: [{ type: 'text', text: 'Delta' }] }] }] }, { type: 'element', tag: 'tbody', children: [{ type: 'element', tag: 'tr', children: [{ type: 'element', tag: 'th', children: [{ type: 'text', text: 'One' }] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }] }, { type: 'element', tag: 'tr', children: [{ type: 'element', tag: 'th', children: [{ type: 'text', text: 'Two' }] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }] }, { type: 'element', tag: 'tr', children: [{ type: 'element', tag: 'th', children: [{ type: 'text', text: 'Three' }] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }, { type: 'element', tag: 'td', children: [] }] }] }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string var serialized = ""; // Iterate over the table rows for(var i = 0; i < tree.children.length; i++) { @@ -201,10 +198,14 @@ exports.serialize = function(tree, serialize) { // Iterate over the cells in the row for(var k = 0; k < row.children.length; k++) { var cell = row.children[k]; + // if is th, append additional `!` + if(cell.tag === "th") { + serialized += "!"; + } // Serialize the cell content serialized += serialize(cell.children); - // End the cell - serialized += "|"; + // End the cell with a tailing space + serialized += " |"; } // End the row serialized += "\n"; From 3cf93d08e514959401992a696bc3f7572325362a Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Fri, 9 Aug 2024 22:45:14 +0800 Subject: [PATCH 44/98] lint: useless comments --- core/modules/parsers/wikiparser/rules/emphasis/bold.js | 3 --- core/modules/parsers/wikiparser/rules/emphasis/italic.js | 3 --- .../parsers/wikiparser/rules/emphasis/strikethrough.js | 3 --- core/modules/parsers/wikiparser/rules/emphasis/subscript.js | 3 --- core/modules/parsers/wikiparser/rules/emphasis/superscript.js | 3 --- core/modules/parsers/wikiparser/rules/emphasis/underscore.js | 3 --- core/modules/parsers/wikiparser/rules/quoteblock.js | 1 - core/modules/parsers/wikiparser/rules/rules.js | 1 - core/modules/parsers/wikiparser/rules/styleblock.js | 1 - core/modules/parsers/wikiparser/rules/styleinline.js | 2 -- core/modules/parsers/wikiparser/rules/syslink.js | 4 +--- core/modules/parsers/wikiparser/rules/transcludeblock.js | 3 --- core/modules/parsers/wikiparser/rules/transcludeinline.js | 3 --- core/modules/parsers/wikiparser/rules/typedblock.js | 3 --- core/modules/parsers/wikiparser/rules/wikilink.js | 4 +--- core/modules/parsers/wikiparser/rules/wikilinkprefix.js | 3 --- 16 files changed, 2 insertions(+), 41 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/emphasis/bold.js b/core/modules/parsers/wikiparser/rules/emphasis/bold.js index 946fff7cf..6294094ec 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/bold.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/bold.js @@ -48,9 +48,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'strong', children: [{ type: 'text', text: 'bold' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter var serialized = "''"; // Serialize the children of the bold element serialized += serialize(tree.children); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/italic.js b/core/modules/parsers/wikiparser/rules/emphasis/italic.js index 798429ed2..f1070ddfb 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/italic.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/italic.js @@ -48,9 +48,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'em', children: [{ type: 'text', text: 'italic' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter var serialized = "//"; // Serialize the children of the italic element serialized += serialize(tree.children); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js index 572217052..ccd511c42 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js @@ -48,9 +48,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'strike', children: [{ type: 'text', text: 'strikethrough' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter var serialized = "~~"; // Serialize the children of the strikethrough element serialized += serialize(tree.children); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js index f4d9ecc5d..d38d51222 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js @@ -48,9 +48,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'sub', children: [{ type: 'text', text: 'subscript' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter var serialized = ",,"; // Serialize the children of the subscript element serialized += serialize(tree.children); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js index e33e75ac4..82a4b78d6 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js @@ -48,9 +48,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'sup', children: [{ type: 'text', text: 'superscript' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter var serialized = "^^"; // Serialize the children of the superscript element serialized += serialize(tree.children); diff --git a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js index 640b36e02..b07f32fc2 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js @@ -48,9 +48,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'element', tag: 'u', children: [{ type: 'text', text: 'underscore' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter var serialized = "__"; // Serialize the children of the underscore element serialized += serialize(tree.children); diff --git a/core/modules/parsers/wikiparser/rules/quoteblock.js b/core/modules/parsers/wikiparser/rules/quoteblock.js index 329d881b0..be7052795 100644 --- a/core/modules/parsers/wikiparser/rules/quoteblock.js +++ b/core/modules/parsers/wikiparser/rules/quoteblock.js @@ -74,7 +74,6 @@ exports.parse = function() { }; exports.serialize = function (tree, serialize) { - // tree: { type: "element", tag: "blockquote", attributes: { class: { type: "string", value: "tc-quote" } }, children: [{ type: "element", tag: "cite", children: [{ type: "text", text: "tc-quote" }] }, { type: "element", tag: "p", children: [{ type: "text", text: "Quote text\n" }] }] } var result = []; if(tree.type === "element" && tree.tag === "blockquote") { // tree.attributes.class.value: "tc-quote" diff --git a/core/modules/parsers/wikiparser/rules/rules.js b/core/modules/parsers/wikiparser/rules/rules.js index 28af31abc..a5958d67c 100644 --- a/core/modules/parsers/wikiparser/rules/rules.js +++ b/core/modules/parsers/wikiparser/rules/rules.js @@ -69,7 +69,6 @@ exports.parse = function() { }; exports.serialize = function (tree, serialize) { - // tree: { type: "void", attributes: { action: { type: "string", value: "except" }, rules: { type: "string", value: "ruleone ruletwo rulethree" } }, children: [{ type: "void", attributes: { action: { type: "string", value: "only" }, rules: { type: "string", value: "ruleone ruletwo rulethree" } }, children: [] }] } var result = []; if(tree.attributes.action && tree.attributes.rules) { // tree.attributes.action.value: "except" diff --git a/core/modules/parsers/wikiparser/rules/styleblock.js b/core/modules/parsers/wikiparser/rules/styleblock.js index 089c5f395..a5e19cfcc 100644 --- a/core/modules/parsers/wikiparser/rules/styleblock.js +++ b/core/modules/parsers/wikiparser/rules/styleblock.js @@ -74,7 +74,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // serialize: function that serializes an array of nodes or a single node to a string var lines = []; var classes = []; var styles = []; diff --git a/core/modules/parsers/wikiparser/rules/styleinline.js b/core/modules/parsers/wikiparser/rules/styleinline.js index 873226f03..01c047856 100644 --- a/core/modules/parsers/wikiparser/rules/styleinline.js +++ b/core/modules/parsers/wikiparser/rules/styleinline.js @@ -56,8 +56,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: {type: "element", tag: "span", children: [...], attributes: {class: {name: "class", type: "string", value: " myClass "}, style: {name: "style", type: "string", value: "background-color:red;"}}, orderedAttributes: [...], start: 0, end: 43, rule: "styleinline"} - // serialize: function that accepts an array of nodes or a single node and returns a string var result = "@@"; // Add styles if present if(tree.attributes && tree.attributes.style) { diff --git a/core/modules/parsers/wikiparser/rules/syslink.js b/core/modules/parsers/wikiparser/rules/syslink.js index 8eed845ae..0839e9087 100644 --- a/core/modules/parsers/wikiparser/rules/syslink.js +++ b/core/modules/parsers/wikiparser/rules/syslink.js @@ -51,11 +51,9 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'link', attributes: { to: { type: 'string', value: '$:TiddlerTitle' } }, children: [{ type: 'text', text: '$:TiddlerTitle' }] } - // serialize: function that accepts array of nodes or a node and returns a string // Check if the link is suppressed var isSuppressed = tree.children[0].text.substr(0,1) === "~"; - // Initialize the serialized string + var serialized = isSuppressed ? "~" : ""; // Append the link value serialized += tree.attributes.to.value; diff --git a/core/modules/parsers/wikiparser/rules/transcludeblock.js b/core/modules/parsers/wikiparser/rules/transcludeblock.js index a4b1b8a55..9add8f6ad 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeblock.js +++ b/core/modules/parsers/wikiparser/rules/transcludeblock.js @@ -87,9 +87,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'transclude', attributes: { $tiddler: { name: '$tiddler', type: 'string', value: 'MyTiddler' }, $field: { name: '$field', type: 'string', value: 'text' } }, isBlock: true } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string var serialized = "{{"; // Check for tiddler attribute if(tree.attributes.$tiddler) { diff --git a/core/modules/parsers/wikiparser/rules/transcludeinline.js b/core/modules/parsers/wikiparser/rules/transcludeinline.js index 78839f925..346a98671 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeinline.js +++ b/core/modules/parsers/wikiparser/rules/transcludeinline.js @@ -85,9 +85,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'transclude', attributes: { $tiddler: { name: '$tiddler', type: 'string', value: 'MyTiddler' }, $field: { name: '$field', type: 'string', value: 'text' } } } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string var serialized = "{{"; // Check for tiddler attribute if(tree.attributes.$tiddler) { diff --git a/core/modules/parsers/wikiparser/rules/typedblock.js b/core/modules/parsers/wikiparser/rules/typedblock.js index daaefb7b7..e428e85d8 100644 --- a/core/modules/parsers/wikiparser/rules/typedblock.js +++ b/core/modules/parsers/wikiparser/rules/typedblock.js @@ -84,9 +84,6 @@ exports.parse = function() { }; exports.serialize = function (tree, serialize) { - // tree: { type: 'element', tag: 'pre', children: [{ type: 'text', text: 'This will be rendered as JavaScript' }] } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the opening delimiter and type var serialized = '$$$'; // Extract the type from the tree node (assuming it's stored in a specific attribute) if(tree.attributes && tree.attributes.type) { serialized += tree.attributes.type.value; diff --git a/core/modules/parsers/wikiparser/rules/wikilink.js b/core/modules/parsers/wikiparser/rules/wikilink.js index 5762aeee4..dc146a047 100644 --- a/core/modules/parsers/wikiparser/rules/wikilink.js +++ b/core/modules/parsers/wikiparser/rules/wikilink.js @@ -66,11 +66,9 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'link', attributes: { to: { type: 'string', value: 'AWikiLink' } }, children: [{ type: 'text', text: 'AWikiLink' }] } - // serialize: function that accepts array of nodes or a node and returns a string // Check if the link is suppressed var isSuppressed = tree.children[0].text.substr(0,1) === $tw.config.textPrimitives.unWikiLink; - // Initialize the serialized string + var serialized = isSuppressed ? $tw.config.textPrimitives.unWikiLink : ""; // Append the link text serialized += tree.attributes.to.value; diff --git a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js index be902edc8..36aebf063 100644 --- a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js +++ b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js @@ -38,9 +38,6 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - // tree: { type: 'text', text: 'SuppressedLink' } - // serialize: function that accepts array of nodes or a node and returns a string - // Initialize the serialized string with the unwikilink character var serialized = $tw.config.textPrimitives.unWikiLink; // Append the text serialized += tree.text; From 589241a406b7cfae935e6b61e4fb17d7bf8219ba Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 10 Aug 2024 01:31:43 +0800 Subject: [PATCH 45/98] feat: transcludeblock --- .../wikiparser/rules/transcludeblock.js | 64 ++++++++++++------- .../tiddlers/tests/test-wikitext-serialize.js | 6 +- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/transcludeblock.js b/core/modules/parsers/wikiparser/rules/transcludeblock.js index 9add8f6ad..88519e84d 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeblock.js +++ b/core/modules/parsers/wikiparser/rules/transcludeblock.js @@ -87,37 +87,53 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - var serialized = "{{"; - // Check for tiddler attribute - if(tree.attributes.$tiddler) { - serialized += tree.attributes.$tiddler.value; - // Check for field attribute - if(tree.attributes.$field) { - serialized += "##" + tree.attributes.$field.value; + var result = "{{"; + function handleTransclude(transcludeNode) { + // Handle field + if(transcludeNode.attributes.$field) { + result += "!!" + transcludeNode.attributes.$field.value; } // Check for index attribute - if(tree.attributes.$index) { - serialized += "!!" + tree.attributes.$index.value; + if(transcludeNode.attributes.$index) { + result += "##" + transcludeNode.attributes.$index.value; + } + // Handle template + var tiddlerTitle = tree.attributes.tiddler ? tree.attributes.tiddler.value : undefined; + if(transcludeNode.attributes.$tiddler && transcludeNode.attributes.$tiddler.value !== tiddlerTitle) { + result += "||" + transcludeNode.attributes.$tiddler.value; + } + // Check for parameters + var params = []; + var excludedAttributes = ["tiddler", "$tiddler", "$field", "$index", "$template"]; + for(var key in transcludeNode.attributes) { + if(excludedAttributes.indexOf(key) === -1) { + params.push(transcludeNode.attributes[key].value); + } + } + if(params.length > 0) { + result += "|" + params.join("|"); } } - // Check for template attribute - if(tree.attributes.$template) { - serialized += "||" + tree.attributes.$template.value; - } - // Check for parameters - var params = []; - for(var key in tree.attributes) { - if(key !== "$tiddler" && key !== "$field" && key !== "$index" && key !== "$template") { - params.push(tree.attributes[key].value); + function handleTiddler(tiddlerNode) { + // Check for tiddler attribute + if(tree.attributes.tiddler.value) { + result += tree.attributes.tiddler.value; } + $tw.utils.each(tree.children, function(child) { + if(child.type === "transclude") { + handleTransclude(child); + } + }); } - if(params.length > 0) { - serialized += "|" + params.join("|"); + if(tree.type === "tiddler") { + handleTiddler(tree); + } else if(tree.type === "transclude") { + handleTransclude(tree); } - // Close the serialized string - serialized += "}}"; - // Return the complete serialized string - return serialized; + // Close the result string + result += "}}\n\n"; + // Return the complete result string + return result; }; })(); diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js index bfc4523ad..b2a35e8bc 100644 --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js @@ -354,11 +354,10 @@ describe("WikiAST serialization unit tests", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TableTest").tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText("TableTest").trimEnd()); }); - return; wiki.addTiddler({ title: "TranscludeBlockTest", - text: "{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}", + text: "{{MyTiddler}}\n\n{{MyTiddler||TemplateTitle}}\n\n{{||TemplateTitle}}\n\n{{MyTiddler|Parameter}}\n\n{{MyTiddler||TemplateTitle|Parameter|SecondParameter}}\n\n{{MyTiddler!!field}}\n\n{{!!field}}\n\n{{MyTiddler##index}}\n\n{{##index}}", }); it("should serialize block-level transclusions correctly", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TranscludeBlockTest").tree).trimEnd(); @@ -367,12 +366,13 @@ describe("WikiAST serialization unit tests", function () { wiki.addTiddler({ title: "TranscludeInlineTest", - text: "{{MyTiddler}}\n{{MyTiddler||TemplateTitle}}", + text: "{{MyTiddler}} {{MyTiddler||TemplateTitle}}", }); it("should serialize inline-level transclusions correctly", function () { var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TranscludeInlineTest").tree).trimEnd(); expect(serialized).toBe(wiki.getTiddlerText("TranscludeInlineTest").trimEnd()); }); + return; wiki.addTiddler({ title: "TypedBlockTest", From 0adf638c1a24d60868b5179270cfaddedf61f8ea Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 10 Aug 2024 01:31:55 +0800 Subject: [PATCH 46/98] refactor: reuse block on inline when possible --- .../rules/filteredtranscludeblock.js | 3 +- .../rules/filteredtranscludeinline.js | 18 +++------- .../wikiparser/rules/macrocallinline.js | 20 +++-------- .../wikiparser/rules/transcludeinline.js | 34 ++----------------- 4 files changed, 12 insertions(+), 63 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js index 0e43ec748..994596855 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js @@ -71,8 +71,7 @@ exports.parse = function() { return [node]; }; -exports.serialize = function(tree) { - // Filter expression +exports.serialize = function(tree, serialize) { var serialized = "{{{" + tree.attributes.filter.value; // Tooltip text if(tree.attributes.tooltip) serialized += "|" + tree.attributes.tooltip.value; diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js index 726ceac9e..8ab8887d7 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js @@ -70,20 +70,10 @@ exports.parse = function() { return [node]; }; -exports.serialize = function(tree) { - // Filter expression - var serialized = "{{{" + tree.attributes.filter.value; - // Tooltip text - if(tree.attributes.tooltip) serialized += "|" + tree.attributes.tooltip.value; - // Template title - if(tree.attributes.template) serialized += "||" + tree.attributes.template.value; - serialized += "}}"; - // Inline styles - if(tree.attributes.style) serialized += tree.attributes.style.value; - serialized += "}" - // CSS classes - if(tree.attributes.itemClass) serialized += "." + tree.attributes.itemClass.value.split(" ").join("."); - return serialized; +exports.serialize = function(tree, serialize) { + var filteredtranscludeblock = require("$:/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js"); + var result = filteredtranscludeblock.serialize(tree, serialize); + return result.trimEnd(); }; })(); diff --git a/core/modules/parsers/wikiparser/rules/macrocallinline.js b/core/modules/parsers/wikiparser/rules/macrocallinline.js index bc0ac7f22..132eabef9 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallinline.js +++ b/core/modules/parsers/wikiparser/rules/macrocallinline.js @@ -49,22 +49,10 @@ exports.parse = function() { /* Same as macrocallblock but without \n\n */ -exports.serialize = function (node) { - // Start with macro opener - var result = "<<"; - if(node.attributes && node.attributes["$variable"]) { - result += node.attributes["$variable"].value; // Add macro name - } - // Append ordered arguments if any - if(node.orderedAttributes) { - node.orderedAttributes.forEach(function (attr) { - if(attr.name !== "$variable") { - result += " " + '"' + attr.value + '"'; // Add each additional value - } - }); - } - result += ">>"; - return result; +exports.serialize = function (tree, serialize) { + var macrocallblock = require("$:/core/modules/parsers/wikiparser/rules/macrocallblock.js"); + var result = macrocallblock.serialize(tree, serialize); + return result.trimEnd(); }; })(); diff --git a/core/modules/parsers/wikiparser/rules/transcludeinline.js b/core/modules/parsers/wikiparser/rules/transcludeinline.js index 346a98671..af525b78a 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeinline.js +++ b/core/modules/parsers/wikiparser/rules/transcludeinline.js @@ -85,37 +85,9 @@ exports.parse = function() { }; exports.serialize = function(tree, serialize) { - var serialized = "{{"; - // Check for tiddler attribute - if(tree.attributes.$tiddler) { - serialized += tree.attributes.$tiddler.value; - // Check for field attribute - if(tree.attributes.$field) { - serialized += "##" + tree.attributes.$field.value; - } - // Check for index attribute - if(tree.attributes.$index) { - serialized += "!!" + tree.attributes.$index.value; - } - } - // Check for template attribute - if(tree.attributes.$template) { - serialized += "||" + tree.attributes.$template.value; - } - // Check for parameters - var params = []; - for(var key in tree.attributes) { - if(key !== "$tiddler" && key !== "$field" && key !== "$index" && key !== "$template") { - params.push(tree.attributes[key].value); - } - } - if(params.length > 0) { - serialized += "|" + params.join("|"); - } - // Close the serialized string - serialized += "}}"; - // Return the complete serialized string - return serialized; + var transcludeblock = require("$:/core/modules/parsers/wikiparser/rules/transcludeblock.js"); + var result = transcludeblock.serialize(tree, serialize); + return result.trimEnd(); }; })(); From c4f6136fa7e7a829f07a1daedf74a7b79484a546 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 10 Aug 2024 02:33:50 +0800 Subject: [PATCH 47/98] feat: use void node to carry important info for typedblock --- .../parsers/wikiparser/rules/typedblock.js | 44 ++++++++++++------- .../tiddlers/tests/test-wikitext-serialize.js | 17 ++++--- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/typedblock.js b/core/modules/parsers/wikiparser/rules/typedblock.js index e428e85d8..68d534830 100644 --- a/core/modules/parsers/wikiparser/rules/typedblock.js +++ b/core/modules/parsers/wikiparser/rules/typedblock.js @@ -63,36 +63,46 @@ exports.parse = function() { var parser = this.parser.wiki.parseText(parseType,text,{defaultType: "text/plain"}); // If there's no render type, just return the parse tree if(!renderType) { - return parser.tree; + return [{ + type: "void", + children: $tw.utils.isArray(parser.tree) ? parser.tree : [parser.tree], + parseType: parseType, + renderType: renderType, + text: text, + start: start, + end: this.parser.pos + }]; } else { // Otherwise, render to the rendertype and return in a
             tag
             		var widgetNode = this.parser.wiki.makeWidget(parser),
             			container = $tw.fakeDocument.createElement("div");
             		widgetNode.render(container,null);
            -		text = renderType === "text/html" ? container.innerHTML : container.textContent;
            +		var renderResult = renderType === "text/html" ? container.innerHTML : container.textContent;
             		return [{
            -			type: "element",
            -			tag: "pre",
            +			type: "void",
             			children: [{
            -				type: "text",
            -				text: text,
            -				start: start,
            -				end: this.parser.pos
            -			}]
            +				type: "element",
            +				tag: "pre",
            +				children: [{
            +					type: "text",
            +					text: renderResult,
            +				}]
            +			}],
            +			parseType: parseType,
            +			renderType: renderType,
            +			text: text,
            +			start: start,
            +			end: this.parser.pos
             		}];
             	}
             };
             
             exports.serialize = function (tree, serialize) {
            -	var serialized = '$$$'; // Extract the type from the tree node (assuming it's stored in a specific attribute)
            -	if(tree.attributes && tree.attributes.type) {
            -		serialized += tree.attributes.type.value;
            +	if(tree.type === "void") {
            +		// Directly process the tree's text content
            +		return "$$$" + tree.parseType + (tree.renderType ? " > " + tree.renderType : "") + "\n" + tree.text + "\n$$$\n\n";
             	}
            -	serialized += '\n'; // Serialize the children of the block
            -	serialized += serialize(tree.children); 	// Close the serialized string
            -	serialized += "\n$$$";
            -	// Return the complete serialized string
            -	return serialized;
            +	return "";
             };
             
             })();
            diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            index b2a35e8bc..6e881ac12 100644
            --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js
            +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            @@ -372,16 +372,23 @@ describe("WikiAST serialization unit tests", function () {
                 var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TranscludeInlineTest").tree).trimEnd();
                 expect(serialized).toBe(wiki.getTiddlerText("TranscludeInlineTest").trimEnd());
               });
            -  return;
             
               wiki.addTiddler({
            -    title: "TypedBlockTest",
            -    text: '$$$.js\nThis will be rendered as JavaScript\n$$$\n$$$.svg\n\n  \n\n$$$\n$$$text/vnd.tiddlywiki>text/html\nThis will be rendered as an //HTML representation// of WikiText\n$$$',
            +    title: "TypedBlockTest1",
            +    text: "$$$text/vnd.tiddlywiki > text/plain\nThis is ''some'' wikitext\n$$$\n\n$$$text/unknown\nSome plain text, which will not be //formatted//.\n\n$$$text/vnd.tiddlywiki > text/html\nThis is ''some'' wikitext\n$$$\n\n",
               });
            +  wiki.addTiddler({
            +    title: "TypedBlockTest2",
            +    text: '$$$.js\nThis will be rendered as JavaScript\n$$$\n\n$$$.svg\n\n  \n\n$$$\n\n$$$image/svg+xml\n\n  \n\n$$$',
            +  });
            +  
               it("should serialize typed blocks correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TypedBlockTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("TypedBlockTest").trimEnd());
            +    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TypedBlockTest1").tree).trimEnd();
            +    expect(serialized).toBe(wiki.getTiddlerText("TypedBlockTest1").trimEnd());
            +    serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TypedBlockTest2").tree).trimEnd();
            +    expect(serialized).toBe(wiki.getTiddlerText("TypedBlockTest2").trimEnd());
               });
            +  return;
             
               wiki.addTiddler({
                 title: "WikiLinkTest",
            
            From 08e9312295d4d818d71e6c706cbc0e5677b1ff8b Mon Sep 17 00:00:00 2001
            From: lin onetwo 
            Date: Sat, 10 Aug 2024 02:35:07 +0800
            Subject: [PATCH 48/98] feat: run all tests
            
            ---
             core/modules/parsers/wikiparser/rules/wikilink.js       | 2 --
             core/modules/parsers/wikiparser/rules/wikilinkprefix.js | 2 --
             editions/test/tiddlers/tests/test-wikitext-serialize.js | 1 -
             3 files changed, 5 deletions(-)
            
            diff --git a/core/modules/parsers/wikiparser/rules/wikilink.js b/core/modules/parsers/wikiparser/rules/wikilink.js
            index dc146a047..6a59d395f 100644
            --- a/core/modules/parsers/wikiparser/rules/wikilink.js
            +++ b/core/modules/parsers/wikiparser/rules/wikilink.js
            @@ -70,9 +70,7 @@ exports.serialize = function(tree, serialize) {
             	var isSuppressed = tree.children[0].text.substr(0,1) === $tw.config.textPrimitives.unWikiLink;
             
             	var serialized = isSuppressed ? $tw.config.textPrimitives.unWikiLink : "";
            -	// Append the link text
             	serialized += tree.attributes.to.value;
            -	// Return the complete serialized string
             	return serialized;
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js
            index 36aebf063..1de26d25c 100644
            --- a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js
            +++ b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js
            @@ -39,9 +39,7 @@ exports.parse = function() {
             
             exports.serialize = function(tree, serialize) {
             	var serialized = $tw.config.textPrimitives.unWikiLink;
            -	// Append the text
             	serialized += tree.text;
            -	// Return the complete serialized string
             	return serialized;
             };
             
            diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            index 6e881ac12..2871343cc 100644
            --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js
            +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            @@ -388,7 +388,6 @@ describe("WikiAST serialization unit tests", function () {
                 serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TypedBlockTest2").tree).trimEnd();
                 expect(serialized).toBe(wiki.getTiddlerText("TypedBlockTest2").trimEnd());
               });
            -  return;
             
               wiki.addTiddler({
                 title: "WikiLinkTest",
            
            From 398d7f7fe706b3b2680afa9907a7ab6623f6a3f5 Mon Sep 17 00:00:00 2001
            From: lin onetwo 
            Date: Sat, 10 Aug 2024 12:43:26 +0800
            Subject: [PATCH 49/98] lint: useless ai generated comments
            
            ---
             core/modules/parsers/wikiparser/rules/dash.js          |  3 +--
             core/modules/parsers/wikiparser/rules/emphasis/bold.js |  8 +-------
             .../parsers/wikiparser/rules/emphasis/italic.js        |  8 +-------
             .../parsers/wikiparser/rules/emphasis/strikethrough.js |  8 +-------
             .../parsers/wikiparser/rules/emphasis/subscript.js     |  8 +-------
             .../parsers/wikiparser/rules/emphasis/superscript.js   |  8 +-------
             .../parsers/wikiparser/rules/emphasis/underscore.js    |  8 +-------
             core/modules/parsers/wikiparser/rules/entity.js        |  1 -
             .../modules/parsers/wikiparser/rules/hardlinebreaks.js |  5 ++---
             core/modules/parsers/wikiparser/rules/html.js          | 10 +++++-----
             core/modules/parsers/wikiparser/rules/import.js        |  3 +--
             .../modules/parsers/wikiparser/rules/macrocallblock.js |  6 +++---
             core/modules/parsers/wikiparser/rules/macrodef.js      |  4 ----
             core/modules/parsers/wikiparser/rules/parameters.js    |  2 --
             core/modules/parsers/wikiparser/rules/prettyextlink.js |  3 ---
             core/modules/parsers/wikiparser/rules/prettylink.js    |  3 ---
             core/modules/parsers/wikiparser/rules/syslink.js       |  4 +---
             .../parsers/wikiparser/rules/transcludeblock.js        |  2 --
             core/modules/parsers/wikiparser/rules/typedblock.js    |  2 +-
             core/modules/parsers/wikiparser/rules/wikilink.js      |  1 -
             20 files changed, 20 insertions(+), 77 deletions(-)
            
            diff --git a/core/modules/parsers/wikiparser/rules/dash.js b/core/modules/parsers/wikiparser/rules/dash.js
            index 60c82f0a7..4d06a54cd 100644
            --- a/core/modules/parsers/wikiparser/rules/dash.js
            +++ b/core/modules/parsers/wikiparser/rules/dash.js
            @@ -38,8 +38,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree) {
            -	var dash = tree.entity === "–" ? "--" : "---";
            -	return dash;
            +	return tree.entity === "–" ? "--" : "---";
             };
             
             })();
            diff --git a/core/modules/parsers/wikiparser/rules/emphasis/bold.js b/core/modules/parsers/wikiparser/rules/emphasis/bold.js
            index 6294094ec..bcd55f556 100644
            --- a/core/modules/parsers/wikiparser/rules/emphasis/bold.js
            +++ b/core/modules/parsers/wikiparser/rules/emphasis/bold.js
            @@ -48,13 +48,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	var serialized = "''";
            -	// Serialize the children of the bold element
            -	serialized += serialize(tree.children);
            -	// Close the serialized string with the closing delimiter
            -	serialized += "''";
            -	// Return the complete serialized string
            -	return serialized;
            +	return "''" + serialize(tree.children) + "''";
             };
             
             })();
            \ No newline at end of file
            diff --git a/core/modules/parsers/wikiparser/rules/emphasis/italic.js b/core/modules/parsers/wikiparser/rules/emphasis/italic.js
            index f1070ddfb..88be5617a 100644
            --- a/core/modules/parsers/wikiparser/rules/emphasis/italic.js
            +++ b/core/modules/parsers/wikiparser/rules/emphasis/italic.js
            @@ -48,13 +48,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	var serialized = "//";
            -	// Serialize the children of the italic element
            -	serialized += serialize(tree.children);
            -	// Close the serialized string with the closing delimiter
            -	serialized += "//";
            -	// Return the complete serialized string
            -	return serialized;
            +	return "//" + serialize(tree.children) + "//";
             };
             
             })();
            \ No newline at end of file
            diff --git a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js
            index ccd511c42..d42ac62b3 100644
            --- a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js
            +++ b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js
            @@ -48,13 +48,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	var serialized = "~~";
            -	// Serialize the children of the strikethrough element
            -	serialized += serialize(tree.children);
            -	// Close the serialized string with the closing delimiter
            -	serialized += "~~";
            -	// Return the complete serialized string
            -	return serialized;
            +	return "~~" + serialize(tree.children) + "~~";
             };
             
             })();
            diff --git a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js
            index d38d51222..b49598934 100644
            --- a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js
            +++ b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js
            @@ -48,13 +48,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	var serialized = ",,";
            -	// Serialize the children of the subscript element
            -	serialized += serialize(tree.children);
            -	// Close the serialized string with the closing delimiter
            -	serialized += ",,";
            -	// Return the complete serialized string
            -	return serialized;
            +	return ",," + serialize(tree.children) + ",,";
             };
             
             })();
            diff --git a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js
            index 82a4b78d6..a843aec5d 100644
            --- a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js
            +++ b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js
            @@ -48,13 +48,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	var serialized = "^^";
            -	// Serialize the children of the superscript element
            -	serialized += serialize(tree.children);
            -	// Close the serialized string with the closing delimiter
            -	serialized += "^^";
            -	// Return the complete serialized string
            -	return serialized;
            +	return "^^" + serialize(tree.children) + "^^";
             };
             
             })();
            \ No newline at end of file
            diff --git a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js
            index b07f32fc2..4d223185a 100644
            --- a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js
            +++ b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js
            @@ -48,13 +48,7 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	var serialized = "__";
            -	// Serialize the children of the underscore element
            -	serialized += serialize(tree.children);
            -	// Close the serialized string with the closing delimiter
            -	serialized += "__";
            -	// Return the complete serialized string
            -	return serialized;
            +	return "__" + serialize(tree.children) + "__";
             };
             
             })();
            \ No newline at end of file
            diff --git a/core/modules/parsers/wikiparser/rules/entity.js b/core/modules/parsers/wikiparser/rules/entity.js
            index 7f15c8a95..10e288990 100644
            --- a/core/modules/parsers/wikiparser/rules/entity.js
            +++ b/core/modules/parsers/wikiparser/rules/entity.js
            @@ -37,7 +37,6 @@ exports.parse = function() {
             	return [{type: "entity", entity: this.match[0]}];
             };
             
            -// Serialize method for the entity rule
             exports.serialize = function(tree, serialize) {
             	return tree.entity;
             };
            diff --git a/core/modules/parsers/wikiparser/rules/hardlinebreaks.js b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js
            index 9f26c3d95..ae290ef29 100644
            --- a/core/modules/parsers/wikiparser/rules/hardlinebreaks.js
            +++ b/core/modules/parsers/wikiparser/rules/hardlinebreaks.js
            @@ -60,15 +60,14 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree,serialize) {
            -	// we get each of element on tree from `parse` one by one here.
            -	var text = tree.tag === 'br' ? '\n' : tree.text;
            +	var text = tree.tag === "br" ? "\n" : (tree.text || "");
             	if(tree.isRuleStart) {
             		return '"""\n' + text;
             	}
             	if(tree.isRuleEnd) {
             		return text + '"""';
             	}
            -	return text;
            +	return text + serialize(tree.children);
             };
             
             })();
            diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js
            index 1e3f9865b..df52819e2 100644
            --- a/core/modules/parsers/wikiparser/rules/html.js
            +++ b/core/modules/parsers/wikiparser/rules/html.js
            @@ -66,7 +66,7 @@ exports.parse = function() {
             		}
             		tag.end = this.parser.pos;
             		tag.closeTagEnd = tag.end;
            -		if(tag.closeTagEnd === tag.openTagEnd || this.parser.source[tag.closeTagEnd - 1] !== '>') {
            +		if(tag.closeTagEnd === tag.openTagEnd || this.parser.source[tag.closeTagEnd - 1] !== ">") {
             			tag.closeTagStart = tag.end;
             		} else {
             			tag.closeTagStart = tag.closeTagEnd - 2;
            @@ -74,11 +74,11 @@ exports.parse = function() {
             			if(!Number.isSafeInteger(closeTagMinPos)) closeTagMinPos = tag.openTagEnd;
             			while(tag.closeTagStart >= closeTagMinPos) {
             				var char = this.parser.source[tag.closeTagStart];
            -				if(char === '>') {
            +				if(char === ">") {
             					tag.closeTagStart = -1;
             					break;
             				}
            -				if(char === '<') break;
            +				if(char === "<") break;
             				tag.closeTagStart -= 1;
             			}
             			if(tag.closeTagStart < closeTagMinPos) {
            @@ -199,9 +199,9 @@ exports.serialize = function(tree, serialize) {
             	var tag = tree.tag;
             	var attributes = Object.keys(tree.attributes).map(function(key) {
             			return key + '="' + tree.attributes[key].value + '"';
            -	}).join('');
            +	}).join("");
             	// Children
            -	var children = tree.children ? serialize(tree.children) : '';
            +	var children = tree.children ? serialize(tree.children) : "";
             	// Self-closing tag
             	if(tree.isSelfClosing) {
             			return "<" + tag + (attributes ? " " + attributes : "") + " />";
            diff --git a/core/modules/parsers/wikiparser/rules/import.js b/core/modules/parsers/wikiparser/rules/import.js
            index 2142f7a58..3cfcad5d7 100644
            --- a/core/modules/parsers/wikiparser/rules/import.js
            +++ b/core/modules/parsers/wikiparser/rules/import.js
            @@ -52,9 +52,8 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree,serialize) {
            -	// Filter attribute
             	var filter = tree.attributes.filter.value;
            -	// Construct the serialized string with children that is actually the sibling below the pragma.
            +	// Sibling below the pragma become children, so we append the serialized children to the end..
             	return "\\import " + filter + "\n" + serialize(tree.children);
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/macrocallblock.js b/core/modules/parsers/wikiparser/rules/macrocallblock.js
            index 923484bae..1572cce63 100644
            --- a/core/modules/parsers/wikiparser/rules/macrocallblock.js
            +++ b/core/modules/parsers/wikiparser/rules/macrocallblock.js
            @@ -57,16 +57,16 @@ exports.parse = function() {
             Serialize a macro call node to wikitext
             */
             exports.serialize = function (node) {
            -	// Start with macro opener
             	var result = "<<";
            +	// Macro name
             	if(node.attributes && node.attributes["$variable"]) {
            -		result += node.attributes["$variable"].value; // Add macro name
            +		result += node.attributes["$variable"].value;
             	}
             	// Append ordered arguments if any
             	if(node.orderedAttributes) {
             		node.orderedAttributes.forEach(function (attr) {
             			if(attr.name !== "$variable") {
            -				result += " " + '"' + attr.value + '"'; // Add each additional value
            +				result += " " + '"' + attr.value + '"';
             			}
             		});
             	}
            diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js
            index 9dec07682..be000eab0 100644
            --- a/core/modules/parsers/wikiparser/rules/macrodef.js
            +++ b/core/modules/parsers/wikiparser/rules/macrodef.js
            @@ -90,15 +90,11 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree,serialize) {
            -	// Macro name
             	var name = tree.attributes.name.value;
            -	// Parameters
             	var params = tree.params.map(function(param) {
             			return param.name + (param.default ? ":" + param.default : "");
             	}).join(",");
            -	// Definition text
             	var definition = tree.attributes.value.value;
            -	// Construct the serialized string
             	return "\\define " + name + "(" + params + ")\n" + definition + "\n\\end\n\n" + serialize(tree.children);
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/parameters.js b/core/modules/parsers/wikiparser/rules/parameters.js
            index 6be51c24b..a214164ca 100644
            --- a/core/modules/parsers/wikiparser/rules/parameters.js
            +++ b/core/modules/parsers/wikiparser/rules/parameters.js
            @@ -58,11 +58,9 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree,serialize) {
            -	// Parameters
             	var params = tree.orderedAttributes.map(function(param) {
             			return param.name + (param.value ? ":" + param.value : "");
             	}).join(",");
            -	// Construct the serialized string
             	return "\\parameters(" + params + ")\n\n" + serialize(tree.children);
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/prettyextlink.js b/core/modules/parsers/wikiparser/rules/prettyextlink.js
            index e2cc48a7e..f56ee8fe0 100644
            --- a/core/modules/parsers/wikiparser/rules/prettyextlink.js
            +++ b/core/modules/parsers/wikiparser/rules/prettyextlink.js
            @@ -118,11 +118,8 @@ exports.parseLink = function(source,pos) {
             };
             
             exports.serialize = function(tree) {
            -	// Tooltip text
             	var tooltip = tree.children[0].text;
            -	// URL
             	var url = tree.attributes.href.value;
            -	// Construct the serialized string
             	return "[ext[" + (tooltip !== url ? tooltip + "|" : "") + url + "]]";
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/prettylink.js b/core/modules/parsers/wikiparser/rules/prettylink.js
            index 74a275e42..0b798a5dc 100644
            --- a/core/modules/parsers/wikiparser/rules/prettylink.js
            +++ b/core/modules/parsers/wikiparser/rules/prettylink.js
            @@ -68,11 +68,8 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree) {
            -	// Link text
             	var text = tree.children[0].text;
            -	// Link target
             	var target = tree.attributes.to ? tree.attributes.to.value : tree.attributes.href.value;
            -	// Construct the serialized string
             	return "[[" + text + (text !== target ? "|" + target : "") + "]]";
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/syslink.js b/core/modules/parsers/wikiparser/rules/syslink.js
            index 0839e9087..e5387e5ee 100644
            --- a/core/modules/parsers/wikiparser/rules/syslink.js
            +++ b/core/modules/parsers/wikiparser/rules/syslink.js
            @@ -53,11 +53,9 @@ exports.parse = function() {
             exports.serialize = function(tree, serialize) {
             	// Check if the link is suppressed
             	var isSuppressed = tree.children[0].text.substr(0,1) === "~";
            -
             	var serialized = isSuppressed ? "~" : "";
            -	// Append the link value
            +	// Append the link text
             	serialized += tree.attributes.to.value;
            -	// Return the complete serialized string
             	return serialized;
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/transcludeblock.js b/core/modules/parsers/wikiparser/rules/transcludeblock.js
            index 88519e84d..319726f0a 100644
            --- a/core/modules/parsers/wikiparser/rules/transcludeblock.js
            +++ b/core/modules/parsers/wikiparser/rules/transcludeblock.js
            @@ -130,9 +130,7 @@ exports.serialize = function(tree, serialize) {
             	} else if(tree.type === "transclude") {
             		handleTransclude(tree);
             	}
            -	// Close the result string
             	result += "}}\n\n";
            -	// Return the complete result string
             	return result;
             };
             
            diff --git a/core/modules/parsers/wikiparser/rules/typedblock.js b/core/modules/parsers/wikiparser/rules/typedblock.js
            index 68d534830..38985daaa 100644
            --- a/core/modules/parsers/wikiparser/rules/typedblock.js
            +++ b/core/modules/parsers/wikiparser/rules/typedblock.js
            @@ -78,6 +78,7 @@ exports.parse = function() {
             			container = $tw.fakeDocument.createElement("div");
             		widgetNode.render(container,null);
             		var renderResult = renderType === "text/html" ? container.innerHTML : container.textContent;
            +		// Use void node to carry important info for typedblock
             		return [{
             			type: "void",
             			children: [{
            @@ -99,7 +100,6 @@ exports.parse = function() {
             
             exports.serialize = function (tree, serialize) {
             	if(tree.type === "void") {
            -		// Directly process the tree's text content
             		return "$$$" + tree.parseType + (tree.renderType ? " > " + tree.renderType : "") + "\n" + tree.text + "\n$$$\n\n";
             	}
             	return "";
            diff --git a/core/modules/parsers/wikiparser/rules/wikilink.js b/core/modules/parsers/wikiparser/rules/wikilink.js
            index 6a59d395f..d5e1a48ec 100644
            --- a/core/modules/parsers/wikiparser/rules/wikilink.js
            +++ b/core/modules/parsers/wikiparser/rules/wikilink.js
            @@ -66,7 +66,6 @@ exports.parse = function() {
             };
             
             exports.serialize = function(tree, serialize) {
            -	// Check if the link is suppressed
             	var isSuppressed = tree.children[0].text.substr(0,1) === $tw.config.textPrimitives.unWikiLink;
             
             	var serialized = isSuppressed ? $tw.config.textPrimitives.unWikiLink : "";
            
            From f5fca2a4d484cc5c4e3b12a287b24d70985a03a0 Mon Sep 17 00:00:00 2001
            From: lin onetwo 
            Date: Wed, 4 Sep 2024 16:43:05 +0800
            Subject: [PATCH 50/98] Update conditional.js to not include space
            
            ---
             core/modules/parsers/wikiparser/rules/conditional.js | 10 +++++-----
             1 file changed, 5 insertions(+), 5 deletions(-)
            
            diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js
            index 3a4486cf2..8e11c7cdb 100644
            --- a/core/modules/parsers/wikiparser/rules/conditional.js
            +++ b/core/modules/parsers/wikiparser/rules/conditional.js
            @@ -6,7 +6,7 @@ module-type: wikirule
             Conditional shortcut syntax
             
             ```
            -This is a <% if [{something}] %>Elephant<% elseif [{else}] %>Pelican<% else %>Crocodile<% endif %>
            +This is a <%if [{something}] %>Elephant<%elseif [{else}] %>Pelican<%else%>Crocodile<%endif%>
             ```
             
             \*/
            @@ -27,7 +27,7 @@ exports.init = function(parser) {
             };
             
             exports.findNextMatch = function(startPos) {
            -	// Look for the next <% if shortcut
            +	// Look for the next <%if shortcut
             	this.matchRegExp.lastIndex = startPos;
             	this.match = this.matchRegExp.exec(this.parser.source);
             	// If not found then return no match
            @@ -121,7 +121,7 @@ exports.serialize = function(tree, serialize) {
             	var filterCondition = tree.attributes.filter.value;
             	var ifClause = serialize(tree.children[0].children);
             	var elseClause = tree.children[1].children;
            -	var serialized = "<% if " + filterCondition + "%>" + ifClause;
            +	var serialized = "<%if " + filterCondition + "%>" + ifClause;
             
             	if(elseClause && elseClause.length > 0) {
             		for(var i = 0; i < elseClause.length; i++) {
            @@ -129,11 +129,11 @@ exports.serialize = function(tree, serialize) {
             				// Handle elseif clause
             				var elseifCondition = elseClause[i].attributes.filter.value;
             				var elseifClause = serialize(elseClause[i].children[0]);
            -				serialized += "<% elseif " + elseifCondition + "%>" + elseifClause;
            +				serialized += "<%elseif " + elseifCondition + "%>" + elseifClause;
             			}
             			if(elseClause[i].children[1]) {
             				var elseClauseText = serialize(elseClause[i].children[1]);
            -				serialized += "<% else %>" + elseClauseText;
            +				serialized += "<%else%>" + elseClauseText;
             			}
             		}
             	}
            
            From 043f60b299e7f2cc4661d2f79440da50e0eeeb28 Mon Sep 17 00:00:00 2001
            From: lin onetwo 
            Date: Wed, 4 Sep 2024 16:44:03 +0800
            Subject: [PATCH 51/98] Update test-wikitext-serialize.js
            
            ---
             editions/test/tiddlers/tests/test-wikitext-serialize.js | 2 +-
             1 file changed, 1 insertion(+), 1 deletion(-)
            
            diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            index 2871343cc..a8431694a 100644
            --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js
            +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            @@ -116,7 +116,7 @@ describe("WikiAST serialization unit tests", function () {
             
               wiki.addTiddler({
                 title: "ConditionalTest",
            -    text: "This is a <% if [{something}] %>Elephant<% elseif [{else}] %>Pelican<% else %>Crocodile<% endif %>",
            +    text: "This is a <%if [{something}] %>Elephant<%elseif [{else}] %>Pelican<%else%>Crocodile<%endif%>",
               });
               it("should serialize conditional statements correctly", function () {
                 var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ConditionalTest").tree).trimEnd();
            
            From 03798d7fef6a47e7bada5582df1b9ec3d80f5aff Mon Sep 17 00:00:00 2001
            From: linonetwo 
            Date: Wed, 4 Sep 2024 16:46:32 +0800
            Subject: [PATCH 52/98] Update conditional.js
            
            ---
             core/modules/parsers/wikiparser/rules/conditional.js | 2 +-
             1 file changed, 1 insertion(+), 1 deletion(-)
            
            diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js
            index 8e11c7cdb..84ac3cef8 100644
            --- a/core/modules/parsers/wikiparser/rules/conditional.js
            +++ b/core/modules/parsers/wikiparser/rules/conditional.js
            @@ -138,7 +138,7 @@ exports.serialize = function(tree, serialize) {
             		}
             	}
             
            -	serialized += "<% endif %>";
            +	serialized += "<%endif%>";
             	return serialized;
             };
             
            
            From 58507c06b4dad7d4e594fe07ea48f9f3e4311125 Mon Sep 17 00:00:00 2001
            From: linonetwo 
            Date: Mon, 30 Sep 2024 18:11:22 +0800
            Subject: [PATCH 53/98] refactor: move tiddlers to /data
            
            ---
             .../tests/data/serialize/BlockRule.tid        |   7 +
             .../tests/data/serialize/BoldEmphasis.tid     |   5 +
             .../tests/data/serialize/CodeBlock.tid        |  12 +
             .../tests/data/serialize/CommentBlock.tid     |  11 +
             .../tests/data/serialize/CommentInline.tid    |   5 +
             .../tests/data/serialize/Conditional.tid      |   5 +
             .../tiddlers/tests/data/serialize/Dash.tid    |   7 +
             .../tiddlers/tests/data/serialize/Entity.tid  |   5 +
             .../tiddlers/tests/data/serialize/ExtLink.tid |   7 +
             .../serialize/FilteredTranscludeBlock.tid     |   9 +
             .../serialize/FilteredTranscludeInline.tid    |   5 +
             .../data/serialize/FunctionDefinition.tid     |  15 +
             .../tests/data/serialize/HardLineBreaks.tid   |  12 +
             .../tiddlers/tests/data/serialize/Heading.tid |  10 +
             .../tiddlers/tests/data/serialize/Html.tid    |  11 +
             .../tiddlers/tests/data/serialize/Image.tid   |  10 +
             .../tiddlers/tests/data/serialize/Import.tid  |   6 +
             .../tests/data/serialize/ItalicEmphasis.tid   |   5 +
             .../tiddlers/tests/data/serialize/List.tid    |  27 ++
             .../tests/data/serialize/MacroCallBlock.tid   |   7 +
             .../tests/data/serialize/MacroCallInline.tid  |   5 +
             .../tests/data/serialize/MacroDef.tid         |   7 +
             .../tests/data/serialize/Parameters.tid       |   5 +
             .../tests/data/serialize/ParserMode.tid       |   9 +
             .../tests/data/serialize/PrettyExtLink.tid    |   6 +
             .../tests/data/serialize/PrettyLink.tid       |   6 +
             .../tests/data/serialize/QuoteBlock.tid       |   7 +
             .../tests/data/serialize/RulesPragma.tid      |   6 +
             .../tests/data/serialize/SimpleText.tid       |   5 +
             .../tests/data/serialize/SoftLineBreak.tid    |   6 +
             .../data/serialize/StrikethroughEmphasis.tid  |   5 +
             .../tests/data/serialize/StyleBlock.tid       |  17 +
             .../tests/data/serialize/StyleBlock2.tid      |  13 +
             .../tests/data/serialize/StyleInline.tid      |   7 +
             .../data/serialize/SubscriptEmphasis.tid      |   5 +
             .../data/serialize/SuperscriptEmphasis.tid    |   5 +
             .../tiddlers/tests/data/serialize/SysLink.tid |   6 +
             .../tiddlers/tests/data/serialize/Table.tid   |   8 +
             .../tests/data/serialize/TranscludeBlock.tid  |  21 +
             .../tests/data/serialize/TranscludeInline.tid |   5 +
             .../tests/data/serialize/TypedBlock1.tid      |  15 +
             .../tests/data/serialize/TypedBlock2.tid      |  19 +
             .../data/serialize/UnderscoreEmphasis.tid     |   5 +
             .../tests/data/serialize/WikiLink.tid         |   7 +
             .../tests/data/serialize/WikiLinkPrefix.tid   |   5 +
             .../tiddlers/tests/test-wikitext-serialize.js | 405 +-----------------
             46 files changed, 396 insertions(+), 395 deletions(-)
             create mode 100644 editions/test/tiddlers/tests/data/serialize/BlockRule.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/BoldEmphasis.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/CodeBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/CommentBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/CommentInline.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Conditional.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Dash.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Entity.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/ExtLink.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/FilteredTranscludeInline.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/HardLineBreaks.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Heading.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Html.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Image.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Import.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/ItalicEmphasis.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/List.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/MacroDef.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Parameters.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/ParserMode.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/PrettyExtLink.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/PrettyLink.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/QuoteBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/RulesPragma.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/SimpleText.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/SoftLineBreak.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/StrikethroughEmphasis.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/StyleBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/StyleBlock2.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/StyleInline.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/SubscriptEmphasis.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/SuperscriptEmphasis.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/SysLink.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/Table.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/TranscludeBlock.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/TranscludeInline.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/TypedBlock1.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/TypedBlock2.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/UnderscoreEmphasis.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/WikiLink.tid
             create mode 100644 editions/test/tiddlers/tests/data/serialize/WikiLinkPrefix.tid
            
            diff --git a/editions/test/tiddlers/tests/data/serialize/BlockRule.tid b/editions/test/tiddlers/tests/data/serialize/BlockRule.tid
            new file mode 100644
            index 000000000..316f745c6
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/BlockRule.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/BlockRule
            +type: text/vnd.tiddlywiki
            +
            +The speed of sound
            +
            +The light of speed
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/BoldEmphasis.tid b/editions/test/tiddlers/tests/data/serialize/BoldEmphasis.tid
            new file mode 100644
            index 000000000..2caac9172
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/BoldEmphasis.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/BoldEmphasis
            +type: text/vnd.tiddlywiki
            +
            +This is ''bold'' text
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid b/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid
            new file mode 100644
            index 000000000..8b1499970
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid
            @@ -0,0 +1,12 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/CodeBlock
            +type: text/vnd.tiddlywiki
            +
            +Simple `JS` and complex
            +
            +---
            +
            +```js
            +var match = reEnd.exec(this.parser.source)
            +```
            +end
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/CommentBlock.tid b/editions/test/tiddlers/tests/data/serialize/CommentBlock.tid
            new file mode 100644
            index 000000000..c90b67c25
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/CommentBlock.tid
            @@ -0,0 +1,11 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/CommentBlock
            +type: text/vnd.tiddlywiki
            +
            +
            +
            +Some text
            +
            +
            +
            +More text
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/CommentInline.tid b/editions/test/tiddlers/tests/data/serialize/CommentInline.tid
            new file mode 100644
            index 000000000..2d0e98513
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/CommentInline.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/CommentInline
            +type: text/vnd.tiddlywiki
            +
            +This is some text with an inline comment  and some more text.
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Conditional.tid b/editions/test/tiddlers/tests/data/serialize/Conditional.tid
            new file mode 100644
            index 000000000..4e96726f7
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Conditional.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Conditional
            +type: text/vnd.tiddlywiki
            +
            +This is a <%if [{something}] %>Elephant<%elseif [{else}] %>Pelican<%else%>Crocodile<%endif%>
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Dash.tid b/editions/test/tiddlers/tests/data/serialize/Dash.tid
            new file mode 100644
            index 000000000..b0a7ddc55
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Dash.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Dash
            +type: text/vnd.tiddlywiki
            +
            +This is an en-dash: --
            +
            +This is an em-dash: ---
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Entity.tid b/editions/test/tiddlers/tests/data/serialize/Entity.tid
            new file mode 100644
            index 000000000..d8891e4ed
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Entity.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Entity
            +type: text/vnd.tiddlywiki
            +
            +This is a copyright symbol: ©
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/ExtLink.tid b/editions/test/tiddlers/tests/data/serialize/ExtLink.tid
            new file mode 100644
            index 000000000..de966452f
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/ExtLink.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/ExtLink
            +type: text/vnd.tiddlywiki
            +
            +An external link: https://www.tiddlywiki.com/
            +
            +A suppressed external link: ~http://www.tiddlyspace.com/
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid b/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid
            new file mode 100644
            index 000000000..cbfc442c5
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid
            @@ -0,0 +1,9 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/FilteredTranscludeBlock
            +type: text/vnd.tiddlywiki
            +
            +{{{ [tag[docs]] }}}
            +{{{ [tag[docs]] |tooltip}}}
            +{{{ [tag[docs]] ||TemplateTitle}}}
            +{{{ [tag[docs]] |tooltip||TemplateTitle}}}
            +{{{ [tag[docs]] }}width:40;height:50;}.class.class
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeInline.tid b/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeInline.tid
            new file mode 100644
            index 000000000..8b3155882
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeInline.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/FilteredTranscludeInline
            +type: text/vnd.tiddlywiki
            +
            +{{{ [tag[docs]] }}} {{{ [tag[docs]] |tooltip}}} {{{ [tag[docs]] ||TemplateTitle}}} {{{ [tag[docs]] |tooltip||TemplateTitle}}} {{{ [tag[docs]] }}width:40;height:50;}.class.class
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid b/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid
            new file mode 100644
            index 000000000..ebd4119a5
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid
            @@ -0,0 +1,15 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/FunctionDefinition
            +type: text/vnd.tiddlywiki
            +
            +\function name(param:defaultvalue,param2:defaultvalue)
            +definition text
            +\end
            +
            +\procedure name(param:defaultvalue,param2:defaultvalue)
            +definition text
            +\end
            +
            +\widget $mywidget(param:defaultvalue,param2:defaultvalue)
            +definition text
            +\end
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/HardLineBreaks.tid b/editions/test/tiddlers/tests/data/serialize/HardLineBreaks.tid
            new file mode 100644
            index 000000000..b6ea0b985
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/HardLineBreaks.tid
            @@ -0,0 +1,12 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/HardLineBreaks
            +type: text/vnd.tiddlywiki
            +
            +"""
            +This is some text
            +That is set like
            +It is a Poem
            +When it is
            +Clearly
            +Not
            +"""
            diff --git a/editions/test/tiddlers/tests/data/serialize/Heading.tid b/editions/test/tiddlers/tests/data/serialize/Heading.tid
            new file mode 100644
            index 000000000..8f90e379a
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Heading.tid
            @@ -0,0 +1,10 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Heading
            +type: text/vnd.tiddlywiki
            +
            +! Heading 1
            +!! Heading 2
            +!!! Heading 3
            +!!!! Heading 4
            +!!!!! Heading 5
            +!!!!!! Heading 6
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Html.tid b/editions/test/tiddlers/tests/data/serialize/Html.tid
            new file mode 100644
            index 000000000..05507eb56
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Html.tid
            @@ -0,0 +1,11 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Html
            +type: text/vnd.tiddlywiki
            +
            +
            +
            +<$slider target="MyTiddler">
            +This is a widget invocation
            +
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Image.tid b/editions/test/tiddlers/tests/data/serialize/Image.tid
            new file mode 100644
            index 000000000..8641df4cb
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Image.tid
            @@ -0,0 +1,10 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Image
            +type: text/vnd.tiddlywiki
            +
            +[img[https://tiddlywiki.com/fractalveg.jpg]]
            +[img width="23" height="24" [https://tiddlywiki.com/fractalveg.jpg]]
            +[img width={{!!width}} height={{!!height}} [https://tiddlywiki.com/fractalveg.jpg]]
            +[img[Description of image|https://tiddlywiki.com/fractalveg.jpg]]
            +[img[TiddlerTitle]]
            +[img[Description of image|TiddlerTitle]]
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Import.tid b/editions/test/tiddlers/tests/data/serialize/Import.tid
            new file mode 100644
            index 000000000..e467de534
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Import.tid
            @@ -0,0 +1,6 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Import
            +type: text/vnd.tiddlywiki
            +
            +\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
            +\import [[$:/core/ui/PageMacros]]
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/ItalicEmphasis.tid b/editions/test/tiddlers/tests/data/serialize/ItalicEmphasis.tid
            new file mode 100644
            index 000000000..a06ca62ce
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/ItalicEmphasis.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/ItalicEmphasis
            +type: text/vnd.tiddlywiki
            +
            +This is //italic// text
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/List.tid b/editions/test/tiddlers/tests/data/serialize/List.tid
            new file mode 100644
            index 000000000..d4088bcce
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/List.tid
            @@ -0,0 +1,27 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/List
            +type: text/vnd.tiddlywiki
            +
            +* This is an unordered list
            +* It has two items
            +
            +# This is a numbered list
            +## With a subitem
            +# And a third item
            +
            +; This is a term that is being defined
            +: This is the definition of that term
            +
            +#** One
            +#* Two
            +#** Three
            +#**** Four
            +#**# Five
            +#**## Six
            +## Seven
            +### Eight
            +## Nine
            +
            +* List item one
            +*.active List item two has the class `active`
            +* List item three
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid b/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid
            new file mode 100644
            index 000000000..723e23edd
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/MacroCallBlock
            +type: text/vnd.tiddlywiki
            +
            +<>
            +
            +<<.def "macro calls">>
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid b/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid
            new file mode 100644
            index 000000000..0b6b4fc50
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/MacroCallInline
            +type: text/vnd.tiddlywiki
            +
            +These are macro calls in a line: <> and <<.def "macro calls">>
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/MacroDef.tid b/editions/test/tiddlers/tests/data/serialize/MacroDef.tid
            new file mode 100644
            index 000000000..dcbc02e9d
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/MacroDef.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/MacroDef
            +type: text/vnd.tiddlywiki
            +
            +\define name(param:defaultvalue,param2:defaultvalue)
            +definition text, including $param$ markers
            +\end
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Parameters.tid b/editions/test/tiddlers/tests/data/serialize/Parameters.tid
            new file mode 100644
            index 000000000..5b107a73d
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Parameters.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Parameters
            +type: text/vnd.tiddlywiki
            +
            +\parameters(param:defaultvalue,param2:defaultvalue)
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/ParserMode.tid b/editions/test/tiddlers/tests/data/serialize/ParserMode.tid
            new file mode 100644
            index 000000000..b4c31b66b
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/ParserMode.tid
            @@ -0,0 +1,9 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/ParserMode
            +type: text/vnd.tiddlywiki
            +
            +\parsermode block
            +
            +\parsermode inline
            +
            +Test.
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/PrettyExtLink.tid b/editions/test/tiddlers/tests/data/serialize/PrettyExtLink.tid
            new file mode 100644
            index 000000000..1b4002b94
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/PrettyExtLink.tid
            @@ -0,0 +1,6 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/PrettyExtLink
            +type: text/vnd.tiddlywiki
            +
            +[ext[https://tiddlywiki.com/fractalveg.jpg]]
            +[ext[Tooltip|https://tiddlywiki.com/fractalveg.jpg]]
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/PrettyLink.tid b/editions/test/tiddlers/tests/data/serialize/PrettyLink.tid
            new file mode 100644
            index 000000000..8c7afbc7f
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/PrettyLink.tid
            @@ -0,0 +1,6 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/PrettyLink
            +type: text/vnd.tiddlywiki
            +
            +[[Introduction]]
            +[[Link description|TiddlerTitle]]
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/QuoteBlock.tid b/editions/test/tiddlers/tests/data/serialize/QuoteBlock.tid
            new file mode 100644
            index 000000000..a2f698846
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/QuoteBlock.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/QuoteBlock
            +type: text/vnd.tiddlywiki
            +
            +<<` around this list will also have the class `myClass`
            +* List item 2
            +@@
            +
            +@@font-size:1.5em;
            +@@.coloured-text.coloured-bg
            +* Block content
            +* With custom style and classes
            +@@
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/StyleBlock2.tid b/editions/test/tiddlers/tests/data/serialize/StyleBlock2.tid
            new file mode 100644
            index 000000000..cdd31254e
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/StyleBlock2.tid
            @@ -0,0 +1,13 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/StyleBlock2
            +type: text/vnd.tiddlywiki
            +
            +@@width:100px;
            +@@.myFirstClass.mySecondClass.myThirdClass
            +This is a paragraph
            +@@
            +
            +@@background-color:lightcyan;
            +* Item one
            +* Item two
            +@@
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/StyleInline.tid b/editions/test/tiddlers/tests/data/serialize/StyleInline.tid
            new file mode 100644
            index 000000000..c491767f5
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/StyleInline.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/StyleInline
            +type: text/vnd.tiddlywiki
            +
            +@@.myClass This is some text with a class@@
            +@@background-color:red; This is some text with a background colour@@
            +@@width:100px;.myClass This is some text with a class and a width@@
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/SubscriptEmphasis.tid b/editions/test/tiddlers/tests/data/serialize/SubscriptEmphasis.tid
            new file mode 100644
            index 000000000..b39d7f6d5
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/SubscriptEmphasis.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/SubscriptEmphasis
            +type: text/vnd.tiddlywiki
            +
            +This is ,,subscript,, text
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/SuperscriptEmphasis.tid b/editions/test/tiddlers/tests/data/serialize/SuperscriptEmphasis.tid
            new file mode 100644
            index 000000000..9683f9e54
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/SuperscriptEmphasis.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/SuperscriptEmphasis
            +type: text/vnd.tiddlywiki
            +
            +This is ^^superscript^^ text
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/SysLink.tid b/editions/test/tiddlers/tests/data/serialize/SysLink.tid
            new file mode 100644
            index 000000000..fdbc982fe
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/SysLink.tid
            @@ -0,0 +1,6 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/SysLink
            +type: text/vnd.tiddlywiki
            +
            +$:TiddlerTitle
            +~$:TiddlerTitle
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/Table.tid b/editions/test/tiddlers/tests/data/serialize/Table.tid
            new file mode 100644
            index 000000000..213ecebff
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/Table.tid
            @@ -0,0 +1,8 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/Table
            +type: text/vnd.tiddlywiki
            +
            +|! |!Alpha |!Beta |!Gamma |!Delta |
            +|!One | | | | |
            +|!Two | | | | |
            +|!Three | | | | |
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/TranscludeBlock.tid b/editions/test/tiddlers/tests/data/serialize/TranscludeBlock.tid
            new file mode 100644
            index 000000000..344171af0
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/TranscludeBlock.tid
            @@ -0,0 +1,21 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/TranscludeBlock
            +type: text/vnd.tiddlywiki
            +
            +{{MyTiddler}}
            +
            +{{MyTiddler||TemplateTitle}}
            +
            +{{||TemplateTitle}}
            +
            +{{MyTiddler|Parameter}}
            +
            +{{MyTiddler||TemplateTitle|Parameter|SecondParameter}}
            +
            +{{MyTiddler!!field}}
            +
            +{{!!field}}
            +
            +{{MyTiddler##index}}
            +
            +{{##index}}
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/TranscludeInline.tid b/editions/test/tiddlers/tests/data/serialize/TranscludeInline.tid
            new file mode 100644
            index 000000000..df20658cf
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/TranscludeInline.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/TranscludeInline
            +type: text/vnd.tiddlywiki
            +
            +{{MyTiddler}} {{MyTiddler||TemplateTitle}}
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/TypedBlock1.tid b/editions/test/tiddlers/tests/data/serialize/TypedBlock1.tid
            new file mode 100644
            index 000000000..06362d062
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/TypedBlock1.tid
            @@ -0,0 +1,15 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/TypedBlock1
            +type: text/vnd.tiddlywiki
            +
            +$$$text/vnd.tiddlywiki > text/plain
            +This is ''some'' wikitext
            +$$$
            +
            +$$$text/unknown
            +Some plain text, which will not be //formatted//.
            +
            +$$$text/vnd.tiddlywiki > text/html
            +This is ''some'' wikitext
            +$$$
            +
            diff --git a/editions/test/tiddlers/tests/data/serialize/TypedBlock2.tid b/editions/test/tiddlers/tests/data/serialize/TypedBlock2.tid
            new file mode 100644
            index 000000000..082ca533a
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/TypedBlock2.tid
            @@ -0,0 +1,19 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/TypedBlock2
            +type: text/vnd.tiddlywiki
            +
            +$$$.js
            +This will be rendered as JavaScript
            +$$$
            +
            +$$$.svg
            +
            +  
            +
            +$$$
            +
            +$$$image/svg+xml
            +
            +  
            +
            +$$$
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/UnderscoreEmphasis.tid b/editions/test/tiddlers/tests/data/serialize/UnderscoreEmphasis.tid
            new file mode 100644
            index 000000000..73dc6425c
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/UnderscoreEmphasis.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/UnderscoreEmphasis
            +type: text/vnd.tiddlywiki
            +
            +This is __underscore__ text
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/WikiLink.tid b/editions/test/tiddlers/tests/data/serialize/WikiLink.tid
            new file mode 100644
            index 000000000..18b04caf1
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/WikiLink.tid
            @@ -0,0 +1,7 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/WikiLink
            +type: text/vnd.tiddlywiki
            +
            +AWikiLink
            +AnotherLink
            +~SuppressedLink
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/data/serialize/WikiLinkPrefix.tid b/editions/test/tiddlers/tests/data/serialize/WikiLinkPrefix.tid
            new file mode 100644
            index 000000000..982ed9071
            --- /dev/null
            +++ b/editions/test/tiddlers/tests/data/serialize/WikiLinkPrefix.tid
            @@ -0,0 +1,5 @@
            +tags: $:/tags/wikitext-serialize-test-spec
            +title: Serialize/WikiLinkPrefix
            +type: text/vnd.tiddlywiki
            +
            +~SuppressedLink
            \ No newline at end of file
            diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            index a8431694a..79d5c8306 100644
            --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js
            +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            @@ -10,400 +10,15 @@ Tests the wikitext inverse-rendering from Wiki AST.
             describe("WikiAST serialization unit tests", function () {
               var wiki = new $tw.Wiki();
             
            -  wiki.addTiddler({
            -    title: "BoldEmphasisTest",
            -    text: "This is ''bold'' text",
            -  });
            -  it("should serialize bold emphasis correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("BoldEmphasisTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("BoldEmphasisTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "ItalicEmphasisTest",
            -    text: "This is //italic// text",
            -  });
            -  it("should serialize italic emphasis correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ItalicEmphasisTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("ItalicEmphasisTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "StrikethroughEmphasisTest",
            -    text: "This is ~~strikethrough~~ text",
            -  });
            -  it("should serialize strikethrough emphasis correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StrikethroughEmphasisTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("StrikethroughEmphasisTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "SubscriptEmphasisTest",
            -    text: "This is ,,subscript,, text",
            -  });
            -  it("should serialize subscript emphasis correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("SubscriptEmphasisTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("SubscriptEmphasisTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "SuperscriptEmphasisTest",
            -    text: "This is ^^superscript^^ text",
            -  });
            -  it("should serialize superscript emphasis correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("SuperscriptEmphasisTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("SuperscriptEmphasisTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "UnderscoreEmphasisTest",
            -    text: "This is __underscore__ text",
            -  });
            -  it("should serialize underscore emphasis correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("UnderscoreEmphasisTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("UnderscoreEmphasisTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({ title: "SimpleTextTest", text: "The quick brown fox" });
            -  it("should render tiddlers with no special markup as-is", function () {
            -    // `trimEnd` because when we handle `p` element when parsing block rules, we always add a newline. But original text that may not have a trailing newline, will still be recognized as a block.
            -    expect($tw.utils.serializeParseTree(wiki.parseTiddler("SimpleTextTest").tree).trimEnd()).toBe(
            -      wiki.getTiddlerText("SimpleTextTest")
            -    );
            -  });
            -
            -  wiki.addTiddler({ title: "SoftLineBreakTest", text: "The rain in Spain\nfalls mainly on the plain" });
            -  it("should preserve single new lines", function () {
            -    expect($tw.utils.serializeParseTree(wiki.parseTiddler("SoftLineBreakTest").tree).trimEnd()).toBe(
            -      wiki.getTiddlerText("SoftLineBreakTest")
            -    );
            -  });
            -
            -  wiki.addTiddler({ title: "BlockRule", text: "The speed of sound\n\nThe light of speed" });
            -  it("should preserve double new lines to create paragraphs", function () {
            -    expect($tw.utils.serializeParseTree(wiki.parseTiddler("BlockRule").tree).trimEnd()).toBe(
            -      wiki.getTiddlerText("BlockRule")
            -    );
            -  });
            -
            -  wiki.addTiddler({
            -    title: "CodeBlockTest",
            -    text: "Simple `JS` and complex\n\n---\n\n```js\nvar match = reEnd.exec(this.parser.source)\n```\nend",
            -  });
            -  it("should render inline code and block code", function () {
            -    expect($tw.utils.serializeParseTree(wiki.parseTiddler("CodeBlockTest").tree).trimEnd()).toBe(
            -      wiki.getTiddlerText("CodeBlockTest")
            -    );
            -  });
            -
            -  wiki.addTiddler({
            -    title: "CommentBlockTest",
            -    text: "\n\nSome text\n\n\n\nMore text",
            -  });
            -  it("should serialize block comments correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("CommentBlockTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("CommentBlockTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "CommentInlineTest",
            -    text: "This is some text with an inline comment  and some more text.",
            -  });
            -  it("should serialize inline comments correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("CommentInlineTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("CommentInlineTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "ConditionalTest",
            -    text: "This is a <%if [{something}] %>Elephant<%elseif [{else}] %>Pelican<%else%>Crocodile<%endif%>",
            -  });
            -  it("should serialize conditional statements correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ConditionalTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("ConditionalTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "DashTest",
            -    text: "This is an en-dash: --\n\nThis is an em-dash: ---",
            -  });
            -  it("should serialize dashes correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("DashTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("DashTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "EntityTest",
            -    text: "This is a copyright symbol: ©",
            -  });
            -  it("should serialize HTML entities correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("EntityTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("EntityTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "ExtLinkTest",
            -    text: "An external link: https://www.tiddlywiki.com/\n\nA suppressed external link: ~http://www.tiddlyspace.com/",
            -  });
            -  it("should serialize external links correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ExtLinkTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("ExtLinkTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "FilteredTranscludeBlockTest",
            -    text: "{{{ [tag[docs]] }}}\n{{{ [tag[docs]] |tooltip}}}\n{{{ [tag[docs]] ||TemplateTitle}}}\n{{{ [tag[docs]] |tooltip||TemplateTitle}}}\n{{{ [tag[docs]] }}width:40;height:50;}.class.class",
            -  });
            -  it("should serialize block-level filtered transclusion correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("FilteredTranscludeBlockTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("FilteredTranscludeBlockTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "FilteredTranscludeInlineTest",
            -    text: "{{{ [tag[docs]] }}} {{{ [tag[docs]] |tooltip}}} {{{ [tag[docs]] ||TemplateTitle}}} {{{ [tag[docs]] |tooltip||TemplateTitle}}} {{{ [tag[docs]] }}width:40;height:50;}.class.class",
            -  });
            -  it("should serialize inline filtered transclusion correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("FilteredTranscludeInlineTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("FilteredTranscludeInlineTest").trimEnd());
            -  });
            -
            -  // Test case based on the rule code's comment
            -  wiki.addTiddler({
            -    title: "FunctionDefinition",
            -    text: "\\function name(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end\n\n\\procedure name(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end\n\n\\widget $mywidget(param:defaultvalue,param2:defaultvalue)\ndefinition text\n\\end",
            -  });
            -  it("should serialize function, procedure, and widget definitions correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("FunctionDefinition").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("FunctionDefinition").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "HardLineBreaksTest",
            -    text: '"""\nThis is some text\nThat is set like\nIt is a Poem\nWhen it is\nClearly\nNot\n"""\n',
            -  });
            -  it("should serialize hard line breaks correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("HardLineBreaksTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("HardLineBreaksTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "HeadingTest",
            -    text: "! Heading 1\n!! Heading 2\n!!! Heading 3\n!!!! Heading 4\n!!!!! Heading 5\n!!!!!! Heading 6",
            -  });
            -  it("should serialize headings correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("HeadingTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("HeadingTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "HtmlTest",
            -    text: '\n\n<$slider target="MyTiddler">\nThis is a widget invocation\n',
            -  });
            -  it("should serialize HTML elements and widgets correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("HtmlTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("HtmlTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "ImageTest",
            -    text: '[img[https://tiddlywiki.com/fractalveg.jpg]]\n[img width="23" height="24" [https://tiddlywiki.com/fractalveg.jpg]]\n[img width={{!!width}} height={{!!height}} [https://tiddlywiki.com/fractalveg.jpg]]\n[img[Description of image|https://tiddlywiki.com/fractalveg.jpg]]\n[img[TiddlerTitle]]\n[img[Description of image|TiddlerTitle]]',
            -  });
            -  it("should serialize image tags correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ImageTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("ImageTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "ImportTest",
            -    text: "\\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]\n\\import [[$:/core/ui/PageMacros]]",
            -  });
            -  it("should serialize import pragma correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ImportTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("ImportTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "ListTest",
            -    text: "* This is an unordered list\n* It has two items\n\n# This is a numbered list\n## With a subitem\n# And a third item\n\n; This is a term that is being defined\n: This is the definition of that term\n\n#** One\n#* Two\n#** Three\n#**** Four\n#**# Five\n#**## Six\n## Seven\n### Eight\n## Nine\n\n* List item one\n*.active List item two has the class `active`\n* List item three",
            -  });
            -  it("should serialize lists correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ListTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("ListTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "MacroCallBlockTest",
            -    text: '<>\n\n<<.def "macro calls">>',
            -  });
            -  it("should serialize block macro calls correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("MacroCallBlockTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("MacroCallBlockTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "MacroCallInlineTest",
            -    text: 'These are macro calls in a line: <> and <<.def "macro calls">>',
            -  });
            -  it("should serialize inline macro calls correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("MacroCallInlineTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("MacroCallInlineTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "MacroDefTest",
            -    text: "\\define name(param:defaultvalue,param2:defaultvalue)\ndefinition text, including $param$ markers\n\\end",
            -  });
            -  it("should serialize macro definitions correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("MacroDefTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("MacroDefTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "ParametersTest",
            -    text: "\\parameters(param:defaultvalue,param2:defaultvalue)",
            -  });
            -  it("should serialize parameter definitions correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ParametersTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("ParametersTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "ParserModeTest",
            -    text: "\\parsermode block\n\n\\parsermode inline\n\nTest.",
            -  });
            -  it("should serialize parser mode specifications correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("ParserModeTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("ParserModeTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "PrettyExtLinkTest",
            -    text: "[ext[https://tiddlywiki.com/fractalveg.jpg]]\n[ext[Tooltip|https://tiddlywiki.com/fractalveg.jpg]]",
            -  });
            -  it("should serialize pretty external links correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("PrettyExtLinkTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("PrettyExtLinkTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "PrettyLinkTest",
            -    text: "[[Introduction]]\n[[Link description|TiddlerTitle]]",
            -  });
            -  it("should serialize pretty links correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("PrettyLinkTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("PrettyLinkTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "QuoteBlockTest",
            -    text: "<<` around this list will also have the class `myClass`\n* List item 2\n@@\n\n@@font-size:1.5em;\n@@.coloured-text.coloured-bg\n* Block content\n* With custom style and classes\n@@",
            -  });
            -  wiki.addTiddler({
            -    title: "StyleBlockTest2",
            -    text: "@@width:100px;\n@@.myFirstClass.mySecondClass.myThirdClass\nThis is a paragraph\n@@\n\n@@background-color:lightcyan;\n* Item one\n* Item two\n@@",
            -  });
            -  it("should serialize style blocks correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleBlockTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("StyleBlockTest").trimEnd());
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleBlockTest2").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("StyleBlockTest2").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "StyleInlineTest",
            -    text: "@@.myClass This is some text with a class@@\n@@background-color:red; This is some text with a background colour@@\n@@width:100px;.myClass This is some text with a class and a width@@",
            -  });
            -  it("should serialize style inlines correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("StyleInlineTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("StyleInlineTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "SysLinkTest",
            -    text: "$:TiddlerTitle\n~$:TiddlerTitle",
            -  });
            -  it("should serialize system links correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("SysLinkTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("SysLinkTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "TableTest",
            -    text: "|! |!Alpha |!Beta |!Gamma |!Delta |\n|!One | | | | |\n|!Two | | | | |\n|!Three | | | | |",
            -  });
            -  it("should serialize tables correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TableTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("TableTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "TranscludeBlockTest",
            -    text: "{{MyTiddler}}\n\n{{MyTiddler||TemplateTitle}}\n\n{{||TemplateTitle}}\n\n{{MyTiddler|Parameter}}\n\n{{MyTiddler||TemplateTitle|Parameter|SecondParameter}}\n\n{{MyTiddler!!field}}\n\n{{!!field}}\n\n{{MyTiddler##index}}\n\n{{##index}}",
            -  });
            -  it("should serialize block-level transclusions correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TranscludeBlockTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("TranscludeBlockTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "TranscludeInlineTest",
            -    text: "{{MyTiddler}} {{MyTiddler||TemplateTitle}}",
            -  });
            -  it("should serialize inline-level transclusions correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TranscludeInlineTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("TranscludeInlineTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "TypedBlockTest1",
            -    text: "$$$text/vnd.tiddlywiki > text/plain\nThis is ''some'' wikitext\n$$$\n\n$$$text/unknown\nSome plain text, which will not be //formatted//.\n\n$$$text/vnd.tiddlywiki > text/html\nThis is ''some'' wikitext\n$$$\n\n",
            -  });
            -  wiki.addTiddler({
            -    title: "TypedBlockTest2",
            -    text: '$$$.js\nThis will be rendered as JavaScript\n$$$\n\n$$$.svg\n\n  \n\n$$$\n\n$$$image/svg+xml\n\n  \n\n$$$',
            -  });
            -  
            -  it("should serialize typed blocks correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TypedBlockTest1").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("TypedBlockTest1").trimEnd());
            -    serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("TypedBlockTest2").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("TypedBlockTest2").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "WikiLinkTest",
            -    text: "AWikiLink\nAnotherLink\n~SuppressedLink",
            -  });
            -  it("should serialize wiki links correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("WikiLinkTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("WikiLinkTest").trimEnd());
            -  });
            -
            -  wiki.addTiddler({
            -    title: "WikiLinkPrefixTest",
            -    text: "~SuppressedLink",
            -  });
            -  it("should serialize suppressed wiki links correctly", function () {
            -    var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler("WikiLinkPrefixTest").tree).trimEnd();
            -    expect(serialized).toBe(wiki.getTiddlerText("WikiLinkPrefixTest").trimEnd());
            +  var cases = $tw.wiki.filterTiddlers("[all[shadows+tiddlers]tag[$:/tags/wikitext-serialize-test-spec]]");
            +  $tw.utils.each(cases, function (title) {
            +    wiki.addTiddler({
            +      title: title,
            +      text: wiki.getTiddlerText(title),
            +    });
            +    it("should serialize correctly for" + title, function () {
            +      var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler(title).tree).trimEnd();
            +      expect(serialized).toBe(wiki.getTiddlerText(title).trimEnd());
            +    });
               });
             });
            
            From 23489ce83c1a80444fd8e67f0c6792d60aafb06b Mon Sep 17 00:00:00 2001
            From: linonetwo 
            Date: Mon, 30 Sep 2024 18:15:30 +0800
            Subject: [PATCH 54/98] refactor: no need for new $tw.Wiki()
            
            ---
             .../test/tiddlers/tests/test-wikitext-serialize.js   | 12 +++---------
             1 file changed, 3 insertions(+), 9 deletions(-)
            
            diff --git a/editions/test/tiddlers/tests/test-wikitext-serialize.js b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            index 79d5c8306..e9c6f97cf 100644
            --- a/editions/test/tiddlers/tests/test-wikitext-serialize.js
            +++ b/editions/test/tiddlers/tests/test-wikitext-serialize.js
            @@ -8,17 +8,11 @@ Tests the wikitext inverse-rendering from Wiki AST.
             \*/
             
             describe("WikiAST serialization unit tests", function () {
            -  var wiki = new $tw.Wiki();
            -
               var cases = $tw.wiki.filterTiddlers("[all[shadows+tiddlers]tag[$:/tags/wikitext-serialize-test-spec]]");
               $tw.utils.each(cases, function (title) {
            -    wiki.addTiddler({
            -      title: title,
            -      text: wiki.getTiddlerText(title),
            -    });
            -    it("should serialize correctly for" + title, function () {
            -      var serialized = $tw.utils.serializeParseTree(wiki.parseTiddler(title).tree).trimEnd();
            -      expect(serialized).toBe(wiki.getTiddlerText(title).trimEnd());
            +    it("should serialize correctly for " + title, function () {
            +      var serialized = $tw.utils.serializeParseTree($tw.wiki.parseTiddler(title).tree).trimEnd();
            +      expect(serialized).toBe($tw.wiki.getTiddlerText(title).trimEnd());
                 });
               });
             });
            
            From 1a455209098a462e38c462d2028135e818709378 Mon Sep 17 00:00:00 2001
            From: lin onetwo 
            Date: Wed, 2 Oct 2024 13:47:41 +0800
            Subject: [PATCH 55/98] lint: double quote
            
            ---
             core/modules/parsers/parseutils.js            | 40 +++++++++----------
             core/modules/parsers/wikiparser/wikiparser.js |  2 +-
             2 files changed, 20 insertions(+), 22 deletions(-)
            
            diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js
            index b11300bfe..fcc96b2de 100644
            --- a/core/modules/parsers/parseutils.js
            +++ b/core/modules/parsers/parseutils.js
            @@ -386,33 +386,31 @@ exports.parseAttribute = function(source,pos) {
             };
             
             /*
            -Given a parsed attribute node, serialize it back into its source string representation.
            +Serialize a parsed attribute node
             */
             exports.serializeAttribute = function(node) {
            -	if(!node || typeof node !== 'object' || !node.name || !node.type) {
            -			return null;
            +	if(!node || typeof node !== "object" || !node.name || !node.type) {
            +		return null;
             	}
            -
             	var attributeString = node.name;
            -
            -	if(node.type === 'string') {
            -			if(node.value === 'true') {
            -					return attributeString;
            -			}
            -			attributeString += '="' + node.value + '"';
            -	} else if(node.type === 'filtered') {
            -			attributeString += '={{{' + node.filter + '}}}';
            -	} else if(node.type === 'indirect') {
            -			attributeString += '={{' + node.textReference + '}}';
            -	} else if(node.type === 'substituted') {
            -			attributeString += '=`' + node.rawValue + '`';
            -	} else if(node.type === 'macro') {
            -			// Assuming macro serialization is complex and handled elsewhere
            -			attributeString += '=' + node.value.serialize();
            +	if(node.type === "string") {
            +		if(node.value === "true") {
            +			return attributeString;
            +		}
            +		attributeString += '="' + node.value + '"';
            +	} else if(node.type === "filtered") {
            +		attributeString += "={{{" + node.filter + "}}}";
            +	} else if(node.type === "indirect") {
            +		attributeString += "={{" + node.textReference + "}}";
            +	} else if(node.type === "substituted") {
            +		attributeString += "=`" + node.rawValue + "`";
            +	} else if(node.type === "macro") {
            +		// Assuming macro serialization is complex and handled elsewhere
            +		attributeString += "=" + node.value.serialize();
             	} else {
            -			return null; // Unsupported type
            +		 // Unsupported type
            +		return null;
             	}
            -
             	return attributeString;
             };
             
            diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js
            index 10acf91ec..57f4983f9 100644
            --- a/core/modules/parsers/wikiparser/wikiparser.js
            +++ b/core/modules/parsers/wikiparser/wikiparser.js
            @@ -259,7 +259,7 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) {
             	var start = this.pos;
             	var children = this.parseInlineRun(terminatorRegExp);
             	var end = this.pos;
            -	return [{type: "element", tag: "p", children: children, start: start, end: end, rule: 'parseBlock' }];
            +	return [{type: "element", tag: "p", children: children, start: start, end: end, rule: "parseBlock" }];
             };
             
             /*
            
            From 1c50996a133b8840690d4ace0e68e73408c2a8ef Mon Sep 17 00:00:00 2001
            From: lin onetwo 
            Date: Wed, 2 Oct 2024 13:49:44 +0800
            Subject: [PATCH 56/98] refactor: lowercase the parseblock rule name
            
            ---
             core/modules/parsers/wikiparser/wikiparser.js |  2 +-
             core/modules/utils/parsetree.js               |  2 +-
             .../Parameterised-ParseTreeNodes.tid          |  2 +-
             .../tiddlers/tests/test-wikitext-parser.js    | 60 +++++++++----------
             4 files changed, 33 insertions(+), 33 deletions(-)
            
            diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js
            index 57f4983f9..68977c9d8 100644
            --- a/core/modules/parsers/wikiparser/wikiparser.js
            +++ b/core/modules/parsers/wikiparser/wikiparser.js
            @@ -259,7 +259,7 @@ WikiParser.prototype.parseBlock = function(terminatorRegExpString) {
             	var start = this.pos;
             	var children = this.parseInlineRun(terminatorRegExp);
             	var end = this.pos;
            -	return [{type: "element", tag: "p", children: children, start: start, end: end, rule: "parseBlock" }];
            +	return [{type: "element", tag: "p", children: children, start: start, end: end, rule: "parseblock" }];
             };
             
             /*
            diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js
            index 670d6307b..ad3f30150 100644
            --- a/core/modules/utils/parsetree.js
            +++ b/core/modules/utils/parsetree.js
            @@ -143,7 +143,7 @@ exports.serializeParseTree = function serializeParseTree(tree,tiddlerType) {
             				Parser.prototype.pragmaRuleClasses[tree.rule];
             			if(Rule && Rule.prototype.serialize) {
             				output.push(Rule.prototype.serialize(tree,serializeParseTree));
            -			} else if(tree.rule === "parseBlock") {
            +			} else if(tree.rule === "parseblock") {
             				output.push(serializeParseTree(tree.children,tiddlerType),"\n\n");
             			} else {
             				// when no rule is found, just serialize the children
            diff --git a/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid b/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid
            index 6db3f8be2..fc0d785f8 100644
            --- a/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid
            +++ b/editions/test/tiddlers/tests/data/transclude/Parameterised-ParseTreeNodes.tid
            @@ -26,4 +26,4 @@ title: TiddlerOne
             +
             title: ExpectedResult
             
            -

            [{"type":"element","tag":"p","children":[{"type":"text","text":"This is a block","start":68,"end":83}],"start":68,"end":83,"rule":"parseBlock"}]

            [{"type":"text","text":"This is inline","start":136,"end":152}]

            \ No newline at end of file +

            [{"type":"element","tag":"p","children":[{"type":"text","text":"This is a block","start":68,"end":83}],"start":68,"end":83,"rule":"parseblock"}]

            [{"type":"text","text":"This is inline","start":136,"end":152}]

            \ No newline at end of file diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index a3fe0d2d3..cdec74619 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -26,87 +26,87 @@ describe("WikiText parser tests", function() { it("should parse tags", function() { expect(parse("
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 4, children : [ { type : "element", tag : "br", start : 0, end : 4, openTagStart: 0, openTagEnd: 4, rule: "html", isBlock : false, attributes : { }, orderedAttributes: [ ] } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start : 0, end : 4, children : [ { type : "element", tag : "br", start : 0, end : 4, openTagStart: 0, openTagEnd: 4, rule: "html", isBlock : false, attributes : { }, orderedAttributes: [ ] } ] } ] ); expect(parse("
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 5, children : [ { type : "text", text : "
            ", start : 0, end : 5 } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start : 0, end : 5, children : [ { type : "text", text : "
            ", start : 0, end : 5 } ] } ] ); expect(parse("
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 5, children : [ { type : "element", tag : "div", start : 0, end : 5, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 5, rule: "html", isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ] } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start : 0, end : 5, children : [ { type : "element", tag : "div", start : 0, end : 5, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 5, rule: "html", isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ] } ] } ] ); expect(parse("
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 6, children : [ { type : "element", tag : "div", isSelfClosing : true, isBlock : false, attributes : { }, orderedAttributes: [ ], start : 0, end : 6, rule: "html" } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start : 0, end : 6, children : [ { type : "element", tag : "div", isSelfClosing : true, isBlock : false, attributes : { }, orderedAttributes: [ ], start : 0, end : 6, rule: "html" } ] } ] ); expect(parse("
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 11, children : [ { type : "element", tag : "div", isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ], start : 0, end : 11, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 11, rule: "html" } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start : 0, end : 11, children : [ { type : "element", tag : "div", isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ ], start : 0, end : 11, openTagStart: 0, openTagEnd: 5, closeTagStart: 5, closeTagEnd: 11, rule: "html" } ] } ] ); expect(parse("
            some text
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 20, children : [ { type : "element", tag : "div", openTagStart: 0, openTagEnd: 5, closeTagStart: 14, closeTagEnd: 20, rule: "html", isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ { type : "text", text : "some text", start : 5, end : 14 } ], start : 0, end : 20 } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start : 0, end : 20, children : [ { type : "element", tag : "div", openTagStart: 0, openTagEnd: 5, closeTagStart: 14, closeTagEnd: 20, rule: "html", isBlock : false, attributes : { }, orderedAttributes: [ ], children : [ { type : "text", text : "some text", start : 5, end : 14 } ], start : 0, end : 20 } ] } ] ); expect(parse("
            some text
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 30, children : [ { type : "element", tag : "div", isBlock : false, attributes : { attribute : { type : "string", value : "true", start : 4, end : 14, name: "attribute" } }, orderedAttributes: [ { type : "string", value : "true", start : 4, end : 14, name: "attribute" } ], children : [ { type : "text", text : "some text", start : 15, end : 24 } ], start : 0, end : 30, openTagStart: 0, openTagEnd: 15, closeTagStart: 24, closeTagEnd: 30, rule: "html" } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start : 0, end : 30, children : [ { type : "element", tag : "div", isBlock : false, attributes : { attribute : { type : "string", value : "true", start : 4, end : 14, name: "attribute" } }, orderedAttributes: [ { type : "string", value : "true", start : 4, end : 14, name: "attribute" } ], children : [ { type : "text", text : "some text", start : 15, end : 24 } ], start : 0, end : 30, openTagStart: 0, openTagEnd: 15, closeTagStart: 24, closeTagEnd: 30, rule: "html" } ] } ] ); expect(parse("
            some text
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 38, children : [ { type : "element", tag : "div", openTagStart: 0, openTagEnd: 23, closeTagStart: 32, closeTagEnd: 38, rule: "html", isBlock : false, attributes : { attribute : { type : "string", name: "attribute", value : "value", start: 4, end: 22 } }, orderedAttributes: [ { type: "string", name: "attribute", value : "value", start: 4, end: 22 } ], children : [ { type : "text", text : "some text", start : 23, end : 32 } ], start : 0, end : 38 } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start : 0, end : 38, children : [ { type : "element", tag : "div", openTagStart: 0, openTagEnd: 23, closeTagStart: 32, closeTagEnd: 38, rule: "html", isBlock : false, attributes : { attribute : { type : "string", name: "attribute", value : "value", start: 4, end: 22 } }, orderedAttributes: [ { type: "string", name: "attribute", value : "value", start: 4, end: 22 } ], children : [ { type : "text", text : "some text", start : 23, end : 32 } ], start : 0, end : 38 } ] } ] ); expect(parse("
            some text
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 47, children : [ { type : "element", tag : "div", isBlock : false, attributes : { attribute : { type : "indirect", name: "attribute", textReference : "TiddlerTitle", start : 4, end : 31 } }, orderedAttributes: [ { type : "indirect", name: "attribute", textReference : "TiddlerTitle", start : 4, end : 31 } ], children : [ { type : "text", text : "some text", start : 32, end : 41 } ], start : 0, end : 47, openTagStart: 0, openTagEnd: 32, closeTagStart: 41, closeTagEnd: 47, rule: "html" } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start: 0, end: 47, children : [ { type : "element", tag : "div", isBlock : false, attributes : { attribute : { type : "indirect", name: "attribute", textReference : "TiddlerTitle", start : 4, end : 31 } }, orderedAttributes: [ { type : "indirect", name: "attribute", textReference : "TiddlerTitle", start : 4, end : 31 } ], children : [ { type : "text", text : "some text", start : 32, end : 41 } ], start : 0, end : 47, openTagStart: 0, openTagEnd: 32, closeTagStart: 41, closeTagEnd: 47, rule: "html" } ] } ] ); expect(parse("<$reveal state='$:/temp/search' type='nomatch' text=''>")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 55, children : [ { type : "reveal", tag: "$reveal", rule: "html", attributes : { state : { start : 8, name : "state", type : "string", value : "$:/temp/search", end : 31 }, type : { start : 31, name : "type", type : "string", value : "nomatch", end : 46 }, text : { start : 46, name : "text", type : "string", value : "", end : 54 } }, orderedAttributes: [ { start : 8, name : "state", type : "string", value : "$:/temp/search", end : 31 }, { start : 31, name : "type", type : "string", value : "nomatch", end : 46 }, { start : 46, name : "text", type : "string", value : "", end : 54 } ], start: 0, end : 55, openTagStart: 0, openTagEnd: 55, closeTagStart: 55, closeTagEnd: 55, isBlock : false, children : [ ] } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start: 0, end: 55, children : [ { type : "reveal", tag: "$reveal", rule: "html", attributes : { state : { start : 8, name : "state", type : "string", value : "$:/temp/search", end : 31 }, type : { start : 31, name : "type", type : "string", value : "nomatch", end : 46 }, text : { start : 46, name : "text", type : "string", value : "", end : 54 } }, orderedAttributes: [ { start : 8, name : "state", type : "string", value : "$:/temp/search", end : 31 }, { start : 31, name : "type", type : "string", value : "nomatch", end : 46 }, { start : 46, name : "text", type : "string", value : "", end : 54 } ], start: 0, end : 55, openTagStart: 0, openTagEnd: 55, closeTagStart: 55, closeTagEnd: 55, isBlock : false, children : [ ] } ] } ] ); expect(parse("
            some text
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 54, children : [ { type : "element", tag : "div", rule: "html", isBlock : false, attributes : { attribute : { type : "indirect", name : "attribute", textReference : "TiddlerTitle!!field", start : 4, end : 38 } }, orderedAttributes: [ { type : "indirect", name : "attribute", textReference : "TiddlerTitle!!field", start : 4, end : 38 } ], children : [ { type : "text", text : "some text", start : 39, end : 48 } ], start : 0, end : 54, openTagStart: 0, openTagEnd: 39, closeTagStart: 48, closeTagEnd: 54 } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start: 0, end: 54, children : [ { type : "element", tag : "div", rule: "html", isBlock : false, attributes : { attribute : { type : "indirect", name : "attribute", textReference : "TiddlerTitle!!field", start : 4, end : 38 } }, orderedAttributes: [ { type : "indirect", name : "attribute", textReference : "TiddlerTitle!!field", start : 4, end : 38 } ], children : [ { type : "text", text : "some text", start : 39, end : 48 } ], start : 0, end : 54, openTagStart: 0, openTagEnd: 39, closeTagStart: 48, closeTagEnd: 54 } ] } ] ); expect(parse("
            some text
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 55, children : [ { type : "element", tag : "div", rule: "html", isBlock : false, attributes : { attribute : { type : "indirect", name : "attribute", textReference : "Tiddler Title!!field", start : 4, end : 39 } }, orderedAttributes: [ { type : "indirect", name : "attribute", textReference : "Tiddler Title!!field", start : 4, end : 39 } ], children : [ { type : "text", text : "some text", start : 40, end : 49 } ], start : 0, end : 55, openTagStart: 0, openTagEnd: 40, closeTagStart: 49, closeTagEnd: 55 } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start: 0, end: 55, children : [ { type : "element", tag : "div", rule: "html", isBlock : false, attributes : { attribute : { type : "indirect", name : "attribute", textReference : "Tiddler Title!!field", start : 4, end : 39 } }, orderedAttributes: [ { type : "indirect", name : "attribute", textReference : "Tiddler Title!!field", start : 4, end : 39 } ], children : [ { type : "text", text : "some text", start : 40, end : 49 } ], start : 0, end : 55, openTagStart: 0, openTagEnd: 40, closeTagStart: 49, closeTagEnd: 55 } ] } ] ); expect(parse("
            \n\nsome text
            ")).toEqual( - [ { type : "element", start : 0, attributes : { attribute : { start : 4, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 38 } }, orderedAttributes: [ { start : 4, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 38 } ], tag : "div", rule: "html", end : 56, openTagStart: 0, openTagEnd: 39, closeTagStart: 50, closeTagEnd: 56, isBlock : true, children : [ { type : "element", tag : "p", rule: "parseBlock", start : 41, end : 50, children : [ { type : "text", text : "some text", start : 41, end : 50 } ] } ] } ] + [ { type : "element", start : 0, attributes : { attribute : { start : 4, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 38 } }, orderedAttributes: [ { start : 4, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 38 } ], tag : "div", rule: "html", end : 56, openTagStart: 0, openTagEnd: 39, closeTagStart: 50, closeTagEnd: 56, isBlock : true, children : [ { type : "element", tag : "p", rule: "parseblock", start : 41, end : 50, children : [ { type : "text", text : "some text", start : 41, end : 50 } ] } ] } ] ); expect(parse("
            \n\nsome text
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 67, children : [ { type : "element", start : 0, end: 67, openTagStart: 0, openTagEnd: 5, closeTagStart: 61, closeTagEnd: 67, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { attribute : { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } }, orderedAttributes: [ { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } ], tag : "div", end : 61, openTagStart: 5, openTagEnd: 44, closeTagStart: 55, closeTagEnd: 61, rule: "html", isBlock : true, children : [ { type : "element", tag : "p", rule: "parseBlock", start : 46, end : 55, children : [ { type : "text", text : "some text", start : 46, end : 55 } ] } ] } ] } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start: 0, end: 67, children : [ { type : "element", start : 0, end: 67, openTagStart: 0, openTagEnd: 5, closeTagStart: 61, closeTagEnd: 67, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { attribute : { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } }, orderedAttributes: [ { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } ], tag : "div", end : 61, openTagStart: 5, openTagEnd: 44, closeTagStart: 55, closeTagEnd: 61, rule: "html", isBlock : true, children : [ { type : "element", tag : "p", rule: "parseblock", start : 46, end : 55, children : [ { type : "text", text : "some text", start : 46, end : 55 } ] } ] } ] } ] } ] ); expect(parse("
            \n\n!some heading
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 71, children : [ { type : "element", start : 0, end: 71, openTagStart: 0, openTagEnd: 5, closeTagStart: 71, closeTagEnd: 71, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { attribute : { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } }, orderedAttributes: [ { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } ], tag : "div", end : 71, openTagStart: 5, openTagEnd: 44, closeTagStart: 71, closeTagEnd: 71, rule: "html", isBlock : true, children : [ { type : "element", tag : "h1", start: 46, end: 71, rule: "heading", attributes : { class : { type : "string", value : "", start: 47, end: 47 } }, children : [ { type : "text", text : "some heading
            ", start : 47, end : 71 } ] } ] } ] } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start: 0, end: 71, children : [ { type : "element", start : 0, end: 71, openTagStart: 0, openTagEnd: 5, closeTagStart: 71, closeTagEnd: 71, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { attribute : { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } }, orderedAttributes: [ { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } ], tag : "div", end : 71, openTagStart: 5, openTagEnd: 44, closeTagStart: 71, closeTagEnd: 71, rule: "html", isBlock : true, children : [ { type : "element", tag : "h1", start: 46, end: 71, rule: "heading", attributes : { class : { type : "string", value : "", start: 47, end: 47 } }, children : [ { type : "text", text : "some heading", start : 47, end : 71 } ] } ] } ] } ] } ] ); expect(parse("
            \n!some heading
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 70, children : [ { type : "element", start : 0, end: 70, openTagStart: 0, openTagEnd: 5, closeTagStart: 64, closeTagEnd: 70, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { attribute : { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } }, orderedAttributes: [ { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } ], tag : "div", end : 64, openTagStart: 5, openTagEnd: 44, closeTagStart: 58, closeTagEnd: 64, rule: "html", isBlock : false, children : [ { type : "text", text : "\n!some heading", start : 44, end : 58 } ] } ] } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start: 0, end: 70, children : [ { type : "element", start : 0, end: 70, openTagStart: 0, openTagEnd: 5, closeTagStart: 64, closeTagEnd: 70, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { attribute : { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } }, orderedAttributes: [ { start : 9, name : "attribute", type : "indirect", textReference : "TiddlerTitle!!field", end : 43 } ], tag : "div", end : 64, openTagStart: 5, openTagEnd: 44, closeTagStart: 58, closeTagEnd: 64, rule: "html", isBlock : false, children : [ { type : "text", text : "\n!some heading", start : 44, end : 58 } ] } ] } ] } ] ); // Regression test for issue (#3306) expect(parse("
            \n\nSome text
            ")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start: 0, end: 48, children : [ { type : "element", start : 0, end: 48, openTagStart: 0, openTagEnd: 5, closeTagStart: 42, closeTagEnd: 48, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { }, orderedAttributes: [ ], tag : "span", end : 42, openTagStart: 5, openTagEnd: 11, closeTagStart: 35, closeTagEnd: 42, rule: "html", isBlock : false, children : [ { type : "element", start : 11, attributes : { }, orderedAttributes: [ ], tag : "span", end : 35, openTagStart: 11, openTagEnd: 17, closeTagStart: 28, closeTagEnd: 35, rule: "html", isBlock : true, children : [ { type : "element", tag : "p", rule: "parseBlock", start : 19, end : 28, children : [ { type : "text", text : "Some text", start : 19, end : 28 } ] } ] } ] } ] } ] } ] + [ { type : "element", tag : "p", rule: "parseblock", start: 0, end: 48, children : [ { type : "element", start : 0, end: 48, openTagStart: 0, openTagEnd: 5, closeTagStart: 42, closeTagEnd: 48, attributes : { }, orderedAttributes: [ ], tag : "div", rule: "html", isBlock : false, children : [ { type : "element", start : 5, attributes : { }, orderedAttributes: [ ], tag : "span", end : 42, openTagStart: 5, openTagEnd: 11, closeTagStart: 35, closeTagEnd: 42, rule: "html", isBlock : false, children : [ { type : "element", start : 11, attributes : { }, orderedAttributes: [ ], tag : "span", end : 35, openTagStart: 11, openTagEnd: 17, closeTagStart: 28, closeTagEnd: 35, rule: "html", isBlock : true, children : [ { type : "element", tag : "p", rule: "parseblock", start : 19, end : 28, children : [ { type : "text", text : "Some text", start : 19, end : 28 } ] } ] } ] } ] } ] } ] ); }); @@ -206,38 +206,38 @@ describe("WikiText parser tests", function() { it("should parse inline macro calls", function() { expect(parse("<><><><>")).toEqual( - [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"transclude","start":8,"end":16,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"paul"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"paul"}]},{"type":"transclude","start":16,"end":26,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"george"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"george"}]},{"type":"transclude","start":26,"end":35,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"ringo"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"ringo"}]}],"start":0,"end":35}] + [{"type":"element","tag":"p",rule:"parseblock","children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"transclude","start":8,"end":16,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"paul"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"paul"}]},{"type":"transclude","start":16,"end":26,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"george"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"george"}]},{"type":"transclude","start":26,"end":35,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"ringo"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"ringo"}]}],"start":0,"end":35}] ); expect(parse("text <>")).toEqual( - [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},"three":{"name":"three","type":"string","value":"val '3'","start":35,"end":52},"four":{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},"five":{"name":"five","type":"string","value":"val 5","start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":11,"end":20},{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},{"name":"three","type":"string","value":"val '3'","start":35,"end":52},{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},{"name":"five","type":"string","value":"val 5","start":73,"end":89}]}],"start":0,"end":92}] + [{"type":"element","tag":"p",rule:"parseblock","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":92,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"},"one":{"name":"one","type":"string","value":"val1","start":11,"end":20},"two":{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},"three":{"name":"three","type":"string","value":"val '3'","start":35,"end":52},"four":{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},"five":{"name":"five","type":"string","value":"val 5","start":73,"end":89}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"one","type":"string","value":"val1","start":11,"end":20},{"name":"two","type":"string","value":"val \"2\"","start":20,"end":35},{"name":"three","type":"string","value":"val '3'","start":35,"end":52},{"name":"four","type":"string","value":"val 4\"5'","start":52,"end":73},{"name":"five","type":"string","value":"val 5","start":73,"end":89}]}],"start":0,"end":92}] ); expect(parse("ignored << carrots <>")).toEqual( - [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"text","text":"ignored << carrots ","start":0,"end":19},{"type":"transclude","start":19,"end":27,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":27}] + [{"type":"element","tag":"p",rule:"parseblock","children":[{"type":"text","text":"ignored << carrots ","start":0,"end":19},{"type":"transclude","start":19,"end":27,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":27}] ); expect(parse("text <<>")).toEqual( - [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":14,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":">")).toEqual( - [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"text","text":"before\n","start":0,"end":7},{"type":"transclude","start":7,"end":15,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":15}] + [{"type":"element","tag":"p",rule:"parseblock","children":[{"type":"text","text":"before\n","start":0,"end":7},{"type":"transclude","start":7,"end":15,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]}],"start":0,"end":15}] ); // A single space will cause it to be inline expect(parse("<> ")).toEqual( - [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"text","text":" ","start":8,"end":9}],"start":0,"end":9}] + [{"type":"element","tag":"p",rule:"parseblock","children":[{"type":"transclude","start":0,"end":8,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"}]},{"type":"text","text":" ","start":8,"end":9}],"start":0,"end":9}] ); expect(parse("text <>' >>")).toEqual( - [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","type":"string","value":"my <>","start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","type":"string","value":"my <>","start":12,"end":31}]}],"start":0,"end":34}] + [{"type":"element","tag":"p",rule:"parseblock","children":[{"type":"text","text":"text ","start":0,"end":5},{"type":"transclude","start":5,"end":34,"rule":"macrocallinline","attributes":{"$variable":{"name":"$variable","type":"string","value":"outie"},"one":{"name":"one","type":"string","value":"my <>","start":12,"end":31}},"orderedAttributes":[{"name":"$variable","type":"string","value":"outie"},{"name":"one","type":"string","value":"my <>","start":12,"end":31}]}],"start":0,"end":34}] ); @@ -256,17 +256,17 @@ describe("WikiText parser tests", function() { ); expect(parse("<< carrots\n\n<>")).toEqual( - [ { type: "element", tag: "p", rule: "parseBlock", start : 0, end : 10, children: [ { type: "text", text: "<< carrots", start : 0, end : 10 } ] }, { type: "transclude", start: 12, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 20, isBlock: true } ] + [ { type: "element", tag: "p", rule: "parseblock", start : 0, end : 10, children: [ { type: "text", text: "<< carrots", start : 0, end : 10 } ] }, { type: "transclude", start: 12, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 20, isBlock: true } ] ); expect(parse("before\n\n<>")).toEqual( - [ { type: "element", tag: "p", rule: "parseBlock", start : 0, end : 6, children: [ { type: "text", text: "before", start : 0, end : 6 } ] }, { type: "transclude", start: 8, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 16, isBlock: true } ] + [ { type: "element", tag: "p", rule: "parseblock", start : 0, end : 6, children: [ { type: "text", text: "before", start : 0, end : 6 } ] }, { type: "transclude", start: 8, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 16, isBlock: true } ] ); expect(parse("<>\nafter")).toEqual( - [ { type: "transclude", start: 0, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 8, isBlock: true }, { type: "element", tag: "p", rule: "parseBlock", start: 9, end: 14, children: [ { type: "text", text: "after", start: 9, end: 14 } ] } ] + [ { type: "transclude", start: 0, rule: "macrocallblock", attributes: { $variable: {name: "$variable", type:"string", value: "john"} }, orderedAttributes: [ {name: "$variable", type:"string", value: "john"} ], end: 8, isBlock: true }, { type: "element", tag: "p", rule: "parseblock", start: 9, end: 14, children: [ { type: "text", text: "after", start: 9, end: 14 } ] } ] ); expect(parse("<>")).toEqual( @@ -294,7 +294,7 @@ describe("WikiText parser tests", function() { ); expect(parse("<>>")).toEqual( - [{"type":"element","tag":"p",rule:"parseBlock","children":[{"type":"transclude","start":0,"end":14,"rule":"macrocallinline","attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}] + [{"type":"element","tag":"p",rule:"parseblock","children":[{"type":"transclude","start":0,"end":14,"rule":"macrocallinline","attributes":{"0":{"name":"0","type":"string","value":"param","start":6,"end":12},"$variable":{"name":"$variable","type":"string","value":"john"}},"orderedAttributes":[{"name":"$variable","type":"string","value":"john"},{"name":"0","type":"string","value":"param","start":6,"end":12}]},{"type":"text","text":">","start":14,"end":15}],"start":0,"end":15}] ); // equals signs should be allowed @@ -309,7 +309,7 @@ describe("WikiText parser tests", function() { it("should parse horizontal rules", function() { expect(parse("---Not a rule\n\n----\n\nBetween\n\n---")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", start : 0, end : 13, children : [ { type : "entity", entity : "—", start: 0, end: 3, rule: "dash" }, { type : "text", text : "Not a rule", start : 3, end : 13 } ] }, { type : "element", tag : "hr", start: 15, end: 20, rule: "horizrule" }, { type : "element", tag : "p", rule: "parseBlock", start : 21, end : 28, children : [ { type : "text", text : "Between", start : 21, end : 28 } ] }, { type : "element", tag : "hr", start: 30, end: 33, rule: "horizrule" } ] + [ { type : "element", tag : "p", rule: "parseblock", start : 0, end : 13, children : [ { type : "entity", entity : "—", start: 0, end: 3, rule: "dash" }, { type : "text", text : "Not a rule", start : 3, end : 13 } ] }, { type : "element", tag : "hr", start: 15, end: 20, rule: "horizrule" }, { type : "element", tag : "p", rule: "parseblock", start : 21, end : 28, children : [ { type : "text", text : "Between", start : 21, end : 28 } ] }, { type : "element", tag : "hr", start: 30, end: 33, rule: "horizrule" } ] ); @@ -318,7 +318,7 @@ describe("WikiText parser tests", function() { it("should parse hard linebreak areas", function() { expect(parse("\"\"\"Something\nin the\nway she moves\n\"\"\"\n\n")).toEqual( - [ { type : "element", tag : "p", rule: "parseBlock", children : [ { type : "text", text : "Something", start : 3, end : 12, rule: "hardlinebreaks", isRuleStart: true }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 12, end: 13 }, { type : "text", text : "in the", start : 13, end : 19, rule: "hardlinebreaks" }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 19, end: 20 }, { type : "text", text : "way she moves", start : 20, end : 33, rule: "hardlinebreaks" }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 33, end: 34, isRuleEnd: true } ], start : 0, end : 37 } ] + [ { type : "element", tag : "p", rule: "parseblock", children : [ { type : "text", text : "Something", start : 3, end : 12, rule: "hardlinebreaks", isRuleStart: true }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 12, end: 13 }, { type : "text", text : "in the", start : 13, end : 19, rule: "hardlinebreaks" }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 19, end: 20 }, { type : "text", text : "way she moves", start : 20, end : 33, rule: "hardlinebreaks" }, { type : "element", tag : "br", rule: "hardlinebreaks", start: 33, end: 34, isRuleEnd: true } ], start : 0, end : 37 } ] ); From f0babe4388377bba53dd1cc14e7bb950dc1fa0ad Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 03:13:51 +0800 Subject: [PATCH 57/98] fix: Wiki parser initialize blockRuleClasses only when first new an instance --- core/modules/utils/parsetree.js | 25 +++++++++++++++++++++++-- core/modules/wiki.js | 18 +----------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/core/modules/utils/parsetree.js b/core/modules/utils/parsetree.js index ad3f30150..9940b1c17 100644 --- a/core/modules/utils/parsetree.js +++ b/core/modules/utils/parsetree.js @@ -123,11 +123,28 @@ exports.getParseTreeText = function getParseTreeText(tree) { return output.join(""); }; +exports.getParser = function(type,options) { + options = options || {}; + // Select a parser + var Parser = $tw.Wiki.parsers[type]; + if(!Parser && $tw.utils.getFileExtensionInfo(type)) { + Parser = $tw.Wiki.parsers[$tw.utils.getFileExtensionInfo(type).type]; + } + if(!Parser) { + Parser = $tw.Wiki.parsers[options.defaultType || "text/vnd.tiddlywiki"]; + } + if(!Parser) { + return null; + } + return Parser; +}; + /* Utility to get the (similarly but not 1:1 equal) original wikitext of a parse tree node or array of nodes. Based on `node.rule` metadata added in `wikiparser.js`. */ -exports.serializeParseTree = function serializeParseTree(tree,tiddlerType) { +exports.serializeParseTree = function serializeParseTree(tree,tiddlerType,options) { + options = options || {}; var output = []; if($tw.utils.isArray(tree)) { $tw.utils.each(tree,function(node) { @@ -137,7 +154,11 @@ exports.serializeParseTree = function serializeParseTree(tree,tiddlerType) { if(tree.type === "text" && !tree.rule) { output.push(tree.text); } else { - var Parser = $tw.wiki.getParser(tiddlerType); + var Parser = $tw.utils.getParser(tiddlerType); + if(!Parser.prototype.blockRuleClasses && !Parser.prototype.inlineRuleClasses && !Parser.prototype.pragmaRuleClasses) { + // Wiki parser initialize blockRuleClasses when first new an instance + new Parser(tiddlerType,undefined,{wiki: options.wiki || $tw.wiki}); + } var Rule = Parser.prototype.blockRuleClasses[tree.rule] || Parser.prototype.inlineRuleClasses[tree.rule] || Parser.prototype.pragmaRuleClasses[tree.rule]; diff --git a/core/modules/wiki.js b/core/modules/wiki.js index 516751a1a..588deef2a 100755 --- a/core/modules/wiki.js +++ b/core/modules/wiki.js @@ -1053,7 +1053,7 @@ Options include: exports.parseText = function(type,text,options) { text = text || ""; options = options || {}; - var Parser = this.getParser(type,options) + var Parser = $tw.utils.getParser(type,options) // Return the parser instance return new Parser(type,text,{ parseAsInline: options.parseAsInline, @@ -1063,22 +1063,6 @@ exports.parseText = function(type,text,options) { }); }; -exports.getParser = function(type,options) { - options = options || {}; - // Select a parser - var Parser = $tw.Wiki.parsers[type]; - if(!Parser && $tw.utils.getFileExtensionInfo(type)) { - Parser = $tw.Wiki.parsers[$tw.utils.getFileExtensionInfo(type).type]; - } - if(!Parser) { - Parser = $tw.Wiki.parsers[options.defaultType || "text/vnd.tiddlywiki"]; - } - if(!Parser) { - return null; - } - return Parser; -}; - /* Parse a tiddler according to its MIME type */ From 375df47b19a4bf56406854887ee726dcd8432674 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 03:26:35 +0800 Subject: [PATCH 58/98] feat: restore inline macro def --- core/modules/parsers/wikiparser/rules/macrodef.js | 9 +++++++-- editions/test/tiddlers/tests/data/serialize/MacroDef.tid | 4 +++- editions/test/tiddlers/tests/test-wikitext-parser.js | 9 +++++++-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js index be000eab0..3fe2195f6 100644 --- a/core/modules/parsers/wikiparser/rules/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/macrodef.js @@ -55,9 +55,10 @@ exports.parse = function() { } } // Is the remainder of the \define line blank after the parameter close paren? - var reEnd; + var reEnd,inline = true; if(this.match[3]) { // If so, it is a multiline definition and the end of the body is marked with \end + inline = false; reEnd = new RegExp("((?:^|\\r?\\n)[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?(?:$|\\r?\\n))","mg"); } else { // Otherwise, the end of the definition is marked by the end of the line @@ -82,7 +83,8 @@ exports.parse = function() { attributes: {}, children: [], params: params, - isMacroDefinition: true + isMacroDefinition: true, + inline: inline && !!endMatch }]; $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[1]); $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text); @@ -95,6 +97,9 @@ exports.serialize = function(tree,serialize) { return param.name + (param.default ? ":" + param.default : ""); }).join(","); var definition = tree.attributes.value.value; + if(tree.inline) { + return "\\define " + name + "(" + params + ") " + definition + "\n\n" + serialize(tree.children); + } return "\\define " + name + "(" + params + ")\n" + definition + "\n\\end\n\n" + serialize(tree.children); }; diff --git a/editions/test/tiddlers/tests/data/serialize/MacroDef.tid b/editions/test/tiddlers/tests/data/serialize/MacroDef.tid index dcbc02e9d..132ee7053 100644 --- a/editions/test/tiddlers/tests/data/serialize/MacroDef.tid +++ b/editions/test/tiddlers/tests/data/serialize/MacroDef.tid @@ -4,4 +4,6 @@ type: text/vnd.tiddlywiki \define name(param:defaultvalue,param2:defaultvalue) definition text, including $param$ markers -\end \ No newline at end of file +\end + +\define lingo-base() $:/language/ControlPanel/Basics/ diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index cdec74619..72136475f 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -114,7 +114,12 @@ describe("WikiText parser tests", function() { it("should parse macro definitions", function() { expect(parse("\\define myMacro()\nnothing\n\\end\n")).toEqual( - [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":30,"rule":"macrodef"}] + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"inline":false,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":30,"rule":"macrodef"}] + + ); + expect(parse("\\define myMacro() nothing\n\n")).toEqual( + + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"inline":true,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":25,"rule":"macrodef"}] ); }); @@ -185,7 +190,7 @@ describe("WikiText parser tests", function() { it("should parse comment in pragma area. Comment will be invisible", function() { expect(parse("\n\\define aMacro()\nnothing\n\\end\n")).toEqual( - [{"type":"void","children":[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}],"start":32,"end":61,"rule":"macrodef"}],"text":"","start":0,"end":31,"rule":"commentblock"}] + [{"type":"void","children":[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"inline":false,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}],"start":32,"end":61,"rule":"macrodef"}],"text":"","start":0,"end":31,"rule":"commentblock"}] ); }); From 53296a484ce92a4b48cf52f3089e63a81a422067 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 20:55:03 +0800 Subject: [PATCH 59/98] fix: macro in widget param --- core/modules/parsers/parseutils.js | 11 +++++++++-- core/modules/parsers/wikiparser/rules/html.js | 6 +++--- .../test/tiddlers/tests/data/serialize/Attribute.tid | 5 +++++ 3 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 editions/test/tiddlers/tests/data/serialize/Attribute.tid diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js index fcc96b2de..e2e95c684 100644 --- a/core/modules/parsers/parseutils.js +++ b/core/modules/parsers/parseutils.js @@ -405,8 +405,15 @@ exports.serializeAttribute = function(node) { } else if(node.type === "substituted") { attributeString += "=`" + node.rawValue + "`"; } else if(node.type === "macro") { - // Assuming macro serialization is complex and handled elsewhere - attributeString += "=" + node.value.serialize(); + if(node.value && typeof node.value === "object" && node.value.type === "macrocall") { + var params = node.value.params.map(function(param) { + return param.value; + }).join(" "); + attributeString += "=<<" + node.value.name + " " + params + ">>"; + } else { + // Unsupported macro structure + return null; + } } else { // Unsupported type return null; diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index df52819e2..e27089086 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -197,9 +197,9 @@ exports.isLegalTag = function(tag) { exports.serialize = function(tree, serialize) { var tag = tree.tag; - var attributes = Object.keys(tree.attributes).map(function(key) { - return key + '="' + tree.attributes[key].value + '"'; - }).join(""); + var attributes = tree.orderedAttributes.map(function(attribute) { + return $tw.utils.serializeAttribute(attribute); + }).join(" "); // Children var children = tree.children ? serialize(tree.children) : ""; // Self-closing tag diff --git a/editions/test/tiddlers/tests/data/serialize/Attribute.tid b/editions/test/tiddlers/tests/data/serialize/Attribute.tid new file mode 100644 index 000000000..6ecda2c01 --- /dev/null +++ b/editions/test/tiddlers/tests/data/serialize/Attribute.tid @@ -0,0 +1,5 @@ +tags: $:/tags/wikitext-serialize-test-spec +title: Serialize/Attribute +type: text/vnd.tiddlywiki + +<$macrocall $name="rpn" a=<> b="pi" operation="*" decimals="4" /> From 72dd18dfa539d1773231377d7dc7ca703a6e32ec Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 21:31:29 +0800 Subject: [PATCH 60/98] fix: positional attribute in macro call --- core/modules/parsers/parseutils.js | 19 ++++++++++++------- .../wikiparser/rules/macrocallblock.js | 6 +++--- .../tests/data/serialize/MacroCallBlock.tid | 4 +++- .../tests/data/serialize/MacroCallInline.tid | 2 +- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/core/modules/parsers/parseutils.js b/core/modules/parsers/parseutils.js index e2e95c684..8d143c5e9 100644 --- a/core/modules/parsers/parseutils.js +++ b/core/modules/parsers/parseutils.js @@ -388,28 +388,33 @@ exports.parseAttribute = function(source,pos) { /* Serialize a parsed attribute node */ -exports.serializeAttribute = function(node) { +exports.serializeAttribute = function(node,options) { + options = options || {}; if(!node || typeof node !== "object" || !node.name || !node.type) { return null; } - var attributeString = node.name; + // If name is number, means it is a positional attribute and name is omitted + var positional = parseInt(node.name) >= 0, + // `=` in a widget and might be `:` in a macro + assign = positional ? "" : (options.assignmentSymbol || "="), + attributeString = positional ? "" : node.name; if(node.type === "string") { if(node.value === "true") { return attributeString; } - attributeString += '="' + node.value + '"'; + attributeString += assign + '"' + node.value + '"'; } else if(node.type === "filtered") { - attributeString += "={{{" + node.filter + "}}}"; + attributeString += assign + "{{{" + node.filter + "}}}"; } else if(node.type === "indirect") { - attributeString += "={{" + node.textReference + "}}"; + attributeString += assign + "{{" + node.textReference + "}}"; } else if(node.type === "substituted") { - attributeString += "=`" + node.rawValue + "`"; + attributeString += assign + "`" + node.rawValue + "`"; } else if(node.type === "macro") { if(node.value && typeof node.value === "object" && node.value.type === "macrocall") { var params = node.value.params.map(function(param) { return param.value; }).join(" "); - attributeString += "=<<" + node.value.name + " " + params + ">>"; + attributeString += assign + "<<" + node.value.name + " " + params + ">>"; } else { // Unsupported macro structure return null; diff --git a/core/modules/parsers/wikiparser/rules/macrocallblock.js b/core/modules/parsers/wikiparser/rules/macrocallblock.js index 1572cce63..a684a2d28 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallblock.js +++ b/core/modules/parsers/wikiparser/rules/macrocallblock.js @@ -64,9 +64,9 @@ exports.serialize = function (node) { } // Append ordered arguments if any if(node.orderedAttributes) { - node.orderedAttributes.forEach(function (attr) { - if(attr.name !== "$variable") { - result += " " + '"' + attr.value + '"'; + node.orderedAttributes.forEach(function (attribute) { + if(attribute.name !== "$variable") { + result += " " + $tw.utils.serializeAttribute(attribute,{assignmentSymbol:":"}); } }); } diff --git a/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid b/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid index 723e23edd..4bd30d451 100644 --- a/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid +++ b/editions/test/tiddlers/tests/data/serialize/MacroCallBlock.tid @@ -4,4 +4,6 @@ type: text/vnd.tiddlywiki <> -<<.def "macro calls">> \ No newline at end of file +<<.def "macro calls">> + +<> diff --git a/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid b/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid index 0b6b4fc50..09127dce0 100644 --- a/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid +++ b/editions/test/tiddlers/tests/data/serialize/MacroCallInline.tid @@ -2,4 +2,4 @@ tags: $:/tags/wikitext-serialize-test-spec title: Serialize/MacroCallInline type: text/vnd.tiddlywiki -These are macro calls in a line: <> and <<.def "macro calls">> \ No newline at end of file +These are macro calls in a line: <> and <<.def "macro calls">> <> From fb9f7a5ea1c3b413aec25f2e0ddba28d1d398888 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 21:31:51 +0800 Subject: [PATCH 61/98] fix: table space and horizrule block new line --- core/modules/parsers/wikiparser/rules/codeblock.js | 2 +- core/modules/parsers/wikiparser/rules/horizrule.js | 2 +- core/modules/parsers/wikiparser/rules/table.js | 10 +++++----- .../test/tiddlers/tests/data/serialize/CodeBlock.tid | 5 +++++ editions/test/tiddlers/tests/data/serialize/Table.tid | 11 +++++++---- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/codeblock.js b/core/modules/parsers/wikiparser/rules/codeblock.js index 99e25af55..aae047316 100644 --- a/core/modules/parsers/wikiparser/rules/codeblock.js +++ b/core/modules/parsers/wikiparser/rules/codeblock.js @@ -58,7 +58,7 @@ exports.parse = function() { }; exports.serialize = function(tree,serialize) { - return "\n```" + tree.attributes.language.value + "\n" + tree.attributes.code.value + "\n```\n"; + return "```" + tree.attributes.language.value + "\n" + tree.attributes.code.value + "\n```\n\n"; } })(); diff --git a/core/modules/parsers/wikiparser/rules/horizrule.js b/core/modules/parsers/wikiparser/rules/horizrule.js index 4fd66de41..386a0aaef 100644 --- a/core/modules/parsers/wikiparser/rules/horizrule.js +++ b/core/modules/parsers/wikiparser/rules/horizrule.js @@ -32,7 +32,7 @@ exports.parse = function() { }; exports.serialize = function(tree,serialize) { - return "---\n"; + return "---\n\n"; } })(); diff --git a/core/modules/parsers/wikiparser/rules/table.js b/core/modules/parsers/wikiparser/rules/table.js index 68811efc0..2c6f4356a 100644 --- a/core/modules/parsers/wikiparser/rules/table.js +++ b/core/modules/parsers/wikiparser/rules/table.js @@ -205,17 +205,17 @@ exports.serialize = function(tree, serialize) { if(cell.tag === "th") { serialized += "!"; } - // Serialize the cell content + // Cell content serialized += serialize(cell.children); - // End the cell with a tailing space - serialized += " |"; + // End the cell + serialized += "|"; } // End the row serialized += "\n"; } } - // Return the complete serialized string - return serialized; + // Return the completed block + return serialized + "\n"; }; })(); diff --git a/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid b/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid index 8b1499970..7a03f3aea 100644 --- a/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid +++ b/editions/test/tiddlers/tests/data/serialize/CodeBlock.tid @@ -9,4 +9,9 @@ Simple `JS` and complex ```js var match = reEnd.exec(this.parser.source) ``` + +```tid +<$list filter="[tag[ExampleTag]sort[title]]"/> +``` + end \ No newline at end of file diff --git a/editions/test/tiddlers/tests/data/serialize/Table.tid b/editions/test/tiddlers/tests/data/serialize/Table.tid index 213ecebff..bd92db4bc 100644 --- a/editions/test/tiddlers/tests/data/serialize/Table.tid +++ b/editions/test/tiddlers/tests/data/serialize/Table.tid @@ -2,7 +2,10 @@ tags: $:/tags/wikitext-serialize-test-spec title: Serialize/Table type: text/vnd.tiddlywiki -|! |!Alpha |!Beta |!Gamma |!Delta | -|!One | | | | | -|!Two | | | | | -|!Three | | | | | \ No newline at end of file +|!|!Alpha|!Beta|!Gamma|!Delta| +|!One||||| +|!Two||||| +|!Three||||| + +|cell one|cell two| +|cell three|cell four| From 47cc03d05db1c07e124f54347299274c061dc5b9 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 21:36:35 +0800 Subject: [PATCH 62/98] feat: make sure block rule all have \n\n for visiblity --- .../parsers/wikiparser/rules/conditional.js | 2 +- .../rules/filteredtranscludeblock.js | 2 +- .../parsers/wikiparser/rules/heading.js | 2 +- .../parsers/wikiparser/rules/quoteblock.js | 2 +- .../serialize/FilteredTranscludeBlock.tid | 6 +++++- .../tiddlers/tests/data/serialize/Heading.tid | 21 ++++++++++++++++++- 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js index 84ac3cef8..6f884de1c 100644 --- a/core/modules/parsers/wikiparser/rules/conditional.js +++ b/core/modules/parsers/wikiparser/rules/conditional.js @@ -139,7 +139,7 @@ exports.serialize = function(tree, serialize) { } serialized += "<%endif%>"; - return serialized; + return serialized += "\n\n"; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js index 994596855..553d68c0e 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js @@ -83,7 +83,7 @@ exports.serialize = function(tree, serialize) { serialized += "}" // CSS classes if(tree.attributes.itemClass) serialized += "." + tree.attributes.itemClass.value.split(" ").join("."); - return serialized + "\n"; + return serialized + "\n\n"; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/heading.js b/core/modules/parsers/wikiparser/rules/heading.js index 67470c9c5..70b58e71d 100644 --- a/core/modules/parsers/wikiparser/rules/heading.js +++ b/core/modules/parsers/wikiparser/rules/heading.js @@ -51,7 +51,7 @@ exports.serialize = function(tree, serialize) { var headingLevel = parseInt(tree.tag.substr(1),10); var classes = tree.attributes.class ? tree.attributes.class.value.split(" ").join(".") : ""; var headingText = serialize(tree.children); - return Array(headingLevel + 1).join("!") + (classes ? "." + classes : "") + " " + headingText + "\n"; + return Array(headingLevel + 1).join("!") + (classes ? "." + classes : "") + " " + headingText + "\n\n"; }; })(); diff --git a/core/modules/parsers/wikiparser/rules/quoteblock.js b/core/modules/parsers/wikiparser/rules/quoteblock.js index be7052795..a652cdf1b 100644 --- a/core/modules/parsers/wikiparser/rules/quoteblock.js +++ b/core/modules/parsers/wikiparser/rules/quoteblock.js @@ -85,7 +85,7 @@ exports.serialize = function (tree, serialize) { }); result.push("<<<"); } - return result.join("\n"); + return result.join("\n") + "\n\n"; }; })(); diff --git a/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid b/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid index cbfc442c5..b1c526d9d 100644 --- a/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid +++ b/editions/test/tiddlers/tests/data/serialize/FilteredTranscludeBlock.tid @@ -3,7 +3,11 @@ title: Serialize/FilteredTranscludeBlock type: text/vnd.tiddlywiki {{{ [tag[docs]] }}} + {{{ [tag[docs]] |tooltip}}} + {{{ [tag[docs]] ||TemplateTitle}}} + {{{ [tag[docs]] |tooltip||TemplateTitle}}} -{{{ [tag[docs]] }}width:40;height:50;}.class.class \ No newline at end of file + +{{{ [tag[docs]] }}width:40;height:50;}.class.class diff --git a/editions/test/tiddlers/tests/data/serialize/Heading.tid b/editions/test/tiddlers/tests/data/serialize/Heading.tid index 8f90e379a..34152e50a 100644 --- a/editions/test/tiddlers/tests/data/serialize/Heading.tid +++ b/editions/test/tiddlers/tests/data/serialize/Heading.tid @@ -3,8 +3,27 @@ title: Serialize/Heading type: text/vnd.tiddlywiki ! Heading 1 + !! Heading 2 + !!! Heading 3 + !!!! Heading 4 + !!!!! Heading 5 -!!!!!! Heading 6 \ No newline at end of file + +!!!!!! Heading 6 + +! AAA + +!! AAA + +!!! AAA + +!!!! AAA + +!!!!! AAA + +!!!!!! AAA + +AAA From 8056d8c11e570ebf76bcdebd37938ad960fdbe64 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 21:38:06 +0800 Subject: [PATCH 63/98] lint: function param --- core/modules/parsers/wikiparser/rules/commentblock.js | 2 +- core/modules/parsers/wikiparser/rules/commentinline.js | 2 +- core/modules/parsers/wikiparser/rules/conditional.js | 2 +- core/modules/parsers/wikiparser/rules/dash.js | 2 +- core/modules/parsers/wikiparser/rules/emphasis/bold.js | 2 +- core/modules/parsers/wikiparser/rules/emphasis/italic.js | 2 +- .../parsers/wikiparser/rules/emphasis/strikethrough.js | 2 +- core/modules/parsers/wikiparser/rules/emphasis/subscript.js | 2 +- core/modules/parsers/wikiparser/rules/emphasis/superscript.js | 2 +- core/modules/parsers/wikiparser/rules/emphasis/underscore.js | 2 +- core/modules/parsers/wikiparser/rules/entity.js | 2 +- core/modules/parsers/wikiparser/rules/extlink.js | 2 +- .../parsers/wikiparser/rules/filteredtranscludeblock.js | 2 +- .../parsers/wikiparser/rules/filteredtranscludeinline.js | 4 ++-- core/modules/parsers/wikiparser/rules/fnprocdef.js | 2 +- core/modules/parsers/wikiparser/rules/heading.js | 2 +- core/modules/parsers/wikiparser/rules/html.js | 2 +- core/modules/parsers/wikiparser/rules/image.js | 2 +- core/modules/parsers/wikiparser/rules/list.js | 2 +- core/modules/parsers/wikiparser/rules/macrocallinline.js | 4 ++-- core/modules/parsers/wikiparser/rules/prettyextlink.js | 2 +- core/modules/parsers/wikiparser/rules/prettylink.js | 2 +- core/modules/parsers/wikiparser/rules/quoteblock.js | 2 +- core/modules/parsers/wikiparser/rules/rules.js | 2 +- core/modules/parsers/wikiparser/rules/styleblock.js | 2 +- core/modules/parsers/wikiparser/rules/styleinline.js | 2 +- core/modules/parsers/wikiparser/rules/syslink.js | 2 +- core/modules/parsers/wikiparser/rules/table.js | 2 +- core/modules/parsers/wikiparser/rules/transcludeblock.js | 2 +- core/modules/parsers/wikiparser/rules/transcludeinline.js | 4 ++-- core/modules/parsers/wikiparser/rules/typedblock.js | 2 +- core/modules/parsers/wikiparser/rules/wikilink.js | 2 +- core/modules/parsers/wikiparser/rules/wikilinkprefix.js | 2 +- 33 files changed, 36 insertions(+), 36 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 7d9a68f14..997be818c 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -63,7 +63,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { return tree.text + "\n\n" + serialize(tree.children); }; diff --git a/core/modules/parsers/wikiparser/rules/commentinline.js b/core/modules/parsers/wikiparser/rules/commentinline.js index 183eea447..f39d9f6ff 100644 --- a/core/modules/parsers/wikiparser/rules/commentinline.js +++ b/core/modules/parsers/wikiparser/rules/commentinline.js @@ -55,7 +55,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { return tree.text; }; diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js index 6f884de1c..6f30ef3a3 100644 --- a/core/modules/parsers/wikiparser/rules/conditional.js +++ b/core/modules/parsers/wikiparser/rules/conditional.js @@ -117,7 +117,7 @@ exports.parseIfClause = function(filterCondition) { return [listWidget]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var filterCondition = tree.attributes.filter.value; var ifClause = serialize(tree.children[0].children); var elseClause = tree.children[1].children; diff --git a/core/modules/parsers/wikiparser/rules/dash.js b/core/modules/parsers/wikiparser/rules/dash.js index 4d06a54cd..84f996cf6 100644 --- a/core/modules/parsers/wikiparser/rules/dash.js +++ b/core/modules/parsers/wikiparser/rules/dash.js @@ -37,7 +37,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { return tree.entity === "–" ? "--" : "---"; }; diff --git a/core/modules/parsers/wikiparser/rules/emphasis/bold.js b/core/modules/parsers/wikiparser/rules/emphasis/bold.js index bcd55f556..c6758819f 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/bold.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/bold.js @@ -47,7 +47,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { return "''" + serialize(tree.children) + "''"; }; diff --git a/core/modules/parsers/wikiparser/rules/emphasis/italic.js b/core/modules/parsers/wikiparser/rules/emphasis/italic.js index 88be5617a..12b9a34c9 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/italic.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/italic.js @@ -47,7 +47,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { return "//" + serialize(tree.children) + "//"; }; diff --git a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js index d42ac62b3..44e180a84 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/strikethrough.js @@ -47,7 +47,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { return "~~" + serialize(tree.children) + "~~"; }; diff --git a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js index b49598934..e2d9f766b 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/subscript.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/subscript.js @@ -47,7 +47,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { return ",," + serialize(tree.children) + ",,"; }; diff --git a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js index a843aec5d..df6d0217c 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/superscript.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/superscript.js @@ -47,7 +47,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { return "^^" + serialize(tree.children) + "^^"; }; diff --git a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js index 4d223185a..2bf57f1bd 100644 --- a/core/modules/parsers/wikiparser/rules/emphasis/underscore.js +++ b/core/modules/parsers/wikiparser/rules/emphasis/underscore.js @@ -47,7 +47,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { return "__" + serialize(tree.children) + "__"; }; diff --git a/core/modules/parsers/wikiparser/rules/entity.js b/core/modules/parsers/wikiparser/rules/entity.js index 10e288990..d5d0405f2 100644 --- a/core/modules/parsers/wikiparser/rules/entity.js +++ b/core/modules/parsers/wikiparser/rules/entity.js @@ -37,7 +37,7 @@ exports.parse = function() { return [{type: "entity", entity: this.match[0]}]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { return tree.entity; }; diff --git a/core/modules/parsers/wikiparser/rules/extlink.js b/core/modules/parsers/wikiparser/rules/extlink.js index 250c9f226..88dfd3e0a 100644 --- a/core/modules/parsers/wikiparser/rules/extlink.js +++ b/core/modules/parsers/wikiparser/rules/extlink.js @@ -53,7 +53,7 @@ exports.parse = function() { } }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { if(tree.type === "text") { return "~" + tree.text; } else if(tree.type === "element" && tree.tag === "a") { diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js index 553d68c0e..f3a342ee0 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js @@ -71,7 +71,7 @@ exports.parse = function() { return [node]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var serialized = "{{{" + tree.attributes.filter.value; // Tooltip text if(tree.attributes.tooltip) serialized += "|" + tree.attributes.tooltip.value; diff --git a/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js b/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js index 8ab8887d7..efc596bba 100644 --- a/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js +++ b/core/modules/parsers/wikiparser/rules/filteredtranscludeinline.js @@ -70,9 +70,9 @@ exports.parse = function() { return [node]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var filteredtranscludeblock = require("$:/core/modules/parsers/wikiparser/rules/filteredtranscludeblock.js"); - var result = filteredtranscludeblock.serialize(tree, serialize); + var result = filteredtranscludeblock.serialize(tree,serialize); return result.trimEnd(); }; diff --git a/core/modules/parsers/wikiparser/rules/fnprocdef.js b/core/modules/parsers/wikiparser/rules/fnprocdef.js index 82c4b6217..cbc36bae5 100644 --- a/core/modules/parsers/wikiparser/rules/fnprocdef.js +++ b/core/modules/parsers/wikiparser/rules/fnprocdef.js @@ -93,7 +93,7 @@ exports.parse = function() { return parseTreeNodes; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { // Type of definition: "function", "procedure", or "widget" var type = tree.isFunctionDefinition ? "function" : (tree.isProcedureDefinition ? "procedure" : "widget"); // Name of the function, procedure, or widget diff --git a/core/modules/parsers/wikiparser/rules/heading.js b/core/modules/parsers/wikiparser/rules/heading.js index 70b58e71d..3c762fd83 100644 --- a/core/modules/parsers/wikiparser/rules/heading.js +++ b/core/modules/parsers/wikiparser/rules/heading.js @@ -46,7 +46,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { // Get heading level from number after `h` var headingLevel = parseInt(tree.tag.substr(1),10); var classes = tree.attributes.class ? tree.attributes.class.value.split(" ").join(".") : ""; diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index e27089086..53a5139c5 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -195,7 +195,7 @@ exports.isLegalTag = function(tag) { } }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var tag = tree.tag; var attributes = tree.orderedAttributes.map(function(attribute) { return $tw.utils.serializeAttribute(attribute); diff --git a/core/modules/parsers/wikiparser/rules/image.js b/core/modules/parsers/wikiparser/rules/image.js index f046c59f1..7b612a9c7 100644 --- a/core/modules/parsers/wikiparser/rules/image.js +++ b/core/modules/parsers/wikiparser/rules/image.js @@ -130,7 +130,7 @@ exports.parseImage = function(source,pos) { return node; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { var width = tree.attributes.width ? " " + $tw.utils.serializeAttribute(tree.attributes.width) : ""; var height = tree.attributes.height ? " " + $tw.utils.serializeAttribute(tree.attributes.height) : ""; var padSpace = width || height ? " " : ""; diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js index 71a7cab5e..e047bab21 100644 --- a/core/modules/parsers/wikiparser/rules/list.js +++ b/core/modules/parsers/wikiparser/rules/list.js @@ -160,7 +160,7 @@ exports.parse = function() { return [listStack[0]]; }; -exports.serialize = function (tree, serialize) { +exports.serialize = function (tree,serialize) { // Helper function to find the marker for a given list container tag and item tag function findMarker(listTag, itemTag) { for(var key in listTypes) { diff --git a/core/modules/parsers/wikiparser/rules/macrocallinline.js b/core/modules/parsers/wikiparser/rules/macrocallinline.js index 132eabef9..ff91b7a91 100644 --- a/core/modules/parsers/wikiparser/rules/macrocallinline.js +++ b/core/modules/parsers/wikiparser/rules/macrocallinline.js @@ -49,9 +49,9 @@ exports.parse = function() { /* Same as macrocallblock but without \n\n */ -exports.serialize = function (tree, serialize) { +exports.serialize = function (tree,serialize) { var macrocallblock = require("$:/core/modules/parsers/wikiparser/rules/macrocallblock.js"); - var result = macrocallblock.serialize(tree, serialize); + var result = macrocallblock.serialize(tree,serialize); return result.trimEnd(); }; diff --git a/core/modules/parsers/wikiparser/rules/prettyextlink.js b/core/modules/parsers/wikiparser/rules/prettyextlink.js index f56ee8fe0..088a981b8 100644 --- a/core/modules/parsers/wikiparser/rules/prettyextlink.js +++ b/core/modules/parsers/wikiparser/rules/prettyextlink.js @@ -117,7 +117,7 @@ exports.parseLink = function(source,pos) { return node; }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { var tooltip = tree.children[0].text; var url = tree.attributes.href.value; return "[ext[" + (tooltip !== url ? tooltip + "|" : "") + url + "]]"; diff --git a/core/modules/parsers/wikiparser/rules/prettylink.js b/core/modules/parsers/wikiparser/rules/prettylink.js index 0b798a5dc..7a516a801 100644 --- a/core/modules/parsers/wikiparser/rules/prettylink.js +++ b/core/modules/parsers/wikiparser/rules/prettylink.js @@ -67,7 +67,7 @@ exports.parse = function() { } }; -exports.serialize = function(tree) { +exports.serialize = function(tree,serialize) { var text = tree.children[0].text; var target = tree.attributes.to ? tree.attributes.to.value : tree.attributes.href.value; return "[[" + text + (text !== target ? "|" + target : "") + "]]"; diff --git a/core/modules/parsers/wikiparser/rules/quoteblock.js b/core/modules/parsers/wikiparser/rules/quoteblock.js index a652cdf1b..05a42f517 100644 --- a/core/modules/parsers/wikiparser/rules/quoteblock.js +++ b/core/modules/parsers/wikiparser/rules/quoteblock.js @@ -73,7 +73,7 @@ exports.parse = function() { }]; }; -exports.serialize = function (tree, serialize) { +exports.serialize = function (tree,serialize) { var result = []; if(tree.type === "element" && tree.tag === "blockquote") { // tree.attributes.class.value: "tc-quote" diff --git a/core/modules/parsers/wikiparser/rules/rules.js b/core/modules/parsers/wikiparser/rules/rules.js index a5958d67c..8aca74e16 100644 --- a/core/modules/parsers/wikiparser/rules/rules.js +++ b/core/modules/parsers/wikiparser/rules/rules.js @@ -68,7 +68,7 @@ exports.parse = function() { }]; }; -exports.serialize = function (tree, serialize) { +exports.serialize = function (tree,serialize) { var result = []; if(tree.attributes.action && tree.attributes.rules) { // tree.attributes.action.value: "except" diff --git a/core/modules/parsers/wikiparser/rules/styleblock.js b/core/modules/parsers/wikiparser/rules/styleblock.js index a5e19cfcc..091ce7f53 100644 --- a/core/modules/parsers/wikiparser/rules/styleblock.js +++ b/core/modules/parsers/wikiparser/rules/styleblock.js @@ -73,7 +73,7 @@ exports.parse = function() { }] }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var lines = []; var classes = []; var styles = []; diff --git a/core/modules/parsers/wikiparser/rules/styleinline.js b/core/modules/parsers/wikiparser/rules/styleinline.js index 01c047856..77857b006 100644 --- a/core/modules/parsers/wikiparser/rules/styleinline.js +++ b/core/modules/parsers/wikiparser/rules/styleinline.js @@ -55,7 +55,7 @@ exports.parse = function() { return [node]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var result = "@@"; // Add styles if present if(tree.attributes && tree.attributes.style) { diff --git a/core/modules/parsers/wikiparser/rules/syslink.js b/core/modules/parsers/wikiparser/rules/syslink.js index e5387e5ee..aeeb4bdf2 100644 --- a/core/modules/parsers/wikiparser/rules/syslink.js +++ b/core/modules/parsers/wikiparser/rules/syslink.js @@ -50,7 +50,7 @@ exports.parse = function() { } }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { // Check if the link is suppressed var isSuppressed = tree.children[0].text.substr(0,1) === "~"; var serialized = isSuppressed ? "~" : ""; diff --git a/core/modules/parsers/wikiparser/rules/table.js b/core/modules/parsers/wikiparser/rules/table.js index 2c6f4356a..992c05b4e 100644 --- a/core/modules/parsers/wikiparser/rules/table.js +++ b/core/modules/parsers/wikiparser/rules/table.js @@ -188,7 +188,7 @@ exports.parse = function() { return [table]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var serialized = ""; // Iterate over the table rows for(var i = 0; i < tree.children.length; i++) { diff --git a/core/modules/parsers/wikiparser/rules/transcludeblock.js b/core/modules/parsers/wikiparser/rules/transcludeblock.js index 319726f0a..8aac3ee65 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeblock.js +++ b/core/modules/parsers/wikiparser/rules/transcludeblock.js @@ -86,7 +86,7 @@ exports.parse = function() { } }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var result = "{{"; function handleTransclude(transcludeNode) { // Handle field diff --git a/core/modules/parsers/wikiparser/rules/transcludeinline.js b/core/modules/parsers/wikiparser/rules/transcludeinline.js index af525b78a..17271bcd5 100644 --- a/core/modules/parsers/wikiparser/rules/transcludeinline.js +++ b/core/modules/parsers/wikiparser/rules/transcludeinline.js @@ -84,9 +84,9 @@ exports.parse = function() { } }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var transcludeblock = require("$:/core/modules/parsers/wikiparser/rules/transcludeblock.js"); - var result = transcludeblock.serialize(tree, serialize); + var result = transcludeblock.serialize(tree,serialize); return result.trimEnd(); }; diff --git a/core/modules/parsers/wikiparser/rules/typedblock.js b/core/modules/parsers/wikiparser/rules/typedblock.js index 38985daaa..c0adb1c0c 100644 --- a/core/modules/parsers/wikiparser/rules/typedblock.js +++ b/core/modules/parsers/wikiparser/rules/typedblock.js @@ -98,7 +98,7 @@ exports.parse = function() { } }; -exports.serialize = function (tree, serialize) { +exports.serialize = function (tree,serialize) { if(tree.type === "void") { return "$$$" + tree.parseType + (tree.renderType ? " > " + tree.renderType : "") + "\n" + tree.text + "\n$$$\n\n"; } diff --git a/core/modules/parsers/wikiparser/rules/wikilink.js b/core/modules/parsers/wikiparser/rules/wikilink.js index d5e1a48ec..40888315f 100644 --- a/core/modules/parsers/wikiparser/rules/wikilink.js +++ b/core/modules/parsers/wikiparser/rules/wikilink.js @@ -65,7 +65,7 @@ exports.parse = function() { }]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var isSuppressed = tree.children[0].text.substr(0,1) === $tw.config.textPrimitives.unWikiLink; var serialized = isSuppressed ? $tw.config.textPrimitives.unWikiLink : ""; diff --git a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js index 1de26d25c..a51544e58 100644 --- a/core/modules/parsers/wikiparser/rules/wikilinkprefix.js +++ b/core/modules/parsers/wikiparser/rules/wikilinkprefix.js @@ -37,7 +37,7 @@ exports.parse = function() { return [{type: "text", text: linkText.substr(1)}]; }; -exports.serialize = function(tree, serialize) { +exports.serialize = function(tree,serialize) { var serialized = $tw.config.textPrimitives.unWikiLink; serialized += tree.text; return serialized; From 0f385675c29b8590d49d22fb38ecdd8e0b27a045 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 13 Oct 2024 22:13:27 +0800 Subject: [PATCH 64/98] fix: empty list item --- core/modules/parsers/wikiparser/rules/list.js | 14 ++++++++++---- .../test/tiddlers/tests/data/serialize/List.tid | 15 ++++++++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js index e047bab21..cf0b1e0d6 100644 --- a/core/modules/parsers/wikiparser/rules/list.js +++ b/core/modules/parsers/wikiparser/rules/list.js @@ -66,6 +66,12 @@ var listTypes = { var listTags = Object.values(listTypes).map(function(type) { return type.listTag; }); +/* +Check if the child is a nested list or a simple line of list item +*/ +function isListNode(node) { + return node && node.type === "element" && listTags.includes(node.tag); +} var itemTags = Object.values(listTypes).map(function(type) { return type.itemTag; }); @@ -174,7 +180,7 @@ exports.serialize = function (tree,serialize) { // Recursive function to serialize list nodes, handling nested lists and formatting output function serializeList(node, markerPrefix) { var result = []; - if(node.type === "element" && listTags.includes(node.tag)) { + if(node.type === "element" && isListNode(node)) { node.children.forEach(function (child) { if(itemTags.includes(child.tag)) { var currentMarker = findMarker(node.tag, child.tag); @@ -183,8 +189,7 @@ exports.serialize = function (tree,serialize) { // same level text nodes may be split into multiple children, and separated by deeper list sub-tree. We collect same level text nodes into this list, and concat then submit them before enter deeper list. var content = []; $tw.utils.each(child.children,function (subNode) { - // Check if the child is a nested list or a simple line of list item - if(listTags.includes(subNode.tag)) { + if(isListNode(subNode)) { // Recursive call for nested lists if(content.length > 0) { result.push(markerPrefix + currentMarker + classAttr + " " + content.join("").trim()); @@ -196,7 +201,8 @@ exports.serialize = function (tree,serialize) { } return ""; // Default return for unhandled node types }); - if(content.length > 0) { + // prepend `#` mark to a new line, if it has content (and has or hasn't nested list), or if it has no content and also no nested list + if(content.length > 0 || child.children.length === 0) { result.push(markerPrefix + currentMarker + classAttr + " " + content.join("").trim()); content = [] } diff --git a/editions/test/tiddlers/tests/data/serialize/List.tid b/editions/test/tiddlers/tests/data/serialize/List.tid index d4088bcce..d25397799 100644 --- a/editions/test/tiddlers/tests/data/serialize/List.tid +++ b/editions/test/tiddlers/tests/data/serialize/List.tid @@ -24,4 +24,17 @@ type: text/vnd.tiddlywiki * List item one *.active List item two has the class `active` -* List item three \ No newline at end of file +* List item three + +# AAA +## [[BBB]] +### CCC +# AAA +## CCC +## DDD +## EEE +# BBB +## FF `/` FFF +## FFF +## GGG +## From f220dacdd80ad0877759169b3dba25b35d620480 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 14 Oct 2024 00:47:13 +0800 Subject: [PATCH 65/98] feat: add \n\n based on isBlock, if could also be inline --- core/modules/parsers/wikiparser/rules/html.js | 12 +++++++++--- editions/test/tiddlers/tests/data/serialize/Html.tid | 6 +++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index 53a5139c5..39ea1e141 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -202,12 +202,18 @@ exports.serialize = function(tree,serialize) { }).join(" "); // Children var children = tree.children ? serialize(tree.children) : ""; + var result = ""; // Self-closing tag if(tree.isSelfClosing) { - return "<" + tag + (attributes ? " " + attributes : "") + " />"; + result += "<" + tag + (attributes ? " " + attributes : "") + " />"; + } else { + // Opening and closing tags + result += "<" + tag + (attributes ? " " + attributes : "") + ">" + children + ""; } - // Opening and closing tags - return "<" + tag + (attributes ? " " + attributes : "") + ">" + children + ""; + if(tree.isBlock) { + result += "\n\n"; + } + return result; }; })(); diff --git a/editions/test/tiddlers/tests/data/serialize/Html.tid b/editions/test/tiddlers/tests/data/serialize/Html.tid index 05507eb56..d4a8db414 100644 --- a/editions/test/tiddlers/tests/data/serialize/Html.tid +++ b/editions/test/tiddlers/tests/data/serialize/Html.tid @@ -8,4 +8,8 @@ This is an HTML5 aside element <$slider target="MyTiddler"> This is a widget invocation - \ No newline at end of file + + +<$list filter="[tag[ExampleTag]sort[title]]" /> + +Plain text in next paragraph. \ No newline at end of file From 5fdc9f365ef3e4c3597914231040c54279f07744 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 14 Oct 2024 00:47:37 +0800 Subject: [PATCH 66/98] fix: conditional without elseif --- .../parsers/wikiparser/rules/conditional.js | 44 +++++++++++-------- .../tests/data/serialize/Conditional.tid | 18 +++++++- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/conditional.js b/core/modules/parsers/wikiparser/rules/conditional.js index 6f30ef3a3..6ec8a6ab5 100644 --- a/core/modules/parsers/wikiparser/rules/conditional.js +++ b/core/modules/parsers/wikiparser/rules/conditional.js @@ -118,28 +118,36 @@ exports.parseIfClause = function(filterCondition) { }; exports.serialize = function(tree,serialize) { + // We always have "if" at the beginning var filterCondition = tree.attributes.filter.value; - var ifClause = serialize(tree.children[0].children); - var elseClause = tree.children[1].children; - var serialized = "<%if " + filterCondition + "%>" + ifClause; - - if(elseClause && elseClause.length > 0) { - for(var i = 0; i < elseClause.length; i++) { - if(elseClause[i].type === "list" && elseClause[i].attributes.filter) { - // Handle elseif clause - var elseifCondition = elseClause[i].attributes.filter.value; - var elseifClause = serialize(elseClause[i].children[0]); - serialized += "<%elseif " + elseifCondition + "%>" + elseifClause; - } - if(elseClause[i].children[1]) { - var elseClauseText = serialize(elseClause[i].children[1]); - serialized += "<%else%>" + elseClauseText; + var ifClauseText = serialize(tree.children[0].children); + var result = "<%if " + filterCondition + "%>" + ifClauseText; + function serializeElseIf(listNode) { + // We receive the only list node inside list-template node + if(!listNode || listNode.type !== "list") { + return "<%else%>" + serialize(listNode); + } + var filter = listNode.attributes.filter.value || ""; + var bodyText = serialize(listNode.children[0].children); + var nextConditionResult = ""; + // May has an only any node inside list-empty node + if(listNode.children[1] && listNode.children[1].children[0]) { + if(listNode.children[1].children[0].type === "list") { + nextConditionResult = serializeElseIf(listNode.children[1].children[0]); + } else { + nextConditionResult = "<%else%>" + serialize(listNode.children[1]); } } + return "<%elseif " + filter + "%>" + bodyText + nextConditionResult; } - - serialized += "<%endif%>"; - return serialized += "\n\n"; + if(tree.children[1] && tree.children[1].children) { + result += serializeElseIf(tree.children[1].children[0]); + } + result += "<%endif%>"; + if(tree.isBlock) { + result += "\n\n"; + } + return result; }; })(); diff --git a/editions/test/tiddlers/tests/data/serialize/Conditional.tid b/editions/test/tiddlers/tests/data/serialize/Conditional.tid index 4e96726f7..4540e6eb4 100644 --- a/editions/test/tiddlers/tests/data/serialize/Conditional.tid +++ b/editions/test/tiddlers/tests/data/serialize/Conditional.tid @@ -2,4 +2,20 @@ tags: $:/tags/wikitext-serialize-test-spec title: Serialize/Conditional type: text/vnd.tiddlywiki -This is a <%if [{something}] %>Elephant<%elseif [{else}] %>Pelican<%else%>Crocodile<%endif%> \ No newline at end of file +This is a <%if [{something}] %>Elephant<%elseif [{else}] %>Pelican<%else%>Crocodile<%endif%> <%if [{something}] %>Elephant<%else%>Crocodile<%endif%> + +<%if [{$:/info/url/protocol}match[file:]]%> + Loaded from a file URI +<%elseif [{$:/info/url/protocol}match[https:]]%> + Loaded from an HTTPS URI +<%elseif [{$:/info/url/protocol}match[http:]]%> + Loaded from an HTTP URI +<%else%> + Loaded from an unknown protocol +<%endif%> + +Plain text in next paragraph. + +<%if [{$:/info/url/protocol}match[file:]]%> + Hidden. +<%endif%> From 87dc05be9da780b667920d5ded6e521c43fb9f29 Mon Sep 17 00:00:00 2001 From: linonetwo Date: Mon, 14 Oct 2024 16:43:50 +0800 Subject: [PATCH 67/98] refactor: use isBlock in macrodef to know inline or block --- core/modules/parsers/wikiparser/rules/macrodef.js | 8 ++++---- editions/test/tiddlers/tests/test-wikitext-parser.js | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/macrodef.js b/core/modules/parsers/wikiparser/rules/macrodef.js index 3fe2195f6..5c20a0302 100644 --- a/core/modules/parsers/wikiparser/rules/macrodef.js +++ b/core/modules/parsers/wikiparser/rules/macrodef.js @@ -55,10 +55,10 @@ exports.parse = function() { } } // Is the remainder of the \define line blank after the parameter close paren? - var reEnd,inline = true; + var reEnd,isBlock = true; if(this.match[3]) { // If so, it is a multiline definition and the end of the body is marked with \end - inline = false; + isBlock = false; reEnd = new RegExp("((?:^|\\r?\\n)[^\\S\\n\\r]*\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?(?:$|\\r?\\n))","mg"); } else { // Otherwise, the end of the definition is marked by the end of the line @@ -84,7 +84,7 @@ exports.parse = function() { children: [], params: params, isMacroDefinition: true, - inline: inline && !!endMatch + isBlock: isBlock && !!endMatch }]; $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"name",this.match[1]); $tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],"value",text); @@ -97,7 +97,7 @@ exports.serialize = function(tree,serialize) { return param.name + (param.default ? ":" + param.default : ""); }).join(","); var definition = tree.attributes.value.value; - if(tree.inline) { + if(tree.isBlock) { return "\\define " + name + "(" + params + ") " + definition + "\n\n" + serialize(tree.children); } return "\\define " + name + "(" + params + ")\n" + definition + "\n\\end\n\n" + serialize(tree.children); diff --git a/editions/test/tiddlers/tests/test-wikitext-parser.js b/editions/test/tiddlers/tests/test-wikitext-parser.js index 72136475f..5fa1c28a3 100644 --- a/editions/test/tiddlers/tests/test-wikitext-parser.js +++ b/editions/test/tiddlers/tests/test-wikitext-parser.js @@ -114,12 +114,12 @@ describe("WikiText parser tests", function() { it("should parse macro definitions", function() { expect(parse("\\define myMacro()\nnothing\n\\end\n")).toEqual( - [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"inline":false,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":30,"rule":"macrodef"}] + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"isBlock":false,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":30,"rule":"macrodef"}] ); expect(parse("\\define myMacro() nothing\n\n")).toEqual( - [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"inline":true,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":25,"rule":"macrodef"}] + [{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"myMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"isBlock":true,"orderedAttributes":[{"name":"name","type":"string","value":"myMacro"},{"name":"value","type":"string","value":"nothing"}],"start":0,"end":25,"rule":"macrodef"}] ); }); @@ -190,7 +190,7 @@ describe("WikiText parser tests", function() { it("should parse comment in pragma area. Comment will be invisible", function() { expect(parse("\n\\define aMacro()\nnothing\n\\end\n")).toEqual( - [{"type":"void","children":[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"inline":false,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}],"start":32,"end":61,"rule":"macrodef"}],"text":"","start":0,"end":31,"rule":"commentblock"}] + [{"type":"void","children":[{"type":"set","attributes":{"name":{"name":"name","type":"string","value":"aMacro"},"value":{"name":"value","type":"string","value":"nothing"}},"children":[],"params":[],"isMacroDefinition":true,"isBlock":false,"orderedAttributes":[{"name":"name","type":"string","value":"aMacro"},{"name":"value","type":"string","value":"nothing"}],"start":32,"end":61,"rule":"macrodef"}],"text":"","start":0,"end":31,"rule":"commentblock"}] ); }); From 2765e995dd0d1da605159cda3eed896cb3687b4d Mon Sep 17 00:00:00 2001 From: linonetwo Date: Wed, 19 Feb 2025 18:58:33 +0800 Subject: [PATCH 68/98] fix: link may not have attribute and children --- core/modules/parsers/wikiparser/rules/syslink.js | 6 +++--- core/modules/parsers/wikiparser/rules/wikilink.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/syslink.js b/core/modules/parsers/wikiparser/rules/syslink.js index aeeb4bdf2..a9a04cc7b 100644 --- a/core/modules/parsers/wikiparser/rules/syslink.js +++ b/core/modules/parsers/wikiparser/rules/syslink.js @@ -51,11 +51,11 @@ exports.parse = function() { }; exports.serialize = function(tree,serialize) { - // Check if the link is suppressed - var isSuppressed = tree.children[0].text.substr(0,1) === "~"; + // Check if the link is suppressed. Tree may only have text, no children and attributes + var isSuppressed = tree.children && tree.children[0].text.substr(0,1) === "~"; var serialized = isSuppressed ? "~" : ""; // Append the link text - serialized += tree.attributes.to.value; + serialized += tree.attributes ? tree.attributes.to.value : tree.text; return serialized; }; diff --git a/core/modules/parsers/wikiparser/rules/wikilink.js b/core/modules/parsers/wikiparser/rules/wikilink.js index 40888315f..8628a4f6c 100644 --- a/core/modules/parsers/wikiparser/rules/wikilink.js +++ b/core/modules/parsers/wikiparser/rules/wikilink.js @@ -66,10 +66,10 @@ exports.parse = function() { }; exports.serialize = function(tree,serialize) { - var isSuppressed = tree.children[0].text.substr(0,1) === $tw.config.textPrimitives.unWikiLink; + var isSuppressed = tree.children && tree.children[0].text.substr(0,1) === $tw.config.textPrimitives.unWikiLink; var serialized = isSuppressed ? $tw.config.textPrimitives.unWikiLink : ""; - serialized += tree.attributes.to.value; + serialized += tree.attributes ? tree.attributes.to.value : tree.text; return serialized; }; From 069181d615a391bec4c7ad37b66dfc7ffc3128f2 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Wed, 19 Feb 2025 15:38:49 +0800 Subject: [PATCH 69/98] DEBUG: render result and diff below body only on browser DEBUG: render result below body only on browser DEBUG: render result below body DEBUG: fix build DEBUG: show render result as ViewTemplate --- core/modules/filters/serializeparsetree.js | 29 ++++++++++++++++++++++ core/ui/ViewTemplate/body/default.tid | 14 +++++++++++ 2 files changed, 43 insertions(+) create mode 100644 core/modules/filters/serializeparsetree.js diff --git a/core/modules/filters/serializeparsetree.js b/core/modules/filters/serializeparsetree.js new file mode 100644 index 000000000..04796a2c9 --- /dev/null +++ b/core/modules/filters/serializeparsetree.js @@ -0,0 +1,29 @@ +/*\ +title: $:/core/modules/filters/serializeparsetree.js +type: application/javascript +module-type: filteroperator + +Filter operator for serializing JSON string of Abstract Syntax Tree (AST) of Wiki parse tree to a raw WikiText string. + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +Export our filter function +*/ +exports.serializeparsetree = function(source,operator,options) { + var results = []; + source(function(tiddler,title) { + var parseTreeObject = $tw.utils.parseJSONSafe(title); + if(parseTreeObject) { + results.push($tw.utils.serializeParseTree(parseTreeObject)); + } + }); + return results; +}; + +})(); diff --git a/core/ui/ViewTemplate/body/default.tid b/core/ui/ViewTemplate/body/default.tid index 5416c6e07..cc2453ecf 100644 --- a/core/ui/ViewTemplate/body/default.tid +++ b/core/ui/ViewTemplate/body/default.tid @@ -6,3 +6,17 @@ code-body: yes <$transclude tiddler="$:/language/MissingTiddler/Hint"/> + +<%if [[$:/info/browser]text[yes]] %> + <$wikify text={{!!text}} name=parsetree output=parsetree > + <$let text2={{{[serializeparsetree[]]}}}> + <$wikify name=rendered text=<> output=html > + + <$diff-text source={{!!text}} dest=<>/> + + <> + + + + +<%endif%> \ No newline at end of file From 86ec4cae45ab79e5553aa043435c53e9830e7b07 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Fri, 28 Feb 2025 23:11:43 +0800 Subject: [PATCH 70/98] fix: remove pad space in /> --- core/modules/parsers/wikiparser/rules/html.js | 2 +- core/ui/ViewTemplate/body/default.tid | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/html.js b/core/modules/parsers/wikiparser/rules/html.js index 39ea1e141..5c128529e 100644 --- a/core/modules/parsers/wikiparser/rules/html.js +++ b/core/modules/parsers/wikiparser/rules/html.js @@ -205,7 +205,7 @@ exports.serialize = function(tree,serialize) { var result = ""; // Self-closing tag if(tree.isSelfClosing) { - result += "<" + tag + (attributes ? " " + attributes : "") + " />"; + result += "<" + tag + (attributes ? " " + attributes : "") + "/>"; } else { // Opening and closing tags result += "<" + tag + (attributes ? " " + attributes : "") + ">" + children + ""; diff --git a/core/ui/ViewTemplate/body/default.tid b/core/ui/ViewTemplate/body/default.tid index cc2453ecf..1b8c3940c 100644 --- a/core/ui/ViewTemplate/body/default.tid +++ b/core/ui/ViewTemplate/body/default.tid @@ -6,12 +6,10 @@ code-body: yes <$transclude tiddler="$:/language/MissingTiddler/Hint"/> - <%if [[$:/info/browser]text[yes]] %> <$wikify text={{!!text}} name=parsetree output=parsetree > <$let text2={{{[serializeparsetree[]]}}}> <$wikify name=rendered text=<> output=html > - <$diff-text source={{!!text}} dest=<>/> <> From 74c9841901d6157db8d675f274e62cc0bdff8b56 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 1 Mar 2025 02:12:09 +0800 Subject: [PATCH 71/98] test: remove pad space in /> --- editions/test/tiddlers/tests/data/serialize/Attribute.tid | 2 +- editions/test/tiddlers/tests/data/serialize/Html.tid | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/editions/test/tiddlers/tests/data/serialize/Attribute.tid b/editions/test/tiddlers/tests/data/serialize/Attribute.tid index 6ecda2c01..3f986784a 100644 --- a/editions/test/tiddlers/tests/data/serialize/Attribute.tid +++ b/editions/test/tiddlers/tests/data/serialize/Attribute.tid @@ -2,4 +2,4 @@ tags: $:/tags/wikitext-serialize-test-spec title: Serialize/Attribute type: text/vnd.tiddlywiki -<$macrocall $name="rpn" a=<> b="pi" operation="*" decimals="4" /> +<$macrocall $name="rpn" a=<> b="pi" operation="*" decimals="4"/> diff --git a/editions/test/tiddlers/tests/data/serialize/Html.tid b/editions/test/tiddlers/tests/data/serialize/Html.tid index d4a8db414..76b86d570 100644 --- a/editions/test/tiddlers/tests/data/serialize/Html.tid +++ b/editions/test/tiddlers/tests/data/serialize/Html.tid @@ -10,6 +10,6 @@ This is an HTML5 aside element This is a widget invocation -<$list filter="[tag[ExampleTag]sort[title]]" /> +<$list filter="[tag[ExampleTag]sort[title]]"/> Plain text in next paragraph. \ No newline at end of file From 8ab12738cf446f169609fd1d6c23d50ec10c2310 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 9 Mar 2025 15:46:10 +0800 Subject: [PATCH 72/98] Revert DEBUG: render result and diff below body only on browser --- core/modules/filters/serializeparsetree.js | 29 ---------------------- core/ui/ViewTemplate/body/default.tid | 12 --------- 2 files changed, 41 deletions(-) delete mode 100644 core/modules/filters/serializeparsetree.js diff --git a/core/modules/filters/serializeparsetree.js b/core/modules/filters/serializeparsetree.js deleted file mode 100644 index 04796a2c9..000000000 --- a/core/modules/filters/serializeparsetree.js +++ /dev/null @@ -1,29 +0,0 @@ -/*\ -title: $:/core/modules/filters/serializeparsetree.js -type: application/javascript -module-type: filteroperator - -Filter operator for serializing JSON string of Abstract Syntax Tree (AST) of Wiki parse tree to a raw WikiText string. - -\*/ -(function(){ - -/*jslint node: true, browser: true */ -/*global $tw: false */ -"use strict"; - -/* -Export our filter function -*/ -exports.serializeparsetree = function(source,operator,options) { - var results = []; - source(function(tiddler,title) { - var parseTreeObject = $tw.utils.parseJSONSafe(title); - if(parseTreeObject) { - results.push($tw.utils.serializeParseTree(parseTreeObject)); - } - }); - return results; -}; - -})(); diff --git a/core/ui/ViewTemplate/body/default.tid b/core/ui/ViewTemplate/body/default.tid index 1b8c3940c..5416c6e07 100644 --- a/core/ui/ViewTemplate/body/default.tid +++ b/core/ui/ViewTemplate/body/default.tid @@ -6,15 +6,3 @@ code-body: yes <$transclude tiddler="$:/language/MissingTiddler/Hint"/> -<%if [[$:/info/browser]text[yes]] %> - <$wikify text={{!!text}} name=parsetree output=parsetree > - <$let text2={{{[serializeparsetree[]]}}}> - <$wikify name=rendered text=<> output=html > - <$diff-text source={{!!text}} dest=<>/> - - <> - - - - -<%endif%> \ No newline at end of file From 711bf01049fccda5c041f6ad5022c936dbbff6f9 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 9 Mar 2025 23:31:15 +0800 Subject: [PATCH 73/98] refactor: fold commentText variable --- core/modules/parsers/wikiparser/rules/commentblock.js | 3 +-- core/modules/parsers/wikiparser/rules/commentinline.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/commentblock.js b/core/modules/parsers/wikiparser/rules/commentblock.js index 997be818c..5f87020ca 100644 --- a/core/modules/parsers/wikiparser/rules/commentblock.js +++ b/core/modules/parsers/wikiparser/rules/commentblock.js @@ -53,11 +53,10 @@ exports.parse = function() { // Return a node representing the comment that is not rendered var commentStart = this.match.index; var commentEnd = this.endMatch.index + this.endMatch[0].length; - var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ type: "void", children: [], - text: commentText, + text: this.parser.source.slice(commentStart, commentEnd), start: commentStart, end: commentEnd }]; diff --git a/core/modules/parsers/wikiparser/rules/commentinline.js b/core/modules/parsers/wikiparser/rules/commentinline.js index f39d9f6ff..b96f5d78b 100644 --- a/core/modules/parsers/wikiparser/rules/commentinline.js +++ b/core/modules/parsers/wikiparser/rules/commentinline.js @@ -46,10 +46,9 @@ exports.parse = function() { // Return a node representing the inline comment var commentStart = this.match.index; var commentEnd = this.endMatch.index + this.endMatch[0].length; - var commentText = this.parser.source.slice(commentStart, commentEnd); return [{ type: "void", - text: commentText, + text: this.parser.source.slice(commentStart, commentEnd), start: commentStart, end: commentEnd }]; From 5c0198b7b5eaeceb99bca568d96d1d983d4c9f8d Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 9 Mar 2025 23:31:49 +0800 Subject: [PATCH 74/98] refactor: fold long comment --- core/modules/parsers/wikiparser/rules/list.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/modules/parsers/wikiparser/rules/list.js b/core/modules/parsers/wikiparser/rules/list.js index cf0b1e0d6..d0a5e2f65 100644 --- a/core/modules/parsers/wikiparser/rules/list.js +++ b/core/modules/parsers/wikiparser/rules/list.js @@ -186,7 +186,10 @@ exports.serialize = function (tree,serialize) { var currentMarker = findMarker(node.tag, child.tag); // Handle class attributes var classAttr = child.attributes && child.attributes.class ? "." + child.attributes.class.value : ""; - // same level text nodes may be split into multiple children, and separated by deeper list sub-tree. We collect same level text nodes into this list, and concat then submit them before enter deeper list. + /** + * same level text nodes may be split into multiple children, and separated by deeper list sub-tree. + * We collect same level text nodes into this list, and concat then submit them before enter deeper list. + */ var content = []; $tw.utils.each(child.children,function (subNode) { if(isListNode(subNode)) { From a97aedec34edd3617eee93de20cb5e7a3522dc2e Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 9 Mar 2025 23:35:52 +0800 Subject: [PATCH 75/98] fix: double quotes for parameter values --- core/modules/parsers/wikiparser/rules/fnprocdef.js | 10 +++++----- .../tests/data/serialize/FunctionDefinition.tid | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/modules/parsers/wikiparser/rules/fnprocdef.js b/core/modules/parsers/wikiparser/rules/fnprocdef.js index cbc36bae5..8343e0cca 100644 --- a/core/modules/parsers/wikiparser/rules/fnprocdef.js +++ b/core/modules/parsers/wikiparser/rules/fnprocdef.js @@ -6,15 +6,15 @@ module-type: wikirule Wiki pragma rule for function, procedure and widget definitions ``` -\function name(param:defaultvalue,param2:defaultvalue) +\function name(param:"defaultvalue", param2:"defaultvalue") definition text \end -\procedure name(param:defaultvalue,param2:defaultvalue) +\procedure name(param:"defaultvalue", param2:"defaultvalue") definition text \end -\widget $mywidget(param:defaultvalue,param2:defaultvalue) +\widget $mywidget(param:"defaultvalue", param2:"defaultvalue") definition text \end ``` @@ -100,8 +100,8 @@ exports.serialize = function(tree,serialize) { var name = tree.attributes.name.value; // Parameters with default values var params = tree.params.map(function(param) { - return param.name + (param.default ? ":" + param.default : ""); - }).join(","); + return param.name + (param.default ? ':"' + param.default + '"' : ""); + }).join(", "); // Definition text var definition = tree.attributes.value.value; // Construct the serialized string, concat the children because pragma rule wrap everything below it as children diff --git a/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid b/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid index ebd4119a5..3585564a9 100644 --- a/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid +++ b/editions/test/tiddlers/tests/data/serialize/FunctionDefinition.tid @@ -2,14 +2,14 @@ tags: $:/tags/wikitext-serialize-test-spec title: Serialize/FunctionDefinition type: text/vnd.tiddlywiki -\function name(param:defaultvalue,param2:defaultvalue) +\function name(param:"defaultvalue", param2:"defaultvalue") definition text \end -\procedure name(param:defaultvalue,param2:defaultvalue) +\procedure name(param:"defaultvalue", param2:"defaultvalue") definition text \end -\widget $mywidget(param:defaultvalue,param2:defaultvalue) +\widget $mywidget(param:"defaultvalue", param2:"defaultvalue") definition text \end \ No newline at end of file From 7c6c0c30e01001dd9bebbff5ae488117fca8a522 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sun, 23 Mar 2025 01:26:38 +0800 Subject: [PATCH 76/98] Update void.js --- core/modules/widgets/void.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/core/modules/widgets/void.js b/core/modules/widgets/void.js index d2b6445a7..2f73db513 100755 --- a/core/modules/widgets/void.js +++ b/core/modules/widgets/void.js @@ -6,10 +6,7 @@ module-type: widget Void widget that is not intended for render. It still renders all its children. \*/ -(function(){ -/*jslint node: true, browser: true */ -/*global $tw: false */ "use strict"; var Widget = require("$:/core/modules/widgets/widget.js").widget; @@ -50,5 +47,3 @@ VoidNodeWidget.prototype.refresh = function(changedTiddlers) { }; exports.void = VoidNodeWidget; - -})(); From 2b7343f831cfaa4212079534c45d50ad3fbcfd7f Mon Sep 17 00:00:00 2001 From: linonetwo Date: Sun, 23 Mar 2025 20:07:15 +0800 Subject: [PATCH 77/98] feat: example editorjs view setup --- editions/tw5.com-server/tiddlywiki.info | 3 +- .../editorjs/files/editorjs-list.umd.js | 8 ++ .../tiddlywiki/editorjs/files/editorjs.umd.js | 51 +++++++++++++ .../tiddlywiki/editorjs/files/header.umd.js | 15 ++++ .../editorjs/files/tiddlywiki.files | 26 +++++++ plugins/tiddlywiki/editorjs/plugin.info | 7 ++ plugins/tiddlywiki/editorjs/readme.tid | 14 ++++ plugins/tiddlywiki/editorjs/widget.js | 75 +++++++++++++++++++ 8 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 plugins/tiddlywiki/editorjs/files/editorjs-list.umd.js create mode 100644 plugins/tiddlywiki/editorjs/files/editorjs.umd.js create mode 100644 plugins/tiddlywiki/editorjs/files/header.umd.js create mode 100755 plugins/tiddlywiki/editorjs/files/tiddlywiki.files create mode 100755 plugins/tiddlywiki/editorjs/plugin.info create mode 100755 plugins/tiddlywiki/editorjs/readme.tid create mode 100644 plugins/tiddlywiki/editorjs/widget.js diff --git a/editions/tw5.com-server/tiddlywiki.info b/editions/tw5.com-server/tiddlywiki.info index cc460be7e..aea777ba1 100644 --- a/editions/tw5.com-server/tiddlywiki.info +++ b/editions/tw5.com-server/tiddlywiki.info @@ -4,7 +4,8 @@ "tiddlywiki/tiddlyweb", "tiddlywiki/filesystem", "tiddlywiki/highlight", - "tiddlywiki/internals" + "tiddlywiki/internals", + "tiddlywiki/editorjs" ], "themes": [ "tiddlywiki/vanilla", diff --git a/plugins/tiddlywiki/editorjs/files/editorjs-list.umd.js b/plugins/tiddlywiki/editorjs/files/editorjs-list.umd.js new file mode 100644 index 000000000..e5777b01a --- /dev/null +++ b/plugins/tiddlywiki/editorjs/files/editorjs-list.umd.js @@ -0,0 +1,8 @@ +/** + * Skipped minification because the original files appears to be already minified. + * Original file: /npm/@editorjs/list@2.0.6/dist/editorjs-list.umd.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode('.cdx-list{margin:0;padding:0;outline:none;display:grid;counter-reset:item;gap:var(--spacing-s);padding:var(--spacing-xs);--spacing-s: 8px;--spacing-xs: 6px;--list-counter-type: numeric;--radius-border: 5px;--checkbox-background: #fff;--color-border: #C9C9C9;--color-bg-checked: #369FFF;--line-height: 1.45em;--color-bg-checked-hover: #0059AB;--color-tick: #fff;--size-checkbox: 1.2em}.cdx-list__item{line-height:var(--line-height);display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto auto;grid-template-areas:"checkbox content" ". child"}.cdx-list__item-children{display:grid;grid-area:child;gap:var(--spacing-s);padding-top:var(--spacing-s)}.cdx-list__item [contenteditable]{outline:none}.cdx-list__item-content{word-break:break-word;white-space:pre-wrap;grid-area:content;padding-left:var(--spacing-s)}.cdx-list__item:before{counter-increment:item;white-space:nowrap}.cdx-list-ordered .cdx-list__item:before{content:counters(item,".",var(--list-counter-type)) "."}.cdx-list-ordered{counter-reset:item}.cdx-list-unordered .cdx-list__item:before{content:"•"}.cdx-list-checklist .cdx-list__item:before{content:""}.cdx-list__settings .cdx-settings-button{width:50%}.cdx-list__checkbox{padding-top:calc((var(--line-height) - var(--size-checkbox)) / 2);grid-area:checkbox;width:var(--size-checkbox);height:var(--size-checkbox);display:flex;cursor:pointer}.cdx-list__checkbox svg{opacity:0;height:var(--size-checkbox);width:var(--size-checkbox);left:-1px;top:-1px;position:absolute}@media (hover: hover){.cdx-list__checkbox:not(.cdx-list__checkbox--no-hover):hover .cdx-list__checkbox-check svg{opacity:1}}.cdx-list__checkbox--checked{line-height:var(--line-height)}@media (hover: hover){.cdx-list__checkbox--checked:not(.cdx-list__checkbox--checked--no-hover):hover .cdx-checklist__checkbox-check{background:var(--color-bg-checked-hover);border-color:var(--color-bg-checked-hover)}}.cdx-list__checkbox--checked .cdx-list__checkbox-check{background:var(--color-bg-checked);border-color:var(--color-bg-checked)}.cdx-list__checkbox--checked .cdx-list__checkbox-check svg{opacity:1}.cdx-list__checkbox--checked .cdx-list__checkbox-check svg path{stroke:var(--color-tick)}.cdx-list__checkbox--checked .cdx-list__checkbox-check:before{opacity:0;visibility:visible;transform:scale(2.5)}.cdx-list__checkbox-check{cursor:pointer;display:inline-block;position:relative;margin:0 auto;width:var(--size-checkbox);height:var(--size-checkbox);box-sizing:border-box;border-radius:var(--radius-border);border:1px solid var(--color-border);background:var(--checkbox-background)}.cdx-list__checkbox-check:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border-radius:100%;background-color:var(--color-bg-checked);visibility:hidden;pointer-events:none;transform:scale(1);transition:transform .4s ease-out,opacity .4s}.cdx-list-start-with-field{background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:2px;display:grid;grid-template-columns:auto auto 1fr;grid-template-rows:auto}.cdx-list-start-with-field--invalid{background:#FFECED;border:1px solid #E13F3F}.cdx-list-start-with-field--invalid .cdx-list-start-with-field__input{color:#e13f3f}.cdx-list-start-with-field__input{font-size:14px;outline:none;font-weight:500;font-family:inherit;border:0;background:transparent;margin:0;padding:0;line-height:22px;min-width:calc(100% - var(--toolbox-buttons-size) - var(--icon-margin-right))}.cdx-list-start-with-field__input::placeholder{color:var(--grayText);font-weight:500}')),document.head.appendChild(e)}}catch(c){console.error("vite-plugin-css-injected-by-js",c)}})(); +(function(P,_){typeof exports=="object"&&typeof module<"u"?module.exports=_():typeof define=="function"&&define.amd?define(_):(P=typeof globalThis<"u"?globalThis:P||self,P.EditorjsList=_())})(this,function(){"use strict";const P='',_='',Be='',We='',ct='',dt='',ft='',pt='',ht='',mt='';var M=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function gt(e){if(e.__esModule)return e;var t=e.default;if(typeof t=="function"){var n=function r(){return this instanceof r?Reflect.construct(t,arguments,this.constructor):t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach(function(r){var i=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(n,r,i.get?i:{enumerable:!0,get:function(){return e[r]}})}),n}var c={},X={},G={};Object.defineProperty(G,"__esModule",{value:!0}),G.allInputsSelector=vt;function vt(){var e=["text","password","email","number","search","tel","url"];return"[contenteditable=true], textarea, input:not([type]), "+e.map(function(t){return'input[type="'.concat(t,'"]')}).join(", ")}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.allInputsSelector=void 0;var t=G;Object.defineProperty(e,"allInputsSelector",{enumerable:!0,get:function(){return t.allInputsSelector}})})(X);var O={},V={};Object.defineProperty(V,"__esModule",{value:!0}),V.isNativeInput=bt;function bt(e){var t=["INPUT","TEXTAREA"];return e&&e.tagName?t.includes(e.tagName):!1}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isNativeInput=void 0;var t=V;Object.defineProperty(e,"isNativeInput",{enumerable:!0,get:function(){return t.isNativeInput}})})(O);var De={},Y={};Object.defineProperty(Y,"__esModule",{value:!0}),Y.append=yt;function yt(e,t){Array.isArray(t)?t.forEach(function(n){e.appendChild(n)}):e.appendChild(t)}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.append=void 0;var t=Y;Object.defineProperty(e,"append",{enumerable:!0,get:function(){return t.append}})})(De);var J={},Q={};Object.defineProperty(Q,"__esModule",{value:!0}),Q.blockElements=Ct;function Ct(){return["address","article","aside","blockquote","canvas","div","dl","dt","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","li","main","nav","noscript","ol","output","p","pre","ruby","section","table","tbody","thead","tr","tfoot","ul","video"]}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.blockElements=void 0;var t=Q;Object.defineProperty(e,"blockElements",{enumerable:!0,get:function(){return t.blockElements}})})(J);var He={},Z={};Object.defineProperty(Z,"__esModule",{value:!0}),Z.calculateBaseline=St;function St(e){var t=window.getComputedStyle(e),n=parseFloat(t.fontSize),r=parseFloat(t.lineHeight)||n*1.2,i=parseFloat(t.paddingTop),a=parseFloat(t.borderTopWidth),l=parseFloat(t.marginTop),s=n*.8,o=(r-n)/2,d=l+a+i+o+s;return d}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.calculateBaseline=void 0;var t=Z;Object.defineProperty(e,"calculateBaseline",{enumerable:!0,get:function(){return t.calculateBaseline}})})(He);var Fe={},x={},ee={},te={};Object.defineProperty(te,"__esModule",{value:!0}),te.isContentEditable=Ot;function Ot(e){return e.contentEditable==="true"}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isContentEditable=void 0;var t=te;Object.defineProperty(e,"isContentEditable",{enumerable:!0,get:function(){return t.isContentEditable}})})(ee),Object.defineProperty(x,"__esModule",{value:!0}),x.canSetCaret=Et;var kt=O,_t=ee;function Et(e){var t=!0;if((0,kt.isNativeInput)(e))switch(e.type){case"file":case"checkbox":case"radio":case"hidden":case"submit":case"button":case"image":case"reset":t=!1;break}else t=(0,_t.isContentEditable)(e);return t}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.canSetCaret=void 0;var t=x;Object.defineProperty(e,"canSetCaret",{enumerable:!0,get:function(){return t.canSetCaret}})})(Fe);var N={},ne={};function It(e,t,n){const r=n.value!==void 0?"value":"get",i=n[r],a=`#${t}Cache`;if(n[r]=function(...l){return this[a]===void 0&&(this[a]=i.apply(this,l)),this[a]},r==="get"&&n.set){const l=n.set;n.set=function(s){delete e[a],l.apply(this,s)}}return n}function Re(){const e={win:!1,mac:!1,x11:!1,linux:!1},t=Object.keys(e).find(n=>window.navigator.appVersion.toLowerCase().indexOf(n)!==-1);return t!==void 0&&(e[t]=!0),e}function re(e){return e!=null&&e!==""&&(typeof e!="object"||Object.keys(e).length>0)}function wt(e){return!re(e)}const Pt=()=>typeof window<"u"&&window.navigator!==null&&re(window.navigator.platform)&&(/iP(ad|hone|od)/.test(window.navigator.platform)||window.navigator.platform==="MacIntel"&&window.navigator.maxTouchPoints>1);function jt(e){const t=Re();return e=e.replace(/shift/gi,"⇧").replace(/backspace/gi,"⌫").replace(/enter/gi,"⏎").replace(/up/gi,"↑").replace(/left/gi,"→").replace(/down/gi,"↓").replace(/right/gi,"←").replace(/escape/gi,"⎋").replace(/insert/gi,"Ins").replace(/delete/gi,"␡").replace(/\+/gi,"+"),t.mac?e=e.replace(/ctrl|cmd/gi,"⌘").replace(/alt/gi,"⌥"):e=e.replace(/cmd/gi,"Ctrl").replace(/windows/gi,"WIN"),e}function Tt(e){return e[0].toUpperCase()+e.slice(1)}function Lt(e){const t=document.createElement("div");t.style.position="absolute",t.style.left="-999px",t.style.bottom="-999px",t.innerHTML=e,document.body.appendChild(t);const n=window.getSelection(),r=document.createRange();if(r.selectNode(t),n===null)throw new Error("Cannot copy text to clipboard");n.removeAllRanges(),n.addRange(r),document.execCommand("copy"),document.body.removeChild(t)}function Mt(e,t,n){let r;return(...i)=>{const a=this,l=()=>{r=void 0,n!==!0&&e.apply(a,i)},s=n===!0&&r!==void 0;window.clearTimeout(r),r=window.setTimeout(l,t),s&&e.apply(a,i)}}function C(e){return Object.prototype.toString.call(e).match(/\s([a-zA-Z]+)/)[1].toLowerCase()}function Nt(e){return C(e)==="boolean"}function qe(e){return C(e)==="function"||C(e)==="asyncfunction"}function At(e){return qe(e)&&/^\s*class\s+/.test(e.toString())}function $t(e){return C(e)==="number"}function A(e){return C(e)==="object"}function Bt(e){return Promise.resolve(e)===e}function Wt(e){return C(e)==="string"}function Dt(e){return C(e)==="undefined"}function ie(e,...t){if(!t.length)return e;const n=t.shift();if(A(e)&&A(n))for(const r in n)A(n[r])?(e[r]===void 0&&Object.assign(e,{[r]:{}}),ie(e[r],n[r])):Object.assign(e,{[r]:n[r]});return ie(e,...t)}function Ht(e,t,n){const r=`«${t}» is deprecated and will be removed in the next major release. Please use the «${n}» instead.`;e&&console.warn(r)}function Ft(e){try{return new URL(e).href}catch{}return e.substring(0,2)==="//"?window.location.protocol+e:window.location.origin+e}function Rt(e){return e>47&&e<58||e===32||e===13||e===229||e>64&&e<91||e>95&&e<112||e>185&&e<193||e>218&&e<223}const qt={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,LEFT:37,UP:38,DOWN:40,RIGHT:39,DELETE:46,META:91,SLASH:191},Ut={LEFT:0,WHEEL:1,RIGHT:2,BACKWARD:3,FORWARD:4};class zt{constructor(){this.completed=Promise.resolve()}add(t){return new Promise((n,r)=>{this.completed=this.completed.then(t).then(n).catch(r)})}}function Kt(e,t,n=void 0){let r,i,a,l=null,s=0;n||(n={});const o=function(){s=n.leading===!1?0:Date.now(),l=null,a=e.apply(r,i),l===null&&(r=i=null)};return function(){const d=Date.now();!s&&n.leading===!1&&(s=d);const u=t-(d-s);return r=this,i=arguments,u<=0||u>t?(l&&(clearTimeout(l),l=null),s=d,a=e.apply(r,i),l===null&&(r=i=null)):!l&&n.trailing!==!1&&(l=setTimeout(o,u)),a}}const ae=gt(Object.freeze(Object.defineProperty({__proto__:null,PromiseQueue:zt,beautifyShortcut:jt,cacheable:It,capitalize:Tt,copyTextToClipboard:Lt,debounce:Mt,deepMerge:ie,deprecationAssert:Ht,getUserOS:Re,getValidUrl:Ft,isBoolean:Nt,isClass:At,isEmpty:wt,isFunction:qe,isIosDevice:Pt,isNumber:$t,isObject:A,isPrintableKey:Rt,isPromise:Bt,isString:Wt,isUndefined:Dt,keyCodes:qt,mouseButtons:Ut,notEmpty:re,throttle:Kt,typeOf:C},Symbol.toStringTag,{value:"Module"})));Object.defineProperty(ne,"__esModule",{value:!0}),ne.containsOnlyInlineElements=Vt;var Xt=ae,Gt=J;function Vt(e){var t;(0,Xt.isString)(e)?(t=document.createElement("div"),t.innerHTML=e):t=e;var n=function(r){return!(0,Gt.blockElements)().includes(r.tagName.toLowerCase())&&Array.from(r.children).every(n)};return Array.from(t.children).every(n)}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.containsOnlyInlineElements=void 0;var t=ne;Object.defineProperty(e,"containsOnlyInlineElements",{enumerable:!0,get:function(){return t.containsOnlyInlineElements}})})(N);var Ue={},le={},$={},se={};Object.defineProperty(se,"__esModule",{value:!0}),se.make=Yt;function Yt(e,t,n){var r;t===void 0&&(t=null),n===void 0&&(n={});var i=document.createElement(e);if(Array.isArray(t)){var a=t.filter(function(s){return s!==void 0});(r=i.classList).add.apply(r,a)}else t!==null&&i.classList.add(t);for(var l in n)Object.prototype.hasOwnProperty.call(n,l)&&(i[l]=n[l]);return i}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.make=void 0;var t=se;Object.defineProperty(e,"make",{enumerable:!0,get:function(){return t.make}})})($),Object.defineProperty(le,"__esModule",{value:!0}),le.fragmentToString=Qt;var Jt=$;function Qt(e){var t=(0,Jt.make)("div");return t.appendChild(e),t.innerHTML}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.fragmentToString=void 0;var t=le;Object.defineProperty(e,"fragmentToString",{enumerable:!0,get:function(){return t.fragmentToString}})})(Ue);var ze={},oe={};Object.defineProperty(oe,"__esModule",{value:!0}),oe.getContentLength=xt;var Zt=O;function xt(e){var t,n;return(0,Zt.isNativeInput)(e)?e.value.length:e.nodeType===Node.TEXT_NODE?e.length:(n=(t=e.textContent)===null||t===void 0?void 0:t.length)!==null&&n!==void 0?n:0}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.getContentLength=void 0;var t=oe;Object.defineProperty(e,"getContentLength",{enumerable:!0,get:function(){return t.getContentLength}})})(ze);var ue={},ce={},Ke=M&&M.__spreadArray||function(e,t,n){if(n||arguments.length===2)for(var r=0,i=t.length,a;r0;){var r=n.shift();if(r){if(e=r,(0,Sn.isLeaf)(e)&&!(0,On.isNodeEmpty)(e,t))return!1;n.push.apply(n,Array.from(e.childNodes))}}return!0}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isEmpty=void 0;var t=be;Object.defineProperty(e,"isEmpty",{enumerable:!0,get:function(){return t.isEmpty}})})(Qe);var Ze={},ke={};Object.defineProperty(ke,"__esModule",{value:!0}),ke.isFragment=En;var _n=ae;function En(e){return(0,_n.isNumber)(e)?!1:!!e&&!!e.nodeType&&e.nodeType===Node.DOCUMENT_FRAGMENT_NODE}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isFragment=void 0;var t=ke;Object.defineProperty(e,"isFragment",{enumerable:!0,get:function(){return t.isFragment}})})(Ze);var xe={},_e={};Object.defineProperty(_e,"__esModule",{value:!0}),_e.isHTMLString=wn;var In=$;function wn(e){var t=(0,In.make)("div");return t.innerHTML=e,t.childElementCount>0}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isHTMLString=void 0;var t=_e;Object.defineProperty(e,"isHTMLString",{enumerable:!0,get:function(){return t.isHTMLString}})})(xe);var et={},Ee={};Object.defineProperty(Ee,"__esModule",{value:!0}),Ee.offset=Pn;function Pn(e){var t=e.getBoundingClientRect(),n=window.pageXOffset||document.documentElement.scrollLeft,r=window.pageYOffset||document.documentElement.scrollTop,i=t.top+r,a=t.left+n;return{top:i,left:a,bottom:i+t.height,right:a+t.width}}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.offset=void 0;var t=Ee;Object.defineProperty(e,"offset",{enumerable:!0,get:function(){return t.offset}})})(et);var tt={},Ie={};Object.defineProperty(Ie,"__esModule",{value:!0}),Ie.prepend=jn;function jn(e,t){Array.isArray(t)?(t=t.reverse(),t.forEach(function(n){return e.prepend(n)})):e.prepend(t)}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.prepend=void 0;var t=Ie;Object.defineProperty(e,"prepend",{enumerable:!0,get:function(){return t.prepend}})})(tt),function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.prepend=e.offset=e.make=e.isLineBreakTag=e.isSingleTag=e.isNodeEmpty=e.isLeaf=e.isHTMLString=e.isFragment=e.isEmpty=e.isElement=e.isContentEditable=e.isCollapsedWhitespaces=e.findAllInputs=e.isNativeInput=e.allInputsSelector=e.getDeepestNode=e.getDeepestBlockElements=e.getContentLength=e.fragmentToString=e.containsOnlyInlineElements=e.canSetCaret=e.calculateBaseline=e.blockElements=e.append=void 0;var t=X;Object.defineProperty(e,"allInputsSelector",{enumerable:!0,get:function(){return t.allInputsSelector}});var n=O;Object.defineProperty(e,"isNativeInput",{enumerable:!0,get:function(){return n.isNativeInput}});var r=De;Object.defineProperty(e,"append",{enumerable:!0,get:function(){return r.append}});var i=J;Object.defineProperty(e,"blockElements",{enumerable:!0,get:function(){return i.blockElements}});var a=He;Object.defineProperty(e,"calculateBaseline",{enumerable:!0,get:function(){return a.calculateBaseline}});var l=Fe;Object.defineProperty(e,"canSetCaret",{enumerable:!0,get:function(){return l.canSetCaret}});var s=N;Object.defineProperty(e,"containsOnlyInlineElements",{enumerable:!0,get:function(){return s.containsOnlyInlineElements}});var o=Ue;Object.defineProperty(e,"fragmentToString",{enumerable:!0,get:function(){return o.fragmentToString}});var d=ze;Object.defineProperty(e,"getContentLength",{enumerable:!0,get:function(){return d.getContentLength}});var u=ue;Object.defineProperty(e,"getDeepestBlockElements",{enumerable:!0,get:function(){return u.getDeepestBlockElements}});var h=Ge;Object.defineProperty(e,"getDeepestNode",{enumerable:!0,get:function(){return h.getDeepestNode}});var g=Ye;Object.defineProperty(e,"findAllInputs",{enumerable:!0,get:function(){return g.findAllInputs}});var L=Je;Object.defineProperty(e,"isCollapsedWhitespaces",{enumerable:!0,get:function(){return L.isCollapsedWhitespaces}});var w=ee;Object.defineProperty(e,"isContentEditable",{enumerable:!0,get:function(){return w.isContentEditable}});var nr=ge;Object.defineProperty(e,"isElement",{enumerable:!0,get:function(){return nr.isElement}});var rr=Qe;Object.defineProperty(e,"isEmpty",{enumerable:!0,get:function(){return rr.isEmpty}});var ir=Ze;Object.defineProperty(e,"isFragment",{enumerable:!0,get:function(){return ir.isFragment}});var ar=xe;Object.defineProperty(e,"isHTMLString",{enumerable:!0,get:function(){return ar.isHTMLString}});var lr=ye;Object.defineProperty(e,"isLeaf",{enumerable:!0,get:function(){return lr.isLeaf}});var sr=Se;Object.defineProperty(e,"isNodeEmpty",{enumerable:!0,get:function(){return sr.isNodeEmpty}});var or=B;Object.defineProperty(e,"isLineBreakTag",{enumerable:!0,get:function(){return or.isLineBreakTag}});var ur=W;Object.defineProperty(e,"isSingleTag",{enumerable:!0,get:function(){return ur.isSingleTag}});var cr=$;Object.defineProperty(e,"make",{enumerable:!0,get:function(){return cr.make}});var dr=et;Object.defineProperty(e,"offset",{enumerable:!0,get:function(){return dr.offset}});var fr=tt;Object.defineProperty(e,"prepend",{enumerable:!0,get:function(){return fr.prepend}})}(c);const m="cdx-list",p={wrapper:m,item:`${m}__item`,itemContent:`${m}__item-content`,itemChildren:`${m}__item-children`};class v{static get CSS(){return{...p,orderedList:`${m}-ordered`}}constructor(t,n){this.config=n,this.readOnly=t}renderWrapper(t){let n;return t===!0?n=c.make("ol",[v.CSS.wrapper,v.CSS.orderedList]):n=c.make("ol",[v.CSS.orderedList,v.CSS.itemChildren]),n}renderItem(t,n){const r=c.make("li",v.CSS.item),i=c.make("div",v.CSS.itemContent,{innerHTML:t,contentEditable:(!this.readOnly).toString()});return r.appendChild(i),r}getItemContent(t){const n=t.querySelector(`.${v.CSS.itemContent}`);return!n||c.isEmpty(n)?"":n.innerHTML}getItemMeta(){return{}}composeDefaultMeta(){return{}}}class b{static get CSS(){return{...p,unorderedList:`${m}-unordered`}}constructor(t,n){this.config=n,this.readOnly=t}renderWrapper(t){let n;return t===!0?n=c.make("ul",[b.CSS.wrapper,b.CSS.unorderedList]):n=c.make("ul",[b.CSS.unorderedList,b.CSS.itemChildren]),n}renderItem(t,n){const r=c.make("li",b.CSS.item),i=c.make("div",b.CSS.itemContent,{innerHTML:t,contentEditable:(!this.readOnly).toString()});return r.appendChild(i),r}getItemContent(t){const n=t.querySelector(`.${b.CSS.itemContent}`);return!n||c.isEmpty(n)?"":n.innerHTML}getItemMeta(){return{}}composeDefaultMeta(){return{}}}function k(e){return e.nodeType===Node.ELEMENT_NODE}var j={},we={},H={},F={};Object.defineProperty(F,"__esModule",{value:!0}),F.getContenteditableSlice=Ln;var Tn=c;function Ln(e,t,n,r,i){var a;i===void 0&&(i=!1);var l=document.createRange();if(r==="left"?(l.setStart(e,0),l.setEnd(t,n)):(l.setStart(t,n),l.setEnd(e,e.childNodes.length)),i===!0){var s=l.extractContents();return(0,Tn.fragmentToString)(s)}var o=l.cloneContents(),d=document.createElement("div");d.appendChild(o);var u=(a=d.textContent)!==null&&a!==void 0?a:"";return u}Object.defineProperty(H,"__esModule",{value:!0}),H.checkContenteditableSliceForEmptiness=An;var Mn=c,Nn=F;function An(e,t,n,r){var i=(0,Nn.getContenteditableSlice)(e,t,n,r);return(0,Mn.isCollapsedWhitespaces)(i)}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.checkContenteditableSliceForEmptiness=void 0;var t=H;Object.defineProperty(e,"checkContenteditableSliceForEmptiness",{enumerable:!0,get:function(){return t.checkContenteditableSliceForEmptiness}})})(we);var nt={};(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.getContenteditableSlice=void 0;var t=F;Object.defineProperty(e,"getContenteditableSlice",{enumerable:!0,get:function(){return t.getContenteditableSlice}})})(nt);var rt={},Pe={};Object.defineProperty(Pe,"__esModule",{value:!0}),Pe.focus=Bn;var $n=c;function Bn(e,t){var n,r;if(t===void 0&&(t=!0),(0,$n.isNativeInput)(e)){e.focus();var i=t?0:e.value.length;e.setSelectionRange(i,i)}else{var a=document.createRange(),l=window.getSelection();if(!l)return;var s=function(g,L){L===void 0&&(L=!1);var w=document.createTextNode("");L?g.insertBefore(w,g.firstChild):g.appendChild(w),a.setStart(w,0),a.setEnd(w,0)},o=function(g){return g!=null},d=e.childNodes,u=t?d[0]:d[d.length-1];if(o(u)){for(;o(u)&&u.nodeType!==Node.TEXT_NODE;)u=t?u.firstChild:u.lastChild;if(o(u)&&u.nodeType===Node.TEXT_NODE){var h=(r=(n=u.textContent)===null||n===void 0?void 0:n.length)!==null&&r!==void 0?r:0,i=t?0:h;a.setStart(u,i),a.setEnd(u,i)}else s(e,t)}else s(e);l.removeAllRanges(),l.addRange(a)}}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.focus=void 0;var t=Pe;Object.defineProperty(e,"focus",{enumerable:!0,get:function(){return t.focus}})})(rt);var je={},R={};Object.defineProperty(R,"__esModule",{value:!0}),R.getCaretNodeAndOffset=Wn;function Wn(){var e=window.getSelection();if(e===null)return[null,0];var t=e.focusNode,n=e.focusOffset;return t===null?[null,0]:(t.nodeType!==Node.TEXT_NODE&&t.childNodes.length>0&&(t.childNodes[n]!==void 0?(t=t.childNodes[n],n=0):(t=t.childNodes[n-1],t.textContent!==null&&(n=t.textContent.length))),[t,n])}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.getCaretNodeAndOffset=void 0;var t=R;Object.defineProperty(e,"getCaretNodeAndOffset",{enumerable:!0,get:function(){return t.getCaretNodeAndOffset}})})(je);var it={},q={};Object.defineProperty(q,"__esModule",{value:!0}),q.getRange=Dn;function Dn(){var e=window.getSelection();return e&&e.rangeCount?e.getRangeAt(0):null}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.getRange=void 0;var t=q;Object.defineProperty(e,"getRange",{enumerable:!0,get:function(){return t.getRange}})})(it);var at={},Te={};Object.defineProperty(Te,"__esModule",{value:!0}),Te.isCaretAtEndOfInput=Rn;var lt=c,Hn=je,Fn=we;function Rn(e){var t=(0,lt.getDeepestNode)(e,!0);if(t===null)return!0;if((0,lt.isNativeInput)(t))return t.selectionEnd===t.value.length;var n=(0,Hn.getCaretNodeAndOffset)(),r=n[0],i=n[1];return r===null?!1:(0,Fn.checkContenteditableSliceForEmptiness)(e,r,i,"right")}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isCaretAtEndOfInput=void 0;var t=Te;Object.defineProperty(e,"isCaretAtEndOfInput",{enumerable:!0,get:function(){return t.isCaretAtEndOfInput}})})(at);var st={},Le={};Object.defineProperty(Le,"__esModule",{value:!0}),Le.isCaretAtStartOfInput=zn;var U=c,qn=R,Un=H;function zn(e){var t=(0,U.getDeepestNode)(e);if(t===null||(0,U.isEmpty)(e))return!0;if((0,U.isNativeInput)(t))return t.selectionEnd===0;if((0,U.isEmpty)(e))return!0;var n=(0,qn.getCaretNodeAndOffset)(),r=n[0],i=n[1];return r===null?!1:(0,Un.checkContenteditableSliceForEmptiness)(e,r,i,"left")}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isCaretAtStartOfInput=void 0;var t=Le;Object.defineProperty(e,"isCaretAtStartOfInput",{enumerable:!0,get:function(){return t.isCaretAtStartOfInput}})})(st);var ot={},Me={};Object.defineProperty(Me,"__esModule",{value:!0}),Me.save=Gn;var Kn=c,Xn=q;function Gn(){var e=(0,Xn.getRange)(),t=(0,Kn.make)("span");if(t.id="cursor",t.hidden=!0,!!e)return e.insertNode(t),function(){var r=window.getSelection();r&&(e.setStartAfter(t),e.setEndAfter(t),r.removeAllRanges(),r.addRange(e),setTimeout(function(){t.remove()},150))}}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.save=void 0;var t=Me;Object.defineProperty(e,"save",{enumerable:!0,get:function(){return t.save}})})(ot),function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.save=e.isCaretAtStartOfInput=e.isCaretAtEndOfInput=e.getRange=e.getCaretNodeAndOffset=e.focus=e.getContenteditableSlice=e.checkContenteditableSliceForEmptiness=void 0;var t=we;Object.defineProperty(e,"checkContenteditableSliceForEmptiness",{enumerable:!0,get:function(){return t.checkContenteditableSliceForEmptiness}});var n=nt;Object.defineProperty(e,"getContenteditableSlice",{enumerable:!0,get:function(){return n.getContenteditableSlice}});var r=rt;Object.defineProperty(e,"focus",{enumerable:!0,get:function(){return r.focus}});var i=je;Object.defineProperty(e,"getCaretNodeAndOffset",{enumerable:!0,get:function(){return i.getCaretNodeAndOffset}});var a=it;Object.defineProperty(e,"getRange",{enumerable:!0,get:function(){return a.getRange}});var l=at;Object.defineProperty(e,"isCaretAtEndOfInput",{enumerable:!0,get:function(){return l.isCaretAtEndOfInput}});var s=st;Object.defineProperty(e,"isCaretAtStartOfInput",{enumerable:!0,get:function(){return s.isCaretAtStartOfInput}});var o=ot;Object.defineProperty(e,"save",{enumerable:!0,get:function(){return o.save}})}(j);class f{static get CSS(){return{...p,checklist:`${m}-checklist`,itemChecked:`${m}__checkbox--checked`,noHover:`${m}__checkbox--no-hover`,checkbox:`${m}__checkbox-check`,checkboxContainer:`${m}__checkbox`}}constructor(t,n){this.config=n,this.readOnly=t}renderWrapper(t){let n;return t===!0?(n=c.make("ul",[f.CSS.wrapper,f.CSS.checklist]),n.addEventListener("click",r=>{const i=r.target;if(i){const a=i.closest(`.${f.CSS.checkboxContainer}`);a&&a.contains(i)&&this.toggleCheckbox(a)}})):n=c.make("ul",[f.CSS.checklist,f.CSS.itemChildren]),n}renderItem(t,n){const r=c.make("li",[f.CSS.item,f.CSS.item]),i=c.make("div",f.CSS.itemContent,{innerHTML:t,contentEditable:(!this.readOnly).toString()}),a=c.make("span",f.CSS.checkbox),l=c.make("div",f.CSS.checkboxContainer);return n.checked===!0&&l.classList.add(f.CSS.itemChecked),a.innerHTML=P,l.appendChild(a),r.appendChild(l),r.appendChild(i),r}getItemContent(t){const n=t.querySelector(`.${f.CSS.itemContent}`);return!n||c.isEmpty(n)?"":n.innerHTML}getItemMeta(t){const n=t.querySelector(`.${f.CSS.checkboxContainer}`);return{checked:n?n.classList.contains(f.CSS.itemChecked):!1}}composeDefaultMeta(){return{checked:!1}}toggleCheckbox(t){t.classList.toggle(f.CSS.itemChecked),t.classList.add(f.CSS.noHover),t.addEventListener("mouseleave",()=>this.removeSpecialHoverBehavior(t),{once:!0})}removeSpecialHoverBehavior(t){t.classList.remove(f.CSS.noHover)}}function Ne(e,t="after"){const n=[];let r;function i(a){switch(t){case"after":return a.nextElementSibling;case"before":return a.previousElementSibling}}for(r=i(e);r!==null;)n.push(r),r=i(r);return n.length!==0?n:null}function y(e,t=!0){let n=e;return e.classList.contains(p.item)&&(n=e.querySelector(`.${p.itemChildren}`)),n===null?[]:t?Array.from(n.querySelectorAll(`:scope > .${p.item}`)):Array.from(n.querySelectorAll(`.${p.item}`))}function Vn(e){return e.nextElementSibling===null}function Yn(e){return e.querySelector(`.${p.itemChildren}`)!==null}function S(e){return e.querySelector(`.${p.itemChildren}`)}function Ae(e){let t=e;e.classList.contains(p.item)&&(t=S(e)),t!==null&&y(t).length===0&&t.remove()}function z(e){return e.querySelector(`.${p.itemContent}`)}function E(e,t=!0){const n=z(e);n&&j.focus(n,t)}class $e{get currentItem(){const t=window.getSelection();if(!t)return null;let n=t.anchorNode;return!n||(k(n)||(n=n.parentNode),!n)||!k(n)?null:n.closest(`.${p.item}`)}get currentItemLevel(){const t=this.currentItem;if(t===null)return null;let n=t.parentNode,r=0;for(;n!==null&&n!==this.listWrapper;)k(n)&&n.classList.contains(p.item)&&(r+=1),n=n.parentNode;return r+1}constructor({data:t,config:n,api:r,readOnly:i,block:a},l){this.config=n,this.data=t,this.readOnly=i,this.api=r,this.block=a,this.renderer=l}render(){return this.listWrapper=this.renderer.renderWrapper(!0),this.data.items.length?this.appendItems(this.data.items,this.listWrapper):this.appendItems([{content:"",meta:{},items:[]}],this.listWrapper),this.readOnly||this.listWrapper.addEventListener("keydown",t=>{switch(t.key){case"Enter":this.enterPressed(t);break;case"Backspace":this.backspace(t);break;case"Tab":t.shiftKey?this.shiftTab(t):this.addTab(t);break}},!1),"start"in this.data.meta&&this.data.meta.start!==void 0&&this.changeStartWith(this.data.meta.start),"counterType"in this.data.meta&&this.data.meta.counterType!==void 0&&this.changeCounters(this.data.meta.counterType),this.listWrapper}save(t){const n=t??this.listWrapper,r=l=>y(l).map(o=>{const d=S(o),u=this.renderer.getItemContent(o),h=this.renderer.getItemMeta(o),g=d?r(d):[];return{content:u,meta:h,items:g}}),i=n?r(n):[];let a={style:this.data.style,meta:{},items:i};return this.data.style==="ordered"&&(a.meta={start:this.data.meta.start,counterType:this.data.meta.counterType}),a}static get pasteConfig(){return{tags:["OL","UL","LI"]}}merge(t){const n=this.block.holder.querySelectorAll(`.${p.item}`),r=n[n.length-1],i=z(r);if(r===null||i===null||(i.insertAdjacentHTML("beforeend",t.items[0].content),this.listWrapper===void 0))return;const a=y(this.listWrapper);if(a.length===0)return;const l=a[a.length-1];let s=S(l);const o=t.items.shift();o!==void 0&&(o.items.length!==0&&(s===null&&(s=this.renderer.renderWrapper(!1)),this.appendItems(o.items,s)),t.items.length>0&&this.appendItems(t.items,this.listWrapper))}onPaste(t){const n=t.detail.data;this.data=this.pasteHandler(n);const r=this.listWrapper;r&&r.parentNode&&r.parentNode.replaceChild(this.render(),r)}pasteHandler(t){const{tagName:n}=t;let r="unordered",i;switch(n){case"OL":r="ordered",i="ol";break;case"UL":case"LI":r="unordered",i="ul"}const a={style:r,meta:{},items:[]};r==="ordered"&&(this.data.meta.counterType="numeric",this.data.meta.start=1);const l=s=>Array.from(s.querySelectorAll(":scope > li")).map(d=>{const u=d.querySelector(`:scope > ${i}`),h=u?l(u):[];return{content:d.innerHTML??"",meta:{},items:h}});return a.items=l(t),a}changeStartWith(t){this.listWrapper.style.setProperty("counter-reset",`item ${t-1}`),this.data.meta.start=t}changeCounters(t){this.listWrapper.style.setProperty("--list-counter-type",t),this.data.meta.counterType=t}enterPressed(t){var s;const n=this.currentItem;if(t.stopPropagation(),t.preventDefault(),t.isComposing||n===null)return;const r=((s=this.renderer)==null?void 0:s.getItemContent(n).trim().length)===0,i=n.parentNode===this.listWrapper,a=n.previousElementSibling===null,l=this.api.blocks.getCurrentBlockIndex();if(i&&r)if(Vn(n)&&!Yn(n)){a?this.convertItemToDefaultBlock(l,!0):this.convertItemToDefaultBlock();return}else{this.splitList(n);return}else if(r){this.unshiftItem(n);return}else this.splitItem(n)}backspace(t){var r;const n=this.currentItem;if(n!==null&&j.isCaretAtStartOfInput(n)&&((r=window.getSelection())==null?void 0:r.isCollapsed)!==!1){if(t.stopPropagation(),n.parentNode===this.listWrapper&&n.previousElementSibling===null){this.convertFirstItemToDefaultBlock();return}t.preventDefault(),this.mergeItemWithPrevious(n)}}shiftTab(t){t.stopPropagation(),t.preventDefault(),this.currentItem!==null&&this.unshiftItem(this.currentItem)}unshiftItem(t){if(!t.parentNode||!k(t.parentNode))return;const n=t.parentNode.closest(`.${p.item}`);if(!n)return;let r=S(t);if(t.parentElement===null)return;const i=Ne(t);i!==null&&(r===null&&(r=this.renderer.renderWrapper(!1)),i.forEach(a=>{r.appendChild(a)}),t.appendChild(r)),n.after(t),E(t,!1),Ae(n)}splitList(t){const n=y(t),r=this.block,i=this.api.blocks.getCurrentBlockIndex();if(n.length!==0){const o=n[0];this.unshiftItem(o),E(t,!1)}if(t.previousElementSibling===null&&t.parentNode===this.listWrapper){this.convertItemToDefaultBlock(i);return}const a=Ne(t);if(a===null)return;const l=this.renderer.renderWrapper(!0);a.forEach(o=>{l.appendChild(o)});const s=this.save(l);s.meta.start=this.data.style=="ordered"?1:void 0,this.api.blocks.insert(r==null?void 0:r.name,s,this.config,i+1),this.convertItemToDefaultBlock(i+1),l.remove()}splitItem(t){const[n,r]=j.getCaretNodeAndOffset();if(n===null)return;const i=z(t);let a;i===null?a="":a=j.getContenteditableSlice(i,n,r,"right",!0);const l=S(t),s=this.renderItem(a);t==null||t.after(s),l&&s.appendChild(l),E(s)}mergeItemWithPrevious(t){const n=t.previousElementSibling,r=t.parentNode;if(r===null||!k(r))return;const i=r.closest(`.${p.item}`);if(!n&&!i||n&&!k(n))return;let a;if(n){const h=y(n,!1);h.length!==0&&h.length!==0?a=h[h.length-1]:a=n}else a=i;const l=this.renderer.getItemContent(t);if(!a)return;E(a,!1);const s=z(a);if(s===null)return;s.insertAdjacentHTML("beforeend",l);const o=y(t);if(o.length===0){t.remove(),Ae(a);return}const d=n||i,u=S(d)??this.renderer.renderWrapper(!1);n?o.forEach(h=>{u.appendChild(h)}):o.forEach(h=>{u.prepend(h)}),S(d)===null&&a.appendChild(u),t.remove()}addTab(t){var a;t.stopPropagation(),t.preventDefault();const n=this.currentItem;if(!n)return;if(((a=this.config)==null?void 0:a.maxLevel)!==void 0){const l=this.currentItemLevel;if(l!==null&&l===this.config.maxLevel)return}const r=n.previousSibling;if(r===null||!k(r))return;const i=S(r);if(i)i.appendChild(n),y(n).forEach(s=>{i.appendChild(s)});else{const l=this.renderer.renderWrapper(!1);l.appendChild(n),y(n).forEach(o=>{l.appendChild(o)}),r.appendChild(l)}Ae(n),E(n,!1)}convertItemToDefaultBlock(t,n){let r;const i=this.currentItem,a=i!==null?this.renderer.getItemContent(i):"";n===!0&&this.api.blocks.delete(),t!==void 0?r=this.api.blocks.insert(void 0,{text:a},void 0,t):r=this.api.blocks.insert(),i==null||i.remove(),this.api.caret.setToBlock(r,"start")}convertFirstItemToDefaultBlock(){const t=this.currentItem;if(t===null)return;const n=y(t);if(n.length!==0){const l=n[0];this.unshiftItem(l),E(t)}const r=Ne(t),i=this.api.blocks.getCurrentBlockIndex(),a=r===null;this.convertItemToDefaultBlock(i,a)}renderItem(t,n){const r=n??this.renderer.composeDefaultMeta();switch(!0){case this.renderer instanceof v:return this.renderer.renderItem(t,r);case this.renderer instanceof b:return this.renderer.renderItem(t,r);default:return this.renderer.renderItem(t,r)}}appendItems(t,n){t.forEach(r=>{var a;const i=this.renderItem(r.content,r.meta);if(n.appendChild(i),r.items.length){const l=(a=this.renderer)==null?void 0:a.renderWrapper(!1);this.appendItems(r.items,l),i.appendChild(l)}})}}const I={wrapper:`${m}-start-with-field`,input:`${m}-start-with-field__input`,startWithElementWrapperInvalid:`${m}-start-with-field--invalid`};function Jn(e,{value:t,placeholder:n,attributes:r,sanitize:i}){const a=c.make("div",I.wrapper),l=c.make("input",I.input,{placeholder:n,tabIndex:-1,value:t});for(const s in r)l.setAttribute(s,r[s]);return a.appendChild(l),l.addEventListener("input",()=>{i!==void 0&&(l.value=i(l.value));const s=l.checkValidity();!s&&!a.classList.contains(I.startWithElementWrapperInvalid)&&a.classList.add(I.startWithElementWrapperInvalid),s&&a.classList.contains(I.startWithElementWrapperInvalid)&&a.classList.remove(I.startWithElementWrapperInvalid),s&&e(l.value)}),a}const T=new Map([["Numeric","numeric"],["Lower Roman","lower-roman"],["Upper Roman","upper-roman"],["Lower Alpha","lower-alpha"],["Upper Alpha","upper-alpha"]]),ut=new Map([["numeric",ct],["lower-roman",dt],["upper-roman",ft],["lower-alpha",ht],["upper-alpha",pt]]),hr="",mr="";function Qn(e){return e.replace(/\D+/g,"")}function Zn(e){return typeof e.items[0]=="string"}function xn(e){return!("meta"in e)}function er(e){return typeof e.items[0]!="string"&&"text"in e.items[0]&&"checked"in e.items[0]&&typeof e.items[0].text=="string"&&typeof e.items[0].checked=="boolean"}function tr(e){const t=[];return Zn(e)?(e.items.forEach(n=>{t.push({content:n,meta:{},items:[]})}),{style:e.style,meta:{},items:t}):er(e)?(e.items.forEach(n=>{t.push({content:n.text,meta:{checked:n.checked},items:[]})}),{style:"checklist",meta:{},items:t}):xn(e)?{style:e.style,meta:{},items:e.items}:e}class K{static get isReadOnlySupported(){return!0}static get enableLineBreaks(){return!0}static get toolbox(){return[{icon:Be,title:"Unordered List",data:{style:"unordered"}},{icon:We,title:"Ordered List",data:{style:"ordered"}},{icon:_,title:"Checklist",data:{style:"checklist"}}]}static get pasteConfig(){return{tags:["OL","UL","LI"]}}static get conversionConfig(){return{export:t=>K.joinRecursive(t),import:(t,n)=>({meta:{},items:[{content:t,meta:{},items:[]}],style:(n==null?void 0:n.defaultStyle)!==void 0?n.defaultStyle:"unordered"})}}get listStyle(){return this.data.style||this.defaultListStyle}set listStyle(t){var r;this.data.style=t,this.changeTabulatorByStyle();const n=this.list.render();(r=this.listElement)==null||r.replaceWith(n),this.listElement=n}constructor({data:t,config:n,api:r,readOnly:i,block:a}){var s;this.api=r,this.readOnly=i,this.config=n,this.block=a,this.defaultListStyle=((s=this.config)==null?void 0:s.defaultStyle)||"unordered",this.defaultCounterTypes=this.config.counterTypes||Array.from(T.values());const l={style:this.defaultListStyle,meta:{},items:[]};this.data=Object.keys(t).length?tr(t):l,this.listStyle==="ordered"&&this.data.meta.counterType===void 0&&(this.data.meta.counterType="numeric"),this.changeTabulatorByStyle()}static joinRecursive(t){return t.items.map(n=>`${n.content} ${K.joinRecursive(n)}`).join("")}render(){return this.listElement=this.list.render(),this.listElement}save(){return this.data=this.list.save(),this.data}merge(t){this.list.merge(t)}renderSettings(){const t=[{label:this.api.i18n.t("Unordered"),icon:Be,closeOnActivate:!0,isActive:this.listStyle=="unordered",onActivate:()=>{this.listStyle="unordered"}},{label:this.api.i18n.t("Ordered"),icon:We,closeOnActivate:!0,isActive:this.listStyle=="ordered",onActivate:()=>{this.listStyle="ordered"}},{label:this.api.i18n.t("Checklist"),icon:_,closeOnActivate:!0,isActive:this.listStyle=="checklist",onActivate:()=>{this.listStyle="checklist"}}];if(this.listStyle==="ordered"){const n=Jn(a=>this.changeStartWith(Number(a)),{value:String(this.data.meta.start??1),placeholder:"",attributes:{required:"true"},sanitize:a=>Qn(a)}),r=[{label:this.api.i18n.t("Start with"),icon:mt,children:{items:[{element:n,type:"html"}]}}],i={label:this.api.i18n.t("Counter type"),icon:ut.get(this.data.meta.counterType),children:{items:[]}};T.forEach((a,l)=>{const s=T.get(l);this.defaultCounterTypes.includes(s)&&i.children.items.push({title:this.api.i18n.t(l),icon:ut.get(s),isActive:this.data.meta.counterType===T.get(l),closeOnActivate:!0,onActivate:()=>{this.changeCounters(T.get(l))}})}),i.children.items.length>1&&r.push(i),t.push({type:"separator"},...r)}return t}onPaste(t){const{tagName:n}=t.detail.data;switch(n){case"OL":this.listStyle="ordered";break;case"UL":case"LI":this.listStyle="unordered"}this.list.onPaste(t)}pasteHandler(t){return this.list.pasteHandler(t)}changeCounters(t){var n;(n=this.list)==null||n.changeCounters(t),this.data.meta.counterType=t}changeStartWith(t){var n;(n=this.list)==null||n.changeStartWith(t),this.data.meta.start=t}changeTabulatorByStyle(){switch(this.listStyle){case"ordered":this.list=new $e({data:this.data,readOnly:this.readOnly,api:this.api,config:this.config,block:this.block},new v(this.readOnly,this.config));break;case"unordered":this.list=new $e({data:this.data,readOnly:this.readOnly,api:this.api,config:this.config,block:this.block},new b(this.readOnly,this.config));break;case"checklist":this.list=new $e({data:this.data,readOnly:this.readOnly,api:this.api,config:this.config,block:this.block},new f(this.readOnly,this.config));break}}}return K}); diff --git a/plugins/tiddlywiki/editorjs/files/editorjs.umd.js b/plugins/tiddlywiki/editorjs/files/editorjs.umd.js new file mode 100644 index 000000000..0a6a1ddcb --- /dev/null +++ b/plugins/tiddlywiki/editorjs/files/editorjs.umd.js @@ -0,0 +1,51 @@ +(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(".ce-hint--align-start{text-align:left}.ce-hint--align-center{text-align:center}.ce-hint__description{opacity:.6;margin-top:3px}")),document.head.appendChild(e)}}catch(t){console.error("vite-plugin-css-injected-by-js",t)}})(); +(function(J,ne){typeof exports=="object"&&typeof module<"u"?module.exports=ne():typeof define=="function"&&define.amd?define(ne):(J=typeof globalThis<"u"?globalThis:J||self,J.EditorJS=ne())})(this,function(){"use strict";var J=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function ne(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}function Yn(n){if(n.__esModule)return n;var e=n.default;if(typeof e=="function"){var t=function o(){return this instanceof o?Reflect.construct(e,arguments,this.constructor):e.apply(this,arguments)};t.prototype=e.prototype}else t={};return Object.defineProperty(t,"__esModule",{value:!0}),Object.keys(n).forEach(function(o){var i=Object.getOwnPropertyDescriptor(n,o);Object.defineProperty(t,o,i.get?i:{enumerable:!0,get:function(){return n[o]}})}),t}function tt(){}Object.assign(tt,{default:tt,register:tt,revert:function(){},__esModule:!0}),Element.prototype.matches||(Element.prototype.matches=Element.prototype.matchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||Element.prototype.webkitMatchesSelector||function(n){const e=(this.document||this.ownerDocument).querySelectorAll(n);let t=e.length;for(;--t>=0&&e.item(t)!==this;);return t>-1}),Element.prototype.closest||(Element.prototype.closest=function(n){let e=this;if(!document.documentElement.contains(e))return null;do{if(e.matches(n))return e;e=e.parentElement||e.parentNode}while(e!==null);return null}),Element.prototype.prepend||(Element.prototype.prepend=function(e){const t=document.createDocumentFragment();Array.isArray(e)||(e=[e]),e.forEach(o=>{const i=o instanceof Node;t.appendChild(i?o:document.createTextNode(o))}),this.insertBefore(t,this.firstChild)}),Element.prototype.scrollIntoViewIfNeeded||(Element.prototype.scrollIntoViewIfNeeded=function(n){n=arguments.length===0?!0:!!n;const e=this.parentNode,t=window.getComputedStyle(e,null),o=parseInt(t.getPropertyValue("border-top-width")),i=parseInt(t.getPropertyValue("border-left-width")),s=this.offsetTop-e.offsetTope.scrollTop+e.clientHeight,a=this.offsetLeft-e.offsetLefte.scrollLeft+e.clientWidth,c=s&&!r;(s||r)&&n&&(e.scrollTop=this.offsetTop-e.offsetTop-e.clientHeight/2-o+this.clientHeight/2),(a||l)&&n&&(e.scrollLeft=this.offsetLeft-e.offsetLeft-e.clientWidth/2-i+this.clientWidth/2),(s||r||a||l)&&!n&&this.scrollIntoView(c)}),window.requestIdleCallback=window.requestIdleCallback||function(n){const e=Date.now();return setTimeout(function(){n({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-e))}})},1)},window.cancelIdleCallback=window.cancelIdleCallback||function(n){clearTimeout(n)};let Kn=(n=21)=>crypto.getRandomValues(new Uint8Array(n)).reduce((e,t)=>(t&=63,t<36?e+=t.toString(36):t<62?e+=(t-26).toString(36).toUpperCase():t>62?e+="-":e+="_",e),"");var ko=(n=>(n.VERBOSE="VERBOSE",n.INFO="INFO",n.WARN="WARN",n.ERROR="ERROR",n))(ko||{});const y={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,LEFT:37,UP:38,DOWN:40,RIGHT:39,DELETE:46,META:91,SLASH:191},Xn={LEFT:0,WHEEL:1,RIGHT:2,BACKWARD:3,FORWARD:4};function ye(n,e,t="log",o,i="color: inherit"){if(!("console"in window)||!window.console[t])return;const s=["info","log","warn","error"].includes(t),r=[];switch(ye.logLevel){case"ERROR":if(t!=="error")return;break;case"WARN":if(!["error","warn"].includes(t))return;break;case"INFO":if(!s||n)return;break}o&&r.push(o);const a="Editor.js 2.31.0-rc.9",l=`line-height: 1em; + color: #006FEA; + display: inline-block; + font-size: 11px; + line-height: 1em; + background-color: #fff; + padding: 4px 9px; + border-radius: 30px; + border: 1px solid rgba(56, 138, 229, 0.16); + margin: 4px 5px 4px 0;`;n&&(s?(r.unshift(l,i),e=`%c${a}%c ${e}`):e=`( ${a} )${e}`);try{s?o?console[t](`${e} %o`,...r):console[t](e,...r):console[t](e)}catch{}}ye.logLevel="VERBOSE";function Vn(n){ye.logLevel=n}const T=ye.bind(window,!1),X=ye.bind(window,!0);function re(n){return Object.prototype.toString.call(n).match(/\s([a-zA-Z]+)/)[1].toLowerCase()}function M(n){return re(n)==="function"||re(n)==="asyncfunction"}function N(n){return re(n)==="object"}function Q(n){return re(n)==="string"}function qn(n){return re(n)==="boolean"}function yo(n){return re(n)==="number"}function wo(n){return re(n)==="undefined"}function V(n){return n?Object.keys(n).length===0&&n.constructor===Object:!0}function Eo(n){return n>47&&n<58||n===32||n===13||n===229||n>64&&n<91||n>95&&n<112||n>185&&n<193||n>218&&n<223}async function Zn(n,e=()=>{},t=()=>{}){async function o(i,s,r){try{await i.function(i.data),await s(wo(i.data)?{}:i.data)}catch{r(wo(i.data)?{}:i.data)}}return n.reduce(async(i,s)=>(await i,o(s,e,t)),Promise.resolve())}function xo(n){return Array.prototype.slice.call(n)}function Ae(n,e){return function(){const t=this,o=arguments;window.setTimeout(()=>n.apply(t,o),e)}}function Gn(n){return n.name.split(".").pop()}function Jn(n){return/^[-\w]+\/([-+\w]+|\*)$/.test(n)}function Bo(n,e,t){let o;return(...i)=>{const s=this,r=()=>{o=null,t||n.apply(s,i)},a=t&&!o;window.clearTimeout(o),o=window.setTimeout(r,e),a&&n.apply(s,i)}}function ot(n,e,t=void 0){let o,i,s,r=null,a=0;t||(t={});const l=function(){a=t.leading===!1?0:Date.now(),r=null,s=n.apply(o,i),r||(o=i=null)};return function(){const c=Date.now();!a&&t.leading===!1&&(a=c);const u=e-(c-a);return o=this,i=arguments,u<=0||u>e?(r&&(clearTimeout(r),r=null),a=c,s=n.apply(o,i),r||(o=i=null)):!r&&t.trailing!==!1&&(r=setTimeout(l,u)),s}}function Qn(){const n={win:!1,mac:!1,x11:!1,linux:!1},e=Object.keys(n).find(t=>window.navigator.appVersion.toLowerCase().indexOf(t)!==-1);return e&&(n[e]=!0),n}function Le(n){return n[0].toUpperCase()+n.slice(1)}function nt(n,...e){if(!e.length)return n;const t=e.shift();if(N(n)&&N(t))for(const o in t)N(t[o])?(n[o]||Object.assign(n,{[o]:{}}),nt(n[o],t[o])):Object.assign(n,{[o]:t[o]});return nt(n,...e)}function it(n){const e=Qn();return n=n.replace(/shift/gi,"⇧").replace(/backspace/gi,"⌫").replace(/enter/gi,"⏎").replace(/up/gi,"↑").replace(/left/gi,"→").replace(/down/gi,"↓").replace(/right/gi,"←").replace(/escape/gi,"⎋").replace(/insert/gi,"Ins").replace(/delete/gi,"␡").replace(/\+/gi," + "),e.mac?n=n.replace(/ctrl|cmd/gi,"⌘").replace(/alt/gi,"⌥"):n=n.replace(/cmd/gi,"Ctrl").replace(/windows/gi,"WIN"),n}function ei(n){try{return new URL(n).href}catch{}return n.substring(0,2)==="//"?window.location.protocol+n:window.location.origin+n}function ti(){return Kn(10)}function oi(n){window.open(n,"_blank")}function ni(n=""){return`${n}${Math.floor(Math.random()*1e8).toString(16)}`}function st(n,e,t){const o=`«${e}» is deprecated and will be removed in the next major release. Please use the «${t}» instead.`;n&&X(o,"warn")}function fe(n,e,t){const o=t.value?"value":"get",i=t[o],s=`#${e}Cache`;if(t[o]=function(...r){return this[s]===void 0&&(this[s]=i.apply(this,...r)),this[s]},o==="get"&&t.set){const r=t.set;t.set=function(a){delete n[s],r.apply(this,a)}}return t}const Co=650;function ge(){return window.matchMedia(`(max-width: ${Co}px)`).matches}const rt=typeof window<"u"&&window.navigator&&window.navigator.platform&&(/iP(ad|hone|od)/.test(window.navigator.platform)||window.navigator.platform==="MacIntel"&&window.navigator.maxTouchPoints>1);function ii(n,e){const t=Array.isArray(n)||N(n),o=Array.isArray(e)||N(e);return t||o?JSON.stringify(n)===JSON.stringify(e):n===e}class d{static isSingleTag(e){return e.tagName&&["AREA","BASE","BR","COL","COMMAND","EMBED","HR","IMG","INPUT","KEYGEN","LINK","META","PARAM","SOURCE","TRACK","WBR"].includes(e.tagName)}static isLineBreakTag(e){return e&&e.tagName&&["BR","WBR"].includes(e.tagName)}static make(e,t=null,o={}){const i=document.createElement(e);if(Array.isArray(t)){const s=t.filter(r=>r!==void 0);i.classList.add(...s)}else t&&i.classList.add(t);for(const s in o)Object.prototype.hasOwnProperty.call(o,s)&&(i[s]=o[s]);return i}static text(e){return document.createTextNode(e)}static append(e,t){Array.isArray(t)?t.forEach(o=>e.appendChild(o)):e.appendChild(t)}static prepend(e,t){Array.isArray(t)?(t=t.reverse(),t.forEach(o=>e.prepend(o))):e.prepend(t)}static swap(e,t){const o=document.createElement("div"),i=e.parentNode;i.insertBefore(o,e),i.insertBefore(e,t),i.insertBefore(t,o),i.removeChild(o)}static find(e=document,t){return e.querySelector(t)}static get(e){return document.getElementById(e)}static findAll(e=document,t){return e.querySelectorAll(t)}static get allInputsSelector(){return"[contenteditable=true], textarea, input:not([type]), "+["text","password","email","number","search","tel","url"].map(t=>`input[type="${t}"]`).join(", ")}static findAllInputs(e){return xo(e.querySelectorAll(d.allInputsSelector)).reduce((t,o)=>d.isNativeInput(o)||d.containsOnlyInlineElements(o)?[...t,o]:[...t,...d.getDeepestBlockElements(o)],[])}static getDeepestNode(e,t=!1){const o=t?"lastChild":"firstChild",i=t?"previousSibling":"nextSibling";if(e&&e.nodeType===Node.ELEMENT_NODE&&e[o]){let s=e[o];if(d.isSingleTag(s)&&!d.isNativeInput(s)&&!d.isLineBreakTag(s))if(s[i])s=s[i];else if(s.parentNode[i])s=s.parentNode[i];else return s.parentNode;return this.getDeepestNode(s,t)}return e}static isElement(e){return yo(e)?!1:e&&e.nodeType&&e.nodeType===Node.ELEMENT_NODE}static isFragment(e){return yo(e)?!1:e&&e.nodeType&&e.nodeType===Node.DOCUMENT_FRAGMENT_NODE}static isContentEditable(e){return e.contentEditable==="true"}static isNativeInput(e){const t=["INPUT","TEXTAREA"];return e&&e.tagName?t.includes(e.tagName):!1}static canSetCaret(e){let t=!0;if(d.isNativeInput(e))switch(e.type){case"file":case"checkbox":case"radio":case"hidden":case"submit":case"button":case"image":case"reset":t=!1;break}else t=d.isContentEditable(e);return t}static isNodeEmpty(e,t){let o;return this.isSingleTag(e)&&!this.isLineBreakTag(e)?!1:(this.isElement(e)&&this.isNativeInput(e)?o=e.value:o=e.textContent.replace("​",""),t&&(o=o.replace(new RegExp(t,"g"),"")),o.length===0)}static isLeaf(e){return e?e.childNodes.length===0:!1}static isEmpty(e,t){const o=[e];for(;o.length>0;)if(e=o.shift(),!!e){if(this.isLeaf(e)&&!this.isNodeEmpty(e,t))return!1;e.childNodes&&o.push(...Array.from(e.childNodes))}return!0}static isHTMLString(e){const t=d.make("div");return t.innerHTML=e,t.childElementCount>0}static getContentLength(e){return d.isNativeInput(e)?e.value.length:e.nodeType===Node.TEXT_NODE?e.length:e.textContent.length}static get blockElements(){return["address","article","aside","blockquote","canvas","div","dl","dt","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","li","main","nav","noscript","ol","output","p","pre","ruby","section","table","tbody","thead","tr","tfoot","ul","video"]}static containsOnlyInlineElements(e){let t;Q(e)?(t=document.createElement("div"),t.innerHTML=e):t=e;const o=i=>!d.blockElements.includes(i.tagName.toLowerCase())&&Array.from(i.children).every(o);return Array.from(t.children).every(o)}static getDeepestBlockElements(e){return d.containsOnlyInlineElements(e)?[e]:Array.from(e.children).reduce((t,o)=>[...t,...d.getDeepestBlockElements(o)],[])}static getHolder(e){return Q(e)?document.getElementById(e):e}static isAnchor(e){return e.tagName.toLowerCase()==="a"}static offset(e){const t=e.getBoundingClientRect(),o=window.pageXOffset||document.documentElement.scrollLeft,i=window.pageYOffset||document.documentElement.scrollTop,s=t.top+i,r=t.left+o;return{top:s,left:r,bottom:s+t.height,right:r+t.width}}}function si(n){return!/[^\t\n\r ]/.test(n)}function ri(n){const e=window.getComputedStyle(n),t=parseFloat(e.fontSize),o=parseFloat(e.lineHeight)||t*1.2,i=parseFloat(e.paddingTop),s=parseFloat(e.borderTopWidth),r=parseFloat(e.marginTop),a=t*.8,l=(o-t)/2;return r+s+i+l+a}function To(n){n.dataset.empty=d.isEmpty(n)?"true":"false"}const So={ui:{blockTunes:{toggler:{"Click to tune":"","or drag to move":""}},inlineToolbar:{converter:{"Convert to":""}},toolbar:{toolbox:{Add:""}},popover:{Filter:"","Nothing found":"","Convert to":""}},toolNames:{Text:"",Link:"",Bold:"",Italic:""},tools:{link:{"Add a link":""},stub:{"The block can not be displayed correctly.":""}},blockTunes:{delete:{Delete:"","Click to delete":""},moveUp:{"Move up":""},moveDown:{"Move down":""}}},Io=class ke{static ui(e,t){return ke._t(e,t)}static t(e,t){return ke._t(e,t)}static setDictionary(e){ke.currentDictionary=e}static _t(e,t){const o=ke.getNamespace(e);return!o||!o[t]?t:o[t]}static getNamespace(e){return e.split(".").reduce((o,i)=>!o||!Object.keys(o).length?{}:o[i],ke.currentDictionary)}};Io.currentDictionary=So;let H=Io;class Oo extends Error{}class we{constructor(){this.subscribers={}}on(e,t){e in this.subscribers||(this.subscribers[e]=[]),this.subscribers[e].push(t)}once(e,t){e in this.subscribers||(this.subscribers[e]=[]);const o=i=>{const s=t(i),r=this.subscribers[e].indexOf(o);return r!==-1&&this.subscribers[e].splice(r,1),s};this.subscribers[e].push(o)}emit(e,t){V(this.subscribers)||!this.subscribers[e]||this.subscribers[e].reduce((o,i)=>{const s=i(o);return s!==void 0?s:o},t)}off(e,t){if(this.subscribers[e]===void 0){console.warn(`EventDispatcher .off(): there is no subscribers for event "${e.toString()}". Probably, .off() called before .on()`);return}for(let o=0;o{const l=this.allListeners.indexOf(s[a]);l>-1&&(this.allListeners.splice(l,1),r.element.removeEventListener(r.eventType,r.handler,r.options))})}offById(e){const t=this.findById(e);t&&t.element.removeEventListener(t.eventType,t.handler,t.options)}findOne(e,t,o){const i=this.findAll(e,t,o);return i.length>0?i[0]:null}findAll(e,t,o){let i;const s=e?this.findByEventTarget(e):[];return e&&t&&o?i=s.filter(r=>r.eventType===t&&r.handler===o):e&&t?i=s.filter(r=>r.eventType===t):i=s,i}removeAll(){this.allListeners.map(e=>{e.element.removeEventListener(e.eventType,e.handler,e.options)}),this.allListeners=[]}destroy(){this.removeAll()}findByEventTarget(e){return this.allListeners.filter(t=>{if(t.element===e)return t})}findByType(e){return this.allListeners.filter(t=>{if(t.eventType===e)return t})}findByHandler(e){return this.allListeners.filter(t=>{if(t.handler===e)return t})}findById(e){return this.allListeners.find(t=>t.id===e)}}class E{constructor({config:e,eventsDispatcher:t}){if(this.nodes={},this.listeners=new Ee,this.readOnlyMutableListeners={on:(o,i,s,r=!1)=>{this.mutableListenerIds.push(this.listeners.on(o,i,s,r))},clearAll:()=>{for(const o of this.mutableListenerIds)this.listeners.offById(o);this.mutableListenerIds=[]}},this.mutableListenerIds=[],new.target===E)throw new TypeError("Constructors for abstract class Module are not allowed.");this.config=e,this.eventsDispatcher=t}set state(e){this.Editor=e}removeAllNodes(){for(const e in this.nodes){const t=this.nodes[e];t instanceof HTMLElement&&t.remove()}}get isRtl(){return this.config.i18n.direction==="rtl"}}class b{constructor(){this.instance=null,this.selection=null,this.savedSelectionRange=null,this.isFakeBackgroundEnabled=!1,this.commandBackground="backColor",this.commandRemoveFormat="removeFormat"}static get CSS(){return{editorWrapper:"codex-editor",editorZone:"codex-editor__redactor"}}static get anchorNode(){const e=window.getSelection();return e?e.anchorNode:null}static get anchorElement(){const e=window.getSelection();if(!e)return null;const t=e.anchorNode;return t?d.isElement(t)?t:t.parentElement:null}static get anchorOffset(){const e=window.getSelection();return e?e.anchorOffset:null}static get isCollapsed(){const e=window.getSelection();return e?e.isCollapsed:null}static get isAtEditor(){return this.isSelectionAtEditor(b.get())}static isSelectionAtEditor(e){if(!e)return!1;let t=e.anchorNode||e.focusNode;t&&t.nodeType===Node.TEXT_NODE&&(t=t.parentNode);let o=null;return t&&t instanceof Element&&(o=t.closest(`.${b.CSS.editorZone}`)),o?o.nodeType===Node.ELEMENT_NODE:!1}static isRangeAtEditor(e){if(!e)return;let t=e.startContainer;t&&t.nodeType===Node.TEXT_NODE&&(t=t.parentNode);let o=null;return t&&t instanceof Element&&(o=t.closest(`.${b.CSS.editorZone}`)),o?o.nodeType===Node.ELEMENT_NODE:!1}static get isSelectionExists(){return!!b.get().anchorNode}static get range(){return this.getRangeFromSelection(this.get())}static getRangeFromSelection(e){return e&&e.rangeCount?e.getRangeAt(0):null}static get rect(){let e=document.selection,t,o={x:0,y:0,width:0,height:0};if(e&&e.type!=="Control")return e=e,t=e.createRange(),o.x=t.boundingLeft,o.y=t.boundingTop,o.width=t.boundingWidth,o.height=t.boundingHeight,o;if(!window.getSelection)return T("Method window.getSelection is not supported","warn"),o;if(e=window.getSelection(),e.rangeCount===null||isNaN(e.rangeCount))return T("Method SelectionUtils.rangeCount is not supported","warn"),o;if(e.rangeCount===0)return o;if(t=e.getRangeAt(0).cloneRange(),t.getBoundingClientRect&&(o=t.getBoundingClientRect()),o.x===0&&o.y===0){const i=document.createElement("span");if(i.getBoundingClientRect){i.appendChild(document.createTextNode("​")),t.insertNode(i),o=i.getBoundingClientRect();const s=i.parentNode;s.removeChild(i),s.normalize()}}return o}static get text(){return window.getSelection?window.getSelection().toString():""}static get(){return window.getSelection()}static setCursor(e,t=0){const o=document.createRange(),i=window.getSelection();return d.isNativeInput(e)?d.canSetCaret(e)?(e.focus(),e.selectionStart=e.selectionEnd=t,e.getBoundingClientRect()):void 0:(o.setStart(e,t),o.setEnd(e,t),i.removeAllRanges(),i.addRange(o),o.getBoundingClientRect())}static isRangeInsideContainer(e){const t=b.range;return t===null?!1:e.contains(t.startContainer)}static addFakeCursor(){const e=b.range;if(e===null)return;const t=d.make("span","codex-editor__fake-cursor");t.dataset.mutationFree="true",e.collapse(),e.insertNode(t)}static isFakeCursorInsideContainer(e){return d.find(e,".codex-editor__fake-cursor")!==null}static removeFakeCursor(e=document.body){const t=d.find(e,".codex-editor__fake-cursor");t&&t.remove()}removeFakeBackground(){this.isFakeBackgroundEnabled&&(this.isFakeBackgroundEnabled=!1,document.execCommand(this.commandRemoveFormat))}setFakeBackground(){document.execCommand(this.commandBackground,!1,"#a8d6ff"),this.isFakeBackgroundEnabled=!0}save(){this.savedSelectionRange=b.range}restore(){if(!this.savedSelectionRange)return;const e=window.getSelection();e.removeAllRanges(),e.addRange(this.savedSelectionRange)}clearSaved(){this.savedSelectionRange=null}collapseToEnd(){const e=window.getSelection(),t=document.createRange();t.selectNodeContents(e.focusNode),t.collapse(!1),e.removeAllRanges(),e.addRange(t)}findParentTag(e,t,o=10){const i=window.getSelection();let s=null;return!i||!i.anchorNode||!i.focusNode?null:([i.anchorNode,i.focusNode].forEach(a=>{let l=o;for(;l>0&&a.parentNode&&!(a.tagName===e&&(s=a,t&&a.classList&&!a.classList.contains(t)&&(s=null),s));)a=a.parentNode,l--}),s)}expandToTag(e){const t=window.getSelection();t.removeAllRanges();const o=document.createRange();o.selectNodeContents(e),t.addRange(o)}}function ai(n,e){const{type:t,target:o,addedNodes:i,removedNodes:s}=n;return n.type==="attributes"&&n.attributeName==="data-empty"?!1:!!(e.contains(o)||t==="childList"&&(Array.from(i).some(l=>l===e)||Array.from(s).some(l=>l===e)))}const at="redactor dom changed",_o="block changed",Mo="fake cursor is about to be toggled",Ao="fake cursor have been set",xe="editor mobile layout toggled";function lt(n,e){if(!n.conversionConfig)return!1;const t=n.conversionConfig[e];return M(t)||Q(t)}function Pe(n,e){return lt(n.tool,e)}function Lo(n,e){return Object.entries(n).some(([t,o])=>e[t]&&ii(e[t],o))}async function Po(n,e){const o=(await n.save()).data,i=e.find(s=>s.name===n.name);return i!==void 0&&!lt(i,"export")?[]:e.reduce((s,r)=>{if(!lt(r,"import")||r.toolbox===void 0)return s;const a=r.toolbox.filter(l=>{if(V(l)||l.icon===void 0)return!1;if(l.data!==void 0){if(Lo(l.data,o))return!1}else if(r.name===n.name)return!1;return!0});return s.push({...r,toolbox:a}),s},[])}function No(n,e){return n.mergeable?n.name===e.name?!0:Pe(e,"export")&&Pe(n,"import"):!1}function li(n,e){const t=e==null?void 0:e.export;return M(t)?t(n):Q(t)?n[t]:(t!==void 0&&T("Conversion «export» property must be a string or function. String means key of saved data object to export. Function should export processed string to export."),"")}function Ro(n,e,t){const o=e==null?void 0:e.import;return M(o)?o(n,t):Q(o)?{[o]:n}:(o!==void 0&&T("Conversion «import» property must be a string or function. String means key of tool data to import. Function accepts a imported string and return composed tool data."),{})}var _=(n=>(n.Default="default",n.Separator="separator",n.Html="html",n))(_||{}),te=(n=>(n.APPEND_CALLBACK="appendCallback",n.RENDERED="rendered",n.MOVED="moved",n.UPDATED="updated",n.REMOVED="removed",n.ON_PASTE="onPaste",n))(te||{});class R extends we{constructor({id:e=ti(),data:t,tool:o,readOnly:i,tunesData:s},r){super(),this.cachedInputs=[],this.toolRenderedElement=null,this.tunesInstances=new Map,this.defaultTunesInstances=new Map,this.unavailableTunesData={},this.inputIndex=0,this.editorEventBus=null,this.handleFocus=()=>{this.dropInputsCache(),this.updateCurrentInput()},this.didMutated=(a=void 0)=>{const l=a===void 0,c=a instanceof InputEvent;!l&&!c&&this.detectToolRootChange(a);let u;l||c?u=!0:u=!(a.length>0&&a.every(p=>{const{addedNodes:g,removedNodes:f,target:v}=p;return[...Array.from(g),...Array.from(f),v].some(S=>(d.isElement(S)||(S=S.parentElement),S&&S.closest('[data-mutation-free="true"]')!==null))})),u&&(this.dropInputsCache(),this.updateCurrentInput(),this.toggleInputsEmptyMark(),this.call("updated"),this.emit("didMutated",this))},this.name=o.name,this.id=e,this.settings=o.settings,this.config=o.settings.config||{},this.editorEventBus=r||null,this.blockAPI=new ee(this),this.tool=o,this.toolInstance=o.create(t,this.blockAPI,i),this.tunes=o.tunes,this.composeTunes(s),this.holder=this.compose(),window.requestIdleCallback(()=>{this.watchBlockMutations(),this.addInputEvents(),this.toggleInputsEmptyMark()})}static get CSS(){return{wrapper:"ce-block",wrapperStretched:"ce-block--stretched",content:"ce-block__content",selected:"ce-block--selected",dropTarget:"ce-block--drop-target"}}get inputs(){if(this.cachedInputs.length!==0)return this.cachedInputs;const e=d.findAllInputs(this.holder);return this.inputIndex>e.length-1&&(this.inputIndex=e.length-1),this.cachedInputs=e,e}get currentInput(){return this.inputs[this.inputIndex]}set currentInput(e){const t=this.inputs.findIndex(o=>o===e||o.contains(e));t!==-1&&(this.inputIndex=t)}get firstInput(){return this.inputs[0]}get lastInput(){const e=this.inputs;return e[e.length-1]}get nextInput(){return this.inputs[this.inputIndex+1]}get previousInput(){return this.inputs[this.inputIndex-1]}get data(){return this.save().then(e=>e&&!V(e.data)?e.data:{})}get sanitize(){return this.tool.sanitizeConfig}get mergeable(){return M(this.toolInstance.merge)}get focusable(){return this.inputs.length!==0}get isEmpty(){const e=d.isEmpty(this.pluginsContent,"/"),t=!this.hasMedia;return e&&t}get hasMedia(){const e=["img","iframe","video","audio","source","input","textarea","twitterwidget"];return!!this.holder.querySelector(e.join(","))}set selected(e){var i,s;this.holder.classList.toggle(R.CSS.selected,e);const t=e===!0&&b.isRangeInsideContainer(this.holder),o=e===!1&&b.isFakeCursorInsideContainer(this.holder);(t||o)&&((i=this.editorEventBus)==null||i.emit(Mo,{state:e}),t?b.addFakeCursor():b.removeFakeCursor(this.holder),(s=this.editorEventBus)==null||s.emit(Ao,{state:e}))}get selected(){return this.holder.classList.contains(R.CSS.selected)}set stretched(e){this.holder.classList.toggle(R.CSS.wrapperStretched,e)}get stretched(){return this.holder.classList.contains(R.CSS.wrapperStretched)}set dropTarget(e){this.holder.classList.toggle(R.CSS.dropTarget,e)}get pluginsContent(){return this.toolRenderedElement}call(e,t){if(M(this.toolInstance[e])){e==="appendCallback"&&T("`appendCallback` hook is deprecated and will be removed in the next major release. Use `rendered` hook instead","warn");try{this.toolInstance[e].call(this.toolInstance,t)}catch(o){T(`Error during '${e}' call: ${o.message}`,"error")}}}async mergeWith(e){await this.toolInstance.merge(e)}async save(){const e=await this.toolInstance.save(this.pluginsContent),t=this.unavailableTunesData;[...this.tunesInstances.entries(),...this.defaultTunesInstances.entries()].forEach(([s,r])=>{if(M(r.save))try{t[s]=r.save()}catch(a){T(`Tune ${r.constructor.name} save method throws an Error %o`,"warn",a)}});const o=window.performance.now();let i;return Promise.resolve(e).then(s=>(i=window.performance.now(),{id:this.id,tool:this.name,data:s,tunes:t,time:i-o})).catch(s=>{T(`Saving process for ${this.name} tool failed due to the ${s}`,"log","red")})}async validate(e){let t=!0;return this.toolInstance.validate instanceof Function&&(t=await this.toolInstance.validate(e)),t}getTunes(){const e=[],t=[],o=typeof this.toolInstance.renderSettings=="function"?this.toolInstance.renderSettings():[];return d.isElement(o)?e.push({type:_.Html,element:o}):Array.isArray(o)?e.push(...o):e.push(o),[...this.tunesInstances.values(),...this.defaultTunesInstances.values()].map(s=>s.render()).forEach(s=>{d.isElement(s)?t.push({type:_.Html,element:s}):Array.isArray(s)?t.push(...s):t.push(s)}),{toolTunes:e,commonTunes:t}}updateCurrentInput(){this.currentInput=d.isNativeInput(document.activeElement)||!b.anchorNode?document.activeElement:b.anchorNode}dispatchChange(){this.didMutated()}destroy(){this.unwatchBlockMutations(),this.removeInputEvents(),super.destroy(),M(this.toolInstance.destroy)&&this.toolInstance.destroy()}async getActiveToolboxEntry(){const e=this.tool.toolbox;if(e.length===1)return Promise.resolve(this.tool.toolbox[0]);const t=await this.data,o=e;return o==null?void 0:o.find(i=>Lo(i.data,t))}async exportDataAsString(){const e=await this.data;return li(e,this.tool.conversionConfig)}compose(){const e=d.make("div",R.CSS.wrapper),t=d.make("div",R.CSS.content),o=this.toolInstance.render();e.dataset.id=this.id,this.toolRenderedElement=o,t.appendChild(this.toolRenderedElement);let i=t;return[...this.tunesInstances.values(),...this.defaultTunesInstances.values()].forEach(s=>{if(M(s.wrap))try{i=s.wrap(i)}catch(r){T(`Tune ${s.constructor.name} wrap method throws an Error %o`,"warn",r)}}),e.appendChild(i),e}composeTunes(e){Array.from(this.tunes.values()).forEach(t=>{(t.isInternal?this.defaultTunesInstances:this.tunesInstances).set(t.name,t.create(e[t.name],this.blockAPI))}),Object.entries(e).forEach(([t,o])=>{this.tunesInstances.has(t)||(this.unavailableTunesData[t]=o)})}addInputEvents(){this.inputs.forEach(e=>{e.addEventListener("focus",this.handleFocus),d.isNativeInput(e)&&e.addEventListener("input",this.didMutated)})}removeInputEvents(){this.inputs.forEach(e=>{e.removeEventListener("focus",this.handleFocus),d.isNativeInput(e)&&e.removeEventListener("input",this.didMutated)})}watchBlockMutations(){var e;this.redactorDomChangedCallback=t=>{const{mutations:o}=t;o.some(s=>ai(s,this.toolRenderedElement))&&this.didMutated(o)},(e=this.editorEventBus)==null||e.on(at,this.redactorDomChangedCallback)}unwatchBlockMutations(){var e;(e=this.editorEventBus)==null||e.off(at,this.redactorDomChangedCallback)}detectToolRootChange(e){e.forEach(t=>{if(Array.from(t.removedNodes).includes(this.toolRenderedElement)){const i=t.addedNodes[t.addedNodes.length-1];this.toolRenderedElement=i}})}dropInputsCache(){this.cachedInputs=[]}toggleInputsEmptyMark(){this.inputs.forEach(To)}}class ci extends E{constructor(){super(...arguments),this.insert=(e=this.config.defaultBlock,t={},o={},i,s,r,a)=>{const l=this.Editor.BlockManager.insert({id:a,tool:e,data:t,index:i,needToFocus:s,replace:r});return new ee(l)},this.composeBlockData=async e=>{const t=this.Editor.Tools.blockTools.get(e);return new R({tool:t,api:this.Editor.API,readOnly:!0,data:{},tunesData:{}}).data},this.update=async(e,t,o)=>{const{BlockManager:i}=this.Editor,s=i.getBlockById(e);if(s===void 0)throw new Error(`Block with id "${e}" not found`);const r=await i.update(s,t,o);return new ee(r)},this.convert=async(e,t,o)=>{var h,p;const{BlockManager:i,Tools:s}=this.Editor,r=i.getBlockById(e);if(!r)throw new Error(`Block with id "${e}" not found`);const a=s.blockTools.get(r.name),l=s.blockTools.get(t);if(!l)throw new Error(`Block Tool with type "${t}" not found`);const c=((h=a==null?void 0:a.conversionConfig)==null?void 0:h.export)!==void 0,u=((p=l.conversionConfig)==null?void 0:p.import)!==void 0;if(c&&u){const g=await i.convert(r,t,o);return new ee(g)}else{const g=[c?!1:Le(r.name),u?!1:Le(t)].filter(Boolean).join(" and ");throw new Error(`Conversion from "${r.name}" to "${t}" is not possible. ${g} tool(s) should provide a "conversionConfig"`)}},this.insertMany=(e,t=this.Editor.BlockManager.blocks.length-1)=>{this.validateIndex(t);const o=e.map(({id:i,type:s,data:r})=>this.Editor.BlockManager.composeBlock({id:i,tool:s||this.config.defaultBlock,data:r}));return this.Editor.BlockManager.insertMany(o,t),o.map(i=>new ee(i))}}get methods(){return{clear:()=>this.clear(),render:e=>this.render(e),renderFromHTML:e=>this.renderFromHTML(e),delete:e=>this.delete(e),swap:(e,t)=>this.swap(e,t),move:(e,t)=>this.move(e,t),getBlockByIndex:e=>this.getBlockByIndex(e),getById:e=>this.getById(e),getCurrentBlockIndex:()=>this.getCurrentBlockIndex(),getBlockIndex:e=>this.getBlockIndex(e),getBlocksCount:()=>this.getBlocksCount(),getBlockByElement:e=>this.getBlockByElement(e),stretchBlock:(e,t=!0)=>this.stretchBlock(e,t),insertNewBlock:()=>this.insertNewBlock(),insert:this.insert,insertMany:this.insertMany,update:this.update,composeBlockData:this.composeBlockData,convert:this.convert}}getBlocksCount(){return this.Editor.BlockManager.blocks.length}getCurrentBlockIndex(){return this.Editor.BlockManager.currentBlockIndex}getBlockIndex(e){const t=this.Editor.BlockManager.getBlockById(e);if(!t){X("There is no block with id `"+e+"`","warn");return}return this.Editor.BlockManager.getBlockIndex(t)}getBlockByIndex(e){const t=this.Editor.BlockManager.getBlockByIndex(e);if(t===void 0){X("There is no block at index `"+e+"`","warn");return}return new ee(t)}getById(e){const t=this.Editor.BlockManager.getBlockById(e);return t===void 0?(X("There is no block with id `"+e+"`","warn"),null):new ee(t)}getBlockByElement(e){const t=this.Editor.BlockManager.getBlock(e);if(t===void 0){X("There is no block corresponding to element `"+e+"`","warn");return}return new ee(t)}swap(e,t){T("`blocks.swap()` method is deprecated and will be removed in the next major release. Use `block.move()` method instead","info"),this.Editor.BlockManager.swap(e,t)}move(e,t){this.Editor.BlockManager.move(e,t)}delete(e=this.Editor.BlockManager.currentBlockIndex){try{const t=this.Editor.BlockManager.getBlockByIndex(e);this.Editor.BlockManager.removeBlock(t)}catch(t){X(t,"warn");return}this.Editor.BlockManager.blocks.length===0&&this.Editor.BlockManager.insert(),this.Editor.BlockManager.currentBlock&&this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock,this.Editor.Caret.positions.END),this.Editor.Toolbar.close()}async clear(){await this.Editor.BlockManager.clear(!0),this.Editor.InlineToolbar.close()}async render(e){if(e===void 0||e.blocks===void 0)throw new Error("Incorrect data passed to the render() method");this.Editor.ModificationsObserver.disable(),await this.Editor.BlockManager.clear(),await this.Editor.Renderer.render(e.blocks),this.Editor.ModificationsObserver.enable()}renderFromHTML(e){return this.Editor.BlockManager.clear(),this.Editor.Paste.processText(e,!0)}stretchBlock(e,t=!0){st(!0,"blocks.stretchBlock()","BlockAPI");const o=this.Editor.BlockManager.getBlockByIndex(e);o&&(o.stretched=t)}insertNewBlock(){T("Method blocks.insertNewBlock() is deprecated and it will be removed in the next major release. Use blocks.insert() instead.","warn"),this.insert()}validateIndex(e){if(typeof e!="number")throw new Error("Index should be a number");if(e<0)throw new Error("Index should be greater than or equal to 0");if(e===null)throw new Error("Index should be greater than or equal to 0")}}function di(n,e){return typeof n=="number"?e.BlockManager.getBlockByIndex(n):typeof n=="string"?e.BlockManager.getBlockById(n):e.BlockManager.getBlockById(n.id)}class ui extends E{constructor(){super(...arguments),this.setToFirstBlock=(e=this.Editor.Caret.positions.DEFAULT,t=0)=>this.Editor.BlockManager.firstBlock?(this.Editor.Caret.setToBlock(this.Editor.BlockManager.firstBlock,e,t),!0):!1,this.setToLastBlock=(e=this.Editor.Caret.positions.DEFAULT,t=0)=>this.Editor.BlockManager.lastBlock?(this.Editor.Caret.setToBlock(this.Editor.BlockManager.lastBlock,e,t),!0):!1,this.setToPreviousBlock=(e=this.Editor.Caret.positions.DEFAULT,t=0)=>this.Editor.BlockManager.previousBlock?(this.Editor.Caret.setToBlock(this.Editor.BlockManager.previousBlock,e,t),!0):!1,this.setToNextBlock=(e=this.Editor.Caret.positions.DEFAULT,t=0)=>this.Editor.BlockManager.nextBlock?(this.Editor.Caret.setToBlock(this.Editor.BlockManager.nextBlock,e,t),!0):!1,this.setToBlock=(e,t=this.Editor.Caret.positions.DEFAULT,o=0)=>{const i=di(e,this.Editor);return i===void 0?!1:(this.Editor.Caret.setToBlock(i,t,o),!0)},this.focus=(e=!1)=>e?this.setToLastBlock(this.Editor.Caret.positions.END):this.setToFirstBlock(this.Editor.Caret.positions.START)}get methods(){return{setToFirstBlock:this.setToFirstBlock,setToLastBlock:this.setToLastBlock,setToPreviousBlock:this.setToPreviousBlock,setToNextBlock:this.setToNextBlock,setToBlock:this.setToBlock,focus:this.focus}}}class hi extends E{get methods(){return{emit:(e,t)=>this.emit(e,t),off:(e,t)=>this.off(e,t),on:(e,t)=>this.on(e,t)}}on(e,t){this.eventsDispatcher.on(e,t)}emit(e,t){this.eventsDispatcher.emit(e,t)}off(e,t){this.eventsDispatcher.off(e,t)}}class ct extends E{static getNamespace(e,t){return t?`blockTunes.${e}`:`tools.${e}`}get methods(){return{t:()=>{X("I18n.t() method can be accessed only from Tools","warn")}}}getMethodsForTool(e,t){return Object.assign(this.methods,{t:o=>H.t(ct.getNamespace(e,t),o)})}}class pi extends E{get methods(){return{blocks:this.Editor.BlocksAPI.methods,caret:this.Editor.CaretAPI.methods,tools:this.Editor.ToolsAPI.methods,events:this.Editor.EventsAPI.methods,listeners:this.Editor.ListenersAPI.methods,notifier:this.Editor.NotifierAPI.methods,sanitizer:this.Editor.SanitizerAPI.methods,saver:this.Editor.SaverAPI.methods,selection:this.Editor.SelectionAPI.methods,styles:this.Editor.StylesAPI.classes,toolbar:this.Editor.ToolbarAPI.methods,inlineToolbar:this.Editor.InlineToolbarAPI.methods,tooltip:this.Editor.TooltipAPI.methods,i18n:this.Editor.I18nAPI.methods,readOnly:this.Editor.ReadOnlyAPI.methods,ui:this.Editor.UiAPI.methods}}getMethodsForTool(e,t){return Object.assign(this.methods,{i18n:this.Editor.I18nAPI.getMethodsForTool(e,t)})}}class fi extends E{get methods(){return{close:()=>this.close(),open:()=>this.open()}}open(){this.Editor.InlineToolbar.tryToShow()}close(){this.Editor.InlineToolbar.close()}}class gi extends E{get methods(){return{on:(e,t,o,i)=>this.on(e,t,o,i),off:(e,t,o,i)=>this.off(e,t,o,i),offById:e=>this.offById(e)}}on(e,t,o,i){return this.listeners.on(e,t,o,i)}off(e,t,o,i){this.listeners.off(e,t,o,i)}offById(e){this.listeners.offById(e)}}var Do={exports:{}};(function(n,e){(function(t,o){n.exports=o()})(window,function(){return function(t){var o={};function i(s){if(o[s])return o[s].exports;var r=o[s]={i:s,l:!1,exports:{}};return t[s].call(r.exports,r,r.exports,i),r.l=!0,r.exports}return i.m=t,i.c=o,i.d=function(s,r,a){i.o(s,r)||Object.defineProperty(s,r,{enumerable:!0,get:a})},i.r=function(s){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(s,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(s,"__esModule",{value:!0})},i.t=function(s,r){if(1&r&&(s=i(s)),8&r||4&r&&typeof s=="object"&&s&&s.__esModule)return s;var a=Object.create(null);if(i.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:s}),2&r&&typeof s!="string")for(var l in s)i.d(a,l,(function(c){return s[c]}).bind(null,l));return a},i.n=function(s){var r=s&&s.__esModule?function(){return s.default}:function(){return s};return i.d(r,"a",r),r},i.o=function(s,r){return Object.prototype.hasOwnProperty.call(s,r)},i.p="/",i(i.s=0)}([function(t,o,i){i(1),t.exports=function(){var s=i(6),r="cdx-notify--bounce-in",a=null;return{show:function(l){if(l.message){(function(){if(a)return!0;a=s.getWrapper(),document.body.appendChild(a)})();var c=null,u=l.time||8e3;switch(l.type){case"confirm":c=s.confirm(l);break;case"prompt":c=s.prompt(l);break;default:c=s.alert(l),window.setTimeout(function(){c.remove()},u)}a.appendChild(c),c.classList.add(r)}}}}()},function(t,o,i){var s=i(2);typeof s=="string"&&(s=[[t.i,s,""]]);var r={hmr:!0,transform:void 0,insertInto:void 0};i(4)(s,r),s.locals&&(t.exports=s.locals)},function(t,o,i){(t.exports=i(3)(!1)).push([t.i,`.cdx-notify--error{background:#fffbfb!important}.cdx-notify--error::before{background:#fb5d5d!important}.cdx-notify__input{max-width:130px;padding:5px 10px;background:#f7f7f7;border:0;border-radius:3px;font-size:13px;color:#656b7c;outline:0}.cdx-notify__input:-ms-input-placeholder{color:#656b7c}.cdx-notify__input::placeholder{color:#656b7c}.cdx-notify__input:focus:-ms-input-placeholder{color:rgba(101,107,124,.3)}.cdx-notify__input:focus::placeholder{color:rgba(101,107,124,.3)}.cdx-notify__button{border:none;border-radius:3px;font-size:13px;padding:5px 10px;cursor:pointer}.cdx-notify__button:last-child{margin-left:10px}.cdx-notify__button--cancel{background:#f2f5f7;box-shadow:0 2px 1px 0 rgba(16,19,29,0);color:#656b7c}.cdx-notify__button--cancel:hover{background:#eee}.cdx-notify__button--confirm{background:#34c992;box-shadow:0 1px 1px 0 rgba(18,49,35,.05);color:#fff}.cdx-notify__button--confirm:hover{background:#33b082}.cdx-notify__btns-wrapper{display:-ms-flexbox;display:flex;-ms-flex-flow:row nowrap;flex-flow:row nowrap;margin-top:5px}.cdx-notify__cross{position:absolute;top:5px;right:5px;width:10px;height:10px;padding:5px;opacity:.54;cursor:pointer}.cdx-notify__cross::after,.cdx-notify__cross::before{content:'';position:absolute;left:9px;top:5px;height:12px;width:2px;background:#575d67}.cdx-notify__cross::before{transform:rotate(-45deg)}.cdx-notify__cross::after{transform:rotate(45deg)}.cdx-notify__cross:hover{opacity:1}.cdx-notifies{position:fixed;z-index:2;bottom:20px;left:20px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",sans-serif}.cdx-notify{position:relative;width:220px;margin-top:15px;padding:13px 16px;background:#fff;box-shadow:0 11px 17px 0 rgba(23,32,61,.13);border-radius:5px;font-size:14px;line-height:1.4em;word-wrap:break-word}.cdx-notify::before{content:'';position:absolute;display:block;top:0;left:0;width:3px;height:calc(100% - 6px);margin:3px;border-radius:5px;background:0 0}@keyframes bounceIn{0%{opacity:0;transform:scale(.3)}50%{opacity:1;transform:scale(1.05)}70%{transform:scale(.9)}100%{transform:scale(1)}}.cdx-notify--bounce-in{animation-name:bounceIn;animation-duration:.6s;animation-iteration-count:1}.cdx-notify--success{background:#fafffe!important}.cdx-notify--success::before{background:#41ffb1!important}`,""])},function(t,o){t.exports=function(i){var s=[];return s.toString=function(){return this.map(function(r){var a=function(l,c){var u=l[1]||"",h=l[3];if(!h)return u;if(c&&typeof btoa=="function"){var p=(f=h,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(f))))+" */"),g=h.sources.map(function(v){return"/*# sourceURL="+h.sourceRoot+v+" */"});return[u].concat(g).concat([p]).join(` +`)}var f;return[u].join(` +`)}(r,i);return r[2]?"@media "+r[2]+"{"+a+"}":a}).join("")},s.i=function(r,a){typeof r=="string"&&(r=[[null,r,""]]);for(var l={},c=0;c=0&&p.splice(m,1)}function A(k){var m=document.createElement("style");return k.attrs.type===void 0&&(k.attrs.type="text/css"),G(m,k.attrs),O(k,m),m}function G(k,m){Object.keys(m).forEach(function(w){k.setAttribute(w,m[w])})}function j(k,m){var w,x,I,C;if(m.transform&&k.css){if(!(C=m.transform(k.css)))return function(){};k.css=C}if(m.singleton){var D=h++;w=u||(u=A(m)),x=he.bind(null,w,D,!1),I=he.bind(null,w,D,!0)}else k.sourceMap&&typeof URL=="function"&&typeof URL.createObjectURL=="function"&&typeof URL.revokeObjectURL=="function"&&typeof Blob=="function"&&typeof btoa=="function"?(w=function(B){var K=document.createElement("link");return B.attrs.type===void 0&&(B.attrs.type="text/css"),B.attrs.rel="stylesheet",G(K,B.attrs),O(B,K),K}(m),x=(function(B,K,Oe){var pe=Oe.css,vo=Oe.sourceMap,Ca=K.convertToAbsoluteUrls===void 0&&vo;(K.convertToAbsoluteUrls||Ca)&&(pe=g(pe)),vo&&(pe+=` +/*# sourceMappingURL=data:application/json;base64,`+btoa(unescape(encodeURIComponent(JSON.stringify(vo))))+" */");var Ta=new Blob([pe],{type:"text/css"}),$n=B.href;B.href=URL.createObjectURL(Ta),$n&&URL.revokeObjectURL($n)}).bind(null,w,m),I=function(){S(w),w.href&&URL.revokeObjectURL(w.href)}):(w=A(m),x=(function(B,K){var Oe=K.css,pe=K.media;if(pe&&B.setAttribute("media",pe),B.styleSheet)B.styleSheet.cssText=Oe;else{for(;B.firstChild;)B.removeChild(B.firstChild);B.appendChild(document.createTextNode(Oe))}}).bind(null,w),I=function(){S(w)});return x(k),function(B){if(B){if(B.css===k.css&&B.media===k.media&&B.sourceMap===k.sourceMap)return;x(k=B)}else I()}}t.exports=function(k,m){if(typeof DEBUG<"u"&&DEBUG&&typeof document!="object")throw new Error("The style-loader cannot be used in a non-browser environment");(m=m||{}).attrs=typeof m.attrs=="object"?m.attrs:{},m.singleton||typeof m.singleton=="boolean"||(m.singleton=l()),m.insertInto||(m.insertInto="head"),m.insertAt||(m.insertAt="bottom");var w=v(k,m);return f(w,m),function(x){for(var I=[],C=0;Cthis.show(e)}}show(e){return this.notifier.show(e)}}class yi extends E{get methods(){const e=()=>this.isEnabled;return{toggle:t=>this.toggle(t),get isEnabled(){return e()}}}toggle(e){return this.Editor.ReadOnly.toggle(e)}get isEnabled(){return this.Editor.ReadOnly.isEnabled}}var Fo={exports:{}};(function(n,e){(function(t,o){n.exports=o()})(J,function(){function t(h){var p=h.tags,g=Object.keys(p),f=g.map(function(v){return typeof p[v]}).every(function(v){return v==="object"||v==="boolean"||v==="function"});if(!f)throw new Error("The configuration was invalid");this.config=h}var o=["P","LI","TD","TH","DIV","H1","H2","H3","H4","H5","H6","PRE"];function i(h){return o.indexOf(h.nodeName)!==-1}var s=["A","B","STRONG","I","EM","SUB","SUP","U","STRIKE"];function r(h){return s.indexOf(h.nodeName)!==-1}t.prototype.clean=function(h){const p=document.implementation.createHTMLDocument(),g=p.createElement("div");return g.innerHTML=h,this._sanitize(p,g),g.innerHTML},t.prototype._sanitize=function(h,p){var g=a(h,p),f=g.firstChild();if(f)do{if(f.nodeType===Node.TEXT_NODE)if(f.data.trim()===""&&(f.previousElementSibling&&i(f.previousElementSibling)||f.nextElementSibling&&i(f.nextElementSibling))){p.removeChild(f),this._sanitize(h,p);break}else continue;if(f.nodeType===Node.COMMENT_NODE){p.removeChild(f),this._sanitize(h,p);break}var v=r(f),O;v&&(O=Array.prototype.some.call(f.childNodes,i));var S=!!p.parentNode,A=i(p)&&i(f)&&S,G=f.nodeName.toLowerCase(),j=l(this.config,G,f),U=v&&O;if(U||c(f,j)||!this.config.keepNestedBlockElements&&A){if(!(f.nodeName==="SCRIPT"||f.nodeName==="STYLE"))for(;f.childNodes.length>0;)p.insertBefore(f.childNodes[0],f);p.removeChild(f),this._sanitize(h,p);break}for(var oe=0;oe"u"?!0:typeof p=="boolean"?!p:!1}function u(h,p,g){var f=h.name.toLowerCase();return p===!0?!1:typeof p[f]=="function"?!p[f](h.value,g):typeof p[f]>"u"||p[f]===!1?!0:typeof p[f]=="string"?p[f]!==h.value:!1}return t})})(Fo);var wi=Fo.exports;const Ei=ne(wi);function dt(n,e){return n.map(t=>{const o=M(e)?e(t.tool):e;return V(o)||(t.data=ut(t.data,o)),t})}function q(n,e={}){const t={tags:e};return new Ei(t).clean(n)}function ut(n,e){return Array.isArray(n)?xi(n,e):N(n)?Bi(n,e):Q(n)?Ci(n,e):n}function xi(n,e){return n.map(t=>ut(t,e))}function Bi(n,e){const t={};for(const o in n){if(!Object.prototype.hasOwnProperty.call(n,o))continue;const i=n[o],s=Ti(e[o])?e[o]:e;t[o]=ut(i,s)}return t}function Ci(n,e){return N(e)?q(n,e):e===!1?q(n,{}):n}function Ti(n){return N(n)||qn(n)||M(n)}class Si extends E{get methods(){return{clean:(e,t)=>this.clean(e,t)}}clean(e,t){return q(e,t)}}class Ii extends E{get methods(){return{save:()=>this.save()}}save(){const e="Editor's content can not be saved in read-only mode";return this.Editor.ReadOnly.isEnabled?(X(e,"warn"),Promise.reject(new Error(e))):this.Editor.Saver.save()}}class Oi extends E{constructor(){super(...arguments),this.selectionUtils=new b}get methods(){return{findParentTag:(e,t)=>this.findParentTag(e,t),expandToTag:e=>this.expandToTag(e),save:()=>this.selectionUtils.save(),restore:()=>this.selectionUtils.restore(),setFakeBackground:()=>this.selectionUtils.setFakeBackground(),removeFakeBackground:()=>this.selectionUtils.removeFakeBackground()}}findParentTag(e,t){return this.selectionUtils.findParentTag(e,t)}expandToTag(e){this.selectionUtils.expandToTag(e)}}class _i extends E{get methods(){return{getBlockTools:()=>Array.from(this.Editor.Tools.blockTools.values())}}}class Mi extends E{get classes(){return{block:"cdx-block",inlineToolButton:"ce-inline-tool",inlineToolButtonActive:"ce-inline-tool--active",input:"cdx-input",loader:"cdx-loader",button:"cdx-button",settingsButton:"cdx-settings-button",settingsButtonActive:"cdx-settings-button--active"}}}class Ai extends E{get methods(){return{close:()=>this.close(),open:()=>this.open(),toggleBlockSettings:e=>this.toggleBlockSettings(e),toggleToolbox:e=>this.toggleToolbox(e)}}open(){this.Editor.Toolbar.moveAndOpen()}close(){this.Editor.Toolbar.close()}toggleBlockSettings(e){if(this.Editor.BlockManager.currentBlockIndex===-1){X("Could't toggle the Toolbar because there is no block selected ","warn");return}e??!this.Editor.BlockSettings.opened?(this.Editor.Toolbar.moveAndOpen(),this.Editor.BlockSettings.open()):this.Editor.BlockSettings.close()}toggleToolbox(e){if(this.Editor.BlockManager.currentBlockIndex===-1){X("Could't toggle the Toolbox because there is no block selected ","warn");return}e??!this.Editor.Toolbar.toolbox.opened?(this.Editor.Toolbar.moveAndOpen(),this.Editor.Toolbar.toolbox.open()):this.Editor.Toolbar.toolbox.close()}}var jo={exports:{}};/*! + * CodeX.Tooltips + * + * @version 1.0.5 + * + * @licence MIT + * @author CodeX + * + * + */(function(n,e){(function(t,o){n.exports=o()})(window,function(){return function(t){var o={};function i(s){if(o[s])return o[s].exports;var r=o[s]={i:s,l:!1,exports:{}};return t[s].call(r.exports,r,r.exports,i),r.l=!0,r.exports}return i.m=t,i.c=o,i.d=function(s,r,a){i.o(s,r)||Object.defineProperty(s,r,{enumerable:!0,get:a})},i.r=function(s){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(s,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(s,"__esModule",{value:!0})},i.t=function(s,r){if(1&r&&(s=i(s)),8&r||4&r&&typeof s=="object"&&s&&s.__esModule)return s;var a=Object.create(null);if(i.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:s}),2&r&&typeof s!="string")for(var l in s)i.d(a,l,(function(c){return s[c]}).bind(null,l));return a},i.n=function(s){var r=s&&s.__esModule?function(){return s.default}:function(){return s};return i.d(r,"a",r),r},i.o=function(s,r){return Object.prototype.hasOwnProperty.call(s,r)},i.p="",i(i.s=0)}([function(t,o,i){t.exports=i(1)},function(t,o,i){i.r(o),i.d(o,"default",function(){return s});class s{constructor(){this.nodes={wrapper:null,content:null},this.showed=!1,this.offsetTop=10,this.offsetLeft=10,this.offsetRight=10,this.hidingDelay=0,this.handleWindowScroll=()=>{this.showed&&this.hide(!0)},this.loadStyles(),this.prepare(),window.addEventListener("scroll",this.handleWindowScroll,{passive:!0})}get CSS(){return{tooltip:"ct",tooltipContent:"ct__content",tooltipShown:"ct--shown",placement:{left:"ct--left",bottom:"ct--bottom",right:"ct--right",top:"ct--top"}}}show(a,l,c){this.nodes.wrapper||this.prepare(),this.hidingTimeout&&clearTimeout(this.hidingTimeout);const u=Object.assign({placement:"bottom",marginTop:0,marginLeft:0,marginRight:0,marginBottom:0,delay:70,hidingDelay:0},c);if(u.hidingDelay&&(this.hidingDelay=u.hidingDelay),this.nodes.content.innerHTML="",typeof l=="string")this.nodes.content.appendChild(document.createTextNode(l));else{if(!(l instanceof Node))throw Error("[CodeX Tooltip] Wrong type of «content» passed. It should be an instance of Node or String. But "+typeof l+" given.");this.nodes.content.appendChild(l)}switch(this.nodes.wrapper.classList.remove(...Object.values(this.CSS.placement)),u.placement){case"top":this.placeTop(a,u);break;case"left":this.placeLeft(a,u);break;case"right":this.placeRight(a,u);break;case"bottom":default:this.placeBottom(a,u)}u&&u.delay?this.showingTimeout=setTimeout(()=>{this.nodes.wrapper.classList.add(this.CSS.tooltipShown),this.showed=!0},u.delay):(this.nodes.wrapper.classList.add(this.CSS.tooltipShown),this.showed=!0)}hide(a=!1){if(this.hidingDelay&&!a)return this.hidingTimeout&&clearTimeout(this.hidingTimeout),void(this.hidingTimeout=setTimeout(()=>{this.hide(!0)},this.hidingDelay));this.nodes.wrapper.classList.remove(this.CSS.tooltipShown),this.showed=!1,this.showingTimeout&&clearTimeout(this.showingTimeout)}onHover(a,l,c){a.addEventListener("mouseenter",()=>{this.show(a,l,c)}),a.addEventListener("mouseleave",()=>{this.hide()})}destroy(){this.nodes.wrapper.remove(),window.removeEventListener("scroll",this.handleWindowScroll)}prepare(){this.nodes.wrapper=this.make("div",this.CSS.tooltip),this.nodes.content=this.make("div",this.CSS.tooltipContent),this.append(this.nodes.wrapper,this.nodes.content),this.append(document.body,this.nodes.wrapper)}loadStyles(){const a="codex-tooltips-style";if(document.getElementById(a))return;const l=i(2),c=this.make("style",null,{textContent:l.toString(),id:a});this.prepend(document.head,c)}placeBottom(a,l){const c=a.getBoundingClientRect(),u=c.left+a.clientWidth/2-this.nodes.wrapper.offsetWidth/2,h=c.bottom+window.pageYOffset+this.offsetTop+l.marginTop;this.applyPlacement("bottom",u,h)}placeTop(a,l){const c=a.getBoundingClientRect(),u=c.left+a.clientWidth/2-this.nodes.wrapper.offsetWidth/2,h=c.top+window.pageYOffset-this.nodes.wrapper.clientHeight-this.offsetTop;this.applyPlacement("top",u,h)}placeLeft(a,l){const c=a.getBoundingClientRect(),u=c.left-this.nodes.wrapper.offsetWidth-this.offsetLeft-l.marginLeft,h=c.top+window.pageYOffset+a.clientHeight/2-this.nodes.wrapper.offsetHeight/2;this.applyPlacement("left",u,h)}placeRight(a,l){const c=a.getBoundingClientRect(),u=c.right+this.offsetRight+l.marginRight,h=c.top+window.pageYOffset+a.clientHeight/2-this.nodes.wrapper.offsetHeight/2;this.applyPlacement("right",u,h)}applyPlacement(a,l,c){this.nodes.wrapper.classList.add(this.CSS.placement[a]),this.nodes.wrapper.style.left=l+"px",this.nodes.wrapper.style.top=c+"px"}make(a,l=null,c={}){const u=document.createElement(a);Array.isArray(l)?u.classList.add(...l):l&&u.classList.add(l);for(const h in c)c.hasOwnProperty(h)&&(u[h]=c[h]);return u}append(a,l){Array.isArray(l)?l.forEach(c=>a.appendChild(c)):a.appendChild(l)}prepend(a,l){Array.isArray(l)?(l=l.reverse()).forEach(c=>a.prepend(c)):a.prepend(l)}}},function(t,o){t.exports=`.ct{z-index:999;opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none;-webkit-transition:opacity 50ms ease-in,-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,transform 70ms cubic-bezier(.215,.61,.355,1),-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);will-change:opacity,top,left;-webkit-box-shadow:0 8px 12px 0 rgba(29,32,43,.17),0 4px 5px -3px rgba(5,6,12,.49);box-shadow:0 8px 12px 0 rgba(29,32,43,.17),0 4px 5px -3px rgba(5,6,12,.49);border-radius:9px}.ct,.ct:before{position:absolute;top:0;left:0}.ct:before{content:"";bottom:0;right:0;background-color:#1d202b;z-index:-1;border-radius:4px}@supports(-webkit-mask-box-image:url("")){.ct:before{border-radius:0;-webkit-mask-box-image:url('data:image/svg+xml;charset=utf-8,') 48% 41% 37.9% 53.3%}}@media (--mobile){.ct{display:none}}.ct__content{padding:6px 10px;color:#cdd1e0;font-size:12px;text-align:center;letter-spacing:.02em;line-height:1em}.ct:after{content:"";width:8px;height:8px;position:absolute;background-color:#1d202b;z-index:-1}.ct--bottom{-webkit-transform:translateY(5px);transform:translateY(5px)}.ct--bottom:after{top:-3px;left:50%;-webkit-transform:translateX(-50%) rotate(-45deg);transform:translateX(-50%) rotate(-45deg)}.ct--top{-webkit-transform:translateY(-5px);transform:translateY(-5px)}.ct--top:after{top:auto;bottom:-3px;left:50%;-webkit-transform:translateX(-50%) rotate(-45deg);transform:translateX(-50%) rotate(-45deg)}.ct--left{-webkit-transform:translateX(-5px);transform:translateX(-5px)}.ct--left:after{top:50%;left:auto;right:0;-webkit-transform:translate(41.6%,-50%) rotate(-45deg);transform:translate(41.6%,-50%) rotate(-45deg)}.ct--right{-webkit-transform:translateX(5px);transform:translateX(5px)}.ct--right:after{top:50%;left:0;-webkit-transform:translate(-41.6%,-50%) rotate(-45deg);transform:translate(-41.6%,-50%) rotate(-45deg)}.ct--shown{opacity:1;-webkit-transform:none;transform:none}`}]).default})})(jo);var Li=jo.exports;const Pi=ne(Li);let $=null;function ht(){$||($=new Pi)}function Ni(n,e,t){ht(),$==null||$.show(n,e,t)}function Ne(n=!1){ht(),$==null||$.hide(n)}function Re(n,e,t){ht(),$==null||$.onHover(n,e,t)}function Ri(){$==null||$.destroy(),$=null}class Di extends E{constructor({config:e,eventsDispatcher:t}){super({config:e,eventsDispatcher:t})}get methods(){return{show:(e,t,o)=>this.show(e,t,o),hide:()=>this.hide(),onHover:(e,t,o)=>this.onHover(e,t,o)}}show(e,t,o){Ni(e,t,o)}hide(){Ne()}onHover(e,t,o){Re(e,t,o)}}class Fi extends E{get methods(){return{nodes:this.editorNodes}}get editorNodes(){return{wrapper:this.Editor.UI.nodes.wrapper,redactor:this.Editor.UI.nodes.redactor}}}function Ho(n,e){const t={};return Object.entries(n).forEach(([o,i])=>{if(N(i)){const s=e?`${e}.${o}`:o;Object.values(i).every(a=>Q(a))?t[o]=s:t[o]=Ho(i,s);return}t[o]=i}),t}const W=Ho(So);function ji(n,e){const t={};return Object.keys(n).forEach(o=>{const i=e[o];i!==void 0?t[i]=n[o]:t[o]=n[o]}),t}const $o=class _e{constructor(e,t){this.cursor=-1,this.items=[],this.items=e||[],this.focusedCssClass=t}get currentItem(){return this.cursor===-1?null:this.items[this.cursor]}setCursor(e){e=-1&&(this.dropCursor(),this.cursor=e,this.items[this.cursor].classList.add(this.focusedCssClass))}setItems(e){this.items=e}next(){this.cursor=this.leafNodesAndReturnIndex(_e.directions.RIGHT)}previous(){this.cursor=this.leafNodesAndReturnIndex(_e.directions.LEFT)}dropCursor(){this.cursor!==-1&&(this.items[this.cursor].classList.remove(this.focusedCssClass),this.cursor=-1)}leafNodesAndReturnIndex(e){if(this.items.length===0)return this.cursor;let t=this.cursor;return t===-1?t=e===_e.directions.RIGHT?-1:0:this.items[t].classList.remove(this.focusedCssClass),e===_e.directions.RIGHT?t=(t+1)%this.items.length:t=(this.items.length+t-1)%this.items.length,d.canSetCaret(this.items[t])&&Ae(()=>b.setCursor(this.items[t]),50)(),this.items[t].classList.add(this.focusedCssClass),t}};$o.directions={RIGHT:"right",LEFT:"left"};let Be=$o;class ae{constructor(e){this.iterator=null,this.activated=!1,this.flipCallbacks=[],this.onKeyDown=t=>{if(!(!this.isEventReadyForHandling(t)||t.shiftKey===!0))switch(ae.usedKeys.includes(t.keyCode)&&t.preventDefault(),t.keyCode){case y.TAB:this.handleTabPress(t);break;case y.LEFT:case y.UP:this.flipLeft();break;case y.RIGHT:case y.DOWN:this.flipRight();break;case y.ENTER:this.handleEnterPress(t);break}},this.iterator=new Be(e.items,e.focusedItemClass),this.activateCallback=e.activateCallback,this.allowedKeys=e.allowedKeys||ae.usedKeys}get isActivated(){return this.activated}static get usedKeys(){return[y.TAB,y.LEFT,y.RIGHT,y.ENTER,y.UP,y.DOWN]}activate(e,t){this.activated=!0,e&&this.iterator.setItems(e),t!==void 0&&this.iterator.setCursor(t),document.addEventListener("keydown",this.onKeyDown,!0)}deactivate(){this.activated=!1,this.dropCursor(),document.removeEventListener("keydown",this.onKeyDown)}focusFirst(){this.dropCursor(),this.flipRight()}flipLeft(){this.iterator.previous(),this.flipCallback()}flipRight(){this.iterator.next(),this.flipCallback()}hasFocus(){return!!this.iterator.currentItem}onFlip(e){this.flipCallbacks.push(e)}removeOnFlip(e){this.flipCallbacks=this.flipCallbacks.filter(t=>t!==e)}dropCursor(){this.iterator.dropCursor()}isEventReadyForHandling(e){return this.activated&&this.allowedKeys.includes(e.keyCode)}handleTabPress(e){switch(e.shiftKey?Be.directions.LEFT:Be.directions.RIGHT){case Be.directions.RIGHT:this.flipRight();break;case Be.directions.LEFT:this.flipLeft();break}}handleEnterPress(e){this.activated&&(this.iterator.currentItem&&(e.stopPropagation(),e.preventDefault(),this.iterator.currentItem.click()),M(this.activateCallback)&&this.activateCallback(this.iterator.currentItem))}flipCallback(){this.iterator.currentItem&&this.iterator.currentItem.scrollIntoViewIfNeeded(),this.flipCallbacks.forEach(e=>e())}}const Hi='',$i='',zi='',Ui='',Wi='',Yi='',Ki='',Xi='',zo='',Vi='',qi='',Uo='',Zi='',Gi='',Ji='',Qi="__",es="--";function ie(n){return(e,t)=>[[n,e].filter(i=>!!i).join(Qi),t].filter(i=>!!i).join(es)}const Ce=ie("ce-hint"),Te={root:Ce(),alignedStart:Ce(null,"align-left"),alignedCenter:Ce(null,"align-center"),title:Ce("title"),description:Ce("description")},Ma="";class ts{constructor(e){this.nodes={root:d.make("div",[Te.root,e.alignment==="center"?Te.alignedCenter:Te.alignedStart]),title:d.make("div",Te.title,{textContent:e.title})},this.nodes.root.appendChild(this.nodes.title),e.description!==void 0&&(this.nodes.description=d.make("div",Te.description,{textContent:e.description}),this.nodes.root.appendChild(this.nodes.description))}getElement(){return this.nodes.root}}class pt{constructor(e){this.params=e}get name(){if(this.params!==void 0&&"name"in this.params)return this.params.name}destroy(){Ne()}onChildrenOpen(){var e;this.params!==void 0&&"children"in this.params&&typeof((e=this.params.children)==null?void 0:e.onOpen)=="function"&&this.params.children.onOpen()}onChildrenClose(){var e;this.params!==void 0&&"children"in this.params&&typeof((e=this.params.children)==null?void 0:e.onClose)=="function"&&this.params.children.onClose()}handleClick(){var e,t;this.params!==void 0&&"onActivate"in this.params&&((t=(e=this.params).onActivate)==null||t.call(e,this.params))}addHint(e,t){const o=new ts(t);Re(e,o.getElement(),{placement:t.position,hidingDelay:100})}get children(){var e;return this.params!==void 0&&"children"in this.params&&((e=this.params.children)==null?void 0:e.items)!==void 0?this.params.children.items:[]}get hasChildren(){return this.children.length>0}get isChildrenOpen(){var e;return this.params!==void 0&&"children"in this.params&&((e=this.params.children)==null?void 0:e.isOpen)===!0}get isChildrenFlippable(){var e;return!(this.params===void 0||!("children"in this.params)||((e=this.params.children)==null?void 0:e.isFlippable)===!1)}get isChildrenSearchable(){var e;return this.params!==void 0&&"children"in this.params&&((e=this.params.children)==null?void 0:e.searchable)===!0}get closeOnActivate(){return this.params!==void 0&&"closeOnActivate"in this.params&&this.params.closeOnActivate}get isActive(){return this.params===void 0||!("isActive"in this.params)?!1:typeof this.params.isActive=="function"?this.params.isActive():this.params.isActive===!0}}const Y=ie("ce-popover-item"),L={container:Y(),active:Y(null,"active"),disabled:Y(null,"disabled"),focused:Y(null,"focused"),hidden:Y(null,"hidden"),confirmationState:Y(null,"confirmation"),noHover:Y(null,"no-hover"),noFocus:Y(null,"no-focus"),title:Y("title"),secondaryTitle:Y("secondary-title"),icon:Y("icon"),iconTool:Y("icon","tool"),iconChevronRight:Y("icon","chevron-right"),wobbleAnimation:ie("wobble")()};class le extends pt{constructor(e,t){super(e),this.params=e,this.nodes={root:null,icon:null},this.confirmationState=null,this.removeSpecialFocusBehavior=()=>{var o;(o=this.nodes.root)==null||o.classList.remove(L.noFocus)},this.removeSpecialHoverBehavior=()=>{var o;(o=this.nodes.root)==null||o.classList.remove(L.noHover)},this.onErrorAnimationEnd=()=>{var o,i;(o=this.nodes.icon)==null||o.classList.remove(L.wobbleAnimation),(i=this.nodes.icon)==null||i.removeEventListener("animationend",this.onErrorAnimationEnd)},this.nodes.root=this.make(e,t)}get isDisabled(){return this.params.isDisabled===!0}get toggle(){return this.params.toggle}get title(){return this.params.title}get isConfirmationStateEnabled(){return this.confirmationState!==null}get isFocused(){return this.nodes.root===null?!1:this.nodes.root.classList.contains(L.focused)}getElement(){return this.nodes.root}handleClick(){if(this.isConfirmationStateEnabled&&this.confirmationState!==null){this.activateOrEnableConfirmationMode(this.confirmationState);return}this.activateOrEnableConfirmationMode(this.params)}toggleActive(e){var t;(t=this.nodes.root)==null||t.classList.toggle(L.active,e)}toggleHidden(e){var t;(t=this.nodes.root)==null||t.classList.toggle(L.hidden,e)}reset(){this.isConfirmationStateEnabled&&this.disableConfirmationMode()}onFocus(){this.disableSpecialHoverAndFocusBehavior()}make(e,t){var s,r;const o=(t==null?void 0:t.wrapperTag)||"div",i=d.make(o,L.container,{type:o==="button"?"button":void 0});return e.name&&(i.dataset.itemName=e.name),this.nodes.icon=d.make("div",[L.icon,L.iconTool],{innerHTML:e.icon||Ki}),i.appendChild(this.nodes.icon),e.title!==void 0&&i.appendChild(d.make("div",L.title,{innerHTML:e.title||""})),e.secondaryLabel&&i.appendChild(d.make("div",L.secondaryTitle,{textContent:e.secondaryLabel})),this.hasChildren&&i.appendChild(d.make("div",[L.icon,L.iconChevronRight],{innerHTML:Ui})),this.isActive&&i.classList.add(L.active),e.isDisabled&&i.classList.add(L.disabled),e.hint!==void 0&&((s=t==null?void 0:t.hint)==null?void 0:s.enabled)!==!1&&this.addHint(i,{...e.hint,position:((r=t==null?void 0:t.hint)==null?void 0:r.position)||"right"}),i}enableConfirmationMode(e){if(this.nodes.root===null)return;const t={...this.params,...e,confirmation:"confirmation"in e?e.confirmation:void 0},o=this.make(t);this.nodes.root.innerHTML=o.innerHTML,this.nodes.root.classList.add(L.confirmationState),this.confirmationState=e,this.enableSpecialHoverAndFocusBehavior()}disableConfirmationMode(){if(this.nodes.root===null)return;const e=this.make(this.params);this.nodes.root.innerHTML=e.innerHTML,this.nodes.root.classList.remove(L.confirmationState),this.confirmationState=null,this.disableSpecialHoverAndFocusBehavior()}enableSpecialHoverAndFocusBehavior(){var e,t,o;(e=this.nodes.root)==null||e.classList.add(L.noHover),(t=this.nodes.root)==null||t.classList.add(L.noFocus),(o=this.nodes.root)==null||o.addEventListener("mouseleave",this.removeSpecialHoverBehavior,{once:!0})}disableSpecialHoverAndFocusBehavior(){var e;this.removeSpecialFocusBehavior(),this.removeSpecialHoverBehavior(),(e=this.nodes.root)==null||e.removeEventListener("mouseleave",this.removeSpecialHoverBehavior)}activateOrEnableConfirmationMode(e){var t;if(!("confirmation"in e)||e.confirmation===void 0)try{(t=e.onActivate)==null||t.call(e,e),this.disableConfirmationMode()}catch{this.animateError()}else this.enableConfirmationMode(e.confirmation)}animateError(){var e,t,o;(e=this.nodes.icon)!=null&&e.classList.contains(L.wobbleAnimation)||((t=this.nodes.icon)==null||t.classList.add(L.wobbleAnimation),(o=this.nodes.icon)==null||o.addEventListener("animationend",this.onErrorAnimationEnd))}}const ft=ie("ce-popover-item-separator"),gt={container:ft(),line:ft("line"),hidden:ft(null,"hidden")};class Wo extends pt{constructor(){super(),this.nodes={root:d.make("div",gt.container),line:d.make("div",gt.line)},this.nodes.root.appendChild(this.nodes.line)}getElement(){return this.nodes.root}toggleHidden(e){var t;(t=this.nodes.root)==null||t.classList.toggle(gt.hidden,e)}}var Z=(n=>(n.Closed="closed",n.ClosedOnActivate="closed-on-activate",n))(Z||{});const z=ie("ce-popover"),P={popover:z(),popoverContainer:z("container"),popoverOpenTop:z(null,"open-top"),popoverOpenLeft:z(null,"open-left"),popoverOpened:z(null,"opened"),search:z("search"),nothingFoundMessage:z("nothing-found-message"),nothingFoundMessageDisplayed:z("nothing-found-message","displayed"),items:z("items"),overlay:z("overlay"),overlayHidden:z("overlay","hidden"),popoverNested:z(null,"nested"),getPopoverNestedClass:n=>z(null,`nested-level-${n.toString()}`),popoverInline:z(null,"inline"),popoverHeader:z("header")};var me=(n=>(n.NestingLevel="--nesting-level",n.PopoverHeight="--popover-height",n.InlinePopoverWidth="--inline-popover-width",n.TriggerItemLeft="--trigger-item-left",n.TriggerItemTop="--trigger-item-top",n))(me||{});const Yo=ie("ce-popover-item-html"),Ko={root:Yo(),hidden:Yo(null,"hidden")};class Se extends pt{constructor(e,t){var o,i;super(e),this.nodes={root:d.make("div",Ko.root)},this.nodes.root.appendChild(e.element),e.name&&(this.nodes.root.dataset.itemName=e.name),e.hint!==void 0&&((o=t==null?void 0:t.hint)==null?void 0:o.enabled)!==!1&&this.addHint(this.nodes.root,{...e.hint,position:((i=t==null?void 0:t.hint)==null?void 0:i.position)||"right"})}getElement(){return this.nodes.root}toggleHidden(e){var t;(t=this.nodes.root)==null||t.classList.toggle(Ko.hidden,e)}getControls(){const e=this.nodes.root.querySelectorAll(`button, ${d.allInputsSelector}`);return Array.from(e)}}class Xo extends we{constructor(e,t={}){super(),this.params=e,this.itemsRenderParams=t,this.listeners=new Ee,this.messages={nothingFound:"Nothing found",search:"Search"},this.items=this.buildItems(e.items),e.messages&&(this.messages={...this.messages,...e.messages}),this.nodes={},this.nodes.popoverContainer=d.make("div",[P.popoverContainer]),this.nodes.nothingFoundMessage=d.make("div",[P.nothingFoundMessage],{textContent:this.messages.nothingFound}),this.nodes.popoverContainer.appendChild(this.nodes.nothingFoundMessage),this.nodes.items=d.make("div",[P.items]),this.items.forEach(o=>{const i=o.getElement();i!==null&&this.nodes.items.appendChild(i)}),this.nodes.popoverContainer.appendChild(this.nodes.items),this.listeners.on(this.nodes.popoverContainer,"click",o=>this.handleClick(o)),this.nodes.popover=d.make("div",[P.popover,this.params.class]),this.nodes.popover.appendChild(this.nodes.popoverContainer)}get itemsDefault(){return this.items.filter(e=>e instanceof le)}getElement(){return this.nodes.popover}show(){this.nodes.popover.classList.add(P.popoverOpened),this.search!==void 0&&this.search.focus()}hide(){this.nodes.popover.classList.remove(P.popoverOpened),this.nodes.popover.classList.remove(P.popoverOpenTop),this.itemsDefault.forEach(e=>e.reset()),this.search!==void 0&&this.search.clear(),this.emit(Z.Closed)}destroy(){var e;this.items.forEach(t=>t.destroy()),this.nodes.popover.remove(),this.listeners.removeAll(),(e=this.search)==null||e.destroy()}activateItemByName(e){const t=this.items.find(o=>o.name===e);this.handleItemClick(t)}buildItems(e){return e.map(t=>{switch(t.type){case _.Separator:return new Wo;case _.Html:return new Se(t,this.itemsRenderParams[_.Html]);default:return new le(t,this.itemsRenderParams[_.Default])}})}getTargetItem(e){return this.items.filter(t=>t instanceof le||t instanceof Se).find(t=>{const o=t.getElement();return o===null?!1:e.composedPath().includes(o)})}handleItemClick(e){if(!("isDisabled"in e&&e.isDisabled)){if(e.hasChildren){this.showNestedItems(e),"handleClick"in e&&typeof e.handleClick=="function"&&e.handleClick();return}this.itemsDefault.filter(t=>t!==e).forEach(t=>t.reset()),"handleClick"in e&&typeof e.handleClick=="function"&&e.handleClick(),this.toggleItemActivenessIfNeeded(e),e.closeOnActivate&&(this.hide(),this.emit(Z.ClosedOnActivate))}}handleClick(e){const t=this.getTargetItem(e);t!==void 0&&this.handleItemClick(t)}toggleItemActivenessIfNeeded(e){if(e instanceof le&&(e.toggle===!0&&e.toggleActive(),typeof e.toggle=="string")){const t=this.itemsDefault.filter(o=>o.toggle===e.toggle);if(t.length===1){e.toggleActive();return}t.forEach(o=>{o.toggleActive(o===e)})}}}var De=(n=>(n.Search="search",n))(De||{});const mt=ie("cdx-search-field"),bt={wrapper:mt(),icon:mt("icon"),input:mt("input")};class os extends we{constructor({items:e,placeholder:t}){super(),this.listeners=new Ee,this.items=e,this.wrapper=d.make("div",bt.wrapper);const o=d.make("div",bt.icon,{innerHTML:Zi});this.input=d.make("input",bt.input,{placeholder:t,tabIndex:-1}),this.wrapper.appendChild(o),this.wrapper.appendChild(this.input),this.listeners.on(this.input,"input",()=>{this.searchQuery=this.input.value,this.emit(De.Search,{query:this.searchQuery,items:this.foundItems})})}getElement(){return this.wrapper}focus(){this.input.focus()}clear(){this.input.value="",this.searchQuery="",this.emit(De.Search,{query:"",items:this.foundItems})}destroy(){this.listeners.removeAll()}get foundItems(){return this.items.filter(e=>this.checkItem(e))}checkItem(e){var i,s;const t=((i=e.title)==null?void 0:i.toLowerCase())||"",o=(s=this.searchQuery)==null?void 0:s.toLowerCase();return o!==void 0?t.includes(o):!1}}var ns=Object.defineProperty,is=Object.getOwnPropertyDescriptor,ss=(n,e,t,o)=>{for(var i=o>1?void 0:o?is(e,t):e,s=n.length-1,r;s>=0;s--)(r=n[s])&&(i=(o?r(e,t,i):r(i))||i);return o&&i&&ns(e,t,i),i};const Vo=class zn extends Xo{constructor(e,t){super(e,t),this.nestingLevel=0,this.nestedPopoverTriggerItem=null,this.previouslyHoveredItem=null,this.scopeElement=document.body,this.hide=()=>{var o;super.hide(),this.destroyNestedPopoverIfExists(),(o=this.flipper)==null||o.deactivate(),this.previouslyHoveredItem=null},this.onFlip=()=>{const o=this.itemsDefault.find(i=>i.isFocused);o==null||o.onFocus()},this.onSearch=o=>{var a;const i=o.query==="",s=o.items.length===0;this.items.forEach(l=>{let c=!1;l instanceof le?c=!o.items.includes(l):(l instanceof Wo||l instanceof Se)&&(c=s||!i),l.toggleHidden(c)}),this.toggleNothingFoundMessage(s);const r=o.query===""?this.flippableElements:o.items.map(l=>l.getElement());(a=this.flipper)!=null&&a.isActivated&&(this.flipper.deactivate(),this.flipper.activate(r))},e.nestingLevel!==void 0&&(this.nestingLevel=e.nestingLevel),this.nestingLevel>0&&this.nodes.popover.classList.add(P.popoverNested),e.scopeElement!==void 0&&(this.scopeElement=e.scopeElement),this.nodes.popoverContainer!==null&&this.listeners.on(this.nodes.popoverContainer,"mouseover",o=>this.handleHover(o)),e.searchable&&this.addSearch(),e.flippable!==!1&&(this.flipper=new ae({items:this.flippableElements,focusedItemClass:L.focused,allowedKeys:[y.TAB,y.UP,y.DOWN,y.ENTER]}),this.flipper.onFlip(this.onFlip))}hasFocus(){return this.flipper===void 0?!1:this.flipper.hasFocus()}get scrollTop(){return this.nodes.items===null?0:this.nodes.items.scrollTop}get offsetTop(){return this.nodes.popoverContainer===null?0:this.nodes.popoverContainer.offsetTop}show(){var e;this.nodes.popover.style.setProperty(me.PopoverHeight,this.size.height+"px"),this.shouldOpenBottom||this.nodes.popover.classList.add(P.popoverOpenTop),this.shouldOpenRight||this.nodes.popover.classList.add(P.popoverOpenLeft),super.show(),(e=this.flipper)==null||e.activate(this.flippableElements)}destroy(){this.hide(),super.destroy()}showNestedItems(e){this.nestedPopover!==null&&this.nestedPopover!==void 0||(this.nestedPopoverTriggerItem=e,this.showNestedPopoverForItem(e))}handleHover(e){const t=this.getTargetItem(e);t!==void 0&&this.previouslyHoveredItem!==t&&(this.destroyNestedPopoverIfExists(),this.previouslyHoveredItem=t,t.hasChildren&&this.showNestedPopoverForItem(t))}setTriggerItemPosition(e,t){const o=t.getElement(),i=(o?o.offsetTop:0)-this.scrollTop,s=this.offsetTop+i;e.style.setProperty(me.TriggerItemTop,s+"px")}destroyNestedPopoverIfExists(){var e,t;this.nestedPopover===void 0||this.nestedPopover===null||(this.nestedPopover.off(Z.ClosedOnActivate,this.hide),this.nestedPopover.hide(),this.nestedPopover.destroy(),this.nestedPopover.getElement().remove(),this.nestedPopover=null,(e=this.flipper)==null||e.activate(this.flippableElements),(t=this.nestedPopoverTriggerItem)==null||t.onChildrenClose())}showNestedPopoverForItem(e){var o;this.nestedPopover=new zn({searchable:e.isChildrenSearchable,items:e.children,nestingLevel:this.nestingLevel+1,flippable:e.isChildrenFlippable,messages:this.messages}),e.onChildrenOpen(),this.nestedPopover.on(Z.ClosedOnActivate,this.hide);const t=this.nestedPopover.getElement();return this.nodes.popover.appendChild(t),this.setTriggerItemPosition(t,e),t.style.setProperty(me.NestingLevel,this.nestedPopover.nestingLevel.toString()),this.nestedPopover.show(),(o=this.flipper)==null||o.deactivate(),this.nestedPopover}get shouldOpenBottom(){if(this.nodes.popover===void 0||this.nodes.popover===null)return!1;const e=this.nodes.popoverContainer.getBoundingClientRect(),t=this.scopeElement.getBoundingClientRect(),o=this.size.height,i=e.top+o,s=e.top-o,r=Math.min(window.innerHeight,t.bottom);return s{if(t instanceof le)return t.getElement();if(t instanceof Se)return t.getControls()}).flat().filter(t=>t!=null)}addSearch(){this.search=new os({items:this.itemsDefault,placeholder:this.messages.search}),this.search.on(De.Search,this.onSearch);const e=this.search.getElement();e.classList.add(P.search),this.nodes.popoverContainer.insertBefore(e,this.nodes.popoverContainer.firstChild)}toggleNothingFoundMessage(e){this.nodes.nothingFoundMessage.classList.toggle(P.nothingFoundMessageDisplayed,e)}};ss([fe],Vo.prototype,"size",1);let vt=Vo;class rs extends vt{constructor(e){const t=!ge();super({...e,class:P.popoverInline},{[_.Default]:{wrapperTag:"button",hint:{position:"top",alignment:"center",enabled:t}},[_.Html]:{hint:{position:"top",alignment:"center",enabled:t}}}),this.items.forEach(o=>{!(o instanceof le)&&!(o instanceof Se)||o.hasChildren&&o.isChildrenOpen&&this.showNestedItems(o)})}get offsetLeft(){return this.nodes.popoverContainer===null?0:this.nodes.popoverContainer.offsetLeft}show(){this.nestingLevel===0&&this.nodes.popover.style.setProperty(me.InlinePopoverWidth,this.size.width+"px"),super.show()}handleHover(){}setTriggerItemPosition(e,t){const o=t.getElement(),i=o?o.offsetLeft:0,s=this.offsetLeft+i;e.style.setProperty(me.TriggerItemLeft,s+"px")}showNestedItems(e){if(this.nestedPopoverTriggerItem===e){this.destroyNestedPopoverIfExists(),this.nestedPopoverTriggerItem=null;return}super.showNestedItems(e)}showNestedPopoverForItem(e){const t=super.showNestedPopoverForItem(e);return t.getElement().classList.add(P.getPopoverNestedClass(t.nestingLevel)),t}handleItemClick(e){var t;e!==this.nestedPopoverTriggerItem&&((t=this.nestedPopoverTriggerItem)==null||t.handleClick(),super.destroyNestedPopoverIfExists()),super.handleItemClick(e)}}const qo=class Me{constructor(){this.scrollPosition=null}lock(){rt?this.lockHard():document.body.classList.add(Me.CSS.scrollLocked)}unlock(){rt?this.unlockHard():document.body.classList.remove(Me.CSS.scrollLocked)}lockHard(){this.scrollPosition=window.pageYOffset,document.documentElement.style.setProperty("--window-scroll-offset",`${this.scrollPosition}px`),document.body.classList.add(Me.CSS.scrollLockedHard)}unlockHard(){document.body.classList.remove(Me.CSS.scrollLockedHard),this.scrollPosition!==null&&window.scrollTo(0,this.scrollPosition),this.scrollPosition=null}};qo.CSS={scrollLocked:"ce-scroll-locked",scrollLockedHard:"ce-scroll-locked--hard"};let as=qo;const kt=ie("ce-popover-header"),yt={root:kt(),text:kt("text"),backButton:kt("back-button")};class ls{constructor({text:e,onBackButtonClick:t}){this.listeners=new Ee,this.text=e,this.onBackButtonClick=t,this.nodes={root:d.make("div",[yt.root]),backButton:d.make("button",[yt.backButton]),text:d.make("div",[yt.text])},this.nodes.backButton.innerHTML=zi,this.nodes.root.appendChild(this.nodes.backButton),this.listeners.on(this.nodes.backButton,"click",this.onBackButtonClick),this.nodes.text.innerText=this.text,this.nodes.root.appendChild(this.nodes.text)}getElement(){return this.nodes.root}destroy(){this.nodes.root.remove(),this.listeners.destroy()}}class cs{constructor(){this.history=[]}push(e){this.history.push(e)}pop(){return this.history.pop()}get currentTitle(){return this.history.length===0?"":this.history[this.history.length-1].title}get currentItems(){return this.history.length===0?[]:this.history[this.history.length-1].items}reset(){for(;this.history.length>1;)this.pop()}}class Zo extends Xo{constructor(e){super(e,{[_.Default]:{hint:{enabled:!1}},[_.Html]:{hint:{enabled:!1}}}),this.scrollLocker=new as,this.history=new cs,this.isHidden=!0,this.nodes.overlay=d.make("div",[P.overlay,P.overlayHidden]),this.nodes.popover.insertBefore(this.nodes.overlay,this.nodes.popover.firstChild),this.listeners.on(this.nodes.overlay,"click",()=>{this.hide()}),this.history.push({items:e.items})}show(){this.nodes.overlay.classList.remove(P.overlayHidden),super.show(),this.scrollLocker.lock(),this.isHidden=!1}hide(){this.isHidden||(super.hide(),this.nodes.overlay.classList.add(P.overlayHidden),this.scrollLocker.unlock(),this.history.reset(),this.isHidden=!0)}destroy(){super.destroy(),this.scrollLocker.unlock()}showNestedItems(e){this.updateItemsAndHeader(e.children,e.title),this.history.push({title:e.title,items:e.children})}updateItemsAndHeader(e,t){if(this.header!==null&&this.header!==void 0&&(this.header.destroy(),this.header=null),t!==void 0){this.header=new ls({text:t,onBackButtonClick:()=>{this.history.pop(),this.updateItemsAndHeader(this.history.currentItems,this.history.currentTitle)}});const o=this.header.getElement();o!==null&&this.nodes.popoverContainer.insertBefore(o,this.nodes.popoverContainer.firstChild)}this.items.forEach(o=>{var i;return(i=o.getElement())==null?void 0:i.remove()}),this.items=this.buildItems(e),this.items.forEach(o=>{var s;const i=o.getElement();i!==null&&((s=this.nodes.items)==null||s.appendChild(i))})}}class ds extends E{constructor(){super(...arguments),this.opened=!1,this.selection=new b,this.popover=null,this.close=()=>{this.opened&&(this.opened=!1,b.isAtEditor||this.selection.restore(),this.selection.clearSaved(),!this.Editor.CrossBlockSelection.isCrossBlockSelectionStarted&&this.Editor.BlockManager.currentBlock&&this.Editor.BlockSelection.unselectBlock(this.Editor.BlockManager.currentBlock),this.eventsDispatcher.emit(this.events.closed),this.popover&&(this.popover.off(Z.Closed,this.onPopoverClose),this.popover.destroy(),this.popover.getElement().remove(),this.popover=null))},this.onPopoverClose=()=>{this.close()}}get events(){return{opened:"block-settings-opened",closed:"block-settings-closed"}}get CSS(){return{settings:"ce-settings"}}get flipper(){var e;if(this.popover!==null)return"flipper"in this.popover?(e=this.popover)==null?void 0:e.flipper:void 0}make(){this.nodes.wrapper=d.make("div",[this.CSS.settings]),this.eventsDispatcher.on(xe,this.close)}destroy(){this.removeAllNodes(),this.listeners.destroy(),this.eventsDispatcher.off(xe,this.close)}async open(e=this.Editor.BlockManager.currentBlock){var s;this.opened=!0,this.selection.save(),this.Editor.BlockSelection.selectBlock(e),this.Editor.BlockSelection.clearCache();const{toolTunes:t,commonTunes:o}=e.getTunes();this.eventsDispatcher.emit(this.events.opened);const i=ge()?Zo:vt;this.popover=new i({searchable:!0,items:await this.getTunesItems(e,o,t),scopeElement:this.Editor.API.methods.ui.nodes.redactor,messages:{nothingFound:H.ui(W.ui.popover,"Nothing found"),search:H.ui(W.ui.popover,"Filter")}}),this.popover.on(Z.Closed,this.onPopoverClose),(s=this.nodes.wrapper)==null||s.append(this.popover.getElement()),this.popover.show()}getElement(){return this.nodes.wrapper}async getTunesItems(e,t,o){const i=[];o!==void 0&&o.length>0&&(i.push(...o),i.push({type:_.Separator}));const s=Array.from(this.Editor.Tools.blockTools.values()),a=(await Po(e,s)).reduce((l,c)=>(c.toolbox.forEach(u=>{l.push({icon:u.icon,title:H.t(W.toolNames,u.title),name:c.name,closeOnActivate:!0,onActivate:async()=>{const{BlockManager:h,Caret:p,Toolbar:g}=this.Editor,f=await h.convert(e,c.name,u.data);g.close(),p.setToBlock(f,p.positions.END)}})}),l),[]);return a.length>0&&(i.push({icon:Uo,name:"convert-to",title:H.ui(W.ui.popover,"Convert to"),children:{searchable:!0,items:a}}),i.push({type:_.Separator})),i.push(...t),i.map(l=>this.resolveTuneAliases(l))}resolveTuneAliases(e){if(e.type===_.Separator||e.type===_.Html)return e;const t=ji(e,{label:"title"});return e.confirmation&&(t.confirmation=this.resolveTuneAliases(e.confirmation)),t}}var Go={exports:{}};/*! + * Library for handling keyboard shortcuts + * @copyright CodeX (https://codex.so) + * @license MIT + * @author CodeX (https://codex.so) + * @version 1.2.0 + */(function(n,e){(function(t,o){n.exports=o()})(window,function(){return function(t){var o={};function i(s){if(o[s])return o[s].exports;var r=o[s]={i:s,l:!1,exports:{}};return t[s].call(r.exports,r,r.exports,i),r.l=!0,r.exports}return i.m=t,i.c=o,i.d=function(s,r,a){i.o(s,r)||Object.defineProperty(s,r,{enumerable:!0,get:a})},i.r=function(s){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(s,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(s,"__esModule",{value:!0})},i.t=function(s,r){if(1&r&&(s=i(s)),8&r||4&r&&typeof s=="object"&&s&&s.__esModule)return s;var a=Object.create(null);if(i.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:s}),2&r&&typeof s!="string")for(var l in s)i.d(a,l,(function(c){return s[c]}).bind(null,l));return a},i.n=function(s){var r=s&&s.__esModule?function(){return s.default}:function(){return s};return i.d(r,"a",r),r},i.o=function(s,r){return Object.prototype.hasOwnProperty.call(s,r)},i.p="",i(i.s=0)}([function(t,o,i){function s(l,c){for(var u=0;ur!==o);if(s.length===0){this.registeredShortcuts.delete(e);return}this.registeredShortcuts.set(e,s)}findShortcut(e,t){return(this.registeredShortcuts.get(e)||[]).find(({name:i})=>i===t)}}const be=new ps;var fs=Object.defineProperty,gs=Object.getOwnPropertyDescriptor,Jo=(n,e,t,o)=>{for(var i=o>1?void 0:o?gs(e,t):e,s=n.length-1,r;s>=0;s--)(r=n[s])&&(i=(o?r(e,t,i):r(i))||i);return o&&i&&fs(e,t,i),i},Fe=(n=>(n.Opened="toolbox-opened",n.Closed="toolbox-closed",n.BlockAdded="toolbox-block-added",n))(Fe||{});const wt=class Un extends we{constructor({api:e,tools:t,i18nLabels:o}){super(),this.opened=!1,this.listeners=new Ee,this.popover=null,this.handleMobileLayoutToggle=()=>{this.destroyPopover(),this.initPopover()},this.onPopoverClose=()=>{this.opened=!1,this.emit("toolbox-closed")},this.api=e,this.tools=t,this.i18nLabels=o,this.enableShortcuts(),this.nodes={toolbox:d.make("div",Un.CSS.toolbox)},this.initPopover(),this.api.events.on(xe,this.handleMobileLayoutToggle)}get isEmpty(){return this.toolsToBeDisplayed.length===0}static get CSS(){return{toolbox:"ce-toolbox"}}getElement(){return this.nodes.toolbox}hasFocus(){if(this.popover!==null)return"hasFocus"in this.popover?this.popover.hasFocus():void 0}destroy(){var e;super.destroy(),this.nodes&&this.nodes.toolbox&&this.nodes.toolbox.remove(),this.removeAllShortcuts(),(e=this.popover)==null||e.off(Z.Closed,this.onPopoverClose),this.listeners.destroy(),this.api.events.off(xe,this.handleMobileLayoutToggle)}toolButtonActivated(e,t){this.insertNewBlock(e,t)}open(){var e;this.isEmpty||((e=this.popover)==null||e.show(),this.opened=!0,this.emit("toolbox-opened"))}close(){var e;(e=this.popover)==null||e.hide(),this.opened=!1,this.emit("toolbox-closed")}toggle(){this.opened?this.close():this.open()}initPopover(){var t;const e=ge()?Zo:vt;this.popover=new e({scopeElement:this.api.ui.nodes.redactor,searchable:!0,messages:{nothingFound:this.i18nLabels.nothingFound,search:this.i18nLabels.filter},items:this.toolboxItemsToBeDisplayed}),this.popover.on(Z.Closed,this.onPopoverClose),(t=this.nodes.toolbox)==null||t.append(this.popover.getElement())}destroyPopover(){this.popover!==null&&(this.popover.hide(),this.popover.off(Z.Closed,this.onPopoverClose),this.popover.destroy(),this.popover=null),this.nodes.toolbox!==null&&(this.nodes.toolbox.innerHTML="")}get toolsToBeDisplayed(){const e=[];return this.tools.forEach(t=>{t.toolbox&&e.push(t)}),e}get toolboxItemsToBeDisplayed(){const e=(t,o,i=!0)=>({icon:t.icon,title:H.t(W.toolNames,t.title||Le(o.name)),name:o.name,onActivate:()=>{this.toolButtonActivated(o.name,t.data)},secondaryLabel:o.shortcut&&i?it(o.shortcut):""});return this.toolsToBeDisplayed.reduce((t,o)=>(Array.isArray(o.toolbox)?o.toolbox.forEach((i,s)=>{t.push(e(i,o,s===0))}):o.toolbox!==void 0&&t.push(e(o.toolbox,o)),t),[])}enableShortcuts(){this.toolsToBeDisplayed.forEach(e=>{const t=e.shortcut;t&&this.enableShortcutForTool(e.name,t)})}enableShortcutForTool(e,t){be.add({name:t,on:this.api.ui.nodes.redactor,handler:async o=>{o.preventDefault();const i=this.api.blocks.getCurrentBlockIndex(),s=this.api.blocks.getBlockByIndex(i);if(s)try{const r=await this.api.blocks.convert(s.id,e);this.api.caret.setToBlock(r,"end");return}catch{}this.insertNewBlock(e)}})}removeAllShortcuts(){this.toolsToBeDisplayed.forEach(e=>{const t=e.shortcut;t&&be.remove(this.api.ui.nodes.redactor,t)})}async insertNewBlock(e,t){const o=this.api.blocks.getCurrentBlockIndex(),i=this.api.blocks.getBlockByIndex(o);if(!i)return;const s=i.isEmpty?o:o+1;let r;if(t){const l=await this.api.blocks.composeBlockData(e);r=Object.assign(l,t)}const a=this.api.blocks.insert(e,r,void 0,s,void 0,i.isEmpty);a.call(te.APPEND_CALLBACK),this.api.caret.setToBlock(s),this.emit("toolbox-block-added",{block:a}),this.api.toolbar.close()}};Jo([fe],wt.prototype,"toolsToBeDisplayed",1),Jo([fe],wt.prototype,"toolboxItemsToBeDisplayed",1);let ms=wt;const Qo="block hovered";async function bs(n,e){const t=navigator.keyboard;if(!t)return e;try{return(await t.getLayoutMap()).get(n)||e}catch(o){return console.error(o),e}}class vs extends E{constructor({config:e,eventsDispatcher:t}){super({config:e,eventsDispatcher:t}),this.toolboxInstance=null}get CSS(){return{toolbar:"ce-toolbar",content:"ce-toolbar__content",actions:"ce-toolbar__actions",actionsOpened:"ce-toolbar__actions--opened",toolbarOpened:"ce-toolbar--opened",openedToolboxHolderModifier:"codex-editor--toolbox-opened",plusButton:"ce-toolbar__plus",plusButtonShortcut:"ce-toolbar__plus-shortcut",settingsToggler:"ce-toolbar__settings-btn",settingsTogglerHidden:"ce-toolbar__settings-btn--hidden"}}get opened(){return this.nodes.wrapper.classList.contains(this.CSS.toolbarOpened)}get toolbox(){var e;return{opened:(e=this.toolboxInstance)==null?void 0:e.opened,close:()=>{var t;(t=this.toolboxInstance)==null||t.close()},open:()=>{if(this.toolboxInstance===null){T("toolbox.open() called before initialization is finished","warn");return}this.Editor.BlockManager.currentBlock=this.hoveredBlock,this.toolboxInstance.open()},toggle:()=>{if(this.toolboxInstance===null){T("toolbox.toggle() called before initialization is finished","warn");return}this.toolboxInstance.toggle()},hasFocus:()=>{var t;return(t=this.toolboxInstance)==null?void 0:t.hasFocus()}}}get blockActions(){return{hide:()=>{this.nodes.actions.classList.remove(this.CSS.actionsOpened)},show:()=>{this.nodes.actions.classList.add(this.CSS.actionsOpened)}}}get blockTunesToggler(){return{hide:()=>this.nodes.settingsToggler.classList.add(this.CSS.settingsTogglerHidden),show:()=>this.nodes.settingsToggler.classList.remove(this.CSS.settingsTogglerHidden)}}toggleReadOnly(e){e?(this.destroy(),this.Editor.BlockSettings.destroy(),this.disableModuleBindings()):window.requestIdleCallback(()=>{this.drawUI(),this.enableModuleBindings()},{timeout:2e3})}moveAndOpen(e=this.Editor.BlockManager.currentBlock){if(this.toolboxInstance===null){T("Can't open Toolbar since Editor initialization is not finished yet","warn");return}if(this.toolboxInstance.opened&&this.toolboxInstance.close(),this.Editor.BlockSettings.opened&&this.Editor.BlockSettings.close(),!e)return;this.hoveredBlock=e;const t=e.holder,{isMobile:o}=this.Editor.UI;let i;const s=20,r=e.firstInput,a=t.getBoundingClientRect(),l=r!==void 0?r.getBoundingClientRect():null,c=l!==null?l.top-a.top:null,u=c!==null?c>s:void 0;if(o)i=t.offsetTop+t.offsetHeight;else if(r===void 0||u){const h=parseInt(window.getComputedStyle(e.pluginsContent).paddingTop);i=t.offsetTop+h}else{const h=ri(r),p=parseInt(window.getComputedStyle(this.nodes.plusButton).height,10),g=8;i=t.offsetTop+h-p+g+c}this.nodes.wrapper.style.top=`${Math.floor(i)}px`,this.Editor.BlockManager.blocks.length===1&&e.isEmpty?this.blockTunesToggler.hide():this.blockTunesToggler.show(),this.open()}close(){var e,t;this.Editor.ReadOnly.isEnabled||((e=this.nodes.wrapper)==null||e.classList.remove(this.CSS.toolbarOpened),this.blockActions.hide(),(t=this.toolboxInstance)==null||t.close(),this.Editor.BlockSettings.close(),this.reset())}reset(){this.nodes.wrapper.style.top="unset"}open(e=!0){this.nodes.wrapper.classList.add(this.CSS.toolbarOpened),e?this.blockActions.show():this.blockActions.hide()}async make(){this.nodes.wrapper=d.make("div",this.CSS.toolbar),["content","actions"].forEach(s=>{this.nodes[s]=d.make("div",this.CSS[s])}),d.append(this.nodes.wrapper,this.nodes.content),d.append(this.nodes.content,this.nodes.actions),this.nodes.plusButton=d.make("div",this.CSS.plusButton,{innerHTML:qi}),d.append(this.nodes.actions,this.nodes.plusButton),this.readOnlyMutableListeners.on(this.nodes.plusButton,"click",()=>{Ne(!0),this.plusButtonClicked()},!1);const e=d.make("div");e.appendChild(document.createTextNode(H.ui(W.ui.toolbar.toolbox,"Add"))),e.appendChild(d.make("div",this.CSS.plusButtonShortcut,{textContent:"/"})),Re(this.nodes.plusButton,e,{hidingDelay:400}),this.nodes.settingsToggler=d.make("span",this.CSS.settingsToggler,{innerHTML:Vi}),d.append(this.nodes.actions,this.nodes.settingsToggler);const t=d.make("div"),o=d.text(H.ui(W.ui.blockTunes.toggler,"Click to tune")),i=await bs("Slash","/");t.appendChild(o),t.appendChild(d.make("div",this.CSS.plusButtonShortcut,{textContent:it(`CMD + ${i}`)})),Re(this.nodes.settingsToggler,t,{hidingDelay:400}),d.append(this.nodes.actions,this.makeToolbox()),d.append(this.nodes.actions,this.Editor.BlockSettings.getElement()),d.append(this.Editor.UI.nodes.wrapper,this.nodes.wrapper)}makeToolbox(){return this.toolboxInstance=new ms({api:this.Editor.API.methods,tools:this.Editor.Tools.blockTools,i18nLabels:{filter:H.ui(W.ui.popover,"Filter"),nothingFound:H.ui(W.ui.popover,"Nothing found")}}),this.toolboxInstance.on(Fe.Opened,()=>{this.Editor.UI.nodes.wrapper.classList.add(this.CSS.openedToolboxHolderModifier)}),this.toolboxInstance.on(Fe.Closed,()=>{this.Editor.UI.nodes.wrapper.classList.remove(this.CSS.openedToolboxHolderModifier)}),this.toolboxInstance.on(Fe.BlockAdded,({block:e})=>{const{BlockManager:t,Caret:o}=this.Editor,i=t.getBlockById(e.id);i.inputs.length===0&&(i===t.lastBlock?(t.insertAtEnd(),o.setToBlock(t.lastBlock)):o.setToBlock(t.nextBlock))}),this.toolboxInstance.getElement()}plusButtonClicked(){var e;this.Editor.BlockManager.currentBlock=this.hoveredBlock,(e=this.toolboxInstance)==null||e.toggle()}enableModuleBindings(){this.readOnlyMutableListeners.on(this.nodes.settingsToggler,"mousedown",e=>{var t;e.stopPropagation(),this.settingsTogglerClicked(),(t=this.toolboxInstance)!=null&&t.opened&&this.toolboxInstance.close(),Ne(!0)},!0),ge()||this.eventsDispatcher.on(Qo,e=>{var t;this.Editor.BlockSettings.opened||(t=this.toolboxInstance)!=null&&t.opened||this.moveAndOpen(e.block)})}disableModuleBindings(){this.readOnlyMutableListeners.clearAll()}settingsTogglerClicked(){this.Editor.BlockManager.currentBlock=this.hoveredBlock,this.Editor.BlockSettings.opened?this.Editor.BlockSettings.close():this.Editor.BlockSettings.open(this.hoveredBlock)}drawUI(){this.Editor.BlockSettings.make(),this.make()}destroy(){this.removeAllNodes(),this.toolboxInstance&&this.toolboxInstance.destroy()}}var ce=(n=>(n[n.Block=0]="Block",n[n.Inline=1]="Inline",n[n.Tune=2]="Tune",n))(ce||{}),je=(n=>(n.Shortcut="shortcut",n.Toolbox="toolbox",n.EnabledInlineTools="inlineToolbar",n.EnabledBlockTunes="tunes",n.Config="config",n))(je||{}),en=(n=>(n.Shortcut="shortcut",n.SanitizeConfig="sanitize",n))(en||{}),ve=(n=>(n.IsEnabledLineBreaks="enableLineBreaks",n.Toolbox="toolbox",n.ConversionConfig="conversionConfig",n.IsReadOnlySupported="isReadOnlySupported",n.PasteConfig="pasteConfig",n))(ve||{}),He=(n=>(n.IsInline="isInline",n.Title="title",n.IsReadOnlySupported="isReadOnlySupported",n))(He||{}),Et=(n=>(n.IsTune="isTune",n))(Et||{});class xt{constructor({name:e,constructable:t,config:o,api:i,isDefault:s,isInternal:r=!1,defaultPlaceholder:a}){this.api=i,this.name=e,this.constructable=t,this.config=o,this.isDefault=s,this.isInternal=r,this.defaultPlaceholder=a}get settings(){const e=this.config.config||{};return this.isDefault&&!("placeholder"in e)&&this.defaultPlaceholder&&(e.placeholder=this.defaultPlaceholder),e}reset(){if(M(this.constructable.reset))return this.constructable.reset()}prepare(){if(M(this.constructable.prepare))return this.constructable.prepare({toolName:this.name,config:this.settings})}get shortcut(){const e=this.constructable.shortcut;return this.config.shortcut||e}get sanitizeConfig(){return this.constructable.sanitize||{}}isInline(){return this.type===ce.Inline}isBlock(){return this.type===ce.Block}isTune(){return this.type===ce.Tune}}class ks extends E{constructor({config:e,eventsDispatcher:t}){super({config:e,eventsDispatcher:t}),this.CSS={inlineToolbar:"ce-inline-toolbar"},this.opened=!1,this.popover=null,this.toolbarVerticalMargin=ge()?20:6,this.tools=new Map,window.requestIdleCallback(()=>{this.make()},{timeout:2e3})}async tryToShow(e=!1){e&&this.close(),this.allowedToShow()&&(await this.open(),this.Editor.Toolbar.close())}close(){var e,t;if(this.opened){for(const[o,i]of this.tools){const s=this.getToolShortcut(o.name);s!==void 0&&be.remove(this.Editor.UI.nodes.redactor,s),M(i.clear)&&i.clear()}this.tools=new Map,this.reset(),this.opened=!1,(e=this.popover)==null||e.hide(),(t=this.popover)==null||t.destroy(),this.popover=null}}containsNode(e){return this.nodes.wrapper===void 0?!1:this.nodes.wrapper.contains(e)}destroy(){var e;this.removeAllNodes(),(e=this.popover)==null||e.destroy(),this.popover=null}make(){this.nodes.wrapper=d.make("div",[this.CSS.inlineToolbar,...this.isRtl?[this.Editor.UI.CSS.editorRtlFix]:[]]),d.append(this.Editor.UI.nodes.wrapper,this.nodes.wrapper)}async open(){var t;if(this.opened)return;this.opened=!0,this.popover!==null&&this.popover.destroy(),this.createToolsInstances();const e=await this.getPopoverItems();this.popover=new rs({items:e,scopeElement:this.Editor.API.methods.ui.nodes.redactor,messages:{nothingFound:H.ui(W.ui.popover,"Nothing found"),search:H.ui(W.ui.popover,"Filter")}}),this.move(this.popover.size.width),(t=this.nodes.wrapper)==null||t.append(this.popover.getElement()),this.popover.show()}move(e){const t=b.rect,o=this.Editor.UI.nodes.wrapper.getBoundingClientRect(),i={x:t.x-o.x,y:t.y+t.height-o.top+this.toolbarVerticalMargin};i.x+e+o.x>this.Editor.UI.contentRect.right&&(i.x=this.Editor.UI.contentRect.right-e-o.x),this.nodes.wrapper.style.left=Math.floor(i.x)+"px",this.nodes.wrapper.style.top=Math.floor(i.y)+"px"}reset(){this.nodes.wrapper.style.left="0",this.nodes.wrapper.style.top="0"}allowedToShow(){const e=["IMG","INPUT"],t=b.get(),o=b.text;if(!t||!t.anchorNode||t.isCollapsed||o.length<1)return!1;const i=d.isElement(t.anchorNode)?t.anchorNode:t.anchorNode.parentElement;if(i===null||t!==null&&e.includes(i.tagName))return!1;const s=this.Editor.BlockManager.getBlock(t.anchorNode);return!s||this.getTools().some(c=>s.tool.inlineTools.has(c.name))===!1?!1:i.closest("[contenteditable]")!==null}getTools(){const e=this.Editor.BlockManager.currentBlock;return e?Array.from(e.tool.inlineTools.values()).filter(o=>!(this.Editor.ReadOnly.isEnabled&&o.isReadOnlySupported!==!0)):[]}createToolsInstances(){this.tools=new Map,this.getTools().forEach(t=>{const o=t.create();this.tools.set(t,o)})}async getPopoverItems(){const e=[];let t=0;for(const[o,i]of this.tools){const s=await i.render(),r=this.getToolShortcut(o.name);if(r!==void 0)try{this.enableShortcuts(o.name,r)}catch{}const a=r!==void 0?it(r):void 0,l=H.t(W.toolNames,o.title||Le(o.name));[s].flat().forEach(c=>{var h,p;const u={name:o.name,onActivate:()=>{this.toolClicked(i)},hint:{title:l,description:a}};if(d.isElement(c)){const g={...u,element:c,type:_.Html};if(M(i.renderActions)){const f=i.renderActions();g.children={isOpen:(h=i.checkState)==null?void 0:h.call(i,b.get()),isFlippable:!1,items:[{type:_.Html,element:f}]}}else(p=i.checkState)==null||p.call(i,b.get());e.push(g)}else if(c.type===_.Html)e.push({...u,...c,type:_.Html});else if(c.type===_.Separator)e.push({type:_.Separator});else{const g={...u,...c,type:_.Default};"children"in g&&t!==0&&e.push({type:_.Separator}),e.push(g),"children"in g&&t{var s;const{currentBlock:i}=this.Editor.BlockManager;i&&i.tool.enabledInlineTools&&(o.preventDefault(),(s=this.popover)==null||s.activateItemByName(e))},on:document})}toolClicked(e){var o;const t=b.range;(o=e.surround)==null||o.call(e,t),this.checkToolsState()}checkToolsState(){var e;(e=this.tools)==null||e.forEach(t=>{var o;(o=t.checkState)==null||o.call(t,b.get())})}get inlineTools(){const e={};return Array.from(this.Editor.Tools.inlineTools.entries()).forEach(([t,o])=>{e[t]=o.create()}),e}}function tn(){const n=window.getSelection();if(n===null)return[null,0];let e=n.focusNode,t=n.focusOffset;return e===null?[null,0]:(e.nodeType!==Node.TEXT_NODE&&e.childNodes.length>0&&(e.childNodes[t]?(e=e.childNodes[t],t=0):(e=e.childNodes[t-1],t=e.textContent.length)),[e,t])}function on(n,e,t,o){const i=document.createRange();o==="left"?(i.setStart(n,0),i.setEnd(e,t)):(i.setStart(e,t),i.setEnd(n,n.childNodes.length));const s=i.cloneContents(),r=document.createElement("div");r.appendChild(s);const a=r.textContent||"";return si(a)}function $e(n){const e=d.getDeepestNode(n);if(e===null||d.isEmpty(n))return!0;if(d.isNativeInput(e))return e.selectionEnd===0;if(d.isEmpty(n))return!0;const[t,o]=tn();return t===null?!1:on(n,t,o,"left")}function ze(n){const e=d.getDeepestNode(n,!0);if(e===null)return!0;if(d.isNativeInput(e))return e.selectionEnd===e.value.length;const[t,o]=tn();return t===null?!1:on(n,t,o,"right")}var nn={},Bt={},Ue={},de={},Ct={},Tt={};Object.defineProperty(Tt,"__esModule",{value:!0}),Tt.allInputsSelector=ys;function ys(){var n=["text","password","email","number","search","tel","url"];return"[contenteditable=true], textarea, input:not([type]), "+n.map(function(e){return'input[type="'.concat(e,'"]')}).join(", ")}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.allInputsSelector=void 0;var e=Tt;Object.defineProperty(n,"allInputsSelector",{enumerable:!0,get:function(){return e.allInputsSelector}})})(Ct);var ue={},St={};Object.defineProperty(St,"__esModule",{value:!0}),St.isNativeInput=ws;function ws(n){var e=["INPUT","TEXTAREA"];return n&&n.tagName?e.includes(n.tagName):!1}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isNativeInput=void 0;var e=St;Object.defineProperty(n,"isNativeInput",{enumerable:!0,get:function(){return e.isNativeInput}})})(ue);var sn={},It={};Object.defineProperty(It,"__esModule",{value:!0}),It.append=Es;function Es(n,e){Array.isArray(e)?e.forEach(function(t){n.appendChild(t)}):n.appendChild(e)}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.append=void 0;var e=It;Object.defineProperty(n,"append",{enumerable:!0,get:function(){return e.append}})})(sn);var Ot={},_t={};Object.defineProperty(_t,"__esModule",{value:!0}),_t.blockElements=xs;function xs(){return["address","article","aside","blockquote","canvas","div","dl","dt","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","li","main","nav","noscript","ol","output","p","pre","ruby","section","table","tbody","thead","tr","tfoot","ul","video"]}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.blockElements=void 0;var e=_t;Object.defineProperty(n,"blockElements",{enumerable:!0,get:function(){return e.blockElements}})})(Ot);var rn={},Mt={};Object.defineProperty(Mt,"__esModule",{value:!0}),Mt.calculateBaseline=Bs;function Bs(n){var e=window.getComputedStyle(n),t=parseFloat(e.fontSize),o=parseFloat(e.lineHeight)||t*1.2,i=parseFloat(e.paddingTop),s=parseFloat(e.borderTopWidth),r=parseFloat(e.marginTop),a=t*.8,l=(o-t)/2,c=r+s+i+l+a;return c}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.calculateBaseline=void 0;var e=Mt;Object.defineProperty(n,"calculateBaseline",{enumerable:!0,get:function(){return e.calculateBaseline}})})(rn);var an={},At={},Lt={},Pt={};Object.defineProperty(Pt,"__esModule",{value:!0}),Pt.isContentEditable=Cs;function Cs(n){return n.contentEditable==="true"}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isContentEditable=void 0;var e=Pt;Object.defineProperty(n,"isContentEditable",{enumerable:!0,get:function(){return e.isContentEditable}})})(Lt),Object.defineProperty(At,"__esModule",{value:!0}),At.canSetCaret=Is;var Ts=ue,Ss=Lt;function Is(n){var e=!0;if((0,Ts.isNativeInput)(n))switch(n.type){case"file":case"checkbox":case"radio":case"hidden":case"submit":case"button":case"image":case"reset":e=!1;break}else e=(0,Ss.isContentEditable)(n);return e}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.canSetCaret=void 0;var e=At;Object.defineProperty(n,"canSetCaret",{enumerable:!0,get:function(){return e.canSetCaret}})})(an);var We={},Nt={};function Os(n,e,t){const o=t.value!==void 0?"value":"get",i=t[o],s=`#${e}Cache`;if(t[o]=function(...r){return this[s]===void 0&&(this[s]=i.apply(this,r)),this[s]},o==="get"&&t.set){const r=t.set;t.set=function(a){delete n[s],r.apply(this,a)}}return t}function ln(){const n={win:!1,mac:!1,x11:!1,linux:!1},e=Object.keys(n).find(t=>window.navigator.appVersion.toLowerCase().indexOf(t)!==-1);return e!==void 0&&(n[e]=!0),n}function Rt(n){return n!=null&&n!==""&&(typeof n!="object"||Object.keys(n).length>0)}function _s(n){return!Rt(n)}const Ms=()=>typeof window<"u"&&window.navigator!==null&&Rt(window.navigator.platform)&&(/iP(ad|hone|od)/.test(window.navigator.platform)||window.navigator.platform==="MacIntel"&&window.navigator.maxTouchPoints>1);function As(n){const e=ln();return n=n.replace(/shift/gi,"⇧").replace(/backspace/gi,"⌫").replace(/enter/gi,"⏎").replace(/up/gi,"↑").replace(/left/gi,"→").replace(/down/gi,"↓").replace(/right/gi,"←").replace(/escape/gi,"⎋").replace(/insert/gi,"Ins").replace(/delete/gi,"␡").replace(/\+/gi,"+"),e.mac?n=n.replace(/ctrl|cmd/gi,"⌘").replace(/alt/gi,"⌥"):n=n.replace(/cmd/gi,"Ctrl").replace(/windows/gi,"WIN"),n}function Ls(n){return n[0].toUpperCase()+n.slice(1)}function Ps(n){const e=document.createElement("div");e.style.position="absolute",e.style.left="-999px",e.style.bottom="-999px",e.innerHTML=n,document.body.appendChild(e);const t=window.getSelection(),o=document.createRange();if(o.selectNode(e),t===null)throw new Error("Cannot copy text to clipboard");t.removeAllRanges(),t.addRange(o),document.execCommand("copy"),document.body.removeChild(e)}function Ns(n,e,t){let o;return(...i)=>{const s=this,r=()=>{o=void 0,t!==!0&&n.apply(s,i)},a=t===!0&&o!==void 0;window.clearTimeout(o),o=window.setTimeout(r,e),a&&n.apply(s,i)}}function se(n){return Object.prototype.toString.call(n).match(/\s([a-zA-Z]+)/)[1].toLowerCase()}function Rs(n){return se(n)==="boolean"}function cn(n){return se(n)==="function"||se(n)==="asyncfunction"}function Ds(n){return cn(n)&&/^\s*class\s+/.test(n.toString())}function Fs(n){return se(n)==="number"}function Ye(n){return se(n)==="object"}function js(n){return Promise.resolve(n)===n}function Hs(n){return se(n)==="string"}function $s(n){return se(n)==="undefined"}function Dt(n,...e){if(!e.length)return n;const t=e.shift();if(Ye(n)&&Ye(t))for(const o in t)Ye(t[o])?(n[o]===void 0&&Object.assign(n,{[o]:{}}),Dt(n[o],t[o])):Object.assign(n,{[o]:t[o]});return Dt(n,...e)}function zs(n,e,t){const o=`«${e}» is deprecated and will be removed in the next major release. Please use the «${t}» instead.`;n&&console.warn(o)}function Us(n){try{return new URL(n).href}catch{}return n.substring(0,2)==="//"?window.location.protocol+n:window.location.origin+n}function Ws(n){return n>47&&n<58||n===32||n===13||n===229||n>64&&n<91||n>95&&n<112||n>185&&n<193||n>218&&n<223}const Ys={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,LEFT:37,UP:38,DOWN:40,RIGHT:39,DELETE:46,META:91,SLASH:191},Ks={LEFT:0,WHEEL:1,RIGHT:2,BACKWARD:3,FORWARD:4};let Xs=class{constructor(){this.completed=Promise.resolve()}add(e){return new Promise((t,o)=>{this.completed=this.completed.then(e).then(t).catch(o)})}};function Vs(n,e,t=void 0){let o,i,s,r=null,a=0;t||(t={});const l=function(){a=t.leading===!1?0:Date.now(),r=null,s=n.apply(o,i),r===null&&(o=i=null)};return function(){const c=Date.now();!a&&t.leading===!1&&(a=c);const u=e-(c-a);return o=this,i=arguments,u<=0||u>e?(r&&(clearTimeout(r),r=null),a=c,s=n.apply(o,i),r===null&&(o=i=null)):!r&&t.trailing!==!1&&(r=setTimeout(l,u)),s}}const Ft=Yn(Object.freeze(Object.defineProperty({__proto__:null,PromiseQueue:Xs,beautifyShortcut:As,cacheable:Os,capitalize:Ls,copyTextToClipboard:Ps,debounce:Ns,deepMerge:Dt,deprecationAssert:zs,getUserOS:ln,getValidUrl:Us,isBoolean:Rs,isClass:Ds,isEmpty:_s,isFunction:cn,isIosDevice:Ms,isNumber:Fs,isObject:Ye,isPrintableKey:Ws,isPromise:js,isString:Hs,isUndefined:$s,keyCodes:Ys,mouseButtons:Ks,notEmpty:Rt,throttle:Vs,typeOf:se},Symbol.toStringTag,{value:"Module"})));Object.defineProperty(Nt,"__esModule",{value:!0}),Nt.containsOnlyInlineElements=Gs;var qs=Ft,Zs=Ot;function Gs(n){var e;(0,qs.isString)(n)?(e=document.createElement("div"),e.innerHTML=n):e=n;var t=function(o){return!(0,Zs.blockElements)().includes(o.tagName.toLowerCase())&&Array.from(o.children).every(t)};return Array.from(e.children).every(t)}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.containsOnlyInlineElements=void 0;var e=Nt;Object.defineProperty(n,"containsOnlyInlineElements",{enumerable:!0,get:function(){return e.containsOnlyInlineElements}})})(We);var dn={},jt={},Ke={},Ht={};Object.defineProperty(Ht,"__esModule",{value:!0}),Ht.make=Js;function Js(n,e,t){var o;e===void 0&&(e=null),t===void 0&&(t={});var i=document.createElement(n);if(Array.isArray(e)){var s=e.filter(function(a){return a!==void 0});(o=i.classList).add.apply(o,s)}else e!==null&&i.classList.add(e);for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(i[r]=t[r]);return i}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.make=void 0;var e=Ht;Object.defineProperty(n,"make",{enumerable:!0,get:function(){return e.make}})})(Ke),Object.defineProperty(jt,"__esModule",{value:!0}),jt.fragmentToString=er;var Qs=Ke;function er(n){var e=(0,Qs.make)("div");return e.appendChild(n),e.innerHTML}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.fragmentToString=void 0;var e=jt;Object.defineProperty(n,"fragmentToString",{enumerable:!0,get:function(){return e.fragmentToString}})})(dn);var un={},$t={};Object.defineProperty($t,"__esModule",{value:!0}),$t.getContentLength=or;var tr=ue;function or(n){var e,t;return(0,tr.isNativeInput)(n)?n.value.length:n.nodeType===Node.TEXT_NODE?n.length:(t=(e=n.textContent)===null||e===void 0?void 0:e.length)!==null&&t!==void 0?t:0}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.getContentLength=void 0;var e=$t;Object.defineProperty(n,"getContentLength",{enumerable:!0,get:function(){return e.getContentLength}})})(un);var zt={},Ut={},hn=J&&J.__spreadArray||function(n,e,t){if(t||arguments.length===2)for(var o=0,i=e.length,s;o0;){var o=t.shift();if(o){if(n=o,(0,xr.isLeaf)(n)&&!(0,Br.isNodeEmpty)(n,e))return!1;t.push.apply(t,Array.from(n.childNodes))}}return!0}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isEmpty=void 0;var e=Gt;Object.defineProperty(n,"isEmpty",{enumerable:!0,get:function(){return e.isEmpty}})})(vn);var kn={},oo={};Object.defineProperty(oo,"__esModule",{value:!0}),oo.isFragment=Sr;var Tr=Ft;function Sr(n){return(0,Tr.isNumber)(n)?!1:!!n&&!!n.nodeType&&n.nodeType===Node.DOCUMENT_FRAGMENT_NODE}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isFragment=void 0;var e=oo;Object.defineProperty(n,"isFragment",{enumerable:!0,get:function(){return e.isFragment}})})(kn);var yn={},no={};Object.defineProperty(no,"__esModule",{value:!0}),no.isHTMLString=Or;var Ir=Ke;function Or(n){var e=(0,Ir.make)("div");return e.innerHTML=n,e.childElementCount>0}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isHTMLString=void 0;var e=no;Object.defineProperty(n,"isHTMLString",{enumerable:!0,get:function(){return e.isHTMLString}})})(yn);var wn={},io={};Object.defineProperty(io,"__esModule",{value:!0}),io.offset=_r;function _r(n){var e=n.getBoundingClientRect(),t=window.pageXOffset||document.documentElement.scrollLeft,o=window.pageYOffset||document.documentElement.scrollTop,i=e.top+o,s=e.left+t;return{top:i,left:s,bottom:i+e.height,right:s+e.width}}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.offset=void 0;var e=io;Object.defineProperty(n,"offset",{enumerable:!0,get:function(){return e.offset}})})(wn);var En={},so={};Object.defineProperty(so,"__esModule",{value:!0}),so.prepend=Mr;function Mr(n,e){Array.isArray(e)?(e=e.reverse(),e.forEach(function(t){return n.prepend(t)})):n.prepend(e)}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.prepend=void 0;var e=so;Object.defineProperty(n,"prepend",{enumerable:!0,get:function(){return e.prepend}})})(En),function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.prepend=n.offset=n.make=n.isLineBreakTag=n.isSingleTag=n.isNodeEmpty=n.isLeaf=n.isHTMLString=n.isFragment=n.isEmpty=n.isElement=n.isContentEditable=n.isCollapsedWhitespaces=n.findAllInputs=n.isNativeInput=n.allInputsSelector=n.getDeepestNode=n.getDeepestBlockElements=n.getContentLength=n.fragmentToString=n.containsOnlyInlineElements=n.canSetCaret=n.calculateBaseline=n.blockElements=n.append=void 0;var e=Ct;Object.defineProperty(n,"allInputsSelector",{enumerable:!0,get:function(){return e.allInputsSelector}});var t=ue;Object.defineProperty(n,"isNativeInput",{enumerable:!0,get:function(){return t.isNativeInput}});var o=sn;Object.defineProperty(n,"append",{enumerable:!0,get:function(){return o.append}});var i=Ot;Object.defineProperty(n,"blockElements",{enumerable:!0,get:function(){return i.blockElements}});var s=rn;Object.defineProperty(n,"calculateBaseline",{enumerable:!0,get:function(){return s.calculateBaseline}});var r=an;Object.defineProperty(n,"canSetCaret",{enumerable:!0,get:function(){return r.canSetCaret}});var a=We;Object.defineProperty(n,"containsOnlyInlineElements",{enumerable:!0,get:function(){return a.containsOnlyInlineElements}});var l=dn;Object.defineProperty(n,"fragmentToString",{enumerable:!0,get:function(){return l.fragmentToString}});var c=un;Object.defineProperty(n,"getContentLength",{enumerable:!0,get:function(){return c.getContentLength}});var u=zt;Object.defineProperty(n,"getDeepestBlockElements",{enumerable:!0,get:function(){return u.getDeepestBlockElements}});var h=fn;Object.defineProperty(n,"getDeepestNode",{enumerable:!0,get:function(){return h.getDeepestNode}});var p=mn;Object.defineProperty(n,"findAllInputs",{enumerable:!0,get:function(){return p.findAllInputs}});var g=bn;Object.defineProperty(n,"isCollapsedWhitespaces",{enumerable:!0,get:function(){return g.isCollapsedWhitespaces}});var f=Lt;Object.defineProperty(n,"isContentEditable",{enumerable:!0,get:function(){return f.isContentEditable}});var v=qt;Object.defineProperty(n,"isElement",{enumerable:!0,get:function(){return v.isElement}});var O=vn;Object.defineProperty(n,"isEmpty",{enumerable:!0,get:function(){return O.isEmpty}});var S=kn;Object.defineProperty(n,"isFragment",{enumerable:!0,get:function(){return S.isFragment}});var A=yn;Object.defineProperty(n,"isHTMLString",{enumerable:!0,get:function(){return A.isHTMLString}});var G=Jt;Object.defineProperty(n,"isLeaf",{enumerable:!0,get:function(){return G.isLeaf}});var j=eo;Object.defineProperty(n,"isNodeEmpty",{enumerable:!0,get:function(){return j.isNodeEmpty}});var U=Xe;Object.defineProperty(n,"isLineBreakTag",{enumerable:!0,get:function(){return U.isLineBreakTag}});var oe=Ve;Object.defineProperty(n,"isSingleTag",{enumerable:!0,get:function(){return oe.isSingleTag}});var he=Ke;Object.defineProperty(n,"make",{enumerable:!0,get:function(){return he.make}});var k=wn;Object.defineProperty(n,"offset",{enumerable:!0,get:function(){return k.offset}});var m=En;Object.defineProperty(n,"prepend",{enumerable:!0,get:function(){return m.prepend}})}(de);var Ze={};Object.defineProperty(Ze,"__esModule",{value:!0}),Ze.getContenteditableSlice=Lr;var Ar=de;function Lr(n,e,t,o,i){var s;i===void 0&&(i=!1);var r=document.createRange();if(o==="left"?(r.setStart(n,0),r.setEnd(e,t)):(r.setStart(e,t),r.setEnd(n,n.childNodes.length)),i===!0){var a=r.extractContents();return(0,Ar.fragmentToString)(a)}var l=r.cloneContents(),c=document.createElement("div");c.appendChild(l);var u=(s=c.textContent)!==null&&s!==void 0?s:"";return u}Object.defineProperty(Ue,"__esModule",{value:!0}),Ue.checkContenteditableSliceForEmptiness=Rr;var Pr=de,Nr=Ze;function Rr(n,e,t,o){var i=(0,Nr.getContenteditableSlice)(n,e,t,o);return(0,Pr.isCollapsedWhitespaces)(i)}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.checkContenteditableSliceForEmptiness=void 0;var e=Ue;Object.defineProperty(n,"checkContenteditableSliceForEmptiness",{enumerable:!0,get:function(){return e.checkContenteditableSliceForEmptiness}})})(Bt);var xn={};(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.getContenteditableSlice=void 0;var e=Ze;Object.defineProperty(n,"getContenteditableSlice",{enumerable:!0,get:function(){return e.getContenteditableSlice}})})(xn);var Bn={},ro={};Object.defineProperty(ro,"__esModule",{value:!0}),ro.focus=Fr;var Dr=de;function Fr(n,e){var t,o;if(e===void 0&&(e=!0),(0,Dr.isNativeInput)(n)){n.focus();var i=e?0:n.value.length;n.setSelectionRange(i,i)}else{var s=document.createRange(),r=window.getSelection();if(!r)return;var a=function(p){var g=document.createTextNode("");p.appendChild(g),s.setStart(g,0),s.setEnd(g,0)},l=function(p){return p!=null},c=n.childNodes,u=e?c[0]:c[c.length-1];if(l(u)){for(;l(u)&&u.nodeType!==Node.TEXT_NODE;)u=e?u.firstChild:u.lastChild;if(l(u)&&u.nodeType===Node.TEXT_NODE){var h=(o=(t=u.textContent)===null||t===void 0?void 0:t.length)!==null&&o!==void 0?o:0,i=e?0:h;s.setStart(u,i),s.setEnd(u,i)}else a(n)}else a(n);r.removeAllRanges(),r.addRange(s)}}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.focus=void 0;var e=ro;Object.defineProperty(n,"focus",{enumerable:!0,get:function(){return e.focus}})})(Bn);var ao={},Ge={};Object.defineProperty(Ge,"__esModule",{value:!0}),Ge.getCaretNodeAndOffset=jr;function jr(){var n=window.getSelection();if(n===null)return[null,0];var e=n.focusNode,t=n.focusOffset;return e===null?[null,0]:(e.nodeType!==Node.TEXT_NODE&&e.childNodes.length>0&&(e.childNodes[t]!==void 0?(e=e.childNodes[t],t=0):(e=e.childNodes[t-1],e.textContent!==null&&(t=e.textContent.length))),[e,t])}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.getCaretNodeAndOffset=void 0;var e=Ge;Object.defineProperty(n,"getCaretNodeAndOffset",{enumerable:!0,get:function(){return e.getCaretNodeAndOffset}})})(ao);var Cn={},Je={};Object.defineProperty(Je,"__esModule",{value:!0}),Je.getRange=Hr;function Hr(){var n=window.getSelection();return n&&n.rangeCount?n.getRangeAt(0):null}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.getRange=void 0;var e=Je;Object.defineProperty(n,"getRange",{enumerable:!0,get:function(){return e.getRange}})})(Cn);var Tn={},lo={};Object.defineProperty(lo,"__esModule",{value:!0}),lo.isCaretAtEndOfInput=Ur;var Sn=de,$r=ao,zr=Bt;function Ur(n){var e=(0,Sn.getDeepestNode)(n,!0);if(e===null)return!0;if((0,Sn.isNativeInput)(e))return e.selectionEnd===e.value.length;var t=(0,$r.getCaretNodeAndOffset)(),o=t[0],i=t[1];return o===null?!1:(0,zr.checkContenteditableSliceForEmptiness)(n,o,i,"right")}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isCaretAtEndOfInput=void 0;var e=lo;Object.defineProperty(n,"isCaretAtEndOfInput",{enumerable:!0,get:function(){return e.isCaretAtEndOfInput}})})(Tn);var In={},co={};Object.defineProperty(co,"__esModule",{value:!0}),co.isCaretAtStartOfInput=Kr;var Qe=de,Wr=Ge,Yr=Ue;function Kr(n){var e=(0,Qe.getDeepestNode)(n);if(e===null||(0,Qe.isEmpty)(n))return!0;if((0,Qe.isNativeInput)(e))return e.selectionEnd===0;if((0,Qe.isEmpty)(n))return!0;var t=(0,Wr.getCaretNodeAndOffset)(),o=t[0],i=t[1];return o===null?!1:(0,Yr.checkContenteditableSliceForEmptiness)(n,o,i,"left")}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isCaretAtStartOfInput=void 0;var e=co;Object.defineProperty(n,"isCaretAtStartOfInput",{enumerable:!0,get:function(){return e.isCaretAtStartOfInput}})})(In);var On={},uo={};Object.defineProperty(uo,"__esModule",{value:!0}),uo.save=qr;var Xr=de,Vr=Je;function qr(){var n=(0,Vr.getRange)(),e=(0,Xr.make)("span");if(e.id="cursor",e.hidden=!0,!!n)return n.insertNode(e),function(){var o=window.getSelection();o&&(n.setStartAfter(e),n.setEndAfter(e),o.removeAllRanges(),o.addRange(n),setTimeout(function(){e.remove()},150))}}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.save=void 0;var e=uo;Object.defineProperty(n,"save",{enumerable:!0,get:function(){return e.save}})})(On),function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.save=n.isCaretAtStartOfInput=n.isCaretAtEndOfInput=n.getRange=n.getCaretNodeAndOffset=n.focus=n.getContenteditableSlice=n.checkContenteditableSliceForEmptiness=void 0;var e=Bt;Object.defineProperty(n,"checkContenteditableSliceForEmptiness",{enumerable:!0,get:function(){return e.checkContenteditableSliceForEmptiness}});var t=xn;Object.defineProperty(n,"getContenteditableSlice",{enumerable:!0,get:function(){return t.getContenteditableSlice}});var o=Bn;Object.defineProperty(n,"focus",{enumerable:!0,get:function(){return o.focus}});var i=ao;Object.defineProperty(n,"getCaretNodeAndOffset",{enumerable:!0,get:function(){return i.getCaretNodeAndOffset}});var s=Cn;Object.defineProperty(n,"getRange",{enumerable:!0,get:function(){return s.getRange}});var r=Tn;Object.defineProperty(n,"isCaretAtEndOfInput",{enumerable:!0,get:function(){return r.isCaretAtEndOfInput}});var a=In;Object.defineProperty(n,"isCaretAtStartOfInput",{enumerable:!0,get:function(){return a.isCaretAtStartOfInput}});var l=On;Object.defineProperty(n,"save",{enumerable:!0,get:function(){return l.save}})}(nn);class Zr extends E{keydown(e){switch(this.beforeKeydownProcessing(e),e.keyCode){case y.BACKSPACE:this.backspace(e);break;case y.DELETE:this.delete(e);break;case y.ENTER:this.enter(e);break;case y.DOWN:case y.RIGHT:this.arrowRightAndDown(e);break;case y.UP:case y.LEFT:this.arrowLeftAndUp(e);break;case y.TAB:this.tabPressed(e);break}e.key==="/"&&!e.ctrlKey&&!e.metaKey&&this.slashPressed(e),e.code==="Slash"&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),this.commandSlashPressed())}beforeKeydownProcessing(e){this.needToolbarClosing(e)&&Eo(e.keyCode)&&(this.Editor.Toolbar.close(),e.ctrlKey||e.metaKey||e.altKey||e.shiftKey||this.Editor.BlockSelection.clearSelection(e))}keyup(e){e.shiftKey||this.Editor.UI.checkEmptiness()}dragOver(e){const t=this.Editor.BlockManager.getBlockByChildNode(e.target);t.dropTarget=!0}dragLeave(e){const t=this.Editor.BlockManager.getBlockByChildNode(e.target);t.dropTarget=!1}handleCommandC(e){const{BlockSelection:t}=this.Editor;t.anyBlockSelected&&t.copySelectedBlocks(e)}handleCommandX(e){const{BlockSelection:t,BlockManager:o,Caret:i}=this.Editor;t.anyBlockSelected&&t.copySelectedBlocks(e).then(()=>{const s=o.removeSelectedBlocks(),r=o.insertDefaultBlockAtIndex(s,!0);i.setToBlock(r,i.positions.START),t.clearSelection(e)})}tabPressed(e){const{InlineToolbar:t,Caret:o}=this.Editor;if(t.opened)return;(e.shiftKey?o.navigatePrevious(!0):o.navigateNext(!0))&&e.preventDefault()}commandSlashPressed(){this.Editor.BlockSelection.selectedBlocks.length>1||this.activateBlockSettings()}slashPressed(e){!this.Editor.UI.nodes.wrapper.contains(e.target)||!this.Editor.BlockManager.currentBlock.isEmpty||(e.preventDefault(),this.Editor.Caret.insertContentAtCaretPosition("/"),this.activateToolbox())}enter(e){const{BlockManager:t,UI:o}=this.Editor,i=t.currentBlock;if(i===void 0||i.tool.isLineBreaksEnabled||o.someToolbarOpened&&o.someFlipperButtonFocused||e.shiftKey&&!rt)return;let s=i;i.currentInput!==void 0&&$e(i.currentInput)&&!i.hasMedia?this.Editor.BlockManager.insertDefaultBlockAtIndex(this.Editor.BlockManager.currentBlockIndex):i.currentInput&&ze(i.currentInput)?s=this.Editor.BlockManager.insertDefaultBlockAtIndex(this.Editor.BlockManager.currentBlockIndex+1):s=this.Editor.BlockManager.split(),this.Editor.Caret.setToBlock(s),this.Editor.Toolbar.moveAndOpen(s),e.preventDefault()}backspace(e){const{BlockManager:t,Caret:o}=this.Editor,{currentBlock:i,previousBlock:s}=t;if(i===void 0||!b.isCollapsed||!i.currentInput||!$e(i.currentInput))return;if(e.preventDefault(),this.Editor.Toolbar.close(),!(i.currentInput===i.firstInput)){o.navigatePrevious();return}if(s===null)return;if(s.isEmpty){t.removeBlock(s);return}if(i.isEmpty){t.removeBlock(i);const l=t.currentBlock;o.setToBlock(l,o.positions.END);return}No(s,i)?this.mergeBlocks(s,i):o.setToBlock(s,o.positions.END)}delete(e){const{BlockManager:t,Caret:o}=this.Editor,{currentBlock:i,nextBlock:s}=t;if(!b.isCollapsed||!ze(i.currentInput))return;if(e.preventDefault(),this.Editor.Toolbar.close(),!(i.currentInput===i.lastInput)){o.navigateNext();return}if(s===null)return;if(s.isEmpty){t.removeBlock(s);return}if(i.isEmpty){t.removeBlock(i),o.setToBlock(s,o.positions.START);return}No(i,s)?this.mergeBlocks(i,s):o.setToBlock(s,o.positions.START)}mergeBlocks(e,t){const{BlockManager:o,Toolbar:i}=this.Editor;e.lastInput!==void 0&&(nn.focus(e.lastInput,!1),o.mergeBlocks(e,t).then(()=>{i.close()}))}arrowRightAndDown(e){const t=ae.usedKeys.includes(e.keyCode)&&(!e.shiftKey||e.keyCode===y.TAB);if(this.Editor.UI.someToolbarOpened&&t)return;this.Editor.Toolbar.close();const{currentBlock:o}=this.Editor.BlockManager,s=((o==null?void 0:o.currentInput)!==void 0?ze(o.currentInput):void 0)||this.Editor.BlockSelection.anyBlockSelected;if(e.shiftKey&&e.keyCode===y.DOWN&&s){this.Editor.CrossBlockSelection.toggleBlockSelectedState();return}if(e.keyCode===y.DOWN||e.keyCode===y.RIGHT&&!this.isRtl?this.Editor.Caret.navigateNext():this.Editor.Caret.navigatePrevious()){e.preventDefault();return}Ae(()=>{this.Editor.BlockManager.currentBlock&&this.Editor.BlockManager.currentBlock.updateCurrentInput()},20)(),this.Editor.BlockSelection.clearSelection(e)}arrowLeftAndUp(e){if(this.Editor.UI.someToolbarOpened){if(ae.usedKeys.includes(e.keyCode)&&(!e.shiftKey||e.keyCode===y.TAB))return;this.Editor.UI.closeAllToolbars()}this.Editor.Toolbar.close();const{currentBlock:t}=this.Editor.BlockManager,i=((t==null?void 0:t.currentInput)!==void 0?$e(t.currentInput):void 0)||this.Editor.BlockSelection.anyBlockSelected;if(e.shiftKey&&e.keyCode===y.UP&&i){this.Editor.CrossBlockSelection.toggleBlockSelectedState(!1);return}if(e.keyCode===y.UP||e.keyCode===y.LEFT&&!this.isRtl?this.Editor.Caret.navigatePrevious():this.Editor.Caret.navigateNext()){e.preventDefault();return}Ae(()=>{this.Editor.BlockManager.currentBlock&&this.Editor.BlockManager.currentBlock.updateCurrentInput()},20)(),this.Editor.BlockSelection.clearSelection(e)}needToolbarClosing(e){const t=e.keyCode===y.ENTER&&this.Editor.Toolbar.toolbox.opened,o=e.keyCode===y.ENTER&&this.Editor.BlockSettings.opened,i=e.keyCode===y.ENTER&&this.Editor.InlineToolbar.opened,s=e.keyCode===y.TAB;return!(e.shiftKey||s||t||o||i)}activateToolbox(){this.Editor.Toolbar.opened||this.Editor.Toolbar.moveAndOpen(),this.Editor.Toolbar.toolbox.open()}activateBlockSettings(){this.Editor.Toolbar.opened||this.Editor.Toolbar.moveAndOpen(),this.Editor.BlockSettings.opened||this.Editor.BlockSettings.open()}}class ho{constructor(e){this.blocks=[],this.workingArea=e}get length(){return this.blocks.length}get array(){return this.blocks}get nodes(){return xo(this.workingArea.children)}static set(e,t,o){return isNaN(Number(t))?(Reflect.set(e,t,o),!0):(e.insert(+t,o),!0)}static get(e,t){return isNaN(Number(t))?Reflect.get(e,t):e.get(+t)}push(e){this.blocks.push(e),this.insertToDOM(e)}swap(e,t){const o=this.blocks[t];d.swap(this.blocks[e].holder,o.holder),this.blocks[t]=this.blocks[e],this.blocks[e]=o}move(e,t){const o=this.blocks.splice(t,1)[0],i=e-1,s=Math.max(0,i),r=this.blocks[s];e>0?this.insertToDOM(o,"afterend",r):this.insertToDOM(o,"beforebegin",r),this.blocks.splice(e,0,o);const a=this.composeBlockEvent("move",{fromIndex:t,toIndex:e});o.call(te.MOVED,a)}insert(e,t,o=!1){if(!this.length){this.push(t);return}e>this.length&&(e=this.length),o&&(this.blocks[e].holder.remove(),this.blocks[e].call(te.REMOVED));const i=o?1:0;if(this.blocks.splice(e,i,t),e>0){const s=this.blocks[e-1];this.insertToDOM(t,"afterend",s)}else{const s=this.blocks[e+1];s?this.insertToDOM(t,"beforebegin",s):this.insertToDOM(t)}}replace(e,t){if(this.blocks[e]===void 0)throw Error("Incorrect index");this.blocks[e].holder.replaceWith(t.holder),this.blocks[e]=t}insertMany(e,t){const o=new DocumentFragment;for(const i of e)o.appendChild(i.holder);if(this.length>0){if(t>0){const i=Math.min(t-1,this.length-1);this.blocks[i].holder.after(o)}else t===0&&this.workingArea.prepend(o);this.blocks.splice(t,0,...e)}else this.blocks.push(...e),this.workingArea.appendChild(o);e.forEach(i=>i.call(te.RENDERED))}remove(e){isNaN(e)&&(e=this.length-1),this.blocks[e].holder.remove(),this.blocks[e].call(te.REMOVED),this.blocks.splice(e,1)}removeAll(){this.workingArea.innerHTML="",this.blocks.forEach(e=>e.call(te.REMOVED)),this.blocks.length=0}insertAfter(e,t){const o=this.blocks.indexOf(e);this.insert(o+1,t)}get(e){return this.blocks[e]}indexOf(e){return this.blocks.indexOf(e)}insertToDOM(e,t,o){t?o.holder.insertAdjacentElement(t,e.holder):this.workingArea.appendChild(e.holder),e.call(te.RENDERED)}composeBlockEvent(e,t){return new CustomEvent(e,{detail:t})}}const _n="block-removed",Mn="block-added",Gr="block-moved",An="block-changed";class Jr{constructor(){this.completed=Promise.resolve()}add(e){return new Promise((t,o)=>{this.completed=this.completed.then(e).then(t).catch(o)})}}class Qr extends E{constructor(){super(...arguments),this._currentBlockIndex=-1,this._blocks=null}get currentBlockIndex(){return this._currentBlockIndex}set currentBlockIndex(e){this._currentBlockIndex=e}get firstBlock(){return this._blocks[0]}get lastBlock(){return this._blocks[this._blocks.length-1]}get currentBlock(){return this._blocks[this.currentBlockIndex]}set currentBlock(e){this.currentBlockIndex=this.getBlockIndex(e)}get nextBlock(){return this.currentBlockIndex===this._blocks.length-1?null:this._blocks[this.currentBlockIndex+1]}get nextContentfulBlock(){return this.blocks.slice(this.currentBlockIndex+1).find(t=>!!t.inputs.length)}get previousContentfulBlock(){return this.blocks.slice(0,this.currentBlockIndex).reverse().find(t=>!!t.inputs.length)}get previousBlock(){return this.currentBlockIndex===0?null:this._blocks[this.currentBlockIndex-1]}get blocks(){return this._blocks.array}get isEditorEmpty(){return this.blocks.every(e=>e.isEmpty)}prepare(){const e=new ho(this.Editor.UI.nodes.redactor);this._blocks=new Proxy(e,{set:ho.set,get:ho.get}),this.listeners.on(document,"copy",t=>this.Editor.BlockEvents.handleCommandC(t))}toggleReadOnly(e){e?this.disableModuleBindings():this.enableModuleBindings()}composeBlock({tool:e,data:t={},id:o=void 0,tunes:i={}}){const s=this.Editor.ReadOnly.isEnabled,r=this.Editor.Tools.blockTools.get(e),a=new R({id:o,data:t,tool:r,api:this.Editor.API,readOnly:s,tunesData:i},this.eventsDispatcher);return s||window.requestIdleCallback(()=>{this.bindBlockEvents(a)},{timeout:2e3}),a}insert({id:e=void 0,tool:t=this.config.defaultBlock,data:o={},index:i,needToFocus:s=!0,replace:r=!1,tunes:a={}}={}){let l=i;l===void 0&&(l=this.currentBlockIndex+(r?0:1));const c=this.composeBlock({id:e,tool:t,data:o,tunes:a});return r&&this.blockDidMutated(_n,this.getBlockByIndex(l),{index:l}),this._blocks.insert(l,c,r),this.blockDidMutated(Mn,c,{index:l}),s?this.currentBlockIndex=l:l<=this.currentBlockIndex&&this.currentBlockIndex++,c}insertMany(e,t=0){this._blocks.insertMany(e,t)}async update(e,t,o){if(!t&&!o)return e;const i=await e.data,s=this.composeBlock({id:e.id,tool:e.name,data:Object.assign({},i,t??{}),tunes:o??e.tunes}),r=this.getBlockIndex(e);return this._blocks.replace(r,s),this.blockDidMutated(An,s,{index:r}),s}replace(e,t,o){const i=this.getBlockIndex(e);return this.insert({tool:t,data:o,index:i,replace:!0})}paste(e,t,o=!1){const i=this.insert({tool:e,replace:o});try{window.requestIdleCallback(()=>{i.call(te.ON_PASTE,t)})}catch(s){T(`${e}: onPaste callback call is failed`,"error",s)}return i}insertDefaultBlockAtIndex(e,t=!1){const o=this.composeBlock({tool:this.config.defaultBlock});return this._blocks[e]=o,this.blockDidMutated(Mn,o,{index:e}),t?this.currentBlockIndex=e:e<=this.currentBlockIndex&&this.currentBlockIndex++,o}insertAtEnd(){return this.currentBlockIndex=this.blocks.length-1,this.insert()}async mergeBlocks(e,t){let o;if(e.name===t.name&&e.mergeable){const i=await t.data;if(V(i)){console.error("Could not merge Block. Failed to extract original Block data.");return}const[s]=dt([i],e.tool.sanitizeConfig);o=s}else if(e.mergeable&&Pe(t,"export")&&Pe(e,"import")){const i=await t.exportDataAsString(),s=q(i,e.tool.sanitizeConfig);o=Ro(s,e.tool.conversionConfig)}o!==void 0&&(await e.mergeWith(o),this.removeBlock(t),this.currentBlockIndex=this._blocks.indexOf(e))}removeBlock(e,t=!0){return new Promise(o=>{const i=this._blocks.indexOf(e);if(!this.validateIndex(i))throw new Error("Can't find a Block to remove");e.destroy(),this._blocks.remove(i),this.blockDidMutated(_n,e,{index:i}),this.currentBlockIndex>=i&&this.currentBlockIndex--,this.blocks.length?i===0&&(this.currentBlockIndex=0):(this.unsetCurrentBlock(),t&&this.insert()),o()})}removeSelectedBlocks(){let e;for(let t=this.blocks.length-1;t>=0;t--)this.blocks[t].selected&&(this.removeBlock(this.blocks[t]),e=t);return e}removeAllBlocks(){for(let e=this.blocks.length-1;e>=0;e--)this._blocks.remove(e);this.unsetCurrentBlock(),this.insert(),this.currentBlock.firstInput.focus()}split(){const e=this.Editor.Caret.extractFragmentFromCaretPosition(),t=d.make("div");t.appendChild(e);const o={text:d.isEmpty(t)?"":t.innerHTML};return this.insert({data:o})}getBlockByIndex(e){return e===-1&&(e=this._blocks.length-1),this._blocks[e]}getBlockIndex(e){return this._blocks.indexOf(e)}getBlockById(e){return this._blocks.array.find(t=>t.id===e)}getBlock(e){d.isElement(e)||(e=e.parentNode);const t=this._blocks.nodes,o=e.closest(`.${R.CSS.wrapper}`),i=t.indexOf(o);if(i>=0)return this._blocks[i]}setCurrentBlockByChildNode(e){d.isElement(e)||(e=e.parentNode);const t=e.closest(`.${R.CSS.wrapper}`);if(!t)return;const o=t.closest(`.${this.Editor.UI.CSS.editorWrapper}`);if(o!=null&&o.isEqualNode(this.Editor.UI.nodes.wrapper))return this.currentBlockIndex=this._blocks.nodes.indexOf(t),this.currentBlock.updateCurrentInput(),this.currentBlock}getBlockByChildNode(e){if(!e||!(e instanceof Node))return;d.isElement(e)||(e=e.parentNode);const t=e.closest(`.${R.CSS.wrapper}`);return this.blocks.find(o=>o.holder===t)}swap(e,t){this._blocks.swap(e,t),this.currentBlockIndex=t}move(e,t=this.currentBlockIndex){if(isNaN(e)||isNaN(t)){T("Warning during 'move' call: incorrect indices provided.","warn");return}if(!this.validateIndex(e)||!this.validateIndex(t)){T("Warning during 'move' call: indices cannot be lower than 0 or greater than the amount of blocks.","warn");return}this._blocks.move(e,t),this.currentBlockIndex=e,this.blockDidMutated(Gr,this.currentBlock,{fromIndex:t,toIndex:e})}async convert(e,t,o){if(!await e.save())throw new Error("Could not convert Block. Failed to extract original Block data.");const s=this.Editor.Tools.blockTools.get(t);if(!s)throw new Error(`Could not convert Block. Tool «${t}» not found.`);const r=await e.exportDataAsString(),a=q(r,s.sanitizeConfig);let l=Ro(a,s.conversionConfig,s.settings);return o&&(l=Object.assign(l,o)),this.replace(e,s.name,l)}unsetCurrentBlock(){this.currentBlockIndex=-1}async clear(e=!1){const t=new Jr;this.blocks.forEach(o=>{t.add(async()=>{await this.removeBlock(o,!1)})}),await t.completed,this.unsetCurrentBlock(),e&&this.insert(),this.Editor.UI.checkEmptiness()}async destroy(){await Promise.all(this.blocks.map(e=>e.destroy()))}bindBlockEvents(e){const{BlockEvents:t}=this.Editor;this.readOnlyMutableListeners.on(e.holder,"keydown",o=>{t.keydown(o)}),this.readOnlyMutableListeners.on(e.holder,"keyup",o=>{t.keyup(o)}),this.readOnlyMutableListeners.on(e.holder,"dragover",o=>{t.dragOver(o)}),this.readOnlyMutableListeners.on(e.holder,"dragleave",o=>{t.dragLeave(o)}),e.on("didMutated",o=>this.blockDidMutated(An,o,{index:this.getBlockIndex(o)}))}disableModuleBindings(){this.readOnlyMutableListeners.clearAll()}enableModuleBindings(){this.readOnlyMutableListeners.on(document,"cut",e=>this.Editor.BlockEvents.handleCommandX(e)),this.blocks.forEach(e=>{this.bindBlockEvents(e)})}validateIndex(e){return!(e<0||e>=this._blocks.length)}blockDidMutated(e,t,o){const i=new CustomEvent(e,{detail:{target:new ee(t),...o}});return this.eventsDispatcher.emit(_o,{event:i}),t}}class ea extends E{constructor(){super(...arguments),this.anyBlockSelectedCache=null,this.needToSelectAll=!1,this.nativeInputSelected=!1,this.readyToBlockSelection=!1}get sanitizerConfig(){return{p:{},h1:{},h2:{},h3:{},h4:{},h5:{},h6:{},ol:{},ul:{},li:{},br:!0,img:{src:!0,width:!0,height:!0},a:{href:!0},b:{},i:{},u:{}}}get allBlocksSelected(){const{BlockManager:e}=this.Editor;return e.blocks.every(t=>t.selected===!0)}set allBlocksSelected(e){const{BlockManager:t}=this.Editor;t.blocks.forEach(o=>{o.selected=e}),this.clearCache()}get anyBlockSelected(){const{BlockManager:e}=this.Editor;return this.anyBlockSelectedCache===null&&(this.anyBlockSelectedCache=e.blocks.some(t=>t.selected===!0)),this.anyBlockSelectedCache}get selectedBlocks(){return this.Editor.BlockManager.blocks.filter(e=>e.selected)}prepare(){this.selection=new b,be.add({name:"CMD+A",handler:e=>{const{BlockManager:t,ReadOnly:o}=this.Editor;if(o.isEnabled){e.preventDefault(),this.selectAllBlocks();return}t.currentBlock&&this.handleCommandA(e)},on:this.Editor.UI.nodes.redactor})}toggleReadOnly(){b.get().removeAllRanges(),this.allBlocksSelected=!1}unSelectBlockByIndex(e){const{BlockManager:t}=this.Editor;let o;isNaN(e)?o=t.currentBlock:o=t.getBlockByIndex(e),o.selected=!1,this.clearCache()}clearSelection(e,t=!1){const{BlockManager:o,Caret:i,RectangleSelection:s}=this.Editor;this.needToSelectAll=!1,this.nativeInputSelected=!1,this.readyToBlockSelection=!1;const r=e&&e instanceof KeyboardEvent,a=r&&Eo(e.keyCode);if(this.anyBlockSelected&&r&&a&&!b.isSelectionExists){const l=o.removeSelectedBlocks();o.insertDefaultBlockAtIndex(l,!0),i.setToBlock(o.currentBlock),Ae(()=>{const c=e.key;i.insertContentAtCaretPosition(c.length>1?"":c)},20)()}if(this.Editor.CrossBlockSelection.clear(e),!this.anyBlockSelected||s.isRectActivated()){this.Editor.RectangleSelection.clearSelection();return}t&&this.selection.restore(),this.allBlocksSelected=!1}copySelectedBlocks(e){e.preventDefault();const t=d.make("div");this.selectedBlocks.forEach(s=>{const r=q(s.holder.innerHTML,this.sanitizerConfig),a=d.make("p");a.innerHTML=r,t.appendChild(a)});const o=Array.from(t.childNodes).map(s=>s.textContent).join(` + +`),i=t.innerHTML;return e.clipboardData.setData("text/plain",o),e.clipboardData.setData("text/html",i),Promise.all(this.selectedBlocks.map(s=>s.save())).then(s=>{try{e.clipboardData.setData(this.Editor.Paste.MIME_TYPE,JSON.stringify(s))}catch{}})}selectBlockByIndex(e){const{BlockManager:t}=this.Editor,o=t.getBlockByIndex(e);o!==void 0&&this.selectBlock(o)}selectBlock(e){this.selection.save(),b.get().removeAllRanges(),e.selected=!0,this.clearCache(),this.Editor.InlineToolbar.close()}unselectBlock(e){e.selected=!1,this.clearCache()}clearCache(){this.anyBlockSelectedCache=null}destroy(){be.remove(this.Editor.UI.nodes.redactor,"CMD+A")}handleCommandA(e){if(this.Editor.RectangleSelection.clearSelection(),d.isNativeInput(e.target)&&!this.readyToBlockSelection){this.readyToBlockSelection=!0;return}const t=this.Editor.BlockManager.getBlock(e.target),o=t.inputs;if(o.length>1&&!this.readyToBlockSelection){this.readyToBlockSelection=!0;return}if(o.length===1&&!this.needToSelectAll){this.needToSelectAll=!0;return}this.needToSelectAll?(e.preventDefault(),this.selectAllBlocks(),this.needToSelectAll=!1,this.readyToBlockSelection=!1):this.readyToBlockSelection&&(e.preventDefault(),this.selectBlock(t),this.needToSelectAll=!0)}selectAllBlocks(){this.selection.save(),b.get().removeAllRanges(),this.allBlocksSelected=!0,this.Editor.InlineToolbar.close()}}class et extends E{get positions(){return{START:"start",END:"end",DEFAULT:"default"}}static get CSS(){return{shadowCaret:"cdx-shadow-caret"}}setToBlock(e,t=this.positions.DEFAULT,o=0){var c;const{BlockManager:i,BlockSelection:s}=this.Editor;if(s.clearSelection(),!e.focusable){(c=window.getSelection())==null||c.removeAllRanges(),s.selectBlock(e),i.currentBlock=e;return}let r;switch(t){case this.positions.START:r=e.firstInput;break;case this.positions.END:r=e.lastInput;break;default:r=e.currentInput}if(!r)return;const a=d.getDeepestNode(r,t===this.positions.END),l=d.getContentLength(a);switch(!0){case t===this.positions.START:o=0;break;case t===this.positions.END:case o>l:o=l;break}this.set(a,o),i.setCurrentBlockByChildNode(e.holder),i.currentBlock.currentInput=r}setToInput(e,t=this.positions.DEFAULT,o=0){const{currentBlock:i}=this.Editor.BlockManager,s=d.getDeepestNode(e);switch(t){case this.positions.START:this.set(s,0);break;case this.positions.END:this.set(s,d.getContentLength(s));break;default:o&&this.set(s,o)}i.currentInput=e}set(e,t=0){const{top:i,bottom:s}=b.setCursor(e,t),{innerHeight:r}=window;i<0?window.scrollBy(0,i-30):s>r&&window.scrollBy(0,s-r+30)}setToTheLastBlock(){const e=this.Editor.BlockManager.lastBlock;if(e)if(e.tool.isDefault&&e.isEmpty)this.setToBlock(e);else{const t=this.Editor.BlockManager.insertAtEnd();this.setToBlock(t)}}extractFragmentFromCaretPosition(){const e=b.get();if(e.rangeCount){const t=e.getRangeAt(0),o=this.Editor.BlockManager.currentBlock.currentInput;if(t.deleteContents(),o)if(d.isNativeInput(o)){const i=o,s=document.createDocumentFragment(),r=i.value.substring(0,i.selectionStart),a=i.value.substring(i.selectionStart);return s.textContent=a,i.value=r,s}else{const i=t.cloneRange();return i.selectNodeContents(o),i.setStart(t.endContainer,t.endOffset),i.extractContents()}}}navigateNext(e=!1){const{BlockManager:t}=this.Editor,{currentBlock:o,nextBlock:i}=t;if(o===void 0)return!1;const{nextInput:s,currentInput:r}=o,a=r!==void 0?ze(r):void 0;let l=i;const c=e||a||!o.focusable;if(s&&c)return this.setToInput(s,this.positions.START),!0;if(l===null){if(o.tool.isDefault||!c)return!1;l=t.insertAtEnd()}return c?(this.setToBlock(l,this.positions.START),!0):!1}navigatePrevious(e=!1){const{currentBlock:t,previousBlock:o}=this.Editor.BlockManager;if(!t)return!1;const{previousInput:i,currentInput:s}=t,r=s!==void 0?$e(s):void 0,a=e||r||!t.focusable;return i&&a?(this.setToInput(i,this.positions.END),!0):o!==null&&a?(this.setToBlock(o,this.positions.END),!0):!1}createShadow(e){const t=document.createElement("span");t.classList.add(et.CSS.shadowCaret),e.insertAdjacentElement("beforeend",t)}restoreCaret(e){const t=e.querySelector(`.${et.CSS.shadowCaret}`);if(!t)return;new b().expandToTag(t);const i=document.createRange();i.selectNode(t),i.extractContents()}insertContentAtCaretPosition(e){const t=document.createDocumentFragment(),o=document.createElement("div"),i=b.get(),s=b.range;o.innerHTML=e,Array.from(o.childNodes).forEach(c=>t.appendChild(c)),t.childNodes.length===0&&t.appendChild(new Text);const r=t.lastChild;s.deleteContents(),s.insertNode(t);const a=document.createRange(),l=r.nodeType===Node.TEXT_NODE?r:r.firstChild;l!==null&&l.textContent!==null&&a.setStart(l,l.textContent.length),i.removeAllRanges(),i.addRange(a)}}class ta extends E{constructor(){super(...arguments),this.onMouseUp=()=>{this.listeners.off(document,"mouseover",this.onMouseOver),this.listeners.off(document,"mouseup",this.onMouseUp)},this.onMouseOver=e=>{const{BlockManager:t,BlockSelection:o}=this.Editor;if(e.relatedTarget===null&&e.target===null)return;const i=t.getBlockByChildNode(e.relatedTarget)||this.lastSelectedBlock,s=t.getBlockByChildNode(e.target);if(!(!i||!s)&&s!==i){if(i===this.firstSelectedBlock){b.get().removeAllRanges(),i.selected=!0,s.selected=!0,o.clearCache();return}if(s===this.firstSelectedBlock){i.selected=!1,s.selected=!1,o.clearCache();return}this.Editor.InlineToolbar.close(),this.toggleBlocksSelectedState(i,s),this.lastSelectedBlock=s}}}async prepare(){this.listeners.on(document,"mousedown",e=>{this.enableCrossBlockSelection(e)})}watchSelection(e){if(e.button!==Xn.LEFT)return;const{BlockManager:t}=this.Editor;this.firstSelectedBlock=t.getBlock(e.target),this.lastSelectedBlock=this.firstSelectedBlock,this.listeners.on(document,"mouseover",this.onMouseOver),this.listeners.on(document,"mouseup",this.onMouseUp)}get isCrossBlockSelectionStarted(){return!!this.firstSelectedBlock&&!!this.lastSelectedBlock&&this.firstSelectedBlock!==this.lastSelectedBlock}toggleBlockSelectedState(e=!0){const{BlockManager:t,BlockSelection:o}=this.Editor;this.lastSelectedBlock||(this.lastSelectedBlock=this.firstSelectedBlock=t.currentBlock),this.firstSelectedBlock===this.lastSelectedBlock&&(this.firstSelectedBlock.selected=!0,o.clearCache(),b.get().removeAllRanges());const i=t.blocks.indexOf(this.lastSelectedBlock)+(e?1:-1),s=t.blocks[i];s&&(this.lastSelectedBlock.selected!==s.selected?(s.selected=!0,o.clearCache()):(this.lastSelectedBlock.selected=!1,o.clearCache()),this.lastSelectedBlock=s,this.Editor.InlineToolbar.close(),s.holder.scrollIntoView({block:"nearest"}))}clear(e){const{BlockManager:t,BlockSelection:o,Caret:i}=this.Editor,s=t.blocks.indexOf(this.firstSelectedBlock),r=t.blocks.indexOf(this.lastSelectedBlock);if(o.anyBlockSelected&&s>-1&&r>-1&&e&&e instanceof KeyboardEvent)switch(e.keyCode){case y.DOWN:case y.RIGHT:i.setToBlock(t.blocks[Math.max(s,r)],i.positions.END);break;case y.UP:case y.LEFT:i.setToBlock(t.blocks[Math.min(s,r)],i.positions.START);break;default:i.setToBlock(t.blocks[Math.max(s,r)],i.positions.END)}this.firstSelectedBlock=this.lastSelectedBlock=null}enableCrossBlockSelection(e){const{UI:t}=this.Editor;b.isCollapsed||this.Editor.BlockSelection.clearSelection(e),t.nodes.redactor.contains(e.target)?this.watchSelection(e):this.Editor.BlockSelection.clearSelection(e)}toggleBlocksSelectedState(e,t){const{BlockManager:o,BlockSelection:i}=this.Editor,s=o.blocks.indexOf(e),r=o.blocks.indexOf(t),a=e.selected!==t.selected;for(let l=Math.min(s,r);l<=Math.max(s,r);l++){const c=o.blocks[l];c!==this.firstSelectedBlock&&c!==(a?e:t)&&(o.blocks[l].selected=!o.blocks[l].selected,i.clearCache())}}}class oa extends E{constructor(){super(...arguments),this.isStartedAtEditor=!1}toggleReadOnly(e){e?this.disableModuleBindings():this.enableModuleBindings()}enableModuleBindings(){const{UI:e}=this.Editor;this.readOnlyMutableListeners.on(e.nodes.holder,"drop",async t=>{await this.processDrop(t)},!0),this.readOnlyMutableListeners.on(e.nodes.holder,"dragstart",()=>{this.processDragStart()}),this.readOnlyMutableListeners.on(e.nodes.holder,"dragover",t=>{this.processDragOver(t)},!0)}disableModuleBindings(){this.readOnlyMutableListeners.clearAll()}async processDrop(e){const{BlockManager:t,Paste:o,Caret:i}=this.Editor;e.preventDefault(),t.blocks.forEach(r=>{r.dropTarget=!1}),b.isAtEditor&&!b.isCollapsed&&this.isStartedAtEditor&&document.execCommand("delete"),this.isStartedAtEditor=!1;const s=t.setCurrentBlockByChildNode(e.target);if(s)this.Editor.Caret.setToBlock(s,i.positions.END);else{const r=t.setCurrentBlockByChildNode(t.lastBlock.holder);this.Editor.Caret.setToBlock(r,i.positions.END)}await o.processDataTransfer(e.dataTransfer,!0)}processDragStart(){b.isAtEditor&&!b.isCollapsed&&(this.isStartedAtEditor=!0),this.Editor.InlineToolbar.close()}processDragOver(e){e.preventDefault()}}const na=180,ia=400;class sa extends E{constructor({config:e,eventsDispatcher:t}){super({config:e,eventsDispatcher:t}),this.disabled=!1,this.batchingTimeout=null,this.batchingOnChangeQueue=new Map,this.batchTime=ia,this.mutationObserver=new MutationObserver(o=>{this.redactorChanged(o)}),this.eventsDispatcher.on(_o,o=>{this.particularBlockChanged(o.event)}),this.eventsDispatcher.on(Mo,()=>{this.disable()}),this.eventsDispatcher.on(Ao,()=>{this.enable()})}enable(){this.mutationObserver.observe(this.Editor.UI.nodes.redactor,{childList:!0,subtree:!0,characterData:!0,attributes:!0}),this.disabled=!1}disable(){this.mutationObserver.disconnect(),this.disabled=!0}particularBlockChanged(e){this.disabled||!M(this.config.onChange)||(this.batchingOnChangeQueue.set(`block:${e.detail.target.id}:event:${e.type}`,e),this.batchingTimeout&&clearTimeout(this.batchingTimeout),this.batchingTimeout=setTimeout(()=>{let t;this.batchingOnChangeQueue.size===1?t=this.batchingOnChangeQueue.values().next().value:t=Array.from(this.batchingOnChangeQueue.values()),this.config.onChange&&this.config.onChange(this.Editor.API.methods,t),this.batchingOnChangeQueue.clear()},this.batchTime))}redactorChanged(e){this.eventsDispatcher.emit(at,{mutations:e})}}const Ln=class Wn extends E{constructor(){super(...arguments),this.MIME_TYPE="application/x-editor-js",this.toolsTags={},this.tagsByTool={},this.toolsPatterns=[],this.toolsFiles={},this.exceptionList=[],this.processTool=e=>{try{const t=e.create({},{},!1);if(e.pasteConfig===!1){this.exceptionList.push(e.name);return}if(!M(t.onPaste))return;this.getTagsConfig(e),this.getFilesConfig(e),this.getPatternsConfig(e)}catch(t){T(`Paste handling for «${e.name}» Tool hasn't been set up because of the error`,"warn",t)}},this.handlePasteEvent=async e=>{const{BlockManager:t,Toolbar:o}=this.Editor,i=t.setCurrentBlockByChildNode(e.target);!i||this.isNativeBehaviour(e.target)&&!e.clipboardData.types.includes("Files")||i&&this.exceptionList.includes(i.name)||(e.preventDefault(),this.processDataTransfer(e.clipboardData),o.close())}}async prepare(){this.processTools()}toggleReadOnly(e){e?this.unsetCallback():this.setCallback()}async processDataTransfer(e,t=!1){const{Tools:o}=this.Editor,i=e.types;if((i.includes?i.includes("Files"):i.contains("Files"))&&!V(this.toolsFiles)){await this.processFiles(e.files);return}const r=e.getData(this.MIME_TYPE),a=e.getData("text/plain");let l=e.getData("text/html");if(r)try{this.insertEditorJSData(JSON.parse(r));return}catch{}t&&a.trim()&&l.trim()&&(l="

            "+(l.trim()?l:a)+"

            ");const c=Object.keys(this.toolsTags).reduce((p,g)=>(p[g.toLowerCase()]=this.toolsTags[g].sanitizationConfig??{},p),{}),u=Object.assign({},c,o.getAllInlineToolsSanitizeConfig(),{br:{}}),h=q(l,u);!h.trim()||h.trim()===a||!d.isHTMLString(h)?await this.processText(a):await this.processText(h,!0)}async processText(e,t=!1){const{Caret:o,BlockManager:i}=this.Editor,s=t?this.processHTML(e):this.processPlain(e);if(!s.length)return;if(s.length===1){s[0].isBlock?this.processSingleBlock(s.pop()):this.processInlinePaste(s.pop());return}const a=i.currentBlock&&i.currentBlock.tool.isDefault&&i.currentBlock.isEmpty;s.map(async(l,c)=>this.insertBlock(l,c===0&&a)),i.currentBlock&&o.setToBlock(i.currentBlock,o.positions.END)}setCallback(){this.listeners.on(this.Editor.UI.nodes.holder,"paste",this.handlePasteEvent)}unsetCallback(){this.listeners.off(this.Editor.UI.nodes.holder,"paste",this.handlePasteEvent)}processTools(){const e=this.Editor.Tools.blockTools;Array.from(e.values()).forEach(this.processTool)}collectTagNames(e){return Q(e)?[e]:N(e)?Object.keys(e):[]}getTagsConfig(e){if(e.pasteConfig===!1)return;const t=e.pasteConfig.tags||[],o=[];t.forEach(i=>{const s=this.collectTagNames(i);o.push(...s),s.forEach(r=>{if(Object.prototype.hasOwnProperty.call(this.toolsTags,r)){T(`Paste handler for «${e.name}» Tool on «${r}» tag is skipped because it is already used by «${this.toolsTags[r].tool.name}» Tool.`,"warn");return}const a=N(i)?i[r]:null;this.toolsTags[r.toUpperCase()]={tool:e,sanitizationConfig:a}})}),this.tagsByTool[e.name]=o.map(i=>i.toUpperCase())}getFilesConfig(e){if(e.pasteConfig===!1)return;const{files:t={}}=e.pasteConfig;let{extensions:o,mimeTypes:i}=t;!o&&!i||(o&&!Array.isArray(o)&&(T(`«extensions» property of the onDrop config for «${e.name}» Tool should be an array`),o=[]),i&&!Array.isArray(i)&&(T(`«mimeTypes» property of the onDrop config for «${e.name}» Tool should be an array`),i=[]),i&&(i=i.filter(s=>Jn(s)?!0:(T(`MIME type value «${s}» for the «${e.name}» Tool is not a valid MIME type`,"warn"),!1))),this.toolsFiles[e.name]={extensions:o||[],mimeTypes:i||[]})}getPatternsConfig(e){e.pasteConfig===!1||!e.pasteConfig.patterns||V(e.pasteConfig.patterns)||Object.entries(e.pasteConfig.patterns).forEach(([t,o])=>{o instanceof RegExp||T(`Pattern ${o} for «${e.name}» Tool is skipped because it should be a Regexp instance.`,"warn"),this.toolsPatterns.push({key:t,pattern:o,tool:e})})}isNativeBehaviour(e){return d.isNativeInput(e)}async processFiles(e){const{BlockManager:t}=this.Editor;let o;o=await Promise.all(Array.from(e).map(r=>this.processFile(r))),o=o.filter(r=>!!r);const s=t.currentBlock.tool.isDefault&&t.currentBlock.isEmpty;o.forEach((r,a)=>{t.paste(r.type,r.event,a===0&&s)})}async processFile(e){const t=Gn(e),o=Object.entries(this.toolsFiles).find(([r,{mimeTypes:a,extensions:l}])=>{const[c,u]=e.type.split("/"),h=l.find(g=>g.toLowerCase()===t.toLowerCase()),p=a.find(g=>{const[f,v]=g.split("/");return f===c&&(v===u||v==="*")});return!!h||!!p});if(!o)return;const[i]=o;return{event:this.composePasteEvent("file",{file:e}),type:i}}processHTML(e){const{Tools:t}=this.Editor,o=d.make("DIV");return o.innerHTML=e,this.getNodes(o).map(s=>{let r,a=t.defaultTool,l=!1;switch(s.nodeType){case Node.DOCUMENT_FRAGMENT_NODE:r=d.make("div"),r.appendChild(s);break;case Node.ELEMENT_NODE:r=s,l=!0,this.toolsTags[r.tagName]&&(a=this.toolsTags[r.tagName].tool);break}const{tags:c}=a.pasteConfig||{tags:[]},u=c.reduce((g,f)=>(this.collectTagNames(f).forEach(O=>{const S=N(f)?f[O]:null;g[O.toLowerCase()]=S||{}}),g),{}),h=Object.assign({},u,a.baseSanitizeConfig);if(r.tagName.toLowerCase()==="table"){const g=q(r.outerHTML,h);r=d.make("div",void 0,{innerHTML:g}).firstChild}else r.innerHTML=q(r.innerHTML,h);const p=this.composePasteEvent("tag",{data:r});return{content:r,isBlock:l,tool:a.name,event:p}}).filter(s=>{const r=d.isEmpty(s.content),a=d.isSingleTag(s.content);return!r||a})}processPlain(e){const{defaultBlock:t}=this.config;if(!e)return[];const o=t;return e.split(/\r?\n/).filter(i=>i.trim()).map(i=>{const s=d.make("div");s.textContent=i;const r=this.composePasteEvent("tag",{data:s});return{content:s,tool:o,isBlock:!1,event:r}})}async processSingleBlock(e){const{Caret:t,BlockManager:o}=this.Editor,{currentBlock:i}=o;if(!i||e.tool!==i.name||!d.containsOnlyInlineElements(e.content.innerHTML)){this.insertBlock(e,(i==null?void 0:i.tool.isDefault)&&i.isEmpty);return}t.insertContentAtCaretPosition(e.content.innerHTML)}async processInlinePaste(e){const{BlockManager:t,Caret:o}=this.Editor,{content:i}=e;if(t.currentBlock&&t.currentBlock.tool.isDefault&&i.textContent.length{const s=i.pattern.exec(e);return s?e===s.shift():!1});return t?{event:this.composePasteEvent("pattern",{key:t.key,data:e}),tool:t.tool.name}:void 0}insertBlock(e,t=!1){const{BlockManager:o,Caret:i}=this.Editor,{currentBlock:s}=o;let r;if(t&&s&&s.isEmpty){r=o.paste(e.tool,e.event,!0),i.setToBlock(r,i.positions.END);return}r=o.paste(e.tool,e.event),i.setToBlock(r,i.positions.END)}insertEditorJSData(e){const{BlockManager:t,Caret:o,Tools:i}=this.Editor;dt(e,r=>i.blockTools.get(r).sanitizeConfig).forEach(({tool:r,data:a},l)=>{let c=!1;l===0&&(c=t.currentBlock&&t.currentBlock.tool.isDefault&&t.currentBlock.isEmpty);const u=t.insert({tool:r,data:a,replace:c});o.setToBlock(u,o.positions.END)})}processElementNode(e,t,o){const i=Object.keys(this.toolsTags),s=e,{tool:r}=this.toolsTags[s.tagName]||{},a=this.tagsByTool[r==null?void 0:r.name]||[],l=i.includes(s.tagName),c=d.blockElements.includes(s.tagName.toLowerCase()),u=Array.from(s.children).some(({tagName:p})=>i.includes(p)&&!a.includes(p)),h=Array.from(s.children).some(({tagName:p})=>d.blockElements.includes(p.toLowerCase()));if(!c&&!l&&!u)return o.appendChild(s),[...t,o];if(l&&!u||c&&!h&&!u)return[...t,o,s]}getNodes(e){const t=Array.from(e.childNodes);let o;const i=(s,r)=>{if(d.isEmpty(r)&&!d.isSingleTag(r))return s;const a=s[s.length-1];let l=new DocumentFragment;switch(a&&d.isFragment(a)&&(l=s.pop()),r.nodeType){case Node.ELEMENT_NODE:if(o=this.processElementNode(r,s,l),o)return o;break;case Node.TEXT_NODE:return l.appendChild(r),[...s,l];default:return[...s,l]}return[...s,...Array.from(r.childNodes).reduce(i,[])]};return t.reduce(i,[])}composePasteEvent(e,t){return new CustomEvent(e,{detail:t})}};Ln.PATTERN_PROCESSING_MAX_LENGTH=450;let ra=Ln;class aa extends E{constructor(){super(...arguments),this.toolsDontSupportReadOnly=[],this.readOnlyEnabled=!1}get isEnabled(){return this.readOnlyEnabled}async prepare(){const{Tools:e}=this.Editor,{blockTools:t}=e,o=[];Array.from(t.entries()).forEach(([i,s])=>{s.isReadOnlySupported||o.push(i)}),this.toolsDontSupportReadOnly=o,this.config.readOnly&&o.length>0&&this.throwCriticalError(),this.toggle(this.config.readOnly,!0)}async toggle(e=!this.readOnlyEnabled,t=!1){e&&this.toolsDontSupportReadOnly.length>0&&this.throwCriticalError();const o=this.readOnlyEnabled;this.readOnlyEnabled=e;for(const s in this.Editor)this.Editor[s].toggleReadOnly&&this.Editor[s].toggleReadOnly(e);if(o===e)return this.readOnlyEnabled;if(t)return this.readOnlyEnabled;this.Editor.ModificationsObserver.disable();const i=await this.Editor.Saver.save();return await this.Editor.BlockManager.clear(),await this.Editor.Renderer.render(i.blocks),this.Editor.ModificationsObserver.enable(),this.readOnlyEnabled}throwCriticalError(){throw new Oo(`To enable read-only mode all connected tools should support it. Tools ${this.toolsDontSupportReadOnly.join(", ")} don't support read-only mode.`)}}class Ie extends E{constructor(){super(...arguments),this.isRectSelectionActivated=!1,this.SCROLL_SPEED=3,this.HEIGHT_OF_SCROLL_ZONE=40,this.BOTTOM_SCROLL_ZONE=1,this.TOP_SCROLL_ZONE=2,this.MAIN_MOUSE_BUTTON=0,this.mousedown=!1,this.isScrolling=!1,this.inScrollZone=null,this.startX=0,this.startY=0,this.mouseX=0,this.mouseY=0,this.stackOfSelected=[],this.listenerIds=[]}static get CSS(){return{overlay:"codex-editor-overlay",overlayContainer:"codex-editor-overlay__container",rect:"codex-editor-overlay__rectangle",topScrollZone:"codex-editor-overlay__scroll-zone--top",bottomScrollZone:"codex-editor-overlay__scroll-zone--bottom"}}prepare(){this.enableModuleBindings()}startSelection(e,t){const o=document.elementFromPoint(e-window.pageXOffset,t-window.pageYOffset);o.closest(`.${this.Editor.Toolbar.CSS.toolbar}`)||(this.Editor.BlockSelection.allBlocksSelected=!1,this.clearSelection(),this.stackOfSelected=[]);const s=[`.${R.CSS.content}`,`.${this.Editor.Toolbar.CSS.toolbar}`,`.${this.Editor.InlineToolbar.CSS.inlineToolbar}`],r=o.closest("."+this.Editor.UI.CSS.editorWrapper),a=s.some(l=>!!o.closest(l));!r||a||(this.mousedown=!0,this.startX=e,this.startY=t)}endSelection(){this.mousedown=!1,this.startX=0,this.startY=0,this.overlayRectangle.style.display="none"}isRectActivated(){return this.isRectSelectionActivated}clearSelection(){this.isRectSelectionActivated=!1}enableModuleBindings(){const{container:e}=this.genHTML();this.listeners.on(e,"mousedown",t=>{this.processMouseDown(t)},!1),this.listeners.on(document.body,"mousemove",ot(t=>{this.processMouseMove(t)},10),{passive:!0}),this.listeners.on(document.body,"mouseleave",()=>{this.processMouseLeave()}),this.listeners.on(window,"scroll",ot(t=>{this.processScroll(t)},10),{passive:!0}),this.listeners.on(document.body,"mouseup",()=>{this.processMouseUp()},!1)}processMouseDown(e){if(e.button!==this.MAIN_MOUSE_BUTTON)return;e.target.closest(d.allInputsSelector)!==null||this.startSelection(e.pageX,e.pageY)}processMouseMove(e){this.changingRectangle(e),this.scrollByZones(e.clientY)}processMouseLeave(){this.clearSelection(),this.endSelection()}processScroll(e){this.changingRectangle(e)}processMouseUp(){this.clearSelection(),this.endSelection()}scrollByZones(e){if(this.inScrollZone=null,e<=this.HEIGHT_OF_SCROLL_ZONE&&(this.inScrollZone=this.TOP_SCROLL_ZONE),document.documentElement.clientHeight-e<=this.HEIGHT_OF_SCROLL_ZONE&&(this.inScrollZone=this.BOTTOM_SCROLL_ZONE),!this.inScrollZone){this.isScrolling=!1;return}this.isScrolling||(this.scrollVertical(this.inScrollZone===this.TOP_SCROLL_ZONE?-this.SCROLL_SPEED:this.SCROLL_SPEED),this.isScrolling=!0)}genHTML(){const{UI:e}=this.Editor,t=e.nodes.holder.querySelector("."+e.CSS.editorWrapper),o=d.make("div",Ie.CSS.overlay,{}),i=d.make("div",Ie.CSS.overlayContainer,{}),s=d.make("div",Ie.CSS.rect,{});return i.appendChild(s),o.appendChild(i),t.appendChild(o),this.overlayRectangle=s,{container:t,overlay:o}}scrollVertical(e){if(!(this.inScrollZone&&this.mousedown))return;const t=window.pageYOffset;window.scrollBy(0,e),this.mouseY+=window.pageYOffset-t,setTimeout(()=>{this.scrollVertical(e)},0)}changingRectangle(e){if(!this.mousedown)return;e.pageY!==void 0&&(this.mouseX=e.pageX,this.mouseY=e.pageY);const{rightPos:t,leftPos:o,index:i}=this.genInfoForMouseSelection(),s=this.startX>t&&this.mouseX>t,r=this.startX=this.startY?(this.overlayRectangle.style.top=`${this.startY-window.pageYOffset}px`,this.overlayRectangle.style.bottom=`calc(100% - ${this.mouseY-window.pageYOffset}px`):(this.overlayRectangle.style.bottom=`calc(100% - ${this.startY-window.pageYOffset}px`,this.overlayRectangle.style.top=`${this.mouseY-window.pageYOffset}px`),this.mouseX>=this.startX?(this.overlayRectangle.style.left=`${this.startX-window.pageXOffset}px`,this.overlayRectangle.style.right=`calc(100% - ${this.mouseX-window.pageXOffset}px`):(this.overlayRectangle.style.right=`calc(100% - ${this.startX-window.pageXOffset}px`,this.overlayRectangle.style.left=`${this.mouseX-window.pageXOffset}px`)}genInfoForMouseSelection(){const t=document.body.offsetWidth/2,o=this.mouseY-window.pageYOffset,i=document.elementFromPoint(t,o),s=this.Editor.BlockManager.getBlockByChildNode(i);let r;s!==void 0&&(r=this.Editor.BlockManager.blocks.findIndex(h=>h.holder===s.holder));const a=this.Editor.BlockManager.lastBlock.holder.querySelector("."+R.CSS.content),l=Number.parseInt(window.getComputedStyle(a).width,10)/2,c=t-l,u=t+l;return{index:r,leftPos:c,rightPos:u}}addBlockInSelection(e){this.rectCrossesBlocks&&this.Editor.BlockSelection.selectBlockByIndex(e),this.stackOfSelected.push(e)}trySelectNextBlock(e){const t=this.stackOfSelected[this.stackOfSelected.length-1]===e,o=this.stackOfSelected.length,i=1,s=-1,r=0;if(t)return;const a=this.stackOfSelected[o-1]-this.stackOfSelected[o-2]>0;let l=r;o>1&&(l=a?i:s);const c=e>this.stackOfSelected[o-1]&&l===i,u=ethis.stackOfSelected[o-1]||this.stackOfSelected[o-1]===void 0)){let v=this.stackOfSelected[o-1]+1||e;for(v;v<=e;v++)this.addBlockInSelection(v);return}if(!p&&e=e;v--)this.addBlockInSelection(v);return}if(!p)return;let g=o-1,f;for(e>this.stackOfSelected[o-1]?f=()=>e>this.stackOfSelected[g]:f=()=>e{const{Tools:o,BlockManager:i}=this.Editor;if(e.length===0)i.insert();else{const s=e.map(({type:r,data:a,tunes:l,id:c})=>{o.available.has(r)===!1&&(X(`Tool «${r}» is not found. Check 'tools' property at the Editor.js config.`,"warn"),a=this.composeStubDataForTool(r,a,c),r=o.stubTool);let u;try{u=i.composeBlock({id:c,tool:r,data:a,tunes:l})}catch(h){T(`Block «${r}» skipped because of plugins error`,"error",{data:a,error:h}),a=this.composeStubDataForTool(r,a,c),r=o.stubTool,u=i.composeBlock({id:c,tool:r,data:a,tunes:l})}return u});i.insertMany(s)}window.requestIdleCallback(()=>{t()},{timeout:2e3})})}composeStubDataForTool(e,t,o){const{Tools:i}=this.Editor;let s=e;if(i.unavailable.has(e)){const r=i.unavailable.get(e).toolbox;r!==void 0&&r[0].title!==void 0&&(s=r[0].title)}return{savedData:{id:o,type:e,data:t},title:s}}}class ca extends E{async save(){const{BlockManager:e,Tools:t}=this.Editor,o=e.blocks,i=[];try{o.forEach(a=>{i.push(this.getSavedData(a))});const s=await Promise.all(i),r=await dt(s,a=>t.blockTools.get(a).sanitizeConfig);return this.makeOutput(r)}catch(s){X("Saving failed due to the Error %o","error",s)}}async getSavedData(e){const t=await e.save(),o=t&&await e.validate(t.data);return{...t,isValid:o}}makeOutput(e){const t=[];return e.forEach(({id:o,tool:i,data:s,tunes:r,isValid:a})=>{if(!a){T(`Block «${i}» skipped because saved data is invalid`);return}if(i===this.Editor.Tools.stubTool){t.push(s);return}const l={id:o,type:i,data:s,...!V(r)&&{tunes:r}};t.push(l)}),{time:+new Date,blocks:t,version:"2.31.0-rc.9"}}}(function(){try{if(typeof document<"u"){var n=document.createElement("style");n.appendChild(document.createTextNode(".ce-paragraph{line-height:1.6em;outline:none}.ce-block:only-of-type .ce-paragraph[data-placeholder-active]:empty:before,.ce-block:only-of-type .ce-paragraph[data-placeholder-active][data-empty=true]:before{content:attr(data-placeholder-active)}.ce-paragraph p:first-of-type{margin-top:0}.ce-paragraph p:last-of-type{margin-bottom:0}")),document.head.appendChild(n)}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})();const da='';function ua(n){const e=document.createElement("div");e.innerHTML=n.trim();const t=document.createDocumentFragment();return t.append(...Array.from(e.childNodes)),t}/** + * Base Paragraph Block for the Editor.js. + * Represents a regular text block + * + * @author CodeX (team@codex.so) + * @copyright CodeX 2018 + * @license The MIT License (MIT) + */class po{static get DEFAULT_PLACEHOLDER(){return""}constructor({data:e,config:t,api:o,readOnly:i}){this.api=o,this.readOnly=i,this._CSS={block:this.api.styles.block,wrapper:"ce-paragraph"},this.readOnly||(this.onKeyUp=this.onKeyUp.bind(this)),this._placeholder=t.placeholder?t.placeholder:po.DEFAULT_PLACEHOLDER,this._data=e??{},this._element=null,this._preserveBlank=t.preserveBlank??!1}onKeyUp(e){if(e.code!=="Backspace"&&e.code!=="Delete"||!this._element)return;const{textContent:t}=this._element;t===""&&(this._element.innerHTML="")}drawView(){const e=document.createElement("DIV");return e.classList.add(this._CSS.wrapper,this._CSS.block),e.contentEditable="false",e.dataset.placeholderActive=this.api.i18n.t(this._placeholder),this._data.text&&(e.innerHTML=this._data.text),this.readOnly||(e.contentEditable="true",e.addEventListener("keyup",this.onKeyUp)),e}render(){return this._element=this.drawView(),this._element}merge(e){if(!this._element)return;this._data.text+=e.text;const t=ua(e.text);this._element.appendChild(t),this._element.normalize()}validate(e){return!(e.text.trim()===""&&!this._preserveBlank)}save(e){return{text:e.innerHTML}}onPaste(e){const t={text:e.detail.data.innerHTML};this._data=t,window.requestAnimationFrame(()=>{this._element&&(this._element.innerHTML=this._data.text||"")})}static get conversionConfig(){return{export:"text",import:"text"}}static get sanitize(){return{text:{br:!0}}}static get isReadOnlySupported(){return!0}static get pasteConfig(){return{tags:["P"]}}static get toolbox(){return{icon:da,title:"Text"}}}class fo{constructor(){this.commandName="bold"}static get sanitize(){return{b:{}}}render(){return{icon:Hi,name:"bold",onActivate:()=>{document.execCommand(this.commandName)},isActive:()=>document.queryCommandState(this.commandName)}}get shortcut(){return"CMD+B"}}fo.isInline=!0,fo.title="Bold";class go{constructor(){this.commandName="italic",this.CSS={button:"ce-inline-tool",buttonActive:"ce-inline-tool--active",buttonModifier:"ce-inline-tool--italic"},this.nodes={button:null}}static get sanitize(){return{i:{}}}render(){return this.nodes.button=document.createElement("button"),this.nodes.button.type="button",this.nodes.button.classList.add(this.CSS.button,this.CSS.buttonModifier),this.nodes.button.innerHTML=Xi,this.nodes.button}surround(){document.execCommand(this.commandName)}checkState(){const e=document.queryCommandState(this.commandName);return this.nodes.button.classList.toggle(this.CSS.buttonActive,e),e}get shortcut(){return"CMD+I"}}go.isInline=!0,go.title="Italic";class mo{constructor({api:e}){this.commandLink="createLink",this.commandUnlink="unlink",this.ENTER_KEY=13,this.CSS={button:"ce-inline-tool",buttonActive:"ce-inline-tool--active",buttonModifier:"ce-inline-tool--link",buttonUnlink:"ce-inline-tool--unlink",input:"ce-inline-tool-input",inputShowed:"ce-inline-tool-input--showed"},this.nodes={button:null,input:null},this.inputOpened=!1,this.toolbar=e.toolbar,this.inlineToolbar=e.inlineToolbar,this.notifier=e.notifier,this.i18n=e.i18n,this.selection=new b}static get sanitize(){return{a:{href:!0,target:"_blank",rel:"nofollow"}}}render(){return this.nodes.button=document.createElement("button"),this.nodes.button.type="button",this.nodes.button.classList.add(this.CSS.button,this.CSS.buttonModifier),this.nodes.button.innerHTML=zo,this.nodes.button}renderActions(){return this.nodes.input=document.createElement("input"),this.nodes.input.placeholder=this.i18n.t("Add a link"),this.nodes.input.enterKeyHint="done",this.nodes.input.classList.add(this.CSS.input),this.nodes.input.addEventListener("keydown",e=>{e.keyCode===this.ENTER_KEY&&this.enterPressed(e)}),this.nodes.input}surround(e){if(e){this.inputOpened?(this.selection.restore(),this.selection.removeFakeBackground()):(this.selection.setFakeBackground(),this.selection.save());const t=this.selection.findParentTag("A");if(t){this.selection.expandToTag(t),this.unlink(),this.closeActions(),this.checkState(),this.toolbar.close();return}}this.toggleActions()}checkState(){const e=this.selection.findParentTag("A");if(e){this.nodes.button.innerHTML=Gi,this.nodes.button.classList.add(this.CSS.buttonUnlink),this.nodes.button.classList.add(this.CSS.buttonActive),this.openActions();const t=e.getAttribute("href");this.nodes.input.value=t!=="null"?t:"",this.selection.save()}else this.nodes.button.innerHTML=zo,this.nodes.button.classList.remove(this.CSS.buttonUnlink),this.nodes.button.classList.remove(this.CSS.buttonActive);return!!e}clear(){this.closeActions()}get shortcut(){return"CMD+K"}toggleActions(){this.inputOpened?this.closeActions(!1):this.openActions(!0)}openActions(e=!1){this.nodes.input.classList.add(this.CSS.inputShowed),e&&this.nodes.input.focus(),this.inputOpened=!0}closeActions(e=!0){if(this.selection.isFakeBackgroundEnabled){const t=new b;t.save(),this.selection.restore(),this.selection.removeFakeBackground(),t.restore()}this.nodes.input.classList.remove(this.CSS.inputShowed),this.nodes.input.value="",e&&this.selection.clearSaved(),this.inputOpened=!1}enterPressed(e){let t=this.nodes.input.value||"";if(!t.trim()){this.selection.restore(),this.unlink(),e.preventDefault(),this.closeActions();return}if(!this.validateURL(t)){this.notifier.show({message:"Pasted link is not valid.",style:"error"}),T("Incorrect Link pasted","warn",t);return}t=this.prepareLink(t),this.selection.restore(),this.selection.removeFakeBackground(),this.insertLink(t),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.selection.collapseToEnd(),this.inlineToolbar.close()}validateURL(e){return!/\s/.test(e)}prepareLink(e){return e=e.trim(),e=this.addProtocol(e),e}addProtocol(e){if(/^(\w+):(\/\/)?/.test(e))return e;const t=/^\/[^/\s]/.test(e),o=e.substring(0,1)==="#",i=/^\/\/[^/\s]/.test(e);return!t&&!o&&!i&&(e="http://"+e),e}insertLink(e){const t=this.selection.findParentTag("A");t&&this.selection.expandToTag(t),document.execCommand(this.commandLink,!1,e)}unlink(){document.execCommand(this.commandUnlink)}}mo.isInline=!0,mo.title="Link";class Pn{constructor({api:e}){this.i18nAPI=e.i18n,this.blocksAPI=e.blocks,this.selectionAPI=e.selection,this.toolsAPI=e.tools,this.caretAPI=e.caret}async render(){const e=b.get(),t=this.blocksAPI.getBlockByElement(e.anchorNode);if(t===void 0)return[];const o=this.toolsAPI.getBlockTools(),i=await Po(t,o);if(i.length===0)return[];const s=i.reduce((c,u)=>{var h;return(h=u.toolbox)==null||h.forEach(p=>{c.push({icon:p.icon,title:H.t(W.toolNames,p.title),name:u.name,closeOnActivate:!0,onActivate:async()=>{const g=await this.blocksAPI.convert(t.id,u.name,p.data);this.caretAPI.setToBlock(g,"end")}})}),c},[]),r=await t.getActiveToolboxEntry(),a=r!==void 0?r.icon:Uo,l=!ge();return{icon:a,name:"convert-to",hint:{title:this.i18nAPI.t("Convert to")},children:{searchable:l,items:s,onOpen:()=>{l&&(this.selectionAPI.setFakeBackground(),this.selectionAPI.save())},onClose:()=>{l&&(this.selectionAPI.restore(),this.selectionAPI.removeFakeBackground())}}}}}Pn.isInline=!0;class Nn{constructor({data:e,api:t}){this.CSS={wrapper:"ce-stub",info:"ce-stub__info",title:"ce-stub__title",subtitle:"ce-stub__subtitle"},this.api=t,this.title=e.title||this.api.i18n.t("Error"),this.subtitle=this.api.i18n.t("The block can not be displayed correctly."),this.savedData=e.savedData,this.wrapper=this.make()}render(){return this.wrapper}save(){return this.savedData}make(){const e=d.make("div",this.CSS.wrapper),t=Ji,o=d.make("div",this.CSS.info),i=d.make("div",this.CSS.title,{textContent:this.title}),s=d.make("div",this.CSS.subtitle,{textContent:this.subtitle});return e.innerHTML=t,o.appendChild(i),o.appendChild(s),e.appendChild(o),e}}Nn.isReadOnlySupported=!0;class ha extends xt{constructor(){super(...arguments),this.type=ce.Inline}get title(){return this.constructable[He.Title]}create(){return new this.constructable({api:this.api,config:this.settings})}get isReadOnlySupported(){return this.constructable[He.IsReadOnlySupported]??!1}}class pa extends xt{constructor(){super(...arguments),this.type=ce.Tune}create(e,t){return new this.constructable({api:this.api,config:this.settings,block:t,data:e})}}class F extends Map{get blockTools(){const e=Array.from(this.entries()).filter(([,t])=>t.isBlock());return new F(e)}get inlineTools(){const e=Array.from(this.entries()).filter(([,t])=>t.isInline());return new F(e)}get blockTunes(){const e=Array.from(this.entries()).filter(([,t])=>t.isTune());return new F(e)}get internalTools(){const e=Array.from(this.entries()).filter(([,t])=>t.isInternal);return new F(e)}get externalTools(){const e=Array.from(this.entries()).filter(([,t])=>!t.isInternal);return new F(e)}}var fa=Object.defineProperty,ga=Object.getOwnPropertyDescriptor,Rn=(n,e,t,o)=>{for(var i=o>1?void 0:o?ga(e,t):e,s=n.length-1,r;s>=0;s--)(r=n[s])&&(i=(o?r(e,t,i):r(i))||i);return o&&i&&fa(e,t,i),i};class bo extends xt{constructor(){super(...arguments),this.type=ce.Block,this.inlineTools=new F,this.tunes=new F}create(e,t,o){return new this.constructable({data:e,block:t,readOnly:o,api:this.api,config:this.settings})}get isReadOnlySupported(){return this.constructable[ve.IsReadOnlySupported]===!0}get isLineBreaksEnabled(){return this.constructable[ve.IsEnabledLineBreaks]}get toolbox(){const e=this.constructable[ve.Toolbox],t=this.config[je.Toolbox];if(!V(e)&&t!==!1)return t?Array.isArray(e)?Array.isArray(t)?t.map((o,i)=>{const s=e[i];return s?{...s,...o}:o}):[t]:Array.isArray(t)?t:[{...e,...t}]:Array.isArray(e)?e:[e]}get conversionConfig(){return this.constructable[ve.ConversionConfig]}get enabledInlineTools(){return this.config[je.EnabledInlineTools]||!1}get enabledBlockTunes(){return this.config[je.EnabledBlockTunes]}get pasteConfig(){return this.constructable[ve.PasteConfig]??{}}get sanitizeConfig(){const e=super.sanitizeConfig,t=this.baseSanitizeConfig;if(V(e))return t;const o={};for(const i in e)if(Object.prototype.hasOwnProperty.call(e,i)){const s=e[i];N(s)?o[i]=Object.assign({},t,s):o[i]=s}return o}get baseSanitizeConfig(){const e={};return Array.from(this.inlineTools.values()).forEach(t=>Object.assign(e,t.sanitizeConfig)),Array.from(this.tunes.values()).forEach(t=>Object.assign(e,t.sanitizeConfig)),e}}Rn([fe],bo.prototype,"sanitizeConfig",1),Rn([fe],bo.prototype,"baseSanitizeConfig",1);class ma{constructor(e,t,o){this.api=o,this.config=e,this.editorConfig=t}get(e){const{class:t,isInternal:o=!1,...i}=this.config[e],s=this.getConstructor(t),r=t[Et.IsTune];return new s({name:e,constructable:t,config:i,api:this.api.getMethodsForTool(e,r),isDefault:e===this.editorConfig.defaultBlock,defaultPlaceholder:this.editorConfig.placeholder,isInternal:o})}getConstructor(e){switch(!0){case e[He.IsInline]:return ha;case e[Et.IsTune]:return pa;default:return bo}}}class Dn{constructor({api:e}){this.CSS={animation:"wobble"},this.api=e}render(){return{icon:$i,title:this.api.i18n.t("Move down"),onActivate:()=>this.handleClick(),name:"move-down"}}handleClick(){const e=this.api.blocks.getCurrentBlockIndex(),t=this.api.blocks.getBlockByIndex(e+1);if(!t)throw new Error("Unable to move Block down since it is already the last");const o=t.holder,i=o.getBoundingClientRect();let s=Math.abs(window.innerHeight-o.offsetHeight);i.topthis.handleClick()}}}handleClick(){this.api.blocks.delete()}}Fn.isTune=!0;class jn{constructor({api:e}){this.CSS={animation:"wobble"},this.api=e}render(){return{icon:Wi,title:this.api.i18n.t("Move up"),onActivate:()=>this.handleClick(),name:"move-up"}}handleClick(){const e=this.api.blocks.getCurrentBlockIndex(),t=this.api.blocks.getBlockByIndex(e),o=this.api.blocks.getBlockByIndex(e-1);if(e===0||!t||!o)throw new Error("Unable to move Block up since it is already the first");const i=t.holder,s=o.holder,r=i.getBoundingClientRect(),a=s.getBoundingClientRect();let l;a.top>0?l=Math.abs(r.top)-Math.abs(a.top):l=Math.abs(r.top)+a.height,window.scrollBy(0,-1*l),this.api.blocks.move(e-1),this.api.toolbar.toggleBlockSettings(!0)}}jn.isTune=!0;var ba=Object.defineProperty,va=Object.getOwnPropertyDescriptor,ka=(n,e,t,o)=>{for(var i=o>1?void 0:o?va(e,t):e,s=n.length-1,r;s>=0;s--)(r=n[s])&&(i=(o?r(e,t,i):r(i))||i);return o&&i&&ba(e,t,i),i};class Hn extends E{constructor(){super(...arguments),this.stubTool="stub",this.toolsAvailable=new F,this.toolsUnavailable=new F}get available(){return this.toolsAvailable}get unavailable(){return this.toolsUnavailable}get inlineTools(){return this.available.inlineTools}get blockTools(){return this.available.blockTools}get blockTunes(){return this.available.blockTunes}get defaultTool(){return this.blockTools.get(this.config.defaultBlock)}get internal(){return this.available.internalTools}async prepare(){if(this.validateTools(),this.config.tools=nt({},this.internalTools,this.config.tools),!Object.prototype.hasOwnProperty.call(this.config,"tools")||Object.keys(this.config.tools).length===0)throw Error("Can't start without tools");const e=this.prepareConfig();this.factory=new ma(e,this.config,this.Editor.API);const t=this.getListOfPrepareFunctions(e);if(t.length===0)return Promise.resolve();await Zn(t,o=>{this.toolPrepareMethodSuccess(o)},o=>{this.toolPrepareMethodFallback(o)}),this.prepareBlockTools()}getAllInlineToolsSanitizeConfig(){const e={};return Array.from(this.inlineTools.values()).forEach(t=>{Object.assign(e,t.sanitizeConfig)}),e}destroy(){Object.values(this.available).forEach(async e=>{M(e.reset)&&await e.reset()})}get internalTools(){return{convertTo:{class:Pn,isInternal:!0},link:{class:mo,isInternal:!0},bold:{class:fo,isInternal:!0},italic:{class:go,isInternal:!0},paragraph:{class:po,inlineToolbar:!0,isInternal:!0},stub:{class:Nn,isInternal:!0},moveUp:{class:jn,isInternal:!0},delete:{class:Fn,isInternal:!0},moveDown:{class:Dn,isInternal:!0}}}toolPrepareMethodSuccess(e){const t=this.factory.get(e.toolName);if(t.isInline()){const i=["render"].filter(s=>!t.create()[s]);if(i.length){T(`Incorrect Inline Tool: ${t.name}. Some of required methods is not implemented %o`,"warn",i),this.toolsUnavailable.set(t.name,t);return}}this.toolsAvailable.set(t.name,t)}toolPrepareMethodFallback(e){this.toolsUnavailable.set(e.toolName,this.factory.get(e.toolName))}getListOfPrepareFunctions(e){const t=[];return Object.entries(e).forEach(([o,i])=>{t.push({function:M(i.class.prepare)?i.class.prepare:()=>{},data:{toolName:o,config:i.config}})}),t}prepareBlockTools(){Array.from(this.blockTools.values()).forEach(e=>{this.assignInlineToolsToBlockTool(e),this.assignBlockTunesToBlockTool(e)})}assignInlineToolsToBlockTool(e){if(this.config.inlineToolbar!==!1){if(e.enabledInlineTools===!0){e.inlineTools=new F(Array.isArray(this.config.inlineToolbar)?this.config.inlineToolbar.map(t=>[t,this.inlineTools.get(t)]):Array.from(this.inlineTools.entries()));return}Array.isArray(e.enabledInlineTools)&&(e.inlineTools=new F(["convertTo",...e.enabledInlineTools].map(t=>[t,this.inlineTools.get(t)])))}}assignBlockTunesToBlockTool(e){if(e.enabledBlockTunes!==!1){if(Array.isArray(e.enabledBlockTunes)){const t=new F(e.enabledBlockTunes.map(o=>[o,this.blockTunes.get(o)]));e.tunes=new F([...t,...this.blockTunes.internalTools]);return}if(Array.isArray(this.config.tunes)){const t=new F(this.config.tunes.map(o=>[o,this.blockTunes.get(o)]));e.tunes=new F([...t,...this.blockTunes.internalTools]);return}e.tunes=this.blockTunes.internalTools}}validateTools(){for(const e in this.config.tools)if(Object.prototype.hasOwnProperty.call(this.config.tools,e)){if(e in this.internalTools)return;const t=this.config.tools[e];if(!M(t)&&!M(t.class))throw Error(`Tool «${e}» must be a constructor function or an object with function in the «class» property`)}}prepareConfig(){const e={};for(const t in this.config.tools)N(this.config.tools[t])?e[t]=this.config.tools[t]:e[t]={class:this.config.tools[t]};return e}}ka([fe],Hn.prototype,"getAllInlineToolsSanitizeConfig",1);const ya=`:root{--selectionColor: #e1f2ff;--inlineSelectionColor: #d4ecff;--bg-light: #eff2f5;--grayText: #707684;--color-dark: #1D202B;--color-active-icon: #388AE5;--color-gray-border: rgba(201, 201, 204, .48);--content-width: 650px;--narrow-mode-right-padding: 50px;--toolbox-buttons-size: 26px;--toolbox-buttons-size--mobile: 36px;--icon-size: 20px;--icon-size--mobile: 28px;--block-padding-vertical: .4em;--color-line-gray: #EFF0F1 }.codex-editor{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;z-index:1}.codex-editor .hide{display:none}.codex-editor__redactor [contenteditable]:empty:after{content:"\\feff"}@media (min-width: 651px){.codex-editor--narrow .codex-editor__redactor{margin-right:50px}}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .codex-editor__redactor{margin-left:50px;margin-right:0}}@media (min-width: 651px){.codex-editor--narrow .ce-toolbar__actions{right:-5px}}.codex-editor-copyable{position:absolute;height:1px;width:1px;top:-400%;opacity:.001}.codex-editor-overlay{position:fixed;top:0;left:0;right:0;bottom:0;z-index:999;pointer-events:none;overflow:hidden}.codex-editor-overlay__container{position:relative;pointer-events:auto;z-index:0}.codex-editor-overlay__rectangle{position:absolute;pointer-events:none;background-color:#2eaadc33;border:1px solid transparent}.codex-editor svg{max-height:100%}.codex-editor path{stroke:currentColor}.codex-editor ::-moz-selection{background-color:#d4ecff}.codex-editor ::selection{background-color:#d4ecff}.codex-editor--toolbox-opened [contentEditable=true][data-placeholder]:focus:before{opacity:0!important}.ce-scroll-locked{overflow:hidden}.ce-scroll-locked--hard{overflow:hidden;top:calc(-1 * var(--window-scroll-offset));position:fixed;width:100%}.ce-toolbar{position:absolute;left:0;right:0;top:0;-webkit-transition:opacity .1s ease;transition:opacity .1s ease;will-change:opacity,top;display:none}.ce-toolbar--opened{display:block}.ce-toolbar__content{max-width:650px;margin:0 auto;position:relative}.ce-toolbar__plus{color:#1d202b;cursor:pointer;width:26px;height:26px;border-radius:7px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-ms-flex-negative:0;flex-shrink:0}@media (max-width: 650px){.ce-toolbar__plus{width:36px;height:36px}}@media (hover: hover){.ce-toolbar__plus:hover{background-color:#eff2f5}}.ce-toolbar__plus--active{background-color:#eff2f5;-webkit-animation:bounceIn .75s 1;animation:bounceIn .75s 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.ce-toolbar__plus-shortcut{opacity:.6;word-spacing:-2px;margin-top:5px}@media (max-width: 650px){.ce-toolbar__plus{position:absolute;background-color:#fff;border:1px solid #E8E8EB;-webkit-box-shadow:0 3px 15px -3px rgba(13,20,33,.13);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;z-index:2;position:static}.ce-toolbar__plus--left-oriented:before{left:15px;margin-left:0}.ce-toolbar__plus--right-oriented:before{left:auto;right:15px;margin-left:0}}.ce-toolbar__actions{position:absolute;right:100%;opacity:0;display:-webkit-box;display:-ms-flexbox;display:flex;padding-right:5px}.ce-toolbar__actions--opened{opacity:1}@media (max-width: 650px){.ce-toolbar__actions{right:auto}}.ce-toolbar__settings-btn{color:#1d202b;width:26px;height:26px;border-radius:7px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;margin-left:3px;cursor:pointer;user-select:none}@media (max-width: 650px){.ce-toolbar__settings-btn{width:36px;height:36px}}@media (hover: hover){.ce-toolbar__settings-btn:hover{background-color:#eff2f5}}.ce-toolbar__settings-btn--active{background-color:#eff2f5;-webkit-animation:bounceIn .75s 1;animation:bounceIn .75s 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@media (min-width: 651px){.ce-toolbar__settings-btn{width:24px}}.ce-toolbar__settings-btn--hidden{display:none}@media (max-width: 650px){.ce-toolbar__settings-btn{position:absolute;background-color:#fff;border:1px solid #E8E8EB;-webkit-box-shadow:0 3px 15px -3px rgba(13,20,33,.13);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;z-index:2;position:static}.ce-toolbar__settings-btn--left-oriented:before{left:15px;margin-left:0}.ce-toolbar__settings-btn--right-oriented:before{left:auto;right:15px;margin-left:0}}.ce-toolbar__plus svg,.ce-toolbar__settings-btn svg{width:24px;height:24px}@media (min-width: 651px){.codex-editor--narrow .ce-toolbar__plus{left:5px}}@media (min-width: 651px){.codex-editor--narrow .ce-toolbox .ce-popover{right:0;left:auto;left:initial}}.ce-inline-toolbar{--y-offset: 8px;--color-background-icon-active: rgba(56, 138, 229, .1);--color-text-icon-active: #388AE5;--color-text-primary: black;position:absolute;visibility:hidden;-webkit-transition:opacity .25s ease;transition:opacity .25s ease;will-change:opacity,left,top;top:0;left:0;z-index:3;opacity:1;visibility:visible}.ce-inline-toolbar [hidden]{display:none!important}.ce-inline-toolbar__toggler-and-button-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;padding:0 6px}.ce-inline-toolbar__buttons{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-inline-toolbar__dropdown{display:-webkit-box;display:-ms-flexbox;display:flex;padding:6px;margin:0 6px 0 -6px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;border-right:1px solid rgba(201,201,204,.48);-webkit-box-sizing:border-box;box-sizing:border-box}@media (hover: hover){.ce-inline-toolbar__dropdown:hover{background:#eff2f5}}.ce-inline-toolbar__dropdown--hidden{display:none}.ce-inline-toolbar__dropdown-content,.ce-inline-toolbar__dropdown-arrow{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-inline-toolbar__dropdown-content svg,.ce-inline-toolbar__dropdown-arrow svg{width:20px;height:20px}.ce-inline-toolbar__shortcut{opacity:.6;word-spacing:-3px;margin-top:3px}.ce-inline-tool{color:var(--color-text-primary);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;border-radius:4px;line-height:normal;height:100%;padding:0;width:28px;background-color:transparent;cursor:pointer}@media (max-width: 650px){.ce-inline-tool{width:36px;height:36px}}@media (hover: hover){.ce-inline-tool:hover{background-color:#f8f8f8}}.ce-inline-tool svg{display:block;width:20px;height:20px}@media (max-width: 650px){.ce-inline-tool svg{width:28px;height:28px}}.ce-inline-tool--link .icon--unlink,.ce-inline-tool--unlink .icon--link{display:none}.ce-inline-tool--unlink .icon--unlink{display:inline-block;margin-bottom:-1px}.ce-inline-tool-input{background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:4px 8px;font-size:14px;line-height:22px;outline:none;margin:0;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box;display:none;font-weight:500;-webkit-appearance:none;font-family:inherit}@media (max-width: 650px){.ce-inline-tool-input{font-size:15px;font-weight:500}}.ce-inline-tool-input::-webkit-input-placeholder{color:#707684}.ce-inline-tool-input::-moz-placeholder{color:#707684}.ce-inline-tool-input:-ms-input-placeholder{color:#707684}.ce-inline-tool-input::-ms-input-placeholder{color:#707684}.ce-inline-tool-input::placeholder{color:#707684}.ce-inline-tool-input--showed{display:block}.ce-inline-tool--active{background:var(--color-background-icon-active);color:var(--color-text-icon-active)}@-webkit-keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.ce-block{-webkit-animation:fade-in .3s ease;animation:fade-in .3s ease;-webkit-animation-fill-mode:none;animation-fill-mode:none;-webkit-animation-fill-mode:initial;animation-fill-mode:initial}.ce-block:first-of-type{margin-top:0}.ce-block--selected .ce-block__content{background:#e1f2ff}.ce-block--selected .ce-block__content [contenteditable]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ce-block--selected .ce-block__content img,.ce-block--selected .ce-block__content .ce-stub{opacity:.55}.ce-block--stretched .ce-block__content{max-width:none}.ce-block__content{position:relative;max-width:650px;margin:0 auto;-webkit-transition:background-color .15s ease;transition:background-color .15s ease}.ce-block--drop-target .ce-block__content:before{content:"";position:absolute;top:100%;left:-20px;margin-top:-1px;height:8px;width:8px;border:solid #388AE5;border-width:1px 1px 0 0;-webkit-transform-origin:right;transform-origin:right;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.ce-block--drop-target .ce-block__content:after{content:"";position:absolute;top:100%;height:1px;width:100%;color:#388ae5;background:repeating-linear-gradient(90deg,#388AE5,#388AE5 1px,#fff 1px,#fff 6px)}.ce-block a{cursor:pointer;-webkit-text-decoration:underline;text-decoration:underline}.ce-block b{font-weight:700}.ce-block i{font-style:italic}@-webkit-keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}20%{-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}60%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}20%{-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}60%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@-webkit-keyframes selectionBounce{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}50%{-webkit-transform:scale3d(1.01,1.01,1.01);transform:scale3d(1.01,1.01,1.01)}70%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes selectionBounce{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}50%{-webkit-transform:scale3d(1.01,1.01,1.01);transform:scale3d(1.01,1.01,1.01)}70%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@-webkit-keyframes buttonClicked{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.95,.95,.95);transform:scale3d(.95,.95,.95)}60%{-webkit-transform:scale3d(1.02,1.02,1.02);transform:scale3d(1.02,1.02,1.02)}80%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes buttonClicked{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.95,.95,.95);transform:scale3d(.95,.95,.95)}60%{-webkit-transform:scale3d(1.02,1.02,1.02);transform:scale3d(1.02,1.02,1.02)}80%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}.cdx-block{padding:.4em 0}.cdx-block::-webkit-input-placeholder{line-height:normal!important}.cdx-input{border:1px solid rgba(201,201,204,.48);-webkit-box-shadow:inset 0 1px 2px 0 rgba(35,44,72,.06);box-shadow:inset 0 1px 2px #232c480f;border-radius:3px;padding:10px 12px;outline:none;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.cdx-input[data-placeholder]:before{position:static!important}.cdx-input[data-placeholder]:before{display:inline-block;width:0;white-space:nowrap;pointer-events:none}.cdx-settings-button{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;border-radius:3px;cursor:pointer;border:0;outline:none;background-color:transparent;vertical-align:bottom;color:inherit;margin:0;min-width:26px;min-height:26px}.cdx-settings-button--focused{background:rgba(34,186,255,.08)!important}.cdx-settings-button--focused{-webkit-box-shadow:inset 0 0 0px 1px rgba(7,161,227,.08);box-shadow:inset 0 0 0 1px #07a1e314}.cdx-settings-button--focused-animated{-webkit-animation-name:buttonClicked;animation-name:buttonClicked;-webkit-animation-duration:.25s;animation-duration:.25s}.cdx-settings-button--active{color:#388ae5}.cdx-settings-button svg{width:auto;height:auto}@media (max-width: 650px){.cdx-settings-button svg{width:28px;height:28px}}@media (max-width: 650px){.cdx-settings-button{width:36px;height:36px;border-radius:8px}}@media (hover: hover){.cdx-settings-button:hover{background-color:#eff2f5}}.cdx-loader{position:relative;border:1px solid rgba(201,201,204,.48)}.cdx-loader:before{content:"";position:absolute;left:50%;top:50%;width:18px;height:18px;margin:-11px 0 0 -11px;border:2px solid rgba(201,201,204,.48);border-left-color:#388ae5;border-radius:50%;-webkit-animation:cdxRotation 1.2s infinite linear;animation:cdxRotation 1.2s infinite linear}@-webkit-keyframes cdxRotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes cdxRotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.cdx-button{padding:13px;border-radius:3px;border:1px solid rgba(201,201,204,.48);font-size:14.9px;background:#fff;-webkit-box-shadow:0 2px 2px 0 rgba(18,30,57,.04);box-shadow:0 2px 2px #121e390a;color:#707684;text-align:center;cursor:pointer}@media (hover: hover){.cdx-button:hover{background:#FBFCFE;-webkit-box-shadow:0 1px 3px 0 rgba(18,30,57,.08);box-shadow:0 1px 3px #121e3914}}.cdx-button svg{height:20px;margin-right:.2em;margin-top:-2px}.ce-stub{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:12px 18px;margin:10px 0;border-radius:10px;background:#eff2f5;border:1px solid #EFF0F1;color:#707684;font-size:14px}.ce-stub svg{width:20px;height:20px}.ce-stub__info{margin-left:14px}.ce-stub__title{font-weight:500;text-transform:capitalize}.codex-editor.codex-editor--rtl{direction:rtl}.codex-editor.codex-editor--rtl .cdx-list{padding-left:0;padding-right:40px}.codex-editor.codex-editor--rtl .ce-toolbar__plus{right:-26px;left:auto}.codex-editor.codex-editor--rtl .ce-toolbar__actions{right:auto;left:-26px}@media (max-width: 650px){.codex-editor.codex-editor--rtl .ce-toolbar__actions{margin-left:0;margin-right:auto;padding-right:0;padding-left:10px}}.codex-editor.codex-editor--rtl .ce-settings{left:5px;right:auto}.codex-editor.codex-editor--rtl .ce-settings:before{right:auto;left:25px}.codex-editor.codex-editor--rtl .ce-settings__button:not(:nth-child(3n+3)){margin-left:3px;margin-right:0}.codex-editor.codex-editor--rtl .ce-conversion-tool__icon{margin-right:0;margin-left:10px}.codex-editor.codex-editor--rtl .ce-inline-toolbar__dropdown{border-right:0px solid transparent;border-left:1px solid rgba(201,201,204,.48);margin:0 -6px 0 6px}.codex-editor.codex-editor--rtl .ce-inline-toolbar__dropdown .icon--toggler-down{margin-left:0;margin-right:4px}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .ce-toolbar__plus{left:0;right:5px}}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .ce-toolbar__actions{left:-5px}}.cdx-search-field{--icon-margin-right: 10px;background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:2px;display:grid;grid-template-columns:auto auto 1fr;grid-template-rows:auto}.cdx-search-field__icon{width:26px;height:26px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-right:var(--icon-margin-right)}.cdx-search-field__icon svg{width:20px;height:20px;color:#707684}.cdx-search-field__input{font-size:14px;outline:none;font-weight:500;font-family:inherit;border:0;background:transparent;margin:0;padding:0;line-height:22px;min-width:calc(100% - 26px - var(--icon-margin-right))}.cdx-search-field__input::-webkit-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::-moz-placeholder{color:#707684;font-weight:500}.cdx-search-field__input:-ms-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::-ms-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::placeholder{color:#707684;font-weight:500}.ce-popover{--border-radius: 6px;--width: 200px;--max-height: 270px;--padding: 6px;--offset-from-target: 8px;--color-border: #EFF0F1;--color-shadow: rgba(13, 20, 33, .1);--color-background: white;--color-text-primary: black;--color-text-secondary: #707684;--color-border-icon: rgba(201, 201, 204, .48);--color-border-icon-disabled: #EFF0F1;--color-text-icon-active: #388AE5;--color-background-icon-active: rgba(56, 138, 229, .1);--color-background-item-focus: rgba(34, 186, 255, .08);--color-shadow-item-focus: rgba(7, 161, 227, .08);--color-background-item-hover: #F8F8F8;--color-background-item-confirm: #E24A4A;--color-background-item-confirm-hover: #CE4343;--popover-top: calc(100% + var(--offset-from-target));--popover-left: 0;--nested-popover-overlap: 4px;--icon-size: 20px;--item-padding: 3px;--item-height: calc(var(--icon-size) + 2 * var(--item-padding))}.ce-popover__container{min-width:var(--width);width:var(--width);max-height:var(--max-height);border-radius:var(--border-radius);overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:0px 3px 15px -3px var(--color-shadow);box-shadow:0 3px 15px -3px var(--color-shadow);position:absolute;left:var(--popover-left);top:var(--popover-top);background:var(--color-background);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;z-index:4;opacity:0;max-height:0;pointer-events:none;padding:0;border:none}.ce-popover--opened>.ce-popover__container{opacity:1;padding:var(--padding);max-height:var(--max-height);pointer-events:auto;-webkit-animation:panelShowing .1s ease;animation:panelShowing .1s ease;border:1px solid var(--color-border)}@media (max-width: 650px){.ce-popover--opened>.ce-popover__container{-webkit-animation:panelShowingMobile .25s ease;animation:panelShowingMobile .25s ease}}.ce-popover--open-top .ce-popover__container{--popover-top: calc(-1 * (var(--offset-from-target) + var(--popover-height)))}.ce-popover--open-left .ce-popover__container{--popover-left: calc(-1 * var(--width) + 100%)}.ce-popover__items{overflow-y:auto;-ms-scroll-chaining:none;overscroll-behavior:contain}@media (max-width: 650px){.ce-popover__overlay{position:fixed;top:0;bottom:0;left:0;right:0;background:#1D202B;z-index:3;opacity:.5;-webkit-transition:opacity .12s ease-in;transition:opacity .12s ease-in;will-change:opacity;visibility:visible}}.ce-popover__overlay--hidden{display:none}@media (max-width: 650px){.ce-popover .ce-popover__container{--offset: 5px;position:fixed;max-width:none;min-width:calc(100% - var(--offset) * 2);left:var(--offset);right:var(--offset);bottom:calc(var(--offset) + env(safe-area-inset-bottom));top:auto;border-radius:10px}}.ce-popover__search{margin-bottom:5px}.ce-popover__nothing-found-message{color:#707684;display:none;cursor:default;padding:3px;font-size:14px;line-height:20px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ce-popover__nothing-found-message--displayed{display:block}.ce-popover--nested .ce-popover__container{--popover-left: calc(var(--nesting-level) * (var(--width) - var(--nested-popover-overlap)));top:calc(var(--trigger-item-top) - var(--nested-popover-overlap));position:absolute}.ce-popover--open-top.ce-popover--nested .ce-popover__container{top:calc(var(--trigger-item-top) - var(--popover-height) + var(--item-height) + var(--offset-from-target) + var(--nested-popover-overlap))}.ce-popover--open-left .ce-popover--nested .ce-popover__container{--popover-left: calc(-1 * (var(--nesting-level) + 1) * var(--width) + 100%)}.ce-popover-item-separator{padding:4px 3px}.ce-popover-item-separator--hidden{display:none}.ce-popover-item-separator__line{height:1px;background:var(--color-border);width:100%}.ce-popover-item-html--hidden{display:none}.ce-popover-item{--border-radius: 6px;border-radius:var(--border-radius);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:var(--item-padding);color:var(--color-text-primary);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:none;background:transparent}@media (max-width: 650px){.ce-popover-item{padding:4px}}.ce-popover-item:not(:last-of-type){margin-bottom:1px}.ce-popover-item__icon{width:26px;height:26px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.ce-popover-item__icon svg{width:20px;height:20px}@media (max-width: 650px){.ce-popover-item__icon{width:36px;height:36px;border-radius:8px}.ce-popover-item__icon svg{width:28px;height:28px}}.ce-popover-item__icon--tool{margin-right:4px}.ce-popover-item__title{font-size:14px;line-height:20px;font-weight:500;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-right:auto}@media (max-width: 650px){.ce-popover-item__title{font-size:16px}}.ce-popover-item__secondary-title{color:var(--color-text-secondary);font-size:12px;white-space:nowrap;letter-spacing:-.1em;padding-right:5px;opacity:.6}@media (max-width: 650px){.ce-popover-item__secondary-title{display:none}}.ce-popover-item--active{background:var(--color-background-icon-active);color:var(--color-text-icon-active)}.ce-popover-item--disabled{color:var(--color-text-secondary);cursor:default;pointer-events:none}.ce-popover-item--focused:not(.ce-popover-item--no-focus){background:var(--color-background-item-focus)!important}.ce-popover-item--hidden{display:none}@media (hover: hover){.ce-popover-item:hover{cursor:pointer}.ce-popover-item:hover:not(.ce-popover-item--no-hover){background-color:var(--color-background-item-hover)}}.ce-popover-item--confirmation{background:var(--color-background-item-confirm)}.ce-popover-item--confirmation .ce-popover-item__title,.ce-popover-item--confirmation .ce-popover-item__icon{color:#fff}@media (hover: hover){.ce-popover-item--confirmation:not(.ce-popover-item--no-hover):hover{background:var(--color-background-item-confirm-hover)}}.ce-popover-item--confirmation:not(.ce-popover-item--no-focus).ce-popover-item--focused{background:var(--color-background-item-confirm-hover)!important}@-webkit-keyframes panelShowing{0%{opacity:0;-webkit-transform:translateY(-8px) scale(.9);transform:translateY(-8px) scale(.9)}70%{opacity:1;-webkit-transform:translateY(2px);transform:translateY(2px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes panelShowing{0%{opacity:0;-webkit-transform:translateY(-8px) scale(.9);transform:translateY(-8px) scale(.9)}70%{opacity:1;-webkit-transform:translateY(2px);transform:translateY(2px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes panelShowingMobile{0%{opacity:0;-webkit-transform:translateY(14px) scale(.98);transform:translateY(14px) scale(.98)}70%{opacity:1;-webkit-transform:translateY(-4px);transform:translateY(-4px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes panelShowingMobile{0%{opacity:0;-webkit-transform:translateY(14px) scale(.98);transform:translateY(14px) scale(.98)}70%{opacity:1;-webkit-transform:translateY(-4px);transform:translateY(-4px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}.wobble{-webkit-animation-name:wobble;animation-name:wobble;-webkit-animation-duration:.4s;animation-duration:.4s}@-webkit-keyframes wobble{0%{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-9%,0,0);transform:translate3d(-9%,0,0)}30%{-webkit-transform:translate3d(9%,0,0);transform:translate3d(9%,0,0)}45%{-webkit-transform:translate3d(-4%,0,0);transform:translate3d(-4%,0,0)}60%{-webkit-transform:translate3d(4%,0,0);transform:translate3d(4%,0,0)}75%{-webkit-transform:translate3d(-1%,0,0);transform:translate3d(-1%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}}@keyframes wobble{0%{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-9%,0,0);transform:translate3d(-9%,0,0)}30%{-webkit-transform:translate3d(9%,0,0);transform:translate3d(9%,0,0)}45%{-webkit-transform:translate3d(-4%,0,0);transform:translate3d(-4%,0,0)}60%{-webkit-transform:translate3d(4%,0,0);transform:translate3d(4%,0,0)}75%{-webkit-transform:translate3d(-1%,0,0);transform:translate3d(-1%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}}.ce-popover-header{margin-bottom:8px;margin-top:4px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ce-popover-header__text{font-size:18px;font-weight:600}.ce-popover-header__back-button{border:0;background:transparent;width:36px;height:36px;color:var(--color-text-primary)}.ce-popover-header__back-button svg{display:block;width:28px;height:28px}.ce-popover--inline{--height: 38px;--height-mobile: 46px;--container-padding: 4px;position:relative}.ce-popover--inline .ce-popover__custom-content{margin-bottom:0}.ce-popover--inline .ce-popover__items{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-popover--inline .ce-popover__container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;padding:var(--container-padding);height:var(--height);top:0;min-width:-webkit-max-content;min-width:-moz-max-content;min-width:max-content;width:-webkit-max-content;width:-moz-max-content;width:max-content;-webkit-animation:none;animation:none}@media (max-width: 650px){.ce-popover--inline .ce-popover__container{height:var(--height-mobile);position:absolute}}.ce-popover--inline .ce-popover-item-separator{padding:0 4px}.ce-popover--inline .ce-popover-item-separator__line{height:100%;width:1px}.ce-popover--inline .ce-popover-item{border-radius:4px;padding:4px}.ce-popover--inline .ce-popover-item__icon--tool{-webkit-box-shadow:none;box-shadow:none;background:transparent;margin-right:0}.ce-popover--inline .ce-popover-item__icon{width:auto;width:initial;height:auto;height:initial}.ce-popover--inline .ce-popover-item__icon svg{width:20px;height:20px}@media (max-width: 650px){.ce-popover--inline .ce-popover-item__icon svg{width:28px;height:28px}}.ce-popover--inline .ce-popover-item:not(:last-of-type){margin-bottom:0;margin-bottom:initial}.ce-popover--inline .ce-popover-item-html{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ce-popover--inline .ce-popover-item__icon--chevron-right{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.ce-popover--inline .ce-popover--nested-level-1 .ce-popover__container{--offset: 3px;left:0;top:calc(var(--height) + var(--offset))}@media (max-width: 650px){.ce-popover--inline .ce-popover--nested-level-1 .ce-popover__container{top:calc(var(--height-mobile) + var(--offset))}}.ce-popover--inline .ce-popover--nested .ce-popover__container{min-width:var(--width);width:var(--width);height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;padding:6px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.ce-popover--inline .ce-popover--nested .ce-popover__items{display:block;width:100%}.ce-popover--inline .ce-popover--nested .ce-popover-item{border-radius:6px;padding:3px}@media (max-width: 650px){.ce-popover--inline .ce-popover--nested .ce-popover-item{padding:4px}}.ce-popover--inline .ce-popover--nested .ce-popover-item__icon--tool{margin-right:4px}.ce-popover--inline .ce-popover--nested .ce-popover-item__icon{width:26px;height:26px}.ce-popover--inline .ce-popover--nested .ce-popover-item-separator{padding:4px 3px}.ce-popover--inline .ce-popover--nested .ce-popover-item-separator__line{width:100%;height:1px}.codex-editor [data-placeholder]:empty:before,.codex-editor [data-placeholder][data-empty=true]:before{pointer-events:none;color:#707684;cursor:text;content:attr(data-placeholder)}.codex-editor [data-placeholder-active]:empty:before,.codex-editor [data-placeholder-active][data-empty=true]:before{pointer-events:none;color:#707684;cursor:text}.codex-editor [data-placeholder-active]:empty:focus:before,.codex-editor [data-placeholder-active][data-empty=true]:focus:before{content:attr(data-placeholder-active)} +`;class wa extends E{constructor(){super(...arguments),this.isMobile=!1,this.contentRectCache=null,this.resizeDebouncer=Bo(()=>{this.windowResize()},200),this.selectionChangeDebounced=Bo(()=>{this.selectionChanged()},na),this.documentTouchedListener=e=>{this.documentTouched(e)}}get CSS(){return{editorWrapper:"codex-editor",editorWrapperNarrow:"codex-editor--narrow",editorZone:"codex-editor__redactor",editorZoneHidden:"codex-editor__redactor--hidden",editorEmpty:"codex-editor--empty",editorRtlFix:"codex-editor--rtl"}}get contentRect(){if(this.contentRectCache!==null)return this.contentRectCache;const e=this.nodes.wrapper.querySelector(`.${R.CSS.content}`);return e?(this.contentRectCache=e.getBoundingClientRect(),this.contentRectCache):{width:650,left:0,right:0}}async prepare(){this.setIsMobile(),this.make(),this.loadStyles()}toggleReadOnly(e){e?this.unbindReadOnlySensitiveListeners():window.requestIdleCallback(()=>{this.bindReadOnlySensitiveListeners()},{timeout:2e3})}checkEmptiness(){const{BlockManager:e}=this.Editor;this.nodes.wrapper.classList.toggle(this.CSS.editorEmpty,e.isEditorEmpty)}get someToolbarOpened(){const{Toolbar:e,BlockSettings:t,InlineToolbar:o}=this.Editor;return!!(t.opened||o.opened||e.toolbox.opened)}get someFlipperButtonFocused(){return this.Editor.Toolbar.toolbox.hasFocus()?!0:Object.entries(this.Editor).filter(([e,t])=>t.flipper instanceof ae).some(([e,t])=>t.flipper.hasFocus())}destroy(){this.nodes.holder.innerHTML="",this.unbindReadOnlyInsensitiveListeners()}closeAllToolbars(){const{Toolbar:e,BlockSettings:t,InlineToolbar:o}=this.Editor;t.close(),o.close(),e.toolbox.close()}setIsMobile(){const e=window.innerWidth{this.redactorClicked(e)},!1),this.readOnlyMutableListeners.on(document,"keydown",e=>{this.documentKeydown(e)},!0),this.readOnlyMutableListeners.on(document,"mousedown",e=>{this.documentClicked(e)},!0),this.watchBlockHoveredEvents(),this.enableInputsEmptyMark()}watchBlockHoveredEvents(){let e;this.readOnlyMutableListeners.on(this.nodes.redactor,"mousemove",ot(t=>{const o=t.target.closest(".ce-block");this.Editor.BlockSelection.anyBlockSelected||o&&e!==o&&(e=o,this.eventsDispatcher.emit(Qo,{block:this.Editor.BlockManager.getBlockByChildNode(o)}))},20),{passive:!0})}unbindReadOnlySensitiveListeners(){this.readOnlyMutableListeners.clearAll()}windowResize(){this.contentRectCache=null,this.setIsMobile()}documentKeydown(e){switch(e.keyCode){case y.ENTER:this.enterPressed(e);break;case y.BACKSPACE:case y.DELETE:this.backspacePressed(e);break;case y.ESC:this.escapePressed(e);break;default:this.defaultBehaviour(e);break}}defaultBehaviour(e){const{currentBlock:t}=this.Editor.BlockManager,o=e.target.closest(`.${this.CSS.editorWrapper}`),i=e.altKey||e.ctrlKey||e.metaKey||e.shiftKey;if(t!==void 0&&o===null){this.Editor.BlockEvents.keydown(e);return}o||t&&i||(this.Editor.BlockManager.unsetCurrentBlock(),this.Editor.Toolbar.close())}backspacePressed(e){const{BlockManager:t,BlockSelection:o,Caret:i}=this.Editor;if(o.anyBlockSelected&&!b.isSelectionExists){const s=t.removeSelectedBlocks(),r=t.insertDefaultBlockAtIndex(s,!0);i.setToBlock(r,i.positions.START),o.clearSelection(e),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation()}}escapePressed(e){this.Editor.BlockSelection.clearSelection(e),this.Editor.Toolbar.toolbox.opened?(this.Editor.Toolbar.toolbox.close(),this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock,this.Editor.Caret.positions.END)):this.Editor.BlockSettings.opened?this.Editor.BlockSettings.close():this.Editor.InlineToolbar.opened?this.Editor.InlineToolbar.close():this.Editor.Toolbar.close()}enterPressed(e){const{BlockManager:t,BlockSelection:o}=this.Editor;if(this.someToolbarOpened)return;const i=t.currentBlockIndex>=0;if(o.anyBlockSelected&&!b.isSelectionExists){o.clearSelection(e),e.preventDefault(),e.stopImmediatePropagation(),e.stopPropagation();return}if(!this.someToolbarOpened&&i&&e.target.tagName==="BODY"){const s=this.Editor.BlockManager.insert();e.preventDefault(),this.Editor.Caret.setToBlock(s),this.Editor.Toolbar.moveAndOpen(s)}this.Editor.BlockSelection.clearSelection(e)}documentClicked(e){var a,l;if(!e.isTrusted)return;const t=e.target;this.nodes.holder.contains(t)||b.isAtEditor||(this.Editor.BlockManager.unsetCurrentBlock(),this.Editor.Toolbar.close());const i=(a=this.Editor.BlockSettings.nodes.wrapper)==null?void 0:a.contains(t),s=(l=this.Editor.Toolbar.nodes.settingsToggler)==null?void 0:l.contains(t),r=i||s;if(this.Editor.BlockSettings.opened&&!r){this.Editor.BlockSettings.close();const c=this.Editor.BlockManager.getBlockByChildNode(t);this.Editor.Toolbar.moveAndOpen(c)}this.Editor.BlockSelection.clearSelection(e)}documentTouched(e){let t=e.target;if(t===this.nodes.redactor){const o=e instanceof MouseEvent?e.clientX:e.touches[0].clientX,i=e instanceof MouseEvent?e.clientY:e.touches[0].clientY;t=document.elementFromPoint(o,i)}try{this.Editor.BlockManager.setCurrentBlockByChildNode(t)}catch{this.Editor.RectangleSelection.isRectActivated()||this.Editor.Caret.setToTheLastBlock()}this.Editor.ReadOnly.isEnabled||this.Editor.Toolbar.moveAndOpen()}redactorClicked(e){if(!b.isCollapsed)return;const t=e.target,o=e.metaKey||e.ctrlKey;if(d.isAnchor(t)&&o){e.stopImmediatePropagation(),e.stopPropagation();const i=t.getAttribute("href"),s=ei(i);oi(s);return}this.processBottomZoneClick(e)}processBottomZoneClick(e){const t=this.Editor.BlockManager.getBlockByIndex(-1),o=d.offset(t.holder).bottom,i=e.pageY,{BlockSelection:s}=this.Editor;if(e.target instanceof Element&&e.target.isEqualNode(this.nodes.redactor)&&!s.anyBlockSelected&&o{t=i,o=s}),Promise.resolve().then(async()=>{this.configuration=e,this.validate(),this.init(),await this.start(),await this.render();const{BlockManager:i,Caret:s,UI:r,ModificationsObserver:a}=this.moduleInstances;r.checkEmptiness(),a.enable(),this.configuration.autofocus===!0&&this.configuration.readOnly!==!0&&s.setToBlock(i.blocks[0],s.positions.START),t()}).catch(i=>{T(`Editor.js is not ready because of ${i}`,"error"),o(i)})}set configuration(e){var o,i;N(e)?this.config={...e}:this.config={holder:e},st(!!this.config.holderId,"config.holderId","config.holder"),this.config.holderId&&!this.config.holder&&(this.config.holder=this.config.holderId,this.config.holderId=null),this.config.holder==null&&(this.config.holder="editorjs"),this.config.logLevel||(this.config.logLevel=ko.VERBOSE),Vn(this.config.logLevel),st(!!this.config.initialBlock,"config.initialBlock","config.defaultBlock"),this.config.defaultBlock=this.config.defaultBlock||this.config.initialBlock||"paragraph",this.config.minHeight=this.config.minHeight!==void 0?this.config.minHeight:300;const t={type:this.config.defaultBlock,data:{}};this.config.placeholder=this.config.placeholder||!1,this.config.sanitizer=this.config.sanitizer||{p:!0,b:!0,a:!0},this.config.hideToolbar=this.config.hideToolbar?this.config.hideToolbar:!1,this.config.tools=this.config.tools||{},this.config.i18n=this.config.i18n||{},this.config.data=this.config.data||{blocks:[]},this.config.onReady=this.config.onReady||(()=>{}),this.config.onChange=this.config.onChange||(()=>{}),this.config.inlineToolbar=this.config.inlineToolbar!==void 0?this.config.inlineToolbar:!0,(V(this.config.data)||!this.config.data.blocks||this.config.data.blocks.length===0)&&(this.config.data={blocks:[t]}),this.config.readOnly=this.config.readOnly||!1,(o=this.config.i18n)!=null&&o.messages&&H.setDictionary(this.config.i18n.messages),this.config.i18n.direction=((i=this.config.i18n)==null?void 0:i.direction)||"ltr"}get configuration(){return this.config}validate(){const{holderId:e,holder:t}=this.config;if(e&&t)throw Error("«holderId» and «holder» param can't assign at the same time.");if(Q(t)&&!d.get(t))throw Error(`element with ID «${t}» is missing. Pass correct holder's ID.`);if(t&&N(t)&&!d.isElement(t))throw Error("«holder» value must be an Element node")}init(){this.constructModules(),this.configureModules()}async start(){await["Tools","UI","BlockManager","Paste","BlockSelection","RectangleSelection","CrossBlockSelection","ReadOnly"].reduce((t,o)=>t.then(async()=>{try{await this.moduleInstances[o].prepare()}catch(i){if(i instanceof Oo)throw new Error(i.message);T(`Module ${o} was skipped because of %o`,"warn",i)}}),Promise.resolve())}render(){return this.moduleInstances.Renderer.render(this.config.data.blocks)}constructModules(){Object.entries(Ea).forEach(([e,t])=>{try{this.moduleInstances[e]=new t({config:this.configuration,eventsDispatcher:this.eventsDispatcher})}catch(o){T("[constructModules]",`Module ${e} skipped because`,"error",o)}})}configureModules(){for(const e in this.moduleInstances)Object.prototype.hasOwnProperty.call(this.moduleInstances,e)&&(this.moduleInstances[e].state=this.getModulesDiff(e))}getModulesDiff(e){const t={};for(const o in this.moduleInstances)o!==e&&(t[o]=this.moduleInstances[o]);return t}}/** + * Editor.js + * + * @license Apache-2.0 + * @see Editor.js + * @author CodeX Team + */class Ba{static get version(){return"2.31.0-rc.9"}constructor(e){let t=()=>{};N(e)&&M(e.onReady)&&(t=e.onReady);const o=new xa(e);this.isReady=o.isReady.then(()=>{this.exportAPI(o),t()})}exportAPI(e){const t=["configuration"],o=()=>{Object.values(e.moduleInstances).forEach(s=>{M(s.destroy)&&s.destroy(),s.listeners.removeAll()}),Ri(),e=null;for(const s in this)Object.prototype.hasOwnProperty.call(this,s)&&delete this[s];Object.setPrototypeOf(this,null)};t.forEach(s=>{this[s]=e[s]}),this.destroy=o,Object.setPrototypeOf(this,e.moduleInstances.API.methods),delete this.exportAPI,Object.entries({blocks:{clear:"clear",render:"render"},caret:{focus:"focus"},events:{on:"on",off:"off",emit:"emit"},saver:{save:"save"}}).forEach(([s,r])=>{Object.entries(r).forEach(([a,l])=>{this[l]=e.moduleInstances.API.methods[s][a]})})}}return Ba}); diff --git a/plugins/tiddlywiki/editorjs/files/header.umd.js b/plugins/tiddlywiki/editorjs/files/header.umd.js new file mode 100644 index 000000000..df5649345 --- /dev/null +++ b/plugins/tiddlywiki/editorjs/files/header.umd.js @@ -0,0 +1,15 @@ +/** + * Skipped minification because the original files appears to be already minified. + * Original file: /npm/@editorjs/header@2.8.8/dist/header.umd.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(".ce-header{padding:.6em 0 3px;margin:0;line-height:1.25em;outline:none}.ce-header p,.ce-header div{padding:0!important;margin:0!important}")),document.head.appendChild(e)}}catch(n){console.error("vite-plugin-css-injected-by-js",n)}})(); +(function(n,s){typeof exports=="object"&&typeof module<"u"?module.exports=s():typeof define=="function"&&define.amd?define(s):(n=typeof globalThis<"u"?globalThis:n||self,n.Header=s())})(this,function(){"use strict";const n="",s='',a='',h='',d='',u='',g='',c='';/** + * Header block for the Editor.js. + * + * @author CodeX (team@ifmo.su) + * @copyright CodeX 2018 + * @license MIT + * @version 2.0.0 + */class v{constructor({data:e,config:t,api:i,readOnly:r}){this.api=i,this.readOnly=r,this._settings=t,this._data=this.normalizeData(e),this._element=this.getTag()}get _CSS(){return{block:this.api.styles.block,wrapper:"ce-header"}}isHeaderData(e){return e.text!==void 0}normalizeData(e){const t={text:"",level:this.defaultLevel.number};return this.isHeaderData(e)&&(t.text=e.text||"",e.level!==void 0&&!isNaN(parseInt(e.level.toString()))&&(t.level=parseInt(e.level.toString()))),t}render(){return this._element}renderSettings(){return this.levels.map(e=>({icon:e.svg,label:this.api.i18n.t(`Heading ${e.number}`),onActivate:()=>this.setLevel(e.number),closeOnActivate:!0,isActive:this.currentLevel.number===e.number,render:()=>document.createElement("div")}))}setLevel(e){this.data={level:e,text:this.data.text}}merge(e){this._element.insertAdjacentHTML("beforeend",e.text)}validate(e){return e.text.trim()!==""}save(e){return{text:e.innerHTML,level:this.currentLevel.number}}static get conversionConfig(){return{export:"text",import:"text"}}static get sanitize(){return{level:!1,text:{}}}static get isReadOnlySupported(){return!0}get data(){return this._data.text=this._element.innerHTML,this._data.level=this.currentLevel.number,this._data}set data(e){if(this._data=this.normalizeData(e),e.level!==void 0&&this._element.parentNode){const t=this.getTag();t.innerHTML=this._element.innerHTML,this._element.parentNode.replaceChild(t,this._element),this._element=t}e.text!==void 0&&(this._element.innerHTML=this._data.text||"")}getTag(){const e=document.createElement(this.currentLevel.tag);return e.innerHTML=this._data.text||"",e.classList.add(this._CSS.wrapper),e.contentEditable=this.readOnly?"false":"true",e.dataset.placeholder=this.api.i18n.t(this._settings.placeholder||""),e}get currentLevel(){let e=this.levels.find(t=>t.number===this._data.level);return e||(e=this.defaultLevel),e}get defaultLevel(){if(this._settings.defaultLevel){const e=this.levels.find(t=>t.number===this._settings.defaultLevel);if(e)return e;console.warn("(ง'̀-'́)ง Heading Tool: the default level specified was not found in available levels")}return this.levels[1]}get levels(){const e=[{number:1,tag:"H1",svg:s},{number:2,tag:"H2",svg:a},{number:3,tag:"H3",svg:h},{number:4,tag:"H4",svg:d},{number:5,tag:"H5",svg:u},{number:6,tag:"H6",svg:g}];return this._settings.levels?e.filter(t=>this._settings.levels.includes(t.number)):e}onPaste(e){const t=e.detail;if("data"in t){const i=t.data;let r=this.defaultLevel.number;switch(i.tagName){case"H1":r=1;break;case"H2":r=2;break;case"H3":r=3;break;case"H4":r=4;break;case"H5":r=5;break;case"H6":r=6;break}this._settings.levels&&(r=this._settings.levels.reduce((o,l)=>Math.abs(l-r) + +Downloaded from Github releases: + +* [ext[EditorJs|https://github.com/codex-team/editor.js/releases]]: 2.31.0-rc.9 + +Downloaded from JsDelivr CDN: + +* [ext[Heading|https://github.com/editor-js/header]]: 2.8.8 +* [ext[List|https://github.com/editor-js/list]]: 2.0.6 diff --git a/plugins/tiddlywiki/editorjs/widget.js b/plugins/tiddlywiki/editorjs/widget.js new file mode 100644 index 000000000..511921b1c --- /dev/null +++ b/plugins/tiddlywiki/editorjs/widget.js @@ -0,0 +1,75 @@ +/*\ +title: $:/plugins/tiddlywiki/editorjs/widget.js +type: application/javascript +module-type: widget + +Text node widget + +\*/ + +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget; + +var EditorJSWidget = function(parseTreeNode,options) { + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +EditorJSWidget.prototype = new Widget(); + +/* +Render this widget into the DOM +*/ +EditorJSWidget.prototype.render = function(parent,nextSibling) { + this.parentDomNode = parent; + this.computeAttributes(); + this.execute(); + var container = $tw.utils.domMaker('div', { + class: 'tc-editorjs-container', + }); + var EditorJS = require("$:/plugins/tiddlywiki/editorjs/lib/editorjs.js"); + var List = require("$:/plugins/tiddlywiki/editorjs/lib/editorjs-list.js"); + var Header = require("$:/plugins/tiddlywiki/editorjs/lib/header.js"); + const editor = new EditorJS({ + holder: container, + tools: { + list: List, + header: Header + } + }); + + editor.isReady + .then(() => { + console.log('Editor.js is ready to work!') + }) + .catch((reason) => { + console.log('Editor.js initialization failed because of', reason) + }); + parent.insertBefore(container,nextSibling); + this.domNodes.push(container); +}; + +/* +Compute the internal state of the widget +*/ +EditorJSWidget.prototype.execute = function() { + // Nothing to do for a text node +}; + +/* +Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering +*/ +EditorJSWidget.prototype.refresh = function(changedTiddlers) { + var changedAttributes = this.computeAttributes(); + if(changedAttributes.text) { + this.refreshSelf(); + return true; + } else { + return false; + } +}; + +exports.editorjs = EditorJSWidget; From 3d2392dc7092419ba0a7c2cbbd8db64ecd4d234a Mon Sep 17 00:00:00 2001 From: linonetwo Date: Sun, 23 Mar 2025 20:24:12 +0800 Subject: [PATCH 78/98] feat: debounced on change --- core/modules/utils/debounce.js | 37 +++++++++++++++++++++++++++ plugins/tiddlywiki/editorjs/widget.js | 19 ++++++++++++-- 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 core/modules/utils/debounce.js diff --git a/core/modules/utils/debounce.js b/core/modules/utils/debounce.js new file mode 100644 index 000000000..756c162c2 --- /dev/null +++ b/core/modules/utils/debounce.js @@ -0,0 +1,37 @@ +/*\ +title: $:/core/modules/utils/debounce.js +type: application/javascript +module-type: utils + +Debounce function execution. + +Usage: + +- func: function to be debounced +- wait: time to wait before executing the function +- immediate: if true, the function is executed immediately + +\*/ + +"use strict"; + +function debounce(func, wait, immediate) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if(!immediate) { + func.apply(context, args); + } + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if(callNow) { + func.apply(context, args); + } + }; +}; + +exports.debounce = debounce; diff --git a/plugins/tiddlywiki/editorjs/widget.js b/plugins/tiddlywiki/editorjs/widget.js index 511921b1c..caecb4ad4 100644 --- a/plugins/tiddlywiki/editorjs/widget.js +++ b/plugins/tiddlywiki/editorjs/widget.js @@ -10,6 +10,7 @@ Text node widget "use strict"; var Widget = require("$:/core/modules/widgets/widget.js").widget; +var debounce = require("$:/core/modules/utils/debounce.js").debounce; var EditorJSWidget = function(parseTreeNode,options) { this.initialise(parseTreeNode,options); @@ -38,20 +39,34 @@ EditorJSWidget.prototype.render = function(parent,nextSibling) { tools: { list: List, header: Header - } + }, + onChange: this.debouncedSaveEditorContent.bind(this) }); + this.editor = editor; editor.isReady .then(() => { - console.log('Editor.js is ready to work!') + console.log('Editor.js is ready to work!', editor.onChange); }) .catch((reason) => { console.log('Editor.js initialization failed because of', reason) }); + parent.insertBefore(container,nextSibling); this.domNodes.push(container); }; +EditorJSWidget.prototype.saveEditorContent = function() { + this.editor.save().then((outputData) => { + console.log('Article data: ', outputData) + }).catch((error) => { + console.log('Saving failed: ', error) + }); +} + +// Debounced save function for performance +EditorJSWidget.prototype.debouncedSaveEditorContent = debounce(EditorJSWidget.prototype.saveEditorContent, 300); + /* Compute the internal state of the widget */ From 221193a587b18ad15c9537d30eb28118691ec00d Mon Sep 17 00:00:00 2001 From: linonetwo Date: Sun, 23 Mar 2025 20:57:19 +0800 Subject: [PATCH 79/98] WIP: ast transformers --- .../editorjs/ast/wikiAstFromEditorJSAst.js | 68 +++++++++++++++ .../editorjs/ast/wikiAstToEditorJSAst.js | 83 +++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 plugins/tiddlywiki/editorjs/ast/wikiAstFromEditorJSAst.js create mode 100644 plugins/tiddlywiki/editorjs/ast/wikiAstToEditorJSAst.js diff --git a/plugins/tiddlywiki/editorjs/ast/wikiAstFromEditorJSAst.js b/plugins/tiddlywiki/editorjs/ast/wikiAstFromEditorJSAst.js new file mode 100644 index 000000000..eeb26bd7f --- /dev/null +++ b/plugins/tiddlywiki/editorjs/ast/wikiAstFromEditorJSAst.js @@ -0,0 +1,68 @@ +/*\ +title: $:/plugins/tiddlywiki/editorjs/ast/wikiAstFromEditorJSAst.js +type: application/javascript +module-type: library + +Get the EditorJS AST from a Wiki AST + +\*/ + + +/** + * Key is `node.type`, value is node converter function. + */ +const builders = { + // auto parse basic element nodes + // eslint-disable-next-line unicorn/prefer-object-from-entries + ...(htmlTags).reduce( + (previousValue, currentValue) => { + previousValue[currentValue] = element; + return previousValue; + }, + // eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter, @typescript-eslint/consistent-type-assertions + {}, + ), + [ELEMENT_CODE_BLOCK]: codeblock, + [ELEMENT_LIC]: lic, + text, + widget, + macro: widget, + set, +}; + +function wikiAstFromEditorJSAst(input) { + return convertNodes(builders, Array.isArray(input) ? input : [input]); +} + +exports.wikiAstFromEditorJSAst = wikiAstFromEditorJSAst; + +function convertNodes(builders, nodes) { + if (nodes === undefined || nodes.length === 0) { + return []; + } + + return nodes.reduce((accumulator, node) => { + return [...accumulator, ...convertWikiAstNode(builders, node)]; + }, []); +} + +function convertWikiAstNode(builders, node) { + // only text and root node don't have a `type` field, deal with it first + if (isText(node)) { + return [builders.text(builders, node)]; + } + if (isElement(node)) { + const builder = builders[node.type]; + if (typeof builder === 'function') { + const builtSlateNodeOrNodes = builder(builders, node); + return Array.isArray(builtSlateNodeOrNodes) + ? builtSlateNodeOrNodes.map((child) => ({ ...getSlatePlateASTAdditionalProperties(node), ...child })) + : ([{ ...getSlatePlateASTAdditionalProperties(node), ...builtSlateNodeOrNodes }]); + } + } + // it might be a root or pure parent node, reduce it + if ('children' in node) { + return convertNodes(builders, node.children); + } + return []; +} diff --git a/plugins/tiddlywiki/editorjs/ast/wikiAstToEditorJSAst.js b/plugins/tiddlywiki/editorjs/ast/wikiAstToEditorJSAst.js new file mode 100644 index 000000000..37e953580 --- /dev/null +++ b/plugins/tiddlywiki/editorjs/ast/wikiAstToEditorJSAst.js @@ -0,0 +1,83 @@ +/*\ +title: $:/plugins/tiddlywiki/editorjs/ast/wikiAstToEditorJSAst.js +type: application/javascript +module-type: library + +Get the EditorJS AST from a Wiki AST + +\*/ +function wikiAstToEditorJSAst(node, options) { + return convertNodes({ ...initialContext, ...options }, Array.isArray(node) ? node : [node]); +} + +exports.wikiAstToEditorJSAst = wikiAstToEditorJSAst; + +const initialContext = { + builders, + marks: {}, +}; + +function convertNodes(context, nodes) { + if (nodes === undefined || nodes.length === 0) { + return [{ text: '' }]; + } + + return nodes.reduce((accumulator, node) => { + return [...accumulator, ...editorJSNode(context, node)]; + }, []); +} + +function editorJSNode(context, node) { + const id = context.idCreator?.(); + const withId = (nodeToAddId) => (id === undefined ? nodeToAddId : { ...nodeToAddId, id }); + if ('rule' in node && node.rule !== undefined && node.rule in context.builders) { + const builder = context.builders[node.rule]; + if (typeof builder === 'function') { + // basic elements + const builtEditorJSNodeOrNodes = builder(context, node); + return Array.isArray(builtEditorJSNodeOrNodes) + ? builtEditorJSNodeOrNodes.map((child) => withId(child)) + : ([withId(builtEditorJSNodeOrNodes)]); + } + } else if ('text' in node) { + // text node + return [withId({ text: node.text })]; + } else { + console.warn(`WikiAst get Unknown node type: ${JSON.stringify(node)}`); + return []; + } + return []; +} + +const builders = { + element, + text, +}; + +/** Slate node is compact, we need to filter out some keys from wikiast */ +const textLevelKeysToOmit = ['type', 'start', 'end']; + +function text(context, text) { + return { + text: '', // provides default text + ...omit(text, textLevelKeysToOmit), + ...context.marks, + }; +} + +const elementBuilders = { ul, ol: ul, li, ...marks }; + +function element(context, node) { + const { tag, children } = node; + if (typeof elementBuilders[tag] === 'function') { + return elementBuilders[tag](context, node); + } + const result = { + type: tag, + children: convertNodes(context, children), + }; + if (node.rule) { + result.rule = node.rule; + } + return result; +} From cec30f9ed26cbc84053031fb082928e3f5325530 Mon Sep 17 00:00:00 2001 From: linonetwo Date: Sun, 23 Mar 2025 21:40:47 +0800 Subject: [PATCH 80/98] feat: try prosemirror instead --- editions/tw5.com-server/tiddlywiki.info | 2 +- .../editorjs/files/editorjs-list.umd.js | 8 - .../tiddlywiki/editorjs/files/editorjs.umd.js | 51 - .../tiddlywiki/editorjs/files/header.umd.js | 15 - .../editorjs/files/tiddlywiki.files | 26 - plugins/tiddlywiki/editorjs/readme.tid | 14 - plugins/tiddlywiki/editorjs/widget.js | 90 - .../ast/wikiAstFromEditorJSAst.js | 8 +- .../ast/wikiAstToEditorJSAst.js | 20 +- .../files/prosemirror-example-setup.cjs | 469 ++ .../prosemirror/files/prosemirror-model.cjs | 2893 +++++++++ .../files/prosemirror-schema-basic.cjs | 246 + .../files/prosemirror-schema-list.cjs | 253 + .../prosemirror/files/prosemirror-state.cjs | 1034 ++++ .../prosemirror/files/prosemirror-view.cjs | 5253 +++++++++++++++++ .../prosemirror/files/tiddlywiki.files | 47 + .../{editorjs => prosemirror}/plugin.info | 4 +- plugins/tiddlywiki/prosemirror/readme.tid | 23 + plugins/tiddlywiki/prosemirror/widget.js | 97 + 19 files changed, 10332 insertions(+), 221 deletions(-) delete mode 100644 plugins/tiddlywiki/editorjs/files/editorjs-list.umd.js delete mode 100644 plugins/tiddlywiki/editorjs/files/editorjs.umd.js delete mode 100644 plugins/tiddlywiki/editorjs/files/header.umd.js delete mode 100755 plugins/tiddlywiki/editorjs/files/tiddlywiki.files delete mode 100755 plugins/tiddlywiki/editorjs/readme.tid delete mode 100644 plugins/tiddlywiki/editorjs/widget.js rename plugins/tiddlywiki/{editorjs => prosemirror}/ast/wikiAstFromEditorJSAst.js (88%) rename plugins/tiddlywiki/{editorjs => prosemirror}/ast/wikiAstToEditorJSAst.js (74%) create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-example-setup.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-model.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-schema-basic.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-schema-list.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-state.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-view.cjs create mode 100755 plugins/tiddlywiki/prosemirror/files/tiddlywiki.files rename plugins/tiddlywiki/{editorjs => prosemirror}/plugin.info (62%) create mode 100755 plugins/tiddlywiki/prosemirror/readme.tid create mode 100644 plugins/tiddlywiki/prosemirror/widget.js diff --git a/editions/tw5.com-server/tiddlywiki.info b/editions/tw5.com-server/tiddlywiki.info index aea777ba1..07a6127b0 100644 --- a/editions/tw5.com-server/tiddlywiki.info +++ b/editions/tw5.com-server/tiddlywiki.info @@ -5,7 +5,7 @@ "tiddlywiki/filesystem", "tiddlywiki/highlight", "tiddlywiki/internals", - "tiddlywiki/editorjs" + "tiddlywiki/prosemirror" ], "themes": [ "tiddlywiki/vanilla", diff --git a/plugins/tiddlywiki/editorjs/files/editorjs-list.umd.js b/plugins/tiddlywiki/editorjs/files/editorjs-list.umd.js deleted file mode 100644 index e5777b01a..000000000 --- a/plugins/tiddlywiki/editorjs/files/editorjs-list.umd.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Skipped minification because the original files appears to be already minified. - * Original file: /npm/@editorjs/list@2.0.6/dist/editorjs-list.umd.js - * - * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files - */ -(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode('.cdx-list{margin:0;padding:0;outline:none;display:grid;counter-reset:item;gap:var(--spacing-s);padding:var(--spacing-xs);--spacing-s: 8px;--spacing-xs: 6px;--list-counter-type: numeric;--radius-border: 5px;--checkbox-background: #fff;--color-border: #C9C9C9;--color-bg-checked: #369FFF;--line-height: 1.45em;--color-bg-checked-hover: #0059AB;--color-tick: #fff;--size-checkbox: 1.2em}.cdx-list__item{line-height:var(--line-height);display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto auto;grid-template-areas:"checkbox content" ". child"}.cdx-list__item-children{display:grid;grid-area:child;gap:var(--spacing-s);padding-top:var(--spacing-s)}.cdx-list__item [contenteditable]{outline:none}.cdx-list__item-content{word-break:break-word;white-space:pre-wrap;grid-area:content;padding-left:var(--spacing-s)}.cdx-list__item:before{counter-increment:item;white-space:nowrap}.cdx-list-ordered .cdx-list__item:before{content:counters(item,".",var(--list-counter-type)) "."}.cdx-list-ordered{counter-reset:item}.cdx-list-unordered .cdx-list__item:before{content:"•"}.cdx-list-checklist .cdx-list__item:before{content:""}.cdx-list__settings .cdx-settings-button{width:50%}.cdx-list__checkbox{padding-top:calc((var(--line-height) - var(--size-checkbox)) / 2);grid-area:checkbox;width:var(--size-checkbox);height:var(--size-checkbox);display:flex;cursor:pointer}.cdx-list__checkbox svg{opacity:0;height:var(--size-checkbox);width:var(--size-checkbox);left:-1px;top:-1px;position:absolute}@media (hover: hover){.cdx-list__checkbox:not(.cdx-list__checkbox--no-hover):hover .cdx-list__checkbox-check svg{opacity:1}}.cdx-list__checkbox--checked{line-height:var(--line-height)}@media (hover: hover){.cdx-list__checkbox--checked:not(.cdx-list__checkbox--checked--no-hover):hover .cdx-checklist__checkbox-check{background:var(--color-bg-checked-hover);border-color:var(--color-bg-checked-hover)}}.cdx-list__checkbox--checked .cdx-list__checkbox-check{background:var(--color-bg-checked);border-color:var(--color-bg-checked)}.cdx-list__checkbox--checked .cdx-list__checkbox-check svg{opacity:1}.cdx-list__checkbox--checked .cdx-list__checkbox-check svg path{stroke:var(--color-tick)}.cdx-list__checkbox--checked .cdx-list__checkbox-check:before{opacity:0;visibility:visible;transform:scale(2.5)}.cdx-list__checkbox-check{cursor:pointer;display:inline-block;position:relative;margin:0 auto;width:var(--size-checkbox);height:var(--size-checkbox);box-sizing:border-box;border-radius:var(--radius-border);border:1px solid var(--color-border);background:var(--checkbox-background)}.cdx-list__checkbox-check:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border-radius:100%;background-color:var(--color-bg-checked);visibility:hidden;pointer-events:none;transform:scale(1);transition:transform .4s ease-out,opacity .4s}.cdx-list-start-with-field{background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:2px;display:grid;grid-template-columns:auto auto 1fr;grid-template-rows:auto}.cdx-list-start-with-field--invalid{background:#FFECED;border:1px solid #E13F3F}.cdx-list-start-with-field--invalid .cdx-list-start-with-field__input{color:#e13f3f}.cdx-list-start-with-field__input{font-size:14px;outline:none;font-weight:500;font-family:inherit;border:0;background:transparent;margin:0;padding:0;line-height:22px;min-width:calc(100% - var(--toolbox-buttons-size) - var(--icon-margin-right))}.cdx-list-start-with-field__input::placeholder{color:var(--grayText);font-weight:500}')),document.head.appendChild(e)}}catch(c){console.error("vite-plugin-css-injected-by-js",c)}})(); -(function(P,_){typeof exports=="object"&&typeof module<"u"?module.exports=_():typeof define=="function"&&define.amd?define(_):(P=typeof globalThis<"u"?globalThis:P||self,P.EditorjsList=_())})(this,function(){"use strict";const P='',_='',Be='',We='',ct='',dt='',ft='',pt='',ht='',mt='';var M=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function gt(e){if(e.__esModule)return e;var t=e.default;if(typeof t=="function"){var n=function r(){return this instanceof r?Reflect.construct(t,arguments,this.constructor):t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach(function(r){var i=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(n,r,i.get?i:{enumerable:!0,get:function(){return e[r]}})}),n}var c={},X={},G={};Object.defineProperty(G,"__esModule",{value:!0}),G.allInputsSelector=vt;function vt(){var e=["text","password","email","number","search","tel","url"];return"[contenteditable=true], textarea, input:not([type]), "+e.map(function(t){return'input[type="'.concat(t,'"]')}).join(", ")}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.allInputsSelector=void 0;var t=G;Object.defineProperty(e,"allInputsSelector",{enumerable:!0,get:function(){return t.allInputsSelector}})})(X);var O={},V={};Object.defineProperty(V,"__esModule",{value:!0}),V.isNativeInput=bt;function bt(e){var t=["INPUT","TEXTAREA"];return e&&e.tagName?t.includes(e.tagName):!1}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isNativeInput=void 0;var t=V;Object.defineProperty(e,"isNativeInput",{enumerable:!0,get:function(){return t.isNativeInput}})})(O);var De={},Y={};Object.defineProperty(Y,"__esModule",{value:!0}),Y.append=yt;function yt(e,t){Array.isArray(t)?t.forEach(function(n){e.appendChild(n)}):e.appendChild(t)}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.append=void 0;var t=Y;Object.defineProperty(e,"append",{enumerable:!0,get:function(){return t.append}})})(De);var J={},Q={};Object.defineProperty(Q,"__esModule",{value:!0}),Q.blockElements=Ct;function Ct(){return["address","article","aside","blockquote","canvas","div","dl","dt","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","li","main","nav","noscript","ol","output","p","pre","ruby","section","table","tbody","thead","tr","tfoot","ul","video"]}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.blockElements=void 0;var t=Q;Object.defineProperty(e,"blockElements",{enumerable:!0,get:function(){return t.blockElements}})})(J);var He={},Z={};Object.defineProperty(Z,"__esModule",{value:!0}),Z.calculateBaseline=St;function St(e){var t=window.getComputedStyle(e),n=parseFloat(t.fontSize),r=parseFloat(t.lineHeight)||n*1.2,i=parseFloat(t.paddingTop),a=parseFloat(t.borderTopWidth),l=parseFloat(t.marginTop),s=n*.8,o=(r-n)/2,d=l+a+i+o+s;return d}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.calculateBaseline=void 0;var t=Z;Object.defineProperty(e,"calculateBaseline",{enumerable:!0,get:function(){return t.calculateBaseline}})})(He);var Fe={},x={},ee={},te={};Object.defineProperty(te,"__esModule",{value:!0}),te.isContentEditable=Ot;function Ot(e){return e.contentEditable==="true"}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isContentEditable=void 0;var t=te;Object.defineProperty(e,"isContentEditable",{enumerable:!0,get:function(){return t.isContentEditable}})})(ee),Object.defineProperty(x,"__esModule",{value:!0}),x.canSetCaret=Et;var kt=O,_t=ee;function Et(e){var t=!0;if((0,kt.isNativeInput)(e))switch(e.type){case"file":case"checkbox":case"radio":case"hidden":case"submit":case"button":case"image":case"reset":t=!1;break}else t=(0,_t.isContentEditable)(e);return t}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.canSetCaret=void 0;var t=x;Object.defineProperty(e,"canSetCaret",{enumerable:!0,get:function(){return t.canSetCaret}})})(Fe);var N={},ne={};function It(e,t,n){const r=n.value!==void 0?"value":"get",i=n[r],a=`#${t}Cache`;if(n[r]=function(...l){return this[a]===void 0&&(this[a]=i.apply(this,l)),this[a]},r==="get"&&n.set){const l=n.set;n.set=function(s){delete e[a],l.apply(this,s)}}return n}function Re(){const e={win:!1,mac:!1,x11:!1,linux:!1},t=Object.keys(e).find(n=>window.navigator.appVersion.toLowerCase().indexOf(n)!==-1);return t!==void 0&&(e[t]=!0),e}function re(e){return e!=null&&e!==""&&(typeof e!="object"||Object.keys(e).length>0)}function wt(e){return!re(e)}const Pt=()=>typeof window<"u"&&window.navigator!==null&&re(window.navigator.platform)&&(/iP(ad|hone|od)/.test(window.navigator.platform)||window.navigator.platform==="MacIntel"&&window.navigator.maxTouchPoints>1);function jt(e){const t=Re();return e=e.replace(/shift/gi,"⇧").replace(/backspace/gi,"⌫").replace(/enter/gi,"⏎").replace(/up/gi,"↑").replace(/left/gi,"→").replace(/down/gi,"↓").replace(/right/gi,"←").replace(/escape/gi,"⎋").replace(/insert/gi,"Ins").replace(/delete/gi,"␡").replace(/\+/gi,"+"),t.mac?e=e.replace(/ctrl|cmd/gi,"⌘").replace(/alt/gi,"⌥"):e=e.replace(/cmd/gi,"Ctrl").replace(/windows/gi,"WIN"),e}function Tt(e){return e[0].toUpperCase()+e.slice(1)}function Lt(e){const t=document.createElement("div");t.style.position="absolute",t.style.left="-999px",t.style.bottom="-999px",t.innerHTML=e,document.body.appendChild(t);const n=window.getSelection(),r=document.createRange();if(r.selectNode(t),n===null)throw new Error("Cannot copy text to clipboard");n.removeAllRanges(),n.addRange(r),document.execCommand("copy"),document.body.removeChild(t)}function Mt(e,t,n){let r;return(...i)=>{const a=this,l=()=>{r=void 0,n!==!0&&e.apply(a,i)},s=n===!0&&r!==void 0;window.clearTimeout(r),r=window.setTimeout(l,t),s&&e.apply(a,i)}}function C(e){return Object.prototype.toString.call(e).match(/\s([a-zA-Z]+)/)[1].toLowerCase()}function Nt(e){return C(e)==="boolean"}function qe(e){return C(e)==="function"||C(e)==="asyncfunction"}function At(e){return qe(e)&&/^\s*class\s+/.test(e.toString())}function $t(e){return C(e)==="number"}function A(e){return C(e)==="object"}function Bt(e){return Promise.resolve(e)===e}function Wt(e){return C(e)==="string"}function Dt(e){return C(e)==="undefined"}function ie(e,...t){if(!t.length)return e;const n=t.shift();if(A(e)&&A(n))for(const r in n)A(n[r])?(e[r]===void 0&&Object.assign(e,{[r]:{}}),ie(e[r],n[r])):Object.assign(e,{[r]:n[r]});return ie(e,...t)}function Ht(e,t,n){const r=`«${t}» is deprecated and will be removed in the next major release. Please use the «${n}» instead.`;e&&console.warn(r)}function Ft(e){try{return new URL(e).href}catch{}return e.substring(0,2)==="//"?window.location.protocol+e:window.location.origin+e}function Rt(e){return e>47&&e<58||e===32||e===13||e===229||e>64&&e<91||e>95&&e<112||e>185&&e<193||e>218&&e<223}const qt={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,LEFT:37,UP:38,DOWN:40,RIGHT:39,DELETE:46,META:91,SLASH:191},Ut={LEFT:0,WHEEL:1,RIGHT:2,BACKWARD:3,FORWARD:4};class zt{constructor(){this.completed=Promise.resolve()}add(t){return new Promise((n,r)=>{this.completed=this.completed.then(t).then(n).catch(r)})}}function Kt(e,t,n=void 0){let r,i,a,l=null,s=0;n||(n={});const o=function(){s=n.leading===!1?0:Date.now(),l=null,a=e.apply(r,i),l===null&&(r=i=null)};return function(){const d=Date.now();!s&&n.leading===!1&&(s=d);const u=t-(d-s);return r=this,i=arguments,u<=0||u>t?(l&&(clearTimeout(l),l=null),s=d,a=e.apply(r,i),l===null&&(r=i=null)):!l&&n.trailing!==!1&&(l=setTimeout(o,u)),a}}const ae=gt(Object.freeze(Object.defineProperty({__proto__:null,PromiseQueue:zt,beautifyShortcut:jt,cacheable:It,capitalize:Tt,copyTextToClipboard:Lt,debounce:Mt,deepMerge:ie,deprecationAssert:Ht,getUserOS:Re,getValidUrl:Ft,isBoolean:Nt,isClass:At,isEmpty:wt,isFunction:qe,isIosDevice:Pt,isNumber:$t,isObject:A,isPrintableKey:Rt,isPromise:Bt,isString:Wt,isUndefined:Dt,keyCodes:qt,mouseButtons:Ut,notEmpty:re,throttle:Kt,typeOf:C},Symbol.toStringTag,{value:"Module"})));Object.defineProperty(ne,"__esModule",{value:!0}),ne.containsOnlyInlineElements=Vt;var Xt=ae,Gt=J;function Vt(e){var t;(0,Xt.isString)(e)?(t=document.createElement("div"),t.innerHTML=e):t=e;var n=function(r){return!(0,Gt.blockElements)().includes(r.tagName.toLowerCase())&&Array.from(r.children).every(n)};return Array.from(t.children).every(n)}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.containsOnlyInlineElements=void 0;var t=ne;Object.defineProperty(e,"containsOnlyInlineElements",{enumerable:!0,get:function(){return t.containsOnlyInlineElements}})})(N);var Ue={},le={},$={},se={};Object.defineProperty(se,"__esModule",{value:!0}),se.make=Yt;function Yt(e,t,n){var r;t===void 0&&(t=null),n===void 0&&(n={});var i=document.createElement(e);if(Array.isArray(t)){var a=t.filter(function(s){return s!==void 0});(r=i.classList).add.apply(r,a)}else t!==null&&i.classList.add(t);for(var l in n)Object.prototype.hasOwnProperty.call(n,l)&&(i[l]=n[l]);return i}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.make=void 0;var t=se;Object.defineProperty(e,"make",{enumerable:!0,get:function(){return t.make}})})($),Object.defineProperty(le,"__esModule",{value:!0}),le.fragmentToString=Qt;var Jt=$;function Qt(e){var t=(0,Jt.make)("div");return t.appendChild(e),t.innerHTML}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.fragmentToString=void 0;var t=le;Object.defineProperty(e,"fragmentToString",{enumerable:!0,get:function(){return t.fragmentToString}})})(Ue);var ze={},oe={};Object.defineProperty(oe,"__esModule",{value:!0}),oe.getContentLength=xt;var Zt=O;function xt(e){var t,n;return(0,Zt.isNativeInput)(e)?e.value.length:e.nodeType===Node.TEXT_NODE?e.length:(n=(t=e.textContent)===null||t===void 0?void 0:t.length)!==null&&n!==void 0?n:0}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.getContentLength=void 0;var t=oe;Object.defineProperty(e,"getContentLength",{enumerable:!0,get:function(){return t.getContentLength}})})(ze);var ue={},ce={},Ke=M&&M.__spreadArray||function(e,t,n){if(n||arguments.length===2)for(var r=0,i=t.length,a;r0;){var r=n.shift();if(r){if(e=r,(0,Sn.isLeaf)(e)&&!(0,On.isNodeEmpty)(e,t))return!1;n.push.apply(n,Array.from(e.childNodes))}}return!0}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isEmpty=void 0;var t=be;Object.defineProperty(e,"isEmpty",{enumerable:!0,get:function(){return t.isEmpty}})})(Qe);var Ze={},ke={};Object.defineProperty(ke,"__esModule",{value:!0}),ke.isFragment=En;var _n=ae;function En(e){return(0,_n.isNumber)(e)?!1:!!e&&!!e.nodeType&&e.nodeType===Node.DOCUMENT_FRAGMENT_NODE}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isFragment=void 0;var t=ke;Object.defineProperty(e,"isFragment",{enumerable:!0,get:function(){return t.isFragment}})})(Ze);var xe={},_e={};Object.defineProperty(_e,"__esModule",{value:!0}),_e.isHTMLString=wn;var In=$;function wn(e){var t=(0,In.make)("div");return t.innerHTML=e,t.childElementCount>0}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isHTMLString=void 0;var t=_e;Object.defineProperty(e,"isHTMLString",{enumerable:!0,get:function(){return t.isHTMLString}})})(xe);var et={},Ee={};Object.defineProperty(Ee,"__esModule",{value:!0}),Ee.offset=Pn;function Pn(e){var t=e.getBoundingClientRect(),n=window.pageXOffset||document.documentElement.scrollLeft,r=window.pageYOffset||document.documentElement.scrollTop,i=t.top+r,a=t.left+n;return{top:i,left:a,bottom:i+t.height,right:a+t.width}}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.offset=void 0;var t=Ee;Object.defineProperty(e,"offset",{enumerable:!0,get:function(){return t.offset}})})(et);var tt={},Ie={};Object.defineProperty(Ie,"__esModule",{value:!0}),Ie.prepend=jn;function jn(e,t){Array.isArray(t)?(t=t.reverse(),t.forEach(function(n){return e.prepend(n)})):e.prepend(t)}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.prepend=void 0;var t=Ie;Object.defineProperty(e,"prepend",{enumerable:!0,get:function(){return t.prepend}})})(tt),function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.prepend=e.offset=e.make=e.isLineBreakTag=e.isSingleTag=e.isNodeEmpty=e.isLeaf=e.isHTMLString=e.isFragment=e.isEmpty=e.isElement=e.isContentEditable=e.isCollapsedWhitespaces=e.findAllInputs=e.isNativeInput=e.allInputsSelector=e.getDeepestNode=e.getDeepestBlockElements=e.getContentLength=e.fragmentToString=e.containsOnlyInlineElements=e.canSetCaret=e.calculateBaseline=e.blockElements=e.append=void 0;var t=X;Object.defineProperty(e,"allInputsSelector",{enumerable:!0,get:function(){return t.allInputsSelector}});var n=O;Object.defineProperty(e,"isNativeInput",{enumerable:!0,get:function(){return n.isNativeInput}});var r=De;Object.defineProperty(e,"append",{enumerable:!0,get:function(){return r.append}});var i=J;Object.defineProperty(e,"blockElements",{enumerable:!0,get:function(){return i.blockElements}});var a=He;Object.defineProperty(e,"calculateBaseline",{enumerable:!0,get:function(){return a.calculateBaseline}});var l=Fe;Object.defineProperty(e,"canSetCaret",{enumerable:!0,get:function(){return l.canSetCaret}});var s=N;Object.defineProperty(e,"containsOnlyInlineElements",{enumerable:!0,get:function(){return s.containsOnlyInlineElements}});var o=Ue;Object.defineProperty(e,"fragmentToString",{enumerable:!0,get:function(){return o.fragmentToString}});var d=ze;Object.defineProperty(e,"getContentLength",{enumerable:!0,get:function(){return d.getContentLength}});var u=ue;Object.defineProperty(e,"getDeepestBlockElements",{enumerable:!0,get:function(){return u.getDeepestBlockElements}});var h=Ge;Object.defineProperty(e,"getDeepestNode",{enumerable:!0,get:function(){return h.getDeepestNode}});var g=Ye;Object.defineProperty(e,"findAllInputs",{enumerable:!0,get:function(){return g.findAllInputs}});var L=Je;Object.defineProperty(e,"isCollapsedWhitespaces",{enumerable:!0,get:function(){return L.isCollapsedWhitespaces}});var w=ee;Object.defineProperty(e,"isContentEditable",{enumerable:!0,get:function(){return w.isContentEditable}});var nr=ge;Object.defineProperty(e,"isElement",{enumerable:!0,get:function(){return nr.isElement}});var rr=Qe;Object.defineProperty(e,"isEmpty",{enumerable:!0,get:function(){return rr.isEmpty}});var ir=Ze;Object.defineProperty(e,"isFragment",{enumerable:!0,get:function(){return ir.isFragment}});var ar=xe;Object.defineProperty(e,"isHTMLString",{enumerable:!0,get:function(){return ar.isHTMLString}});var lr=ye;Object.defineProperty(e,"isLeaf",{enumerable:!0,get:function(){return lr.isLeaf}});var sr=Se;Object.defineProperty(e,"isNodeEmpty",{enumerable:!0,get:function(){return sr.isNodeEmpty}});var or=B;Object.defineProperty(e,"isLineBreakTag",{enumerable:!0,get:function(){return or.isLineBreakTag}});var ur=W;Object.defineProperty(e,"isSingleTag",{enumerable:!0,get:function(){return ur.isSingleTag}});var cr=$;Object.defineProperty(e,"make",{enumerable:!0,get:function(){return cr.make}});var dr=et;Object.defineProperty(e,"offset",{enumerable:!0,get:function(){return dr.offset}});var fr=tt;Object.defineProperty(e,"prepend",{enumerable:!0,get:function(){return fr.prepend}})}(c);const m="cdx-list",p={wrapper:m,item:`${m}__item`,itemContent:`${m}__item-content`,itemChildren:`${m}__item-children`};class v{static get CSS(){return{...p,orderedList:`${m}-ordered`}}constructor(t,n){this.config=n,this.readOnly=t}renderWrapper(t){let n;return t===!0?n=c.make("ol",[v.CSS.wrapper,v.CSS.orderedList]):n=c.make("ol",[v.CSS.orderedList,v.CSS.itemChildren]),n}renderItem(t,n){const r=c.make("li",v.CSS.item),i=c.make("div",v.CSS.itemContent,{innerHTML:t,contentEditable:(!this.readOnly).toString()});return r.appendChild(i),r}getItemContent(t){const n=t.querySelector(`.${v.CSS.itemContent}`);return!n||c.isEmpty(n)?"":n.innerHTML}getItemMeta(){return{}}composeDefaultMeta(){return{}}}class b{static get CSS(){return{...p,unorderedList:`${m}-unordered`}}constructor(t,n){this.config=n,this.readOnly=t}renderWrapper(t){let n;return t===!0?n=c.make("ul",[b.CSS.wrapper,b.CSS.unorderedList]):n=c.make("ul",[b.CSS.unorderedList,b.CSS.itemChildren]),n}renderItem(t,n){const r=c.make("li",b.CSS.item),i=c.make("div",b.CSS.itemContent,{innerHTML:t,contentEditable:(!this.readOnly).toString()});return r.appendChild(i),r}getItemContent(t){const n=t.querySelector(`.${b.CSS.itemContent}`);return!n||c.isEmpty(n)?"":n.innerHTML}getItemMeta(){return{}}composeDefaultMeta(){return{}}}function k(e){return e.nodeType===Node.ELEMENT_NODE}var j={},we={},H={},F={};Object.defineProperty(F,"__esModule",{value:!0}),F.getContenteditableSlice=Ln;var Tn=c;function Ln(e,t,n,r,i){var a;i===void 0&&(i=!1);var l=document.createRange();if(r==="left"?(l.setStart(e,0),l.setEnd(t,n)):(l.setStart(t,n),l.setEnd(e,e.childNodes.length)),i===!0){var s=l.extractContents();return(0,Tn.fragmentToString)(s)}var o=l.cloneContents(),d=document.createElement("div");d.appendChild(o);var u=(a=d.textContent)!==null&&a!==void 0?a:"";return u}Object.defineProperty(H,"__esModule",{value:!0}),H.checkContenteditableSliceForEmptiness=An;var Mn=c,Nn=F;function An(e,t,n,r){var i=(0,Nn.getContenteditableSlice)(e,t,n,r);return(0,Mn.isCollapsedWhitespaces)(i)}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.checkContenteditableSliceForEmptiness=void 0;var t=H;Object.defineProperty(e,"checkContenteditableSliceForEmptiness",{enumerable:!0,get:function(){return t.checkContenteditableSliceForEmptiness}})})(we);var nt={};(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.getContenteditableSlice=void 0;var t=F;Object.defineProperty(e,"getContenteditableSlice",{enumerable:!0,get:function(){return t.getContenteditableSlice}})})(nt);var rt={},Pe={};Object.defineProperty(Pe,"__esModule",{value:!0}),Pe.focus=Bn;var $n=c;function Bn(e,t){var n,r;if(t===void 0&&(t=!0),(0,$n.isNativeInput)(e)){e.focus();var i=t?0:e.value.length;e.setSelectionRange(i,i)}else{var a=document.createRange(),l=window.getSelection();if(!l)return;var s=function(g,L){L===void 0&&(L=!1);var w=document.createTextNode("");L?g.insertBefore(w,g.firstChild):g.appendChild(w),a.setStart(w,0),a.setEnd(w,0)},o=function(g){return g!=null},d=e.childNodes,u=t?d[0]:d[d.length-1];if(o(u)){for(;o(u)&&u.nodeType!==Node.TEXT_NODE;)u=t?u.firstChild:u.lastChild;if(o(u)&&u.nodeType===Node.TEXT_NODE){var h=(r=(n=u.textContent)===null||n===void 0?void 0:n.length)!==null&&r!==void 0?r:0,i=t?0:h;a.setStart(u,i),a.setEnd(u,i)}else s(e,t)}else s(e);l.removeAllRanges(),l.addRange(a)}}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.focus=void 0;var t=Pe;Object.defineProperty(e,"focus",{enumerable:!0,get:function(){return t.focus}})})(rt);var je={},R={};Object.defineProperty(R,"__esModule",{value:!0}),R.getCaretNodeAndOffset=Wn;function Wn(){var e=window.getSelection();if(e===null)return[null,0];var t=e.focusNode,n=e.focusOffset;return t===null?[null,0]:(t.nodeType!==Node.TEXT_NODE&&t.childNodes.length>0&&(t.childNodes[n]!==void 0?(t=t.childNodes[n],n=0):(t=t.childNodes[n-1],t.textContent!==null&&(n=t.textContent.length))),[t,n])}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.getCaretNodeAndOffset=void 0;var t=R;Object.defineProperty(e,"getCaretNodeAndOffset",{enumerable:!0,get:function(){return t.getCaretNodeAndOffset}})})(je);var it={},q={};Object.defineProperty(q,"__esModule",{value:!0}),q.getRange=Dn;function Dn(){var e=window.getSelection();return e&&e.rangeCount?e.getRangeAt(0):null}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.getRange=void 0;var t=q;Object.defineProperty(e,"getRange",{enumerable:!0,get:function(){return t.getRange}})})(it);var at={},Te={};Object.defineProperty(Te,"__esModule",{value:!0}),Te.isCaretAtEndOfInput=Rn;var lt=c,Hn=je,Fn=we;function Rn(e){var t=(0,lt.getDeepestNode)(e,!0);if(t===null)return!0;if((0,lt.isNativeInput)(t))return t.selectionEnd===t.value.length;var n=(0,Hn.getCaretNodeAndOffset)(),r=n[0],i=n[1];return r===null?!1:(0,Fn.checkContenteditableSliceForEmptiness)(e,r,i,"right")}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isCaretAtEndOfInput=void 0;var t=Te;Object.defineProperty(e,"isCaretAtEndOfInput",{enumerable:!0,get:function(){return t.isCaretAtEndOfInput}})})(at);var st={},Le={};Object.defineProperty(Le,"__esModule",{value:!0}),Le.isCaretAtStartOfInput=zn;var U=c,qn=R,Un=H;function zn(e){var t=(0,U.getDeepestNode)(e);if(t===null||(0,U.isEmpty)(e))return!0;if((0,U.isNativeInput)(t))return t.selectionEnd===0;if((0,U.isEmpty)(e))return!0;var n=(0,qn.getCaretNodeAndOffset)(),r=n[0],i=n[1];return r===null?!1:(0,Un.checkContenteditableSliceForEmptiness)(e,r,i,"left")}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.isCaretAtStartOfInput=void 0;var t=Le;Object.defineProperty(e,"isCaretAtStartOfInput",{enumerable:!0,get:function(){return t.isCaretAtStartOfInput}})})(st);var ot={},Me={};Object.defineProperty(Me,"__esModule",{value:!0}),Me.save=Gn;var Kn=c,Xn=q;function Gn(){var e=(0,Xn.getRange)(),t=(0,Kn.make)("span");if(t.id="cursor",t.hidden=!0,!!e)return e.insertNode(t),function(){var r=window.getSelection();r&&(e.setStartAfter(t),e.setEndAfter(t),r.removeAllRanges(),r.addRange(e),setTimeout(function(){t.remove()},150))}}(function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.save=void 0;var t=Me;Object.defineProperty(e,"save",{enumerable:!0,get:function(){return t.save}})})(ot),function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.save=e.isCaretAtStartOfInput=e.isCaretAtEndOfInput=e.getRange=e.getCaretNodeAndOffset=e.focus=e.getContenteditableSlice=e.checkContenteditableSliceForEmptiness=void 0;var t=we;Object.defineProperty(e,"checkContenteditableSliceForEmptiness",{enumerable:!0,get:function(){return t.checkContenteditableSliceForEmptiness}});var n=nt;Object.defineProperty(e,"getContenteditableSlice",{enumerable:!0,get:function(){return n.getContenteditableSlice}});var r=rt;Object.defineProperty(e,"focus",{enumerable:!0,get:function(){return r.focus}});var i=je;Object.defineProperty(e,"getCaretNodeAndOffset",{enumerable:!0,get:function(){return i.getCaretNodeAndOffset}});var a=it;Object.defineProperty(e,"getRange",{enumerable:!0,get:function(){return a.getRange}});var l=at;Object.defineProperty(e,"isCaretAtEndOfInput",{enumerable:!0,get:function(){return l.isCaretAtEndOfInput}});var s=st;Object.defineProperty(e,"isCaretAtStartOfInput",{enumerable:!0,get:function(){return s.isCaretAtStartOfInput}});var o=ot;Object.defineProperty(e,"save",{enumerable:!0,get:function(){return o.save}})}(j);class f{static get CSS(){return{...p,checklist:`${m}-checklist`,itemChecked:`${m}__checkbox--checked`,noHover:`${m}__checkbox--no-hover`,checkbox:`${m}__checkbox-check`,checkboxContainer:`${m}__checkbox`}}constructor(t,n){this.config=n,this.readOnly=t}renderWrapper(t){let n;return t===!0?(n=c.make("ul",[f.CSS.wrapper,f.CSS.checklist]),n.addEventListener("click",r=>{const i=r.target;if(i){const a=i.closest(`.${f.CSS.checkboxContainer}`);a&&a.contains(i)&&this.toggleCheckbox(a)}})):n=c.make("ul",[f.CSS.checklist,f.CSS.itemChildren]),n}renderItem(t,n){const r=c.make("li",[f.CSS.item,f.CSS.item]),i=c.make("div",f.CSS.itemContent,{innerHTML:t,contentEditable:(!this.readOnly).toString()}),a=c.make("span",f.CSS.checkbox),l=c.make("div",f.CSS.checkboxContainer);return n.checked===!0&&l.classList.add(f.CSS.itemChecked),a.innerHTML=P,l.appendChild(a),r.appendChild(l),r.appendChild(i),r}getItemContent(t){const n=t.querySelector(`.${f.CSS.itemContent}`);return!n||c.isEmpty(n)?"":n.innerHTML}getItemMeta(t){const n=t.querySelector(`.${f.CSS.checkboxContainer}`);return{checked:n?n.classList.contains(f.CSS.itemChecked):!1}}composeDefaultMeta(){return{checked:!1}}toggleCheckbox(t){t.classList.toggle(f.CSS.itemChecked),t.classList.add(f.CSS.noHover),t.addEventListener("mouseleave",()=>this.removeSpecialHoverBehavior(t),{once:!0})}removeSpecialHoverBehavior(t){t.classList.remove(f.CSS.noHover)}}function Ne(e,t="after"){const n=[];let r;function i(a){switch(t){case"after":return a.nextElementSibling;case"before":return a.previousElementSibling}}for(r=i(e);r!==null;)n.push(r),r=i(r);return n.length!==0?n:null}function y(e,t=!0){let n=e;return e.classList.contains(p.item)&&(n=e.querySelector(`.${p.itemChildren}`)),n===null?[]:t?Array.from(n.querySelectorAll(`:scope > .${p.item}`)):Array.from(n.querySelectorAll(`.${p.item}`))}function Vn(e){return e.nextElementSibling===null}function Yn(e){return e.querySelector(`.${p.itemChildren}`)!==null}function S(e){return e.querySelector(`.${p.itemChildren}`)}function Ae(e){let t=e;e.classList.contains(p.item)&&(t=S(e)),t!==null&&y(t).length===0&&t.remove()}function z(e){return e.querySelector(`.${p.itemContent}`)}function E(e,t=!0){const n=z(e);n&&j.focus(n,t)}class $e{get currentItem(){const t=window.getSelection();if(!t)return null;let n=t.anchorNode;return!n||(k(n)||(n=n.parentNode),!n)||!k(n)?null:n.closest(`.${p.item}`)}get currentItemLevel(){const t=this.currentItem;if(t===null)return null;let n=t.parentNode,r=0;for(;n!==null&&n!==this.listWrapper;)k(n)&&n.classList.contains(p.item)&&(r+=1),n=n.parentNode;return r+1}constructor({data:t,config:n,api:r,readOnly:i,block:a},l){this.config=n,this.data=t,this.readOnly=i,this.api=r,this.block=a,this.renderer=l}render(){return this.listWrapper=this.renderer.renderWrapper(!0),this.data.items.length?this.appendItems(this.data.items,this.listWrapper):this.appendItems([{content:"",meta:{},items:[]}],this.listWrapper),this.readOnly||this.listWrapper.addEventListener("keydown",t=>{switch(t.key){case"Enter":this.enterPressed(t);break;case"Backspace":this.backspace(t);break;case"Tab":t.shiftKey?this.shiftTab(t):this.addTab(t);break}},!1),"start"in this.data.meta&&this.data.meta.start!==void 0&&this.changeStartWith(this.data.meta.start),"counterType"in this.data.meta&&this.data.meta.counterType!==void 0&&this.changeCounters(this.data.meta.counterType),this.listWrapper}save(t){const n=t??this.listWrapper,r=l=>y(l).map(o=>{const d=S(o),u=this.renderer.getItemContent(o),h=this.renderer.getItemMeta(o),g=d?r(d):[];return{content:u,meta:h,items:g}}),i=n?r(n):[];let a={style:this.data.style,meta:{},items:i};return this.data.style==="ordered"&&(a.meta={start:this.data.meta.start,counterType:this.data.meta.counterType}),a}static get pasteConfig(){return{tags:["OL","UL","LI"]}}merge(t){const n=this.block.holder.querySelectorAll(`.${p.item}`),r=n[n.length-1],i=z(r);if(r===null||i===null||(i.insertAdjacentHTML("beforeend",t.items[0].content),this.listWrapper===void 0))return;const a=y(this.listWrapper);if(a.length===0)return;const l=a[a.length-1];let s=S(l);const o=t.items.shift();o!==void 0&&(o.items.length!==0&&(s===null&&(s=this.renderer.renderWrapper(!1)),this.appendItems(o.items,s)),t.items.length>0&&this.appendItems(t.items,this.listWrapper))}onPaste(t){const n=t.detail.data;this.data=this.pasteHandler(n);const r=this.listWrapper;r&&r.parentNode&&r.parentNode.replaceChild(this.render(),r)}pasteHandler(t){const{tagName:n}=t;let r="unordered",i;switch(n){case"OL":r="ordered",i="ol";break;case"UL":case"LI":r="unordered",i="ul"}const a={style:r,meta:{},items:[]};r==="ordered"&&(this.data.meta.counterType="numeric",this.data.meta.start=1);const l=s=>Array.from(s.querySelectorAll(":scope > li")).map(d=>{const u=d.querySelector(`:scope > ${i}`),h=u?l(u):[];return{content:d.innerHTML??"",meta:{},items:h}});return a.items=l(t),a}changeStartWith(t){this.listWrapper.style.setProperty("counter-reset",`item ${t-1}`),this.data.meta.start=t}changeCounters(t){this.listWrapper.style.setProperty("--list-counter-type",t),this.data.meta.counterType=t}enterPressed(t){var s;const n=this.currentItem;if(t.stopPropagation(),t.preventDefault(),t.isComposing||n===null)return;const r=((s=this.renderer)==null?void 0:s.getItemContent(n).trim().length)===0,i=n.parentNode===this.listWrapper,a=n.previousElementSibling===null,l=this.api.blocks.getCurrentBlockIndex();if(i&&r)if(Vn(n)&&!Yn(n)){a?this.convertItemToDefaultBlock(l,!0):this.convertItemToDefaultBlock();return}else{this.splitList(n);return}else if(r){this.unshiftItem(n);return}else this.splitItem(n)}backspace(t){var r;const n=this.currentItem;if(n!==null&&j.isCaretAtStartOfInput(n)&&((r=window.getSelection())==null?void 0:r.isCollapsed)!==!1){if(t.stopPropagation(),n.parentNode===this.listWrapper&&n.previousElementSibling===null){this.convertFirstItemToDefaultBlock();return}t.preventDefault(),this.mergeItemWithPrevious(n)}}shiftTab(t){t.stopPropagation(),t.preventDefault(),this.currentItem!==null&&this.unshiftItem(this.currentItem)}unshiftItem(t){if(!t.parentNode||!k(t.parentNode))return;const n=t.parentNode.closest(`.${p.item}`);if(!n)return;let r=S(t);if(t.parentElement===null)return;const i=Ne(t);i!==null&&(r===null&&(r=this.renderer.renderWrapper(!1)),i.forEach(a=>{r.appendChild(a)}),t.appendChild(r)),n.after(t),E(t,!1),Ae(n)}splitList(t){const n=y(t),r=this.block,i=this.api.blocks.getCurrentBlockIndex();if(n.length!==0){const o=n[0];this.unshiftItem(o),E(t,!1)}if(t.previousElementSibling===null&&t.parentNode===this.listWrapper){this.convertItemToDefaultBlock(i);return}const a=Ne(t);if(a===null)return;const l=this.renderer.renderWrapper(!0);a.forEach(o=>{l.appendChild(o)});const s=this.save(l);s.meta.start=this.data.style=="ordered"?1:void 0,this.api.blocks.insert(r==null?void 0:r.name,s,this.config,i+1),this.convertItemToDefaultBlock(i+1),l.remove()}splitItem(t){const[n,r]=j.getCaretNodeAndOffset();if(n===null)return;const i=z(t);let a;i===null?a="":a=j.getContenteditableSlice(i,n,r,"right",!0);const l=S(t),s=this.renderItem(a);t==null||t.after(s),l&&s.appendChild(l),E(s)}mergeItemWithPrevious(t){const n=t.previousElementSibling,r=t.parentNode;if(r===null||!k(r))return;const i=r.closest(`.${p.item}`);if(!n&&!i||n&&!k(n))return;let a;if(n){const h=y(n,!1);h.length!==0&&h.length!==0?a=h[h.length-1]:a=n}else a=i;const l=this.renderer.getItemContent(t);if(!a)return;E(a,!1);const s=z(a);if(s===null)return;s.insertAdjacentHTML("beforeend",l);const o=y(t);if(o.length===0){t.remove(),Ae(a);return}const d=n||i,u=S(d)??this.renderer.renderWrapper(!1);n?o.forEach(h=>{u.appendChild(h)}):o.forEach(h=>{u.prepend(h)}),S(d)===null&&a.appendChild(u),t.remove()}addTab(t){var a;t.stopPropagation(),t.preventDefault();const n=this.currentItem;if(!n)return;if(((a=this.config)==null?void 0:a.maxLevel)!==void 0){const l=this.currentItemLevel;if(l!==null&&l===this.config.maxLevel)return}const r=n.previousSibling;if(r===null||!k(r))return;const i=S(r);if(i)i.appendChild(n),y(n).forEach(s=>{i.appendChild(s)});else{const l=this.renderer.renderWrapper(!1);l.appendChild(n),y(n).forEach(o=>{l.appendChild(o)}),r.appendChild(l)}Ae(n),E(n,!1)}convertItemToDefaultBlock(t,n){let r;const i=this.currentItem,a=i!==null?this.renderer.getItemContent(i):"";n===!0&&this.api.blocks.delete(),t!==void 0?r=this.api.blocks.insert(void 0,{text:a},void 0,t):r=this.api.blocks.insert(),i==null||i.remove(),this.api.caret.setToBlock(r,"start")}convertFirstItemToDefaultBlock(){const t=this.currentItem;if(t===null)return;const n=y(t);if(n.length!==0){const l=n[0];this.unshiftItem(l),E(t)}const r=Ne(t),i=this.api.blocks.getCurrentBlockIndex(),a=r===null;this.convertItemToDefaultBlock(i,a)}renderItem(t,n){const r=n??this.renderer.composeDefaultMeta();switch(!0){case this.renderer instanceof v:return this.renderer.renderItem(t,r);case this.renderer instanceof b:return this.renderer.renderItem(t,r);default:return this.renderer.renderItem(t,r)}}appendItems(t,n){t.forEach(r=>{var a;const i=this.renderItem(r.content,r.meta);if(n.appendChild(i),r.items.length){const l=(a=this.renderer)==null?void 0:a.renderWrapper(!1);this.appendItems(r.items,l),i.appendChild(l)}})}}const I={wrapper:`${m}-start-with-field`,input:`${m}-start-with-field__input`,startWithElementWrapperInvalid:`${m}-start-with-field--invalid`};function Jn(e,{value:t,placeholder:n,attributes:r,sanitize:i}){const a=c.make("div",I.wrapper),l=c.make("input",I.input,{placeholder:n,tabIndex:-1,value:t});for(const s in r)l.setAttribute(s,r[s]);return a.appendChild(l),l.addEventListener("input",()=>{i!==void 0&&(l.value=i(l.value));const s=l.checkValidity();!s&&!a.classList.contains(I.startWithElementWrapperInvalid)&&a.classList.add(I.startWithElementWrapperInvalid),s&&a.classList.contains(I.startWithElementWrapperInvalid)&&a.classList.remove(I.startWithElementWrapperInvalid),s&&e(l.value)}),a}const T=new Map([["Numeric","numeric"],["Lower Roman","lower-roman"],["Upper Roman","upper-roman"],["Lower Alpha","lower-alpha"],["Upper Alpha","upper-alpha"]]),ut=new Map([["numeric",ct],["lower-roman",dt],["upper-roman",ft],["lower-alpha",ht],["upper-alpha",pt]]),hr="",mr="";function Qn(e){return e.replace(/\D+/g,"")}function Zn(e){return typeof e.items[0]=="string"}function xn(e){return!("meta"in e)}function er(e){return typeof e.items[0]!="string"&&"text"in e.items[0]&&"checked"in e.items[0]&&typeof e.items[0].text=="string"&&typeof e.items[0].checked=="boolean"}function tr(e){const t=[];return Zn(e)?(e.items.forEach(n=>{t.push({content:n,meta:{},items:[]})}),{style:e.style,meta:{},items:t}):er(e)?(e.items.forEach(n=>{t.push({content:n.text,meta:{checked:n.checked},items:[]})}),{style:"checklist",meta:{},items:t}):xn(e)?{style:e.style,meta:{},items:e.items}:e}class K{static get isReadOnlySupported(){return!0}static get enableLineBreaks(){return!0}static get toolbox(){return[{icon:Be,title:"Unordered List",data:{style:"unordered"}},{icon:We,title:"Ordered List",data:{style:"ordered"}},{icon:_,title:"Checklist",data:{style:"checklist"}}]}static get pasteConfig(){return{tags:["OL","UL","LI"]}}static get conversionConfig(){return{export:t=>K.joinRecursive(t),import:(t,n)=>({meta:{},items:[{content:t,meta:{},items:[]}],style:(n==null?void 0:n.defaultStyle)!==void 0?n.defaultStyle:"unordered"})}}get listStyle(){return this.data.style||this.defaultListStyle}set listStyle(t){var r;this.data.style=t,this.changeTabulatorByStyle();const n=this.list.render();(r=this.listElement)==null||r.replaceWith(n),this.listElement=n}constructor({data:t,config:n,api:r,readOnly:i,block:a}){var s;this.api=r,this.readOnly=i,this.config=n,this.block=a,this.defaultListStyle=((s=this.config)==null?void 0:s.defaultStyle)||"unordered",this.defaultCounterTypes=this.config.counterTypes||Array.from(T.values());const l={style:this.defaultListStyle,meta:{},items:[]};this.data=Object.keys(t).length?tr(t):l,this.listStyle==="ordered"&&this.data.meta.counterType===void 0&&(this.data.meta.counterType="numeric"),this.changeTabulatorByStyle()}static joinRecursive(t){return t.items.map(n=>`${n.content} ${K.joinRecursive(n)}`).join("")}render(){return this.listElement=this.list.render(),this.listElement}save(){return this.data=this.list.save(),this.data}merge(t){this.list.merge(t)}renderSettings(){const t=[{label:this.api.i18n.t("Unordered"),icon:Be,closeOnActivate:!0,isActive:this.listStyle=="unordered",onActivate:()=>{this.listStyle="unordered"}},{label:this.api.i18n.t("Ordered"),icon:We,closeOnActivate:!0,isActive:this.listStyle=="ordered",onActivate:()=>{this.listStyle="ordered"}},{label:this.api.i18n.t("Checklist"),icon:_,closeOnActivate:!0,isActive:this.listStyle=="checklist",onActivate:()=>{this.listStyle="checklist"}}];if(this.listStyle==="ordered"){const n=Jn(a=>this.changeStartWith(Number(a)),{value:String(this.data.meta.start??1),placeholder:"",attributes:{required:"true"},sanitize:a=>Qn(a)}),r=[{label:this.api.i18n.t("Start with"),icon:mt,children:{items:[{element:n,type:"html"}]}}],i={label:this.api.i18n.t("Counter type"),icon:ut.get(this.data.meta.counterType),children:{items:[]}};T.forEach((a,l)=>{const s=T.get(l);this.defaultCounterTypes.includes(s)&&i.children.items.push({title:this.api.i18n.t(l),icon:ut.get(s),isActive:this.data.meta.counterType===T.get(l),closeOnActivate:!0,onActivate:()=>{this.changeCounters(T.get(l))}})}),i.children.items.length>1&&r.push(i),t.push({type:"separator"},...r)}return t}onPaste(t){const{tagName:n}=t.detail.data;switch(n){case"OL":this.listStyle="ordered";break;case"UL":case"LI":this.listStyle="unordered"}this.list.onPaste(t)}pasteHandler(t){return this.list.pasteHandler(t)}changeCounters(t){var n;(n=this.list)==null||n.changeCounters(t),this.data.meta.counterType=t}changeStartWith(t){var n;(n=this.list)==null||n.changeStartWith(t),this.data.meta.start=t}changeTabulatorByStyle(){switch(this.listStyle){case"ordered":this.list=new $e({data:this.data,readOnly:this.readOnly,api:this.api,config:this.config,block:this.block},new v(this.readOnly,this.config));break;case"unordered":this.list=new $e({data:this.data,readOnly:this.readOnly,api:this.api,config:this.config,block:this.block},new b(this.readOnly,this.config));break;case"checklist":this.list=new $e({data:this.data,readOnly:this.readOnly,api:this.api,config:this.config,block:this.block},new f(this.readOnly,this.config));break}}}return K}); diff --git a/plugins/tiddlywiki/editorjs/files/editorjs.umd.js b/plugins/tiddlywiki/editorjs/files/editorjs.umd.js deleted file mode 100644 index 0a6a1ddcb..000000000 --- a/plugins/tiddlywiki/editorjs/files/editorjs.umd.js +++ /dev/null @@ -1,51 +0,0 @@ -(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(".ce-hint--align-start{text-align:left}.ce-hint--align-center{text-align:center}.ce-hint__description{opacity:.6;margin-top:3px}")),document.head.appendChild(e)}}catch(t){console.error("vite-plugin-css-injected-by-js",t)}})(); -(function(J,ne){typeof exports=="object"&&typeof module<"u"?module.exports=ne():typeof define=="function"&&define.amd?define(ne):(J=typeof globalThis<"u"?globalThis:J||self,J.EditorJS=ne())})(this,function(){"use strict";var J=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function ne(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}function Yn(n){if(n.__esModule)return n;var e=n.default;if(typeof e=="function"){var t=function o(){return this instanceof o?Reflect.construct(e,arguments,this.constructor):e.apply(this,arguments)};t.prototype=e.prototype}else t={};return Object.defineProperty(t,"__esModule",{value:!0}),Object.keys(n).forEach(function(o){var i=Object.getOwnPropertyDescriptor(n,o);Object.defineProperty(t,o,i.get?i:{enumerable:!0,get:function(){return n[o]}})}),t}function tt(){}Object.assign(tt,{default:tt,register:tt,revert:function(){},__esModule:!0}),Element.prototype.matches||(Element.prototype.matches=Element.prototype.matchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||Element.prototype.webkitMatchesSelector||function(n){const e=(this.document||this.ownerDocument).querySelectorAll(n);let t=e.length;for(;--t>=0&&e.item(t)!==this;);return t>-1}),Element.prototype.closest||(Element.prototype.closest=function(n){let e=this;if(!document.documentElement.contains(e))return null;do{if(e.matches(n))return e;e=e.parentElement||e.parentNode}while(e!==null);return null}),Element.prototype.prepend||(Element.prototype.prepend=function(e){const t=document.createDocumentFragment();Array.isArray(e)||(e=[e]),e.forEach(o=>{const i=o instanceof Node;t.appendChild(i?o:document.createTextNode(o))}),this.insertBefore(t,this.firstChild)}),Element.prototype.scrollIntoViewIfNeeded||(Element.prototype.scrollIntoViewIfNeeded=function(n){n=arguments.length===0?!0:!!n;const e=this.parentNode,t=window.getComputedStyle(e,null),o=parseInt(t.getPropertyValue("border-top-width")),i=parseInt(t.getPropertyValue("border-left-width")),s=this.offsetTop-e.offsetTope.scrollTop+e.clientHeight,a=this.offsetLeft-e.offsetLefte.scrollLeft+e.clientWidth,c=s&&!r;(s||r)&&n&&(e.scrollTop=this.offsetTop-e.offsetTop-e.clientHeight/2-o+this.clientHeight/2),(a||l)&&n&&(e.scrollLeft=this.offsetLeft-e.offsetLeft-e.clientWidth/2-i+this.clientWidth/2),(s||r||a||l)&&!n&&this.scrollIntoView(c)}),window.requestIdleCallback=window.requestIdleCallback||function(n){const e=Date.now();return setTimeout(function(){n({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-e))}})},1)},window.cancelIdleCallback=window.cancelIdleCallback||function(n){clearTimeout(n)};let Kn=(n=21)=>crypto.getRandomValues(new Uint8Array(n)).reduce((e,t)=>(t&=63,t<36?e+=t.toString(36):t<62?e+=(t-26).toString(36).toUpperCase():t>62?e+="-":e+="_",e),"");var ko=(n=>(n.VERBOSE="VERBOSE",n.INFO="INFO",n.WARN="WARN",n.ERROR="ERROR",n))(ko||{});const y={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,LEFT:37,UP:38,DOWN:40,RIGHT:39,DELETE:46,META:91,SLASH:191},Xn={LEFT:0,WHEEL:1,RIGHT:2,BACKWARD:3,FORWARD:4};function ye(n,e,t="log",o,i="color: inherit"){if(!("console"in window)||!window.console[t])return;const s=["info","log","warn","error"].includes(t),r=[];switch(ye.logLevel){case"ERROR":if(t!=="error")return;break;case"WARN":if(!["error","warn"].includes(t))return;break;case"INFO":if(!s||n)return;break}o&&r.push(o);const a="Editor.js 2.31.0-rc.9",l=`line-height: 1em; - color: #006FEA; - display: inline-block; - font-size: 11px; - line-height: 1em; - background-color: #fff; - padding: 4px 9px; - border-radius: 30px; - border: 1px solid rgba(56, 138, 229, 0.16); - margin: 4px 5px 4px 0;`;n&&(s?(r.unshift(l,i),e=`%c${a}%c ${e}`):e=`( ${a} )${e}`);try{s?o?console[t](`${e} %o`,...r):console[t](e,...r):console[t](e)}catch{}}ye.logLevel="VERBOSE";function Vn(n){ye.logLevel=n}const T=ye.bind(window,!1),X=ye.bind(window,!0);function re(n){return Object.prototype.toString.call(n).match(/\s([a-zA-Z]+)/)[1].toLowerCase()}function M(n){return re(n)==="function"||re(n)==="asyncfunction"}function N(n){return re(n)==="object"}function Q(n){return re(n)==="string"}function qn(n){return re(n)==="boolean"}function yo(n){return re(n)==="number"}function wo(n){return re(n)==="undefined"}function V(n){return n?Object.keys(n).length===0&&n.constructor===Object:!0}function Eo(n){return n>47&&n<58||n===32||n===13||n===229||n>64&&n<91||n>95&&n<112||n>185&&n<193||n>218&&n<223}async function Zn(n,e=()=>{},t=()=>{}){async function o(i,s,r){try{await i.function(i.data),await s(wo(i.data)?{}:i.data)}catch{r(wo(i.data)?{}:i.data)}}return n.reduce(async(i,s)=>(await i,o(s,e,t)),Promise.resolve())}function xo(n){return Array.prototype.slice.call(n)}function Ae(n,e){return function(){const t=this,o=arguments;window.setTimeout(()=>n.apply(t,o),e)}}function Gn(n){return n.name.split(".").pop()}function Jn(n){return/^[-\w]+\/([-+\w]+|\*)$/.test(n)}function Bo(n,e,t){let o;return(...i)=>{const s=this,r=()=>{o=null,t||n.apply(s,i)},a=t&&!o;window.clearTimeout(o),o=window.setTimeout(r,e),a&&n.apply(s,i)}}function ot(n,e,t=void 0){let o,i,s,r=null,a=0;t||(t={});const l=function(){a=t.leading===!1?0:Date.now(),r=null,s=n.apply(o,i),r||(o=i=null)};return function(){const c=Date.now();!a&&t.leading===!1&&(a=c);const u=e-(c-a);return o=this,i=arguments,u<=0||u>e?(r&&(clearTimeout(r),r=null),a=c,s=n.apply(o,i),r||(o=i=null)):!r&&t.trailing!==!1&&(r=setTimeout(l,u)),s}}function Qn(){const n={win:!1,mac:!1,x11:!1,linux:!1},e=Object.keys(n).find(t=>window.navigator.appVersion.toLowerCase().indexOf(t)!==-1);return e&&(n[e]=!0),n}function Le(n){return n[0].toUpperCase()+n.slice(1)}function nt(n,...e){if(!e.length)return n;const t=e.shift();if(N(n)&&N(t))for(const o in t)N(t[o])?(n[o]||Object.assign(n,{[o]:{}}),nt(n[o],t[o])):Object.assign(n,{[o]:t[o]});return nt(n,...e)}function it(n){const e=Qn();return n=n.replace(/shift/gi,"⇧").replace(/backspace/gi,"⌫").replace(/enter/gi,"⏎").replace(/up/gi,"↑").replace(/left/gi,"→").replace(/down/gi,"↓").replace(/right/gi,"←").replace(/escape/gi,"⎋").replace(/insert/gi,"Ins").replace(/delete/gi,"␡").replace(/\+/gi," + "),e.mac?n=n.replace(/ctrl|cmd/gi,"⌘").replace(/alt/gi,"⌥"):n=n.replace(/cmd/gi,"Ctrl").replace(/windows/gi,"WIN"),n}function ei(n){try{return new URL(n).href}catch{}return n.substring(0,2)==="//"?window.location.protocol+n:window.location.origin+n}function ti(){return Kn(10)}function oi(n){window.open(n,"_blank")}function ni(n=""){return`${n}${Math.floor(Math.random()*1e8).toString(16)}`}function st(n,e,t){const o=`«${e}» is deprecated and will be removed in the next major release. Please use the «${t}» instead.`;n&&X(o,"warn")}function fe(n,e,t){const o=t.value?"value":"get",i=t[o],s=`#${e}Cache`;if(t[o]=function(...r){return this[s]===void 0&&(this[s]=i.apply(this,...r)),this[s]},o==="get"&&t.set){const r=t.set;t.set=function(a){delete n[s],r.apply(this,a)}}return t}const Co=650;function ge(){return window.matchMedia(`(max-width: ${Co}px)`).matches}const rt=typeof window<"u"&&window.navigator&&window.navigator.platform&&(/iP(ad|hone|od)/.test(window.navigator.platform)||window.navigator.platform==="MacIntel"&&window.navigator.maxTouchPoints>1);function ii(n,e){const t=Array.isArray(n)||N(n),o=Array.isArray(e)||N(e);return t||o?JSON.stringify(n)===JSON.stringify(e):n===e}class d{static isSingleTag(e){return e.tagName&&["AREA","BASE","BR","COL","COMMAND","EMBED","HR","IMG","INPUT","KEYGEN","LINK","META","PARAM","SOURCE","TRACK","WBR"].includes(e.tagName)}static isLineBreakTag(e){return e&&e.tagName&&["BR","WBR"].includes(e.tagName)}static make(e,t=null,o={}){const i=document.createElement(e);if(Array.isArray(t)){const s=t.filter(r=>r!==void 0);i.classList.add(...s)}else t&&i.classList.add(t);for(const s in o)Object.prototype.hasOwnProperty.call(o,s)&&(i[s]=o[s]);return i}static text(e){return document.createTextNode(e)}static append(e,t){Array.isArray(t)?t.forEach(o=>e.appendChild(o)):e.appendChild(t)}static prepend(e,t){Array.isArray(t)?(t=t.reverse(),t.forEach(o=>e.prepend(o))):e.prepend(t)}static swap(e,t){const o=document.createElement("div"),i=e.parentNode;i.insertBefore(o,e),i.insertBefore(e,t),i.insertBefore(t,o),i.removeChild(o)}static find(e=document,t){return e.querySelector(t)}static get(e){return document.getElementById(e)}static findAll(e=document,t){return e.querySelectorAll(t)}static get allInputsSelector(){return"[contenteditable=true], textarea, input:not([type]), "+["text","password","email","number","search","tel","url"].map(t=>`input[type="${t}"]`).join(", ")}static findAllInputs(e){return xo(e.querySelectorAll(d.allInputsSelector)).reduce((t,o)=>d.isNativeInput(o)||d.containsOnlyInlineElements(o)?[...t,o]:[...t,...d.getDeepestBlockElements(o)],[])}static getDeepestNode(e,t=!1){const o=t?"lastChild":"firstChild",i=t?"previousSibling":"nextSibling";if(e&&e.nodeType===Node.ELEMENT_NODE&&e[o]){let s=e[o];if(d.isSingleTag(s)&&!d.isNativeInput(s)&&!d.isLineBreakTag(s))if(s[i])s=s[i];else if(s.parentNode[i])s=s.parentNode[i];else return s.parentNode;return this.getDeepestNode(s,t)}return e}static isElement(e){return yo(e)?!1:e&&e.nodeType&&e.nodeType===Node.ELEMENT_NODE}static isFragment(e){return yo(e)?!1:e&&e.nodeType&&e.nodeType===Node.DOCUMENT_FRAGMENT_NODE}static isContentEditable(e){return e.contentEditable==="true"}static isNativeInput(e){const t=["INPUT","TEXTAREA"];return e&&e.tagName?t.includes(e.tagName):!1}static canSetCaret(e){let t=!0;if(d.isNativeInput(e))switch(e.type){case"file":case"checkbox":case"radio":case"hidden":case"submit":case"button":case"image":case"reset":t=!1;break}else t=d.isContentEditable(e);return t}static isNodeEmpty(e,t){let o;return this.isSingleTag(e)&&!this.isLineBreakTag(e)?!1:(this.isElement(e)&&this.isNativeInput(e)?o=e.value:o=e.textContent.replace("​",""),t&&(o=o.replace(new RegExp(t,"g"),"")),o.length===0)}static isLeaf(e){return e?e.childNodes.length===0:!1}static isEmpty(e,t){const o=[e];for(;o.length>0;)if(e=o.shift(),!!e){if(this.isLeaf(e)&&!this.isNodeEmpty(e,t))return!1;e.childNodes&&o.push(...Array.from(e.childNodes))}return!0}static isHTMLString(e){const t=d.make("div");return t.innerHTML=e,t.childElementCount>0}static getContentLength(e){return d.isNativeInput(e)?e.value.length:e.nodeType===Node.TEXT_NODE?e.length:e.textContent.length}static get blockElements(){return["address","article","aside","blockquote","canvas","div","dl","dt","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","li","main","nav","noscript","ol","output","p","pre","ruby","section","table","tbody","thead","tr","tfoot","ul","video"]}static containsOnlyInlineElements(e){let t;Q(e)?(t=document.createElement("div"),t.innerHTML=e):t=e;const o=i=>!d.blockElements.includes(i.tagName.toLowerCase())&&Array.from(i.children).every(o);return Array.from(t.children).every(o)}static getDeepestBlockElements(e){return d.containsOnlyInlineElements(e)?[e]:Array.from(e.children).reduce((t,o)=>[...t,...d.getDeepestBlockElements(o)],[])}static getHolder(e){return Q(e)?document.getElementById(e):e}static isAnchor(e){return e.tagName.toLowerCase()==="a"}static offset(e){const t=e.getBoundingClientRect(),o=window.pageXOffset||document.documentElement.scrollLeft,i=window.pageYOffset||document.documentElement.scrollTop,s=t.top+i,r=t.left+o;return{top:s,left:r,bottom:s+t.height,right:r+t.width}}}function si(n){return!/[^\t\n\r ]/.test(n)}function ri(n){const e=window.getComputedStyle(n),t=parseFloat(e.fontSize),o=parseFloat(e.lineHeight)||t*1.2,i=parseFloat(e.paddingTop),s=parseFloat(e.borderTopWidth),r=parseFloat(e.marginTop),a=t*.8,l=(o-t)/2;return r+s+i+l+a}function To(n){n.dataset.empty=d.isEmpty(n)?"true":"false"}const So={ui:{blockTunes:{toggler:{"Click to tune":"","or drag to move":""}},inlineToolbar:{converter:{"Convert to":""}},toolbar:{toolbox:{Add:""}},popover:{Filter:"","Nothing found":"","Convert to":""}},toolNames:{Text:"",Link:"",Bold:"",Italic:""},tools:{link:{"Add a link":""},stub:{"The block can not be displayed correctly.":""}},blockTunes:{delete:{Delete:"","Click to delete":""},moveUp:{"Move up":""},moveDown:{"Move down":""}}},Io=class ke{static ui(e,t){return ke._t(e,t)}static t(e,t){return ke._t(e,t)}static setDictionary(e){ke.currentDictionary=e}static _t(e,t){const o=ke.getNamespace(e);return!o||!o[t]?t:o[t]}static getNamespace(e){return e.split(".").reduce((o,i)=>!o||!Object.keys(o).length?{}:o[i],ke.currentDictionary)}};Io.currentDictionary=So;let H=Io;class Oo extends Error{}class we{constructor(){this.subscribers={}}on(e,t){e in this.subscribers||(this.subscribers[e]=[]),this.subscribers[e].push(t)}once(e,t){e in this.subscribers||(this.subscribers[e]=[]);const o=i=>{const s=t(i),r=this.subscribers[e].indexOf(o);return r!==-1&&this.subscribers[e].splice(r,1),s};this.subscribers[e].push(o)}emit(e,t){V(this.subscribers)||!this.subscribers[e]||this.subscribers[e].reduce((o,i)=>{const s=i(o);return s!==void 0?s:o},t)}off(e,t){if(this.subscribers[e]===void 0){console.warn(`EventDispatcher .off(): there is no subscribers for event "${e.toString()}". Probably, .off() called before .on()`);return}for(let o=0;o{const l=this.allListeners.indexOf(s[a]);l>-1&&(this.allListeners.splice(l,1),r.element.removeEventListener(r.eventType,r.handler,r.options))})}offById(e){const t=this.findById(e);t&&t.element.removeEventListener(t.eventType,t.handler,t.options)}findOne(e,t,o){const i=this.findAll(e,t,o);return i.length>0?i[0]:null}findAll(e,t,o){let i;const s=e?this.findByEventTarget(e):[];return e&&t&&o?i=s.filter(r=>r.eventType===t&&r.handler===o):e&&t?i=s.filter(r=>r.eventType===t):i=s,i}removeAll(){this.allListeners.map(e=>{e.element.removeEventListener(e.eventType,e.handler,e.options)}),this.allListeners=[]}destroy(){this.removeAll()}findByEventTarget(e){return this.allListeners.filter(t=>{if(t.element===e)return t})}findByType(e){return this.allListeners.filter(t=>{if(t.eventType===e)return t})}findByHandler(e){return this.allListeners.filter(t=>{if(t.handler===e)return t})}findById(e){return this.allListeners.find(t=>t.id===e)}}class E{constructor({config:e,eventsDispatcher:t}){if(this.nodes={},this.listeners=new Ee,this.readOnlyMutableListeners={on:(o,i,s,r=!1)=>{this.mutableListenerIds.push(this.listeners.on(o,i,s,r))},clearAll:()=>{for(const o of this.mutableListenerIds)this.listeners.offById(o);this.mutableListenerIds=[]}},this.mutableListenerIds=[],new.target===E)throw new TypeError("Constructors for abstract class Module are not allowed.");this.config=e,this.eventsDispatcher=t}set state(e){this.Editor=e}removeAllNodes(){for(const e in this.nodes){const t=this.nodes[e];t instanceof HTMLElement&&t.remove()}}get isRtl(){return this.config.i18n.direction==="rtl"}}class b{constructor(){this.instance=null,this.selection=null,this.savedSelectionRange=null,this.isFakeBackgroundEnabled=!1,this.commandBackground="backColor",this.commandRemoveFormat="removeFormat"}static get CSS(){return{editorWrapper:"codex-editor",editorZone:"codex-editor__redactor"}}static get anchorNode(){const e=window.getSelection();return e?e.anchorNode:null}static get anchorElement(){const e=window.getSelection();if(!e)return null;const t=e.anchorNode;return t?d.isElement(t)?t:t.parentElement:null}static get anchorOffset(){const e=window.getSelection();return e?e.anchorOffset:null}static get isCollapsed(){const e=window.getSelection();return e?e.isCollapsed:null}static get isAtEditor(){return this.isSelectionAtEditor(b.get())}static isSelectionAtEditor(e){if(!e)return!1;let t=e.anchorNode||e.focusNode;t&&t.nodeType===Node.TEXT_NODE&&(t=t.parentNode);let o=null;return t&&t instanceof Element&&(o=t.closest(`.${b.CSS.editorZone}`)),o?o.nodeType===Node.ELEMENT_NODE:!1}static isRangeAtEditor(e){if(!e)return;let t=e.startContainer;t&&t.nodeType===Node.TEXT_NODE&&(t=t.parentNode);let o=null;return t&&t instanceof Element&&(o=t.closest(`.${b.CSS.editorZone}`)),o?o.nodeType===Node.ELEMENT_NODE:!1}static get isSelectionExists(){return!!b.get().anchorNode}static get range(){return this.getRangeFromSelection(this.get())}static getRangeFromSelection(e){return e&&e.rangeCount?e.getRangeAt(0):null}static get rect(){let e=document.selection,t,o={x:0,y:0,width:0,height:0};if(e&&e.type!=="Control")return e=e,t=e.createRange(),o.x=t.boundingLeft,o.y=t.boundingTop,o.width=t.boundingWidth,o.height=t.boundingHeight,o;if(!window.getSelection)return T("Method window.getSelection is not supported","warn"),o;if(e=window.getSelection(),e.rangeCount===null||isNaN(e.rangeCount))return T("Method SelectionUtils.rangeCount is not supported","warn"),o;if(e.rangeCount===0)return o;if(t=e.getRangeAt(0).cloneRange(),t.getBoundingClientRect&&(o=t.getBoundingClientRect()),o.x===0&&o.y===0){const i=document.createElement("span");if(i.getBoundingClientRect){i.appendChild(document.createTextNode("​")),t.insertNode(i),o=i.getBoundingClientRect();const s=i.parentNode;s.removeChild(i),s.normalize()}}return o}static get text(){return window.getSelection?window.getSelection().toString():""}static get(){return window.getSelection()}static setCursor(e,t=0){const o=document.createRange(),i=window.getSelection();return d.isNativeInput(e)?d.canSetCaret(e)?(e.focus(),e.selectionStart=e.selectionEnd=t,e.getBoundingClientRect()):void 0:(o.setStart(e,t),o.setEnd(e,t),i.removeAllRanges(),i.addRange(o),o.getBoundingClientRect())}static isRangeInsideContainer(e){const t=b.range;return t===null?!1:e.contains(t.startContainer)}static addFakeCursor(){const e=b.range;if(e===null)return;const t=d.make("span","codex-editor__fake-cursor");t.dataset.mutationFree="true",e.collapse(),e.insertNode(t)}static isFakeCursorInsideContainer(e){return d.find(e,".codex-editor__fake-cursor")!==null}static removeFakeCursor(e=document.body){const t=d.find(e,".codex-editor__fake-cursor");t&&t.remove()}removeFakeBackground(){this.isFakeBackgroundEnabled&&(this.isFakeBackgroundEnabled=!1,document.execCommand(this.commandRemoveFormat))}setFakeBackground(){document.execCommand(this.commandBackground,!1,"#a8d6ff"),this.isFakeBackgroundEnabled=!0}save(){this.savedSelectionRange=b.range}restore(){if(!this.savedSelectionRange)return;const e=window.getSelection();e.removeAllRanges(),e.addRange(this.savedSelectionRange)}clearSaved(){this.savedSelectionRange=null}collapseToEnd(){const e=window.getSelection(),t=document.createRange();t.selectNodeContents(e.focusNode),t.collapse(!1),e.removeAllRanges(),e.addRange(t)}findParentTag(e,t,o=10){const i=window.getSelection();let s=null;return!i||!i.anchorNode||!i.focusNode?null:([i.anchorNode,i.focusNode].forEach(a=>{let l=o;for(;l>0&&a.parentNode&&!(a.tagName===e&&(s=a,t&&a.classList&&!a.classList.contains(t)&&(s=null),s));)a=a.parentNode,l--}),s)}expandToTag(e){const t=window.getSelection();t.removeAllRanges();const o=document.createRange();o.selectNodeContents(e),t.addRange(o)}}function ai(n,e){const{type:t,target:o,addedNodes:i,removedNodes:s}=n;return n.type==="attributes"&&n.attributeName==="data-empty"?!1:!!(e.contains(o)||t==="childList"&&(Array.from(i).some(l=>l===e)||Array.from(s).some(l=>l===e)))}const at="redactor dom changed",_o="block changed",Mo="fake cursor is about to be toggled",Ao="fake cursor have been set",xe="editor mobile layout toggled";function lt(n,e){if(!n.conversionConfig)return!1;const t=n.conversionConfig[e];return M(t)||Q(t)}function Pe(n,e){return lt(n.tool,e)}function Lo(n,e){return Object.entries(n).some(([t,o])=>e[t]&&ii(e[t],o))}async function Po(n,e){const o=(await n.save()).data,i=e.find(s=>s.name===n.name);return i!==void 0&&!lt(i,"export")?[]:e.reduce((s,r)=>{if(!lt(r,"import")||r.toolbox===void 0)return s;const a=r.toolbox.filter(l=>{if(V(l)||l.icon===void 0)return!1;if(l.data!==void 0){if(Lo(l.data,o))return!1}else if(r.name===n.name)return!1;return!0});return s.push({...r,toolbox:a}),s},[])}function No(n,e){return n.mergeable?n.name===e.name?!0:Pe(e,"export")&&Pe(n,"import"):!1}function li(n,e){const t=e==null?void 0:e.export;return M(t)?t(n):Q(t)?n[t]:(t!==void 0&&T("Conversion «export» property must be a string or function. String means key of saved data object to export. Function should export processed string to export."),"")}function Ro(n,e,t){const o=e==null?void 0:e.import;return M(o)?o(n,t):Q(o)?{[o]:n}:(o!==void 0&&T("Conversion «import» property must be a string or function. String means key of tool data to import. Function accepts a imported string and return composed tool data."),{})}var _=(n=>(n.Default="default",n.Separator="separator",n.Html="html",n))(_||{}),te=(n=>(n.APPEND_CALLBACK="appendCallback",n.RENDERED="rendered",n.MOVED="moved",n.UPDATED="updated",n.REMOVED="removed",n.ON_PASTE="onPaste",n))(te||{});class R extends we{constructor({id:e=ti(),data:t,tool:o,readOnly:i,tunesData:s},r){super(),this.cachedInputs=[],this.toolRenderedElement=null,this.tunesInstances=new Map,this.defaultTunesInstances=new Map,this.unavailableTunesData={},this.inputIndex=0,this.editorEventBus=null,this.handleFocus=()=>{this.dropInputsCache(),this.updateCurrentInput()},this.didMutated=(a=void 0)=>{const l=a===void 0,c=a instanceof InputEvent;!l&&!c&&this.detectToolRootChange(a);let u;l||c?u=!0:u=!(a.length>0&&a.every(p=>{const{addedNodes:g,removedNodes:f,target:v}=p;return[...Array.from(g),...Array.from(f),v].some(S=>(d.isElement(S)||(S=S.parentElement),S&&S.closest('[data-mutation-free="true"]')!==null))})),u&&(this.dropInputsCache(),this.updateCurrentInput(),this.toggleInputsEmptyMark(),this.call("updated"),this.emit("didMutated",this))},this.name=o.name,this.id=e,this.settings=o.settings,this.config=o.settings.config||{},this.editorEventBus=r||null,this.blockAPI=new ee(this),this.tool=o,this.toolInstance=o.create(t,this.blockAPI,i),this.tunes=o.tunes,this.composeTunes(s),this.holder=this.compose(),window.requestIdleCallback(()=>{this.watchBlockMutations(),this.addInputEvents(),this.toggleInputsEmptyMark()})}static get CSS(){return{wrapper:"ce-block",wrapperStretched:"ce-block--stretched",content:"ce-block__content",selected:"ce-block--selected",dropTarget:"ce-block--drop-target"}}get inputs(){if(this.cachedInputs.length!==0)return this.cachedInputs;const e=d.findAllInputs(this.holder);return this.inputIndex>e.length-1&&(this.inputIndex=e.length-1),this.cachedInputs=e,e}get currentInput(){return this.inputs[this.inputIndex]}set currentInput(e){const t=this.inputs.findIndex(o=>o===e||o.contains(e));t!==-1&&(this.inputIndex=t)}get firstInput(){return this.inputs[0]}get lastInput(){const e=this.inputs;return e[e.length-1]}get nextInput(){return this.inputs[this.inputIndex+1]}get previousInput(){return this.inputs[this.inputIndex-1]}get data(){return this.save().then(e=>e&&!V(e.data)?e.data:{})}get sanitize(){return this.tool.sanitizeConfig}get mergeable(){return M(this.toolInstance.merge)}get focusable(){return this.inputs.length!==0}get isEmpty(){const e=d.isEmpty(this.pluginsContent,"/"),t=!this.hasMedia;return e&&t}get hasMedia(){const e=["img","iframe","video","audio","source","input","textarea","twitterwidget"];return!!this.holder.querySelector(e.join(","))}set selected(e){var i,s;this.holder.classList.toggle(R.CSS.selected,e);const t=e===!0&&b.isRangeInsideContainer(this.holder),o=e===!1&&b.isFakeCursorInsideContainer(this.holder);(t||o)&&((i=this.editorEventBus)==null||i.emit(Mo,{state:e}),t?b.addFakeCursor():b.removeFakeCursor(this.holder),(s=this.editorEventBus)==null||s.emit(Ao,{state:e}))}get selected(){return this.holder.classList.contains(R.CSS.selected)}set stretched(e){this.holder.classList.toggle(R.CSS.wrapperStretched,e)}get stretched(){return this.holder.classList.contains(R.CSS.wrapperStretched)}set dropTarget(e){this.holder.classList.toggle(R.CSS.dropTarget,e)}get pluginsContent(){return this.toolRenderedElement}call(e,t){if(M(this.toolInstance[e])){e==="appendCallback"&&T("`appendCallback` hook is deprecated and will be removed in the next major release. Use `rendered` hook instead","warn");try{this.toolInstance[e].call(this.toolInstance,t)}catch(o){T(`Error during '${e}' call: ${o.message}`,"error")}}}async mergeWith(e){await this.toolInstance.merge(e)}async save(){const e=await this.toolInstance.save(this.pluginsContent),t=this.unavailableTunesData;[...this.tunesInstances.entries(),...this.defaultTunesInstances.entries()].forEach(([s,r])=>{if(M(r.save))try{t[s]=r.save()}catch(a){T(`Tune ${r.constructor.name} save method throws an Error %o`,"warn",a)}});const o=window.performance.now();let i;return Promise.resolve(e).then(s=>(i=window.performance.now(),{id:this.id,tool:this.name,data:s,tunes:t,time:i-o})).catch(s=>{T(`Saving process for ${this.name} tool failed due to the ${s}`,"log","red")})}async validate(e){let t=!0;return this.toolInstance.validate instanceof Function&&(t=await this.toolInstance.validate(e)),t}getTunes(){const e=[],t=[],o=typeof this.toolInstance.renderSettings=="function"?this.toolInstance.renderSettings():[];return d.isElement(o)?e.push({type:_.Html,element:o}):Array.isArray(o)?e.push(...o):e.push(o),[...this.tunesInstances.values(),...this.defaultTunesInstances.values()].map(s=>s.render()).forEach(s=>{d.isElement(s)?t.push({type:_.Html,element:s}):Array.isArray(s)?t.push(...s):t.push(s)}),{toolTunes:e,commonTunes:t}}updateCurrentInput(){this.currentInput=d.isNativeInput(document.activeElement)||!b.anchorNode?document.activeElement:b.anchorNode}dispatchChange(){this.didMutated()}destroy(){this.unwatchBlockMutations(),this.removeInputEvents(),super.destroy(),M(this.toolInstance.destroy)&&this.toolInstance.destroy()}async getActiveToolboxEntry(){const e=this.tool.toolbox;if(e.length===1)return Promise.resolve(this.tool.toolbox[0]);const t=await this.data,o=e;return o==null?void 0:o.find(i=>Lo(i.data,t))}async exportDataAsString(){const e=await this.data;return li(e,this.tool.conversionConfig)}compose(){const e=d.make("div",R.CSS.wrapper),t=d.make("div",R.CSS.content),o=this.toolInstance.render();e.dataset.id=this.id,this.toolRenderedElement=o,t.appendChild(this.toolRenderedElement);let i=t;return[...this.tunesInstances.values(),...this.defaultTunesInstances.values()].forEach(s=>{if(M(s.wrap))try{i=s.wrap(i)}catch(r){T(`Tune ${s.constructor.name} wrap method throws an Error %o`,"warn",r)}}),e.appendChild(i),e}composeTunes(e){Array.from(this.tunes.values()).forEach(t=>{(t.isInternal?this.defaultTunesInstances:this.tunesInstances).set(t.name,t.create(e[t.name],this.blockAPI))}),Object.entries(e).forEach(([t,o])=>{this.tunesInstances.has(t)||(this.unavailableTunesData[t]=o)})}addInputEvents(){this.inputs.forEach(e=>{e.addEventListener("focus",this.handleFocus),d.isNativeInput(e)&&e.addEventListener("input",this.didMutated)})}removeInputEvents(){this.inputs.forEach(e=>{e.removeEventListener("focus",this.handleFocus),d.isNativeInput(e)&&e.removeEventListener("input",this.didMutated)})}watchBlockMutations(){var e;this.redactorDomChangedCallback=t=>{const{mutations:o}=t;o.some(s=>ai(s,this.toolRenderedElement))&&this.didMutated(o)},(e=this.editorEventBus)==null||e.on(at,this.redactorDomChangedCallback)}unwatchBlockMutations(){var e;(e=this.editorEventBus)==null||e.off(at,this.redactorDomChangedCallback)}detectToolRootChange(e){e.forEach(t=>{if(Array.from(t.removedNodes).includes(this.toolRenderedElement)){const i=t.addedNodes[t.addedNodes.length-1];this.toolRenderedElement=i}})}dropInputsCache(){this.cachedInputs=[]}toggleInputsEmptyMark(){this.inputs.forEach(To)}}class ci extends E{constructor(){super(...arguments),this.insert=(e=this.config.defaultBlock,t={},o={},i,s,r,a)=>{const l=this.Editor.BlockManager.insert({id:a,tool:e,data:t,index:i,needToFocus:s,replace:r});return new ee(l)},this.composeBlockData=async e=>{const t=this.Editor.Tools.blockTools.get(e);return new R({tool:t,api:this.Editor.API,readOnly:!0,data:{},tunesData:{}}).data},this.update=async(e,t,o)=>{const{BlockManager:i}=this.Editor,s=i.getBlockById(e);if(s===void 0)throw new Error(`Block with id "${e}" not found`);const r=await i.update(s,t,o);return new ee(r)},this.convert=async(e,t,o)=>{var h,p;const{BlockManager:i,Tools:s}=this.Editor,r=i.getBlockById(e);if(!r)throw new Error(`Block with id "${e}" not found`);const a=s.blockTools.get(r.name),l=s.blockTools.get(t);if(!l)throw new Error(`Block Tool with type "${t}" not found`);const c=((h=a==null?void 0:a.conversionConfig)==null?void 0:h.export)!==void 0,u=((p=l.conversionConfig)==null?void 0:p.import)!==void 0;if(c&&u){const g=await i.convert(r,t,o);return new ee(g)}else{const g=[c?!1:Le(r.name),u?!1:Le(t)].filter(Boolean).join(" and ");throw new Error(`Conversion from "${r.name}" to "${t}" is not possible. ${g} tool(s) should provide a "conversionConfig"`)}},this.insertMany=(e,t=this.Editor.BlockManager.blocks.length-1)=>{this.validateIndex(t);const o=e.map(({id:i,type:s,data:r})=>this.Editor.BlockManager.composeBlock({id:i,tool:s||this.config.defaultBlock,data:r}));return this.Editor.BlockManager.insertMany(o,t),o.map(i=>new ee(i))}}get methods(){return{clear:()=>this.clear(),render:e=>this.render(e),renderFromHTML:e=>this.renderFromHTML(e),delete:e=>this.delete(e),swap:(e,t)=>this.swap(e,t),move:(e,t)=>this.move(e,t),getBlockByIndex:e=>this.getBlockByIndex(e),getById:e=>this.getById(e),getCurrentBlockIndex:()=>this.getCurrentBlockIndex(),getBlockIndex:e=>this.getBlockIndex(e),getBlocksCount:()=>this.getBlocksCount(),getBlockByElement:e=>this.getBlockByElement(e),stretchBlock:(e,t=!0)=>this.stretchBlock(e,t),insertNewBlock:()=>this.insertNewBlock(),insert:this.insert,insertMany:this.insertMany,update:this.update,composeBlockData:this.composeBlockData,convert:this.convert}}getBlocksCount(){return this.Editor.BlockManager.blocks.length}getCurrentBlockIndex(){return this.Editor.BlockManager.currentBlockIndex}getBlockIndex(e){const t=this.Editor.BlockManager.getBlockById(e);if(!t){X("There is no block with id `"+e+"`","warn");return}return this.Editor.BlockManager.getBlockIndex(t)}getBlockByIndex(e){const t=this.Editor.BlockManager.getBlockByIndex(e);if(t===void 0){X("There is no block at index `"+e+"`","warn");return}return new ee(t)}getById(e){const t=this.Editor.BlockManager.getBlockById(e);return t===void 0?(X("There is no block with id `"+e+"`","warn"),null):new ee(t)}getBlockByElement(e){const t=this.Editor.BlockManager.getBlock(e);if(t===void 0){X("There is no block corresponding to element `"+e+"`","warn");return}return new ee(t)}swap(e,t){T("`blocks.swap()` method is deprecated and will be removed in the next major release. Use `block.move()` method instead","info"),this.Editor.BlockManager.swap(e,t)}move(e,t){this.Editor.BlockManager.move(e,t)}delete(e=this.Editor.BlockManager.currentBlockIndex){try{const t=this.Editor.BlockManager.getBlockByIndex(e);this.Editor.BlockManager.removeBlock(t)}catch(t){X(t,"warn");return}this.Editor.BlockManager.blocks.length===0&&this.Editor.BlockManager.insert(),this.Editor.BlockManager.currentBlock&&this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock,this.Editor.Caret.positions.END),this.Editor.Toolbar.close()}async clear(){await this.Editor.BlockManager.clear(!0),this.Editor.InlineToolbar.close()}async render(e){if(e===void 0||e.blocks===void 0)throw new Error("Incorrect data passed to the render() method");this.Editor.ModificationsObserver.disable(),await this.Editor.BlockManager.clear(),await this.Editor.Renderer.render(e.blocks),this.Editor.ModificationsObserver.enable()}renderFromHTML(e){return this.Editor.BlockManager.clear(),this.Editor.Paste.processText(e,!0)}stretchBlock(e,t=!0){st(!0,"blocks.stretchBlock()","BlockAPI");const o=this.Editor.BlockManager.getBlockByIndex(e);o&&(o.stretched=t)}insertNewBlock(){T("Method blocks.insertNewBlock() is deprecated and it will be removed in the next major release. Use blocks.insert() instead.","warn"),this.insert()}validateIndex(e){if(typeof e!="number")throw new Error("Index should be a number");if(e<0)throw new Error("Index should be greater than or equal to 0");if(e===null)throw new Error("Index should be greater than or equal to 0")}}function di(n,e){return typeof n=="number"?e.BlockManager.getBlockByIndex(n):typeof n=="string"?e.BlockManager.getBlockById(n):e.BlockManager.getBlockById(n.id)}class ui extends E{constructor(){super(...arguments),this.setToFirstBlock=(e=this.Editor.Caret.positions.DEFAULT,t=0)=>this.Editor.BlockManager.firstBlock?(this.Editor.Caret.setToBlock(this.Editor.BlockManager.firstBlock,e,t),!0):!1,this.setToLastBlock=(e=this.Editor.Caret.positions.DEFAULT,t=0)=>this.Editor.BlockManager.lastBlock?(this.Editor.Caret.setToBlock(this.Editor.BlockManager.lastBlock,e,t),!0):!1,this.setToPreviousBlock=(e=this.Editor.Caret.positions.DEFAULT,t=0)=>this.Editor.BlockManager.previousBlock?(this.Editor.Caret.setToBlock(this.Editor.BlockManager.previousBlock,e,t),!0):!1,this.setToNextBlock=(e=this.Editor.Caret.positions.DEFAULT,t=0)=>this.Editor.BlockManager.nextBlock?(this.Editor.Caret.setToBlock(this.Editor.BlockManager.nextBlock,e,t),!0):!1,this.setToBlock=(e,t=this.Editor.Caret.positions.DEFAULT,o=0)=>{const i=di(e,this.Editor);return i===void 0?!1:(this.Editor.Caret.setToBlock(i,t,o),!0)},this.focus=(e=!1)=>e?this.setToLastBlock(this.Editor.Caret.positions.END):this.setToFirstBlock(this.Editor.Caret.positions.START)}get methods(){return{setToFirstBlock:this.setToFirstBlock,setToLastBlock:this.setToLastBlock,setToPreviousBlock:this.setToPreviousBlock,setToNextBlock:this.setToNextBlock,setToBlock:this.setToBlock,focus:this.focus}}}class hi extends E{get methods(){return{emit:(e,t)=>this.emit(e,t),off:(e,t)=>this.off(e,t),on:(e,t)=>this.on(e,t)}}on(e,t){this.eventsDispatcher.on(e,t)}emit(e,t){this.eventsDispatcher.emit(e,t)}off(e,t){this.eventsDispatcher.off(e,t)}}class ct extends E{static getNamespace(e,t){return t?`blockTunes.${e}`:`tools.${e}`}get methods(){return{t:()=>{X("I18n.t() method can be accessed only from Tools","warn")}}}getMethodsForTool(e,t){return Object.assign(this.methods,{t:o=>H.t(ct.getNamespace(e,t),o)})}}class pi extends E{get methods(){return{blocks:this.Editor.BlocksAPI.methods,caret:this.Editor.CaretAPI.methods,tools:this.Editor.ToolsAPI.methods,events:this.Editor.EventsAPI.methods,listeners:this.Editor.ListenersAPI.methods,notifier:this.Editor.NotifierAPI.methods,sanitizer:this.Editor.SanitizerAPI.methods,saver:this.Editor.SaverAPI.methods,selection:this.Editor.SelectionAPI.methods,styles:this.Editor.StylesAPI.classes,toolbar:this.Editor.ToolbarAPI.methods,inlineToolbar:this.Editor.InlineToolbarAPI.methods,tooltip:this.Editor.TooltipAPI.methods,i18n:this.Editor.I18nAPI.methods,readOnly:this.Editor.ReadOnlyAPI.methods,ui:this.Editor.UiAPI.methods}}getMethodsForTool(e,t){return Object.assign(this.methods,{i18n:this.Editor.I18nAPI.getMethodsForTool(e,t)})}}class fi extends E{get methods(){return{close:()=>this.close(),open:()=>this.open()}}open(){this.Editor.InlineToolbar.tryToShow()}close(){this.Editor.InlineToolbar.close()}}class gi extends E{get methods(){return{on:(e,t,o,i)=>this.on(e,t,o,i),off:(e,t,o,i)=>this.off(e,t,o,i),offById:e=>this.offById(e)}}on(e,t,o,i){return this.listeners.on(e,t,o,i)}off(e,t,o,i){this.listeners.off(e,t,o,i)}offById(e){this.listeners.offById(e)}}var Do={exports:{}};(function(n,e){(function(t,o){n.exports=o()})(window,function(){return function(t){var o={};function i(s){if(o[s])return o[s].exports;var r=o[s]={i:s,l:!1,exports:{}};return t[s].call(r.exports,r,r.exports,i),r.l=!0,r.exports}return i.m=t,i.c=o,i.d=function(s,r,a){i.o(s,r)||Object.defineProperty(s,r,{enumerable:!0,get:a})},i.r=function(s){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(s,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(s,"__esModule",{value:!0})},i.t=function(s,r){if(1&r&&(s=i(s)),8&r||4&r&&typeof s=="object"&&s&&s.__esModule)return s;var a=Object.create(null);if(i.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:s}),2&r&&typeof s!="string")for(var l in s)i.d(a,l,(function(c){return s[c]}).bind(null,l));return a},i.n=function(s){var r=s&&s.__esModule?function(){return s.default}:function(){return s};return i.d(r,"a",r),r},i.o=function(s,r){return Object.prototype.hasOwnProperty.call(s,r)},i.p="/",i(i.s=0)}([function(t,o,i){i(1),t.exports=function(){var s=i(6),r="cdx-notify--bounce-in",a=null;return{show:function(l){if(l.message){(function(){if(a)return!0;a=s.getWrapper(),document.body.appendChild(a)})();var c=null,u=l.time||8e3;switch(l.type){case"confirm":c=s.confirm(l);break;case"prompt":c=s.prompt(l);break;default:c=s.alert(l),window.setTimeout(function(){c.remove()},u)}a.appendChild(c),c.classList.add(r)}}}}()},function(t,o,i){var s=i(2);typeof s=="string"&&(s=[[t.i,s,""]]);var r={hmr:!0,transform:void 0,insertInto:void 0};i(4)(s,r),s.locals&&(t.exports=s.locals)},function(t,o,i){(t.exports=i(3)(!1)).push([t.i,`.cdx-notify--error{background:#fffbfb!important}.cdx-notify--error::before{background:#fb5d5d!important}.cdx-notify__input{max-width:130px;padding:5px 10px;background:#f7f7f7;border:0;border-radius:3px;font-size:13px;color:#656b7c;outline:0}.cdx-notify__input:-ms-input-placeholder{color:#656b7c}.cdx-notify__input::placeholder{color:#656b7c}.cdx-notify__input:focus:-ms-input-placeholder{color:rgba(101,107,124,.3)}.cdx-notify__input:focus::placeholder{color:rgba(101,107,124,.3)}.cdx-notify__button{border:none;border-radius:3px;font-size:13px;padding:5px 10px;cursor:pointer}.cdx-notify__button:last-child{margin-left:10px}.cdx-notify__button--cancel{background:#f2f5f7;box-shadow:0 2px 1px 0 rgba(16,19,29,0);color:#656b7c}.cdx-notify__button--cancel:hover{background:#eee}.cdx-notify__button--confirm{background:#34c992;box-shadow:0 1px 1px 0 rgba(18,49,35,.05);color:#fff}.cdx-notify__button--confirm:hover{background:#33b082}.cdx-notify__btns-wrapper{display:-ms-flexbox;display:flex;-ms-flex-flow:row nowrap;flex-flow:row nowrap;margin-top:5px}.cdx-notify__cross{position:absolute;top:5px;right:5px;width:10px;height:10px;padding:5px;opacity:.54;cursor:pointer}.cdx-notify__cross::after,.cdx-notify__cross::before{content:'';position:absolute;left:9px;top:5px;height:12px;width:2px;background:#575d67}.cdx-notify__cross::before{transform:rotate(-45deg)}.cdx-notify__cross::after{transform:rotate(45deg)}.cdx-notify__cross:hover{opacity:1}.cdx-notifies{position:fixed;z-index:2;bottom:20px;left:20px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",sans-serif}.cdx-notify{position:relative;width:220px;margin-top:15px;padding:13px 16px;background:#fff;box-shadow:0 11px 17px 0 rgba(23,32,61,.13);border-radius:5px;font-size:14px;line-height:1.4em;word-wrap:break-word}.cdx-notify::before{content:'';position:absolute;display:block;top:0;left:0;width:3px;height:calc(100% - 6px);margin:3px;border-radius:5px;background:0 0}@keyframes bounceIn{0%{opacity:0;transform:scale(.3)}50%{opacity:1;transform:scale(1.05)}70%{transform:scale(.9)}100%{transform:scale(1)}}.cdx-notify--bounce-in{animation-name:bounceIn;animation-duration:.6s;animation-iteration-count:1}.cdx-notify--success{background:#fafffe!important}.cdx-notify--success::before{background:#41ffb1!important}`,""])},function(t,o){t.exports=function(i){var s=[];return s.toString=function(){return this.map(function(r){var a=function(l,c){var u=l[1]||"",h=l[3];if(!h)return u;if(c&&typeof btoa=="function"){var p=(f=h,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(f))))+" */"),g=h.sources.map(function(v){return"/*# sourceURL="+h.sourceRoot+v+" */"});return[u].concat(g).concat([p]).join(` -`)}var f;return[u].join(` -`)}(r,i);return r[2]?"@media "+r[2]+"{"+a+"}":a}).join("")},s.i=function(r,a){typeof r=="string"&&(r=[[null,r,""]]);for(var l={},c=0;c=0&&p.splice(m,1)}function A(k){var m=document.createElement("style");return k.attrs.type===void 0&&(k.attrs.type="text/css"),G(m,k.attrs),O(k,m),m}function G(k,m){Object.keys(m).forEach(function(w){k.setAttribute(w,m[w])})}function j(k,m){var w,x,I,C;if(m.transform&&k.css){if(!(C=m.transform(k.css)))return function(){};k.css=C}if(m.singleton){var D=h++;w=u||(u=A(m)),x=he.bind(null,w,D,!1),I=he.bind(null,w,D,!0)}else k.sourceMap&&typeof URL=="function"&&typeof URL.createObjectURL=="function"&&typeof URL.revokeObjectURL=="function"&&typeof Blob=="function"&&typeof btoa=="function"?(w=function(B){var K=document.createElement("link");return B.attrs.type===void 0&&(B.attrs.type="text/css"),B.attrs.rel="stylesheet",G(K,B.attrs),O(B,K),K}(m),x=(function(B,K,Oe){var pe=Oe.css,vo=Oe.sourceMap,Ca=K.convertToAbsoluteUrls===void 0&&vo;(K.convertToAbsoluteUrls||Ca)&&(pe=g(pe)),vo&&(pe+=` -/*# sourceMappingURL=data:application/json;base64,`+btoa(unescape(encodeURIComponent(JSON.stringify(vo))))+" */");var Ta=new Blob([pe],{type:"text/css"}),$n=B.href;B.href=URL.createObjectURL(Ta),$n&&URL.revokeObjectURL($n)}).bind(null,w,m),I=function(){S(w),w.href&&URL.revokeObjectURL(w.href)}):(w=A(m),x=(function(B,K){var Oe=K.css,pe=K.media;if(pe&&B.setAttribute("media",pe),B.styleSheet)B.styleSheet.cssText=Oe;else{for(;B.firstChild;)B.removeChild(B.firstChild);B.appendChild(document.createTextNode(Oe))}}).bind(null,w),I=function(){S(w)});return x(k),function(B){if(B){if(B.css===k.css&&B.media===k.media&&B.sourceMap===k.sourceMap)return;x(k=B)}else I()}}t.exports=function(k,m){if(typeof DEBUG<"u"&&DEBUG&&typeof document!="object")throw new Error("The style-loader cannot be used in a non-browser environment");(m=m||{}).attrs=typeof m.attrs=="object"?m.attrs:{},m.singleton||typeof m.singleton=="boolean"||(m.singleton=l()),m.insertInto||(m.insertInto="head"),m.insertAt||(m.insertAt="bottom");var w=v(k,m);return f(w,m),function(x){for(var I=[],C=0;Cthis.show(e)}}show(e){return this.notifier.show(e)}}class yi extends E{get methods(){const e=()=>this.isEnabled;return{toggle:t=>this.toggle(t),get isEnabled(){return e()}}}toggle(e){return this.Editor.ReadOnly.toggle(e)}get isEnabled(){return this.Editor.ReadOnly.isEnabled}}var Fo={exports:{}};(function(n,e){(function(t,o){n.exports=o()})(J,function(){function t(h){var p=h.tags,g=Object.keys(p),f=g.map(function(v){return typeof p[v]}).every(function(v){return v==="object"||v==="boolean"||v==="function"});if(!f)throw new Error("The configuration was invalid");this.config=h}var o=["P","LI","TD","TH","DIV","H1","H2","H3","H4","H5","H6","PRE"];function i(h){return o.indexOf(h.nodeName)!==-1}var s=["A","B","STRONG","I","EM","SUB","SUP","U","STRIKE"];function r(h){return s.indexOf(h.nodeName)!==-1}t.prototype.clean=function(h){const p=document.implementation.createHTMLDocument(),g=p.createElement("div");return g.innerHTML=h,this._sanitize(p,g),g.innerHTML},t.prototype._sanitize=function(h,p){var g=a(h,p),f=g.firstChild();if(f)do{if(f.nodeType===Node.TEXT_NODE)if(f.data.trim()===""&&(f.previousElementSibling&&i(f.previousElementSibling)||f.nextElementSibling&&i(f.nextElementSibling))){p.removeChild(f),this._sanitize(h,p);break}else continue;if(f.nodeType===Node.COMMENT_NODE){p.removeChild(f),this._sanitize(h,p);break}var v=r(f),O;v&&(O=Array.prototype.some.call(f.childNodes,i));var S=!!p.parentNode,A=i(p)&&i(f)&&S,G=f.nodeName.toLowerCase(),j=l(this.config,G,f),U=v&&O;if(U||c(f,j)||!this.config.keepNestedBlockElements&&A){if(!(f.nodeName==="SCRIPT"||f.nodeName==="STYLE"))for(;f.childNodes.length>0;)p.insertBefore(f.childNodes[0],f);p.removeChild(f),this._sanitize(h,p);break}for(var oe=0;oe"u"?!0:typeof p=="boolean"?!p:!1}function u(h,p,g){var f=h.name.toLowerCase();return p===!0?!1:typeof p[f]=="function"?!p[f](h.value,g):typeof p[f]>"u"||p[f]===!1?!0:typeof p[f]=="string"?p[f]!==h.value:!1}return t})})(Fo);var wi=Fo.exports;const Ei=ne(wi);function dt(n,e){return n.map(t=>{const o=M(e)?e(t.tool):e;return V(o)||(t.data=ut(t.data,o)),t})}function q(n,e={}){const t={tags:e};return new Ei(t).clean(n)}function ut(n,e){return Array.isArray(n)?xi(n,e):N(n)?Bi(n,e):Q(n)?Ci(n,e):n}function xi(n,e){return n.map(t=>ut(t,e))}function Bi(n,e){const t={};for(const o in n){if(!Object.prototype.hasOwnProperty.call(n,o))continue;const i=n[o],s=Ti(e[o])?e[o]:e;t[o]=ut(i,s)}return t}function Ci(n,e){return N(e)?q(n,e):e===!1?q(n,{}):n}function Ti(n){return N(n)||qn(n)||M(n)}class Si extends E{get methods(){return{clean:(e,t)=>this.clean(e,t)}}clean(e,t){return q(e,t)}}class Ii extends E{get methods(){return{save:()=>this.save()}}save(){const e="Editor's content can not be saved in read-only mode";return this.Editor.ReadOnly.isEnabled?(X(e,"warn"),Promise.reject(new Error(e))):this.Editor.Saver.save()}}class Oi extends E{constructor(){super(...arguments),this.selectionUtils=new b}get methods(){return{findParentTag:(e,t)=>this.findParentTag(e,t),expandToTag:e=>this.expandToTag(e),save:()=>this.selectionUtils.save(),restore:()=>this.selectionUtils.restore(),setFakeBackground:()=>this.selectionUtils.setFakeBackground(),removeFakeBackground:()=>this.selectionUtils.removeFakeBackground()}}findParentTag(e,t){return this.selectionUtils.findParentTag(e,t)}expandToTag(e){this.selectionUtils.expandToTag(e)}}class _i extends E{get methods(){return{getBlockTools:()=>Array.from(this.Editor.Tools.blockTools.values())}}}class Mi extends E{get classes(){return{block:"cdx-block",inlineToolButton:"ce-inline-tool",inlineToolButtonActive:"ce-inline-tool--active",input:"cdx-input",loader:"cdx-loader",button:"cdx-button",settingsButton:"cdx-settings-button",settingsButtonActive:"cdx-settings-button--active"}}}class Ai extends E{get methods(){return{close:()=>this.close(),open:()=>this.open(),toggleBlockSettings:e=>this.toggleBlockSettings(e),toggleToolbox:e=>this.toggleToolbox(e)}}open(){this.Editor.Toolbar.moveAndOpen()}close(){this.Editor.Toolbar.close()}toggleBlockSettings(e){if(this.Editor.BlockManager.currentBlockIndex===-1){X("Could't toggle the Toolbar because there is no block selected ","warn");return}e??!this.Editor.BlockSettings.opened?(this.Editor.Toolbar.moveAndOpen(),this.Editor.BlockSettings.open()):this.Editor.BlockSettings.close()}toggleToolbox(e){if(this.Editor.BlockManager.currentBlockIndex===-1){X("Could't toggle the Toolbox because there is no block selected ","warn");return}e??!this.Editor.Toolbar.toolbox.opened?(this.Editor.Toolbar.moveAndOpen(),this.Editor.Toolbar.toolbox.open()):this.Editor.Toolbar.toolbox.close()}}var jo={exports:{}};/*! - * CodeX.Tooltips - * - * @version 1.0.5 - * - * @licence MIT - * @author CodeX - * - * - */(function(n,e){(function(t,o){n.exports=o()})(window,function(){return function(t){var o={};function i(s){if(o[s])return o[s].exports;var r=o[s]={i:s,l:!1,exports:{}};return t[s].call(r.exports,r,r.exports,i),r.l=!0,r.exports}return i.m=t,i.c=o,i.d=function(s,r,a){i.o(s,r)||Object.defineProperty(s,r,{enumerable:!0,get:a})},i.r=function(s){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(s,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(s,"__esModule",{value:!0})},i.t=function(s,r){if(1&r&&(s=i(s)),8&r||4&r&&typeof s=="object"&&s&&s.__esModule)return s;var a=Object.create(null);if(i.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:s}),2&r&&typeof s!="string")for(var l in s)i.d(a,l,(function(c){return s[c]}).bind(null,l));return a},i.n=function(s){var r=s&&s.__esModule?function(){return s.default}:function(){return s};return i.d(r,"a",r),r},i.o=function(s,r){return Object.prototype.hasOwnProperty.call(s,r)},i.p="",i(i.s=0)}([function(t,o,i){t.exports=i(1)},function(t,o,i){i.r(o),i.d(o,"default",function(){return s});class s{constructor(){this.nodes={wrapper:null,content:null},this.showed=!1,this.offsetTop=10,this.offsetLeft=10,this.offsetRight=10,this.hidingDelay=0,this.handleWindowScroll=()=>{this.showed&&this.hide(!0)},this.loadStyles(),this.prepare(),window.addEventListener("scroll",this.handleWindowScroll,{passive:!0})}get CSS(){return{tooltip:"ct",tooltipContent:"ct__content",tooltipShown:"ct--shown",placement:{left:"ct--left",bottom:"ct--bottom",right:"ct--right",top:"ct--top"}}}show(a,l,c){this.nodes.wrapper||this.prepare(),this.hidingTimeout&&clearTimeout(this.hidingTimeout);const u=Object.assign({placement:"bottom",marginTop:0,marginLeft:0,marginRight:0,marginBottom:0,delay:70,hidingDelay:0},c);if(u.hidingDelay&&(this.hidingDelay=u.hidingDelay),this.nodes.content.innerHTML="",typeof l=="string")this.nodes.content.appendChild(document.createTextNode(l));else{if(!(l instanceof Node))throw Error("[CodeX Tooltip] Wrong type of «content» passed. It should be an instance of Node or String. But "+typeof l+" given.");this.nodes.content.appendChild(l)}switch(this.nodes.wrapper.classList.remove(...Object.values(this.CSS.placement)),u.placement){case"top":this.placeTop(a,u);break;case"left":this.placeLeft(a,u);break;case"right":this.placeRight(a,u);break;case"bottom":default:this.placeBottom(a,u)}u&&u.delay?this.showingTimeout=setTimeout(()=>{this.nodes.wrapper.classList.add(this.CSS.tooltipShown),this.showed=!0},u.delay):(this.nodes.wrapper.classList.add(this.CSS.tooltipShown),this.showed=!0)}hide(a=!1){if(this.hidingDelay&&!a)return this.hidingTimeout&&clearTimeout(this.hidingTimeout),void(this.hidingTimeout=setTimeout(()=>{this.hide(!0)},this.hidingDelay));this.nodes.wrapper.classList.remove(this.CSS.tooltipShown),this.showed=!1,this.showingTimeout&&clearTimeout(this.showingTimeout)}onHover(a,l,c){a.addEventListener("mouseenter",()=>{this.show(a,l,c)}),a.addEventListener("mouseleave",()=>{this.hide()})}destroy(){this.nodes.wrapper.remove(),window.removeEventListener("scroll",this.handleWindowScroll)}prepare(){this.nodes.wrapper=this.make("div",this.CSS.tooltip),this.nodes.content=this.make("div",this.CSS.tooltipContent),this.append(this.nodes.wrapper,this.nodes.content),this.append(document.body,this.nodes.wrapper)}loadStyles(){const a="codex-tooltips-style";if(document.getElementById(a))return;const l=i(2),c=this.make("style",null,{textContent:l.toString(),id:a});this.prepend(document.head,c)}placeBottom(a,l){const c=a.getBoundingClientRect(),u=c.left+a.clientWidth/2-this.nodes.wrapper.offsetWidth/2,h=c.bottom+window.pageYOffset+this.offsetTop+l.marginTop;this.applyPlacement("bottom",u,h)}placeTop(a,l){const c=a.getBoundingClientRect(),u=c.left+a.clientWidth/2-this.nodes.wrapper.offsetWidth/2,h=c.top+window.pageYOffset-this.nodes.wrapper.clientHeight-this.offsetTop;this.applyPlacement("top",u,h)}placeLeft(a,l){const c=a.getBoundingClientRect(),u=c.left-this.nodes.wrapper.offsetWidth-this.offsetLeft-l.marginLeft,h=c.top+window.pageYOffset+a.clientHeight/2-this.nodes.wrapper.offsetHeight/2;this.applyPlacement("left",u,h)}placeRight(a,l){const c=a.getBoundingClientRect(),u=c.right+this.offsetRight+l.marginRight,h=c.top+window.pageYOffset+a.clientHeight/2-this.nodes.wrapper.offsetHeight/2;this.applyPlacement("right",u,h)}applyPlacement(a,l,c){this.nodes.wrapper.classList.add(this.CSS.placement[a]),this.nodes.wrapper.style.left=l+"px",this.nodes.wrapper.style.top=c+"px"}make(a,l=null,c={}){const u=document.createElement(a);Array.isArray(l)?u.classList.add(...l):l&&u.classList.add(l);for(const h in c)c.hasOwnProperty(h)&&(u[h]=c[h]);return u}append(a,l){Array.isArray(l)?l.forEach(c=>a.appendChild(c)):a.appendChild(l)}prepend(a,l){Array.isArray(l)?(l=l.reverse()).forEach(c=>a.prepend(c)):a.prepend(l)}}},function(t,o){t.exports=`.ct{z-index:999;opacity:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none;-webkit-transition:opacity 50ms ease-in,-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,transform 70ms cubic-bezier(.215,.61,.355,1);transition:opacity 50ms ease-in,transform 70ms cubic-bezier(.215,.61,.355,1),-webkit-transform 70ms cubic-bezier(.215,.61,.355,1);will-change:opacity,top,left;-webkit-box-shadow:0 8px 12px 0 rgba(29,32,43,.17),0 4px 5px -3px rgba(5,6,12,.49);box-shadow:0 8px 12px 0 rgba(29,32,43,.17),0 4px 5px -3px rgba(5,6,12,.49);border-radius:9px}.ct,.ct:before{position:absolute;top:0;left:0}.ct:before{content:"";bottom:0;right:0;background-color:#1d202b;z-index:-1;border-radius:4px}@supports(-webkit-mask-box-image:url("")){.ct:before{border-radius:0;-webkit-mask-box-image:url('data:image/svg+xml;charset=utf-8,') 48% 41% 37.9% 53.3%}}@media (--mobile){.ct{display:none}}.ct__content{padding:6px 10px;color:#cdd1e0;font-size:12px;text-align:center;letter-spacing:.02em;line-height:1em}.ct:after{content:"";width:8px;height:8px;position:absolute;background-color:#1d202b;z-index:-1}.ct--bottom{-webkit-transform:translateY(5px);transform:translateY(5px)}.ct--bottom:after{top:-3px;left:50%;-webkit-transform:translateX(-50%) rotate(-45deg);transform:translateX(-50%) rotate(-45deg)}.ct--top{-webkit-transform:translateY(-5px);transform:translateY(-5px)}.ct--top:after{top:auto;bottom:-3px;left:50%;-webkit-transform:translateX(-50%) rotate(-45deg);transform:translateX(-50%) rotate(-45deg)}.ct--left{-webkit-transform:translateX(-5px);transform:translateX(-5px)}.ct--left:after{top:50%;left:auto;right:0;-webkit-transform:translate(41.6%,-50%) rotate(-45deg);transform:translate(41.6%,-50%) rotate(-45deg)}.ct--right{-webkit-transform:translateX(5px);transform:translateX(5px)}.ct--right:after{top:50%;left:0;-webkit-transform:translate(-41.6%,-50%) rotate(-45deg);transform:translate(-41.6%,-50%) rotate(-45deg)}.ct--shown{opacity:1;-webkit-transform:none;transform:none}`}]).default})})(jo);var Li=jo.exports;const Pi=ne(Li);let $=null;function ht(){$||($=new Pi)}function Ni(n,e,t){ht(),$==null||$.show(n,e,t)}function Ne(n=!1){ht(),$==null||$.hide(n)}function Re(n,e,t){ht(),$==null||$.onHover(n,e,t)}function Ri(){$==null||$.destroy(),$=null}class Di extends E{constructor({config:e,eventsDispatcher:t}){super({config:e,eventsDispatcher:t})}get methods(){return{show:(e,t,o)=>this.show(e,t,o),hide:()=>this.hide(),onHover:(e,t,o)=>this.onHover(e,t,o)}}show(e,t,o){Ni(e,t,o)}hide(){Ne()}onHover(e,t,o){Re(e,t,o)}}class Fi extends E{get methods(){return{nodes:this.editorNodes}}get editorNodes(){return{wrapper:this.Editor.UI.nodes.wrapper,redactor:this.Editor.UI.nodes.redactor}}}function Ho(n,e){const t={};return Object.entries(n).forEach(([o,i])=>{if(N(i)){const s=e?`${e}.${o}`:o;Object.values(i).every(a=>Q(a))?t[o]=s:t[o]=Ho(i,s);return}t[o]=i}),t}const W=Ho(So);function ji(n,e){const t={};return Object.keys(n).forEach(o=>{const i=e[o];i!==void 0?t[i]=n[o]:t[o]=n[o]}),t}const $o=class _e{constructor(e,t){this.cursor=-1,this.items=[],this.items=e||[],this.focusedCssClass=t}get currentItem(){return this.cursor===-1?null:this.items[this.cursor]}setCursor(e){e=-1&&(this.dropCursor(),this.cursor=e,this.items[this.cursor].classList.add(this.focusedCssClass))}setItems(e){this.items=e}next(){this.cursor=this.leafNodesAndReturnIndex(_e.directions.RIGHT)}previous(){this.cursor=this.leafNodesAndReturnIndex(_e.directions.LEFT)}dropCursor(){this.cursor!==-1&&(this.items[this.cursor].classList.remove(this.focusedCssClass),this.cursor=-1)}leafNodesAndReturnIndex(e){if(this.items.length===0)return this.cursor;let t=this.cursor;return t===-1?t=e===_e.directions.RIGHT?-1:0:this.items[t].classList.remove(this.focusedCssClass),e===_e.directions.RIGHT?t=(t+1)%this.items.length:t=(this.items.length+t-1)%this.items.length,d.canSetCaret(this.items[t])&&Ae(()=>b.setCursor(this.items[t]),50)(),this.items[t].classList.add(this.focusedCssClass),t}};$o.directions={RIGHT:"right",LEFT:"left"};let Be=$o;class ae{constructor(e){this.iterator=null,this.activated=!1,this.flipCallbacks=[],this.onKeyDown=t=>{if(!(!this.isEventReadyForHandling(t)||t.shiftKey===!0))switch(ae.usedKeys.includes(t.keyCode)&&t.preventDefault(),t.keyCode){case y.TAB:this.handleTabPress(t);break;case y.LEFT:case y.UP:this.flipLeft();break;case y.RIGHT:case y.DOWN:this.flipRight();break;case y.ENTER:this.handleEnterPress(t);break}},this.iterator=new Be(e.items,e.focusedItemClass),this.activateCallback=e.activateCallback,this.allowedKeys=e.allowedKeys||ae.usedKeys}get isActivated(){return this.activated}static get usedKeys(){return[y.TAB,y.LEFT,y.RIGHT,y.ENTER,y.UP,y.DOWN]}activate(e,t){this.activated=!0,e&&this.iterator.setItems(e),t!==void 0&&this.iterator.setCursor(t),document.addEventListener("keydown",this.onKeyDown,!0)}deactivate(){this.activated=!1,this.dropCursor(),document.removeEventListener("keydown",this.onKeyDown)}focusFirst(){this.dropCursor(),this.flipRight()}flipLeft(){this.iterator.previous(),this.flipCallback()}flipRight(){this.iterator.next(),this.flipCallback()}hasFocus(){return!!this.iterator.currentItem}onFlip(e){this.flipCallbacks.push(e)}removeOnFlip(e){this.flipCallbacks=this.flipCallbacks.filter(t=>t!==e)}dropCursor(){this.iterator.dropCursor()}isEventReadyForHandling(e){return this.activated&&this.allowedKeys.includes(e.keyCode)}handleTabPress(e){switch(e.shiftKey?Be.directions.LEFT:Be.directions.RIGHT){case Be.directions.RIGHT:this.flipRight();break;case Be.directions.LEFT:this.flipLeft();break}}handleEnterPress(e){this.activated&&(this.iterator.currentItem&&(e.stopPropagation(),e.preventDefault(),this.iterator.currentItem.click()),M(this.activateCallback)&&this.activateCallback(this.iterator.currentItem))}flipCallback(){this.iterator.currentItem&&this.iterator.currentItem.scrollIntoViewIfNeeded(),this.flipCallbacks.forEach(e=>e())}}const Hi='',$i='',zi='',Ui='',Wi='',Yi='',Ki='',Xi='',zo='',Vi='',qi='',Uo='',Zi='',Gi='',Ji='',Qi="__",es="--";function ie(n){return(e,t)=>[[n,e].filter(i=>!!i).join(Qi),t].filter(i=>!!i).join(es)}const Ce=ie("ce-hint"),Te={root:Ce(),alignedStart:Ce(null,"align-left"),alignedCenter:Ce(null,"align-center"),title:Ce("title"),description:Ce("description")},Ma="";class ts{constructor(e){this.nodes={root:d.make("div",[Te.root,e.alignment==="center"?Te.alignedCenter:Te.alignedStart]),title:d.make("div",Te.title,{textContent:e.title})},this.nodes.root.appendChild(this.nodes.title),e.description!==void 0&&(this.nodes.description=d.make("div",Te.description,{textContent:e.description}),this.nodes.root.appendChild(this.nodes.description))}getElement(){return this.nodes.root}}class pt{constructor(e){this.params=e}get name(){if(this.params!==void 0&&"name"in this.params)return this.params.name}destroy(){Ne()}onChildrenOpen(){var e;this.params!==void 0&&"children"in this.params&&typeof((e=this.params.children)==null?void 0:e.onOpen)=="function"&&this.params.children.onOpen()}onChildrenClose(){var e;this.params!==void 0&&"children"in this.params&&typeof((e=this.params.children)==null?void 0:e.onClose)=="function"&&this.params.children.onClose()}handleClick(){var e,t;this.params!==void 0&&"onActivate"in this.params&&((t=(e=this.params).onActivate)==null||t.call(e,this.params))}addHint(e,t){const o=new ts(t);Re(e,o.getElement(),{placement:t.position,hidingDelay:100})}get children(){var e;return this.params!==void 0&&"children"in this.params&&((e=this.params.children)==null?void 0:e.items)!==void 0?this.params.children.items:[]}get hasChildren(){return this.children.length>0}get isChildrenOpen(){var e;return this.params!==void 0&&"children"in this.params&&((e=this.params.children)==null?void 0:e.isOpen)===!0}get isChildrenFlippable(){var e;return!(this.params===void 0||!("children"in this.params)||((e=this.params.children)==null?void 0:e.isFlippable)===!1)}get isChildrenSearchable(){var e;return this.params!==void 0&&"children"in this.params&&((e=this.params.children)==null?void 0:e.searchable)===!0}get closeOnActivate(){return this.params!==void 0&&"closeOnActivate"in this.params&&this.params.closeOnActivate}get isActive(){return this.params===void 0||!("isActive"in this.params)?!1:typeof this.params.isActive=="function"?this.params.isActive():this.params.isActive===!0}}const Y=ie("ce-popover-item"),L={container:Y(),active:Y(null,"active"),disabled:Y(null,"disabled"),focused:Y(null,"focused"),hidden:Y(null,"hidden"),confirmationState:Y(null,"confirmation"),noHover:Y(null,"no-hover"),noFocus:Y(null,"no-focus"),title:Y("title"),secondaryTitle:Y("secondary-title"),icon:Y("icon"),iconTool:Y("icon","tool"),iconChevronRight:Y("icon","chevron-right"),wobbleAnimation:ie("wobble")()};class le extends pt{constructor(e,t){super(e),this.params=e,this.nodes={root:null,icon:null},this.confirmationState=null,this.removeSpecialFocusBehavior=()=>{var o;(o=this.nodes.root)==null||o.classList.remove(L.noFocus)},this.removeSpecialHoverBehavior=()=>{var o;(o=this.nodes.root)==null||o.classList.remove(L.noHover)},this.onErrorAnimationEnd=()=>{var o,i;(o=this.nodes.icon)==null||o.classList.remove(L.wobbleAnimation),(i=this.nodes.icon)==null||i.removeEventListener("animationend",this.onErrorAnimationEnd)},this.nodes.root=this.make(e,t)}get isDisabled(){return this.params.isDisabled===!0}get toggle(){return this.params.toggle}get title(){return this.params.title}get isConfirmationStateEnabled(){return this.confirmationState!==null}get isFocused(){return this.nodes.root===null?!1:this.nodes.root.classList.contains(L.focused)}getElement(){return this.nodes.root}handleClick(){if(this.isConfirmationStateEnabled&&this.confirmationState!==null){this.activateOrEnableConfirmationMode(this.confirmationState);return}this.activateOrEnableConfirmationMode(this.params)}toggleActive(e){var t;(t=this.nodes.root)==null||t.classList.toggle(L.active,e)}toggleHidden(e){var t;(t=this.nodes.root)==null||t.classList.toggle(L.hidden,e)}reset(){this.isConfirmationStateEnabled&&this.disableConfirmationMode()}onFocus(){this.disableSpecialHoverAndFocusBehavior()}make(e,t){var s,r;const o=(t==null?void 0:t.wrapperTag)||"div",i=d.make(o,L.container,{type:o==="button"?"button":void 0});return e.name&&(i.dataset.itemName=e.name),this.nodes.icon=d.make("div",[L.icon,L.iconTool],{innerHTML:e.icon||Ki}),i.appendChild(this.nodes.icon),e.title!==void 0&&i.appendChild(d.make("div",L.title,{innerHTML:e.title||""})),e.secondaryLabel&&i.appendChild(d.make("div",L.secondaryTitle,{textContent:e.secondaryLabel})),this.hasChildren&&i.appendChild(d.make("div",[L.icon,L.iconChevronRight],{innerHTML:Ui})),this.isActive&&i.classList.add(L.active),e.isDisabled&&i.classList.add(L.disabled),e.hint!==void 0&&((s=t==null?void 0:t.hint)==null?void 0:s.enabled)!==!1&&this.addHint(i,{...e.hint,position:((r=t==null?void 0:t.hint)==null?void 0:r.position)||"right"}),i}enableConfirmationMode(e){if(this.nodes.root===null)return;const t={...this.params,...e,confirmation:"confirmation"in e?e.confirmation:void 0},o=this.make(t);this.nodes.root.innerHTML=o.innerHTML,this.nodes.root.classList.add(L.confirmationState),this.confirmationState=e,this.enableSpecialHoverAndFocusBehavior()}disableConfirmationMode(){if(this.nodes.root===null)return;const e=this.make(this.params);this.nodes.root.innerHTML=e.innerHTML,this.nodes.root.classList.remove(L.confirmationState),this.confirmationState=null,this.disableSpecialHoverAndFocusBehavior()}enableSpecialHoverAndFocusBehavior(){var e,t,o;(e=this.nodes.root)==null||e.classList.add(L.noHover),(t=this.nodes.root)==null||t.classList.add(L.noFocus),(o=this.nodes.root)==null||o.addEventListener("mouseleave",this.removeSpecialHoverBehavior,{once:!0})}disableSpecialHoverAndFocusBehavior(){var e;this.removeSpecialFocusBehavior(),this.removeSpecialHoverBehavior(),(e=this.nodes.root)==null||e.removeEventListener("mouseleave",this.removeSpecialHoverBehavior)}activateOrEnableConfirmationMode(e){var t;if(!("confirmation"in e)||e.confirmation===void 0)try{(t=e.onActivate)==null||t.call(e,e),this.disableConfirmationMode()}catch{this.animateError()}else this.enableConfirmationMode(e.confirmation)}animateError(){var e,t,o;(e=this.nodes.icon)!=null&&e.classList.contains(L.wobbleAnimation)||((t=this.nodes.icon)==null||t.classList.add(L.wobbleAnimation),(o=this.nodes.icon)==null||o.addEventListener("animationend",this.onErrorAnimationEnd))}}const ft=ie("ce-popover-item-separator"),gt={container:ft(),line:ft("line"),hidden:ft(null,"hidden")};class Wo extends pt{constructor(){super(),this.nodes={root:d.make("div",gt.container),line:d.make("div",gt.line)},this.nodes.root.appendChild(this.nodes.line)}getElement(){return this.nodes.root}toggleHidden(e){var t;(t=this.nodes.root)==null||t.classList.toggle(gt.hidden,e)}}var Z=(n=>(n.Closed="closed",n.ClosedOnActivate="closed-on-activate",n))(Z||{});const z=ie("ce-popover"),P={popover:z(),popoverContainer:z("container"),popoverOpenTop:z(null,"open-top"),popoverOpenLeft:z(null,"open-left"),popoverOpened:z(null,"opened"),search:z("search"),nothingFoundMessage:z("nothing-found-message"),nothingFoundMessageDisplayed:z("nothing-found-message","displayed"),items:z("items"),overlay:z("overlay"),overlayHidden:z("overlay","hidden"),popoverNested:z(null,"nested"),getPopoverNestedClass:n=>z(null,`nested-level-${n.toString()}`),popoverInline:z(null,"inline"),popoverHeader:z("header")};var me=(n=>(n.NestingLevel="--nesting-level",n.PopoverHeight="--popover-height",n.InlinePopoverWidth="--inline-popover-width",n.TriggerItemLeft="--trigger-item-left",n.TriggerItemTop="--trigger-item-top",n))(me||{});const Yo=ie("ce-popover-item-html"),Ko={root:Yo(),hidden:Yo(null,"hidden")};class Se extends pt{constructor(e,t){var o,i;super(e),this.nodes={root:d.make("div",Ko.root)},this.nodes.root.appendChild(e.element),e.name&&(this.nodes.root.dataset.itemName=e.name),e.hint!==void 0&&((o=t==null?void 0:t.hint)==null?void 0:o.enabled)!==!1&&this.addHint(this.nodes.root,{...e.hint,position:((i=t==null?void 0:t.hint)==null?void 0:i.position)||"right"})}getElement(){return this.nodes.root}toggleHidden(e){var t;(t=this.nodes.root)==null||t.classList.toggle(Ko.hidden,e)}getControls(){const e=this.nodes.root.querySelectorAll(`button, ${d.allInputsSelector}`);return Array.from(e)}}class Xo extends we{constructor(e,t={}){super(),this.params=e,this.itemsRenderParams=t,this.listeners=new Ee,this.messages={nothingFound:"Nothing found",search:"Search"},this.items=this.buildItems(e.items),e.messages&&(this.messages={...this.messages,...e.messages}),this.nodes={},this.nodes.popoverContainer=d.make("div",[P.popoverContainer]),this.nodes.nothingFoundMessage=d.make("div",[P.nothingFoundMessage],{textContent:this.messages.nothingFound}),this.nodes.popoverContainer.appendChild(this.nodes.nothingFoundMessage),this.nodes.items=d.make("div",[P.items]),this.items.forEach(o=>{const i=o.getElement();i!==null&&this.nodes.items.appendChild(i)}),this.nodes.popoverContainer.appendChild(this.nodes.items),this.listeners.on(this.nodes.popoverContainer,"click",o=>this.handleClick(o)),this.nodes.popover=d.make("div",[P.popover,this.params.class]),this.nodes.popover.appendChild(this.nodes.popoverContainer)}get itemsDefault(){return this.items.filter(e=>e instanceof le)}getElement(){return this.nodes.popover}show(){this.nodes.popover.classList.add(P.popoverOpened),this.search!==void 0&&this.search.focus()}hide(){this.nodes.popover.classList.remove(P.popoverOpened),this.nodes.popover.classList.remove(P.popoverOpenTop),this.itemsDefault.forEach(e=>e.reset()),this.search!==void 0&&this.search.clear(),this.emit(Z.Closed)}destroy(){var e;this.items.forEach(t=>t.destroy()),this.nodes.popover.remove(),this.listeners.removeAll(),(e=this.search)==null||e.destroy()}activateItemByName(e){const t=this.items.find(o=>o.name===e);this.handleItemClick(t)}buildItems(e){return e.map(t=>{switch(t.type){case _.Separator:return new Wo;case _.Html:return new Se(t,this.itemsRenderParams[_.Html]);default:return new le(t,this.itemsRenderParams[_.Default])}})}getTargetItem(e){return this.items.filter(t=>t instanceof le||t instanceof Se).find(t=>{const o=t.getElement();return o===null?!1:e.composedPath().includes(o)})}handleItemClick(e){if(!("isDisabled"in e&&e.isDisabled)){if(e.hasChildren){this.showNestedItems(e),"handleClick"in e&&typeof e.handleClick=="function"&&e.handleClick();return}this.itemsDefault.filter(t=>t!==e).forEach(t=>t.reset()),"handleClick"in e&&typeof e.handleClick=="function"&&e.handleClick(),this.toggleItemActivenessIfNeeded(e),e.closeOnActivate&&(this.hide(),this.emit(Z.ClosedOnActivate))}}handleClick(e){const t=this.getTargetItem(e);t!==void 0&&this.handleItemClick(t)}toggleItemActivenessIfNeeded(e){if(e instanceof le&&(e.toggle===!0&&e.toggleActive(),typeof e.toggle=="string")){const t=this.itemsDefault.filter(o=>o.toggle===e.toggle);if(t.length===1){e.toggleActive();return}t.forEach(o=>{o.toggleActive(o===e)})}}}var De=(n=>(n.Search="search",n))(De||{});const mt=ie("cdx-search-field"),bt={wrapper:mt(),icon:mt("icon"),input:mt("input")};class os extends we{constructor({items:e,placeholder:t}){super(),this.listeners=new Ee,this.items=e,this.wrapper=d.make("div",bt.wrapper);const o=d.make("div",bt.icon,{innerHTML:Zi});this.input=d.make("input",bt.input,{placeholder:t,tabIndex:-1}),this.wrapper.appendChild(o),this.wrapper.appendChild(this.input),this.listeners.on(this.input,"input",()=>{this.searchQuery=this.input.value,this.emit(De.Search,{query:this.searchQuery,items:this.foundItems})})}getElement(){return this.wrapper}focus(){this.input.focus()}clear(){this.input.value="",this.searchQuery="",this.emit(De.Search,{query:"",items:this.foundItems})}destroy(){this.listeners.removeAll()}get foundItems(){return this.items.filter(e=>this.checkItem(e))}checkItem(e){var i,s;const t=((i=e.title)==null?void 0:i.toLowerCase())||"",o=(s=this.searchQuery)==null?void 0:s.toLowerCase();return o!==void 0?t.includes(o):!1}}var ns=Object.defineProperty,is=Object.getOwnPropertyDescriptor,ss=(n,e,t,o)=>{for(var i=o>1?void 0:o?is(e,t):e,s=n.length-1,r;s>=0;s--)(r=n[s])&&(i=(o?r(e,t,i):r(i))||i);return o&&i&&ns(e,t,i),i};const Vo=class zn extends Xo{constructor(e,t){super(e,t),this.nestingLevel=0,this.nestedPopoverTriggerItem=null,this.previouslyHoveredItem=null,this.scopeElement=document.body,this.hide=()=>{var o;super.hide(),this.destroyNestedPopoverIfExists(),(o=this.flipper)==null||o.deactivate(),this.previouslyHoveredItem=null},this.onFlip=()=>{const o=this.itemsDefault.find(i=>i.isFocused);o==null||o.onFocus()},this.onSearch=o=>{var a;const i=o.query==="",s=o.items.length===0;this.items.forEach(l=>{let c=!1;l instanceof le?c=!o.items.includes(l):(l instanceof Wo||l instanceof Se)&&(c=s||!i),l.toggleHidden(c)}),this.toggleNothingFoundMessage(s);const r=o.query===""?this.flippableElements:o.items.map(l=>l.getElement());(a=this.flipper)!=null&&a.isActivated&&(this.flipper.deactivate(),this.flipper.activate(r))},e.nestingLevel!==void 0&&(this.nestingLevel=e.nestingLevel),this.nestingLevel>0&&this.nodes.popover.classList.add(P.popoverNested),e.scopeElement!==void 0&&(this.scopeElement=e.scopeElement),this.nodes.popoverContainer!==null&&this.listeners.on(this.nodes.popoverContainer,"mouseover",o=>this.handleHover(o)),e.searchable&&this.addSearch(),e.flippable!==!1&&(this.flipper=new ae({items:this.flippableElements,focusedItemClass:L.focused,allowedKeys:[y.TAB,y.UP,y.DOWN,y.ENTER]}),this.flipper.onFlip(this.onFlip))}hasFocus(){return this.flipper===void 0?!1:this.flipper.hasFocus()}get scrollTop(){return this.nodes.items===null?0:this.nodes.items.scrollTop}get offsetTop(){return this.nodes.popoverContainer===null?0:this.nodes.popoverContainer.offsetTop}show(){var e;this.nodes.popover.style.setProperty(me.PopoverHeight,this.size.height+"px"),this.shouldOpenBottom||this.nodes.popover.classList.add(P.popoverOpenTop),this.shouldOpenRight||this.nodes.popover.classList.add(P.popoverOpenLeft),super.show(),(e=this.flipper)==null||e.activate(this.flippableElements)}destroy(){this.hide(),super.destroy()}showNestedItems(e){this.nestedPopover!==null&&this.nestedPopover!==void 0||(this.nestedPopoverTriggerItem=e,this.showNestedPopoverForItem(e))}handleHover(e){const t=this.getTargetItem(e);t!==void 0&&this.previouslyHoveredItem!==t&&(this.destroyNestedPopoverIfExists(),this.previouslyHoveredItem=t,t.hasChildren&&this.showNestedPopoverForItem(t))}setTriggerItemPosition(e,t){const o=t.getElement(),i=(o?o.offsetTop:0)-this.scrollTop,s=this.offsetTop+i;e.style.setProperty(me.TriggerItemTop,s+"px")}destroyNestedPopoverIfExists(){var e,t;this.nestedPopover===void 0||this.nestedPopover===null||(this.nestedPopover.off(Z.ClosedOnActivate,this.hide),this.nestedPopover.hide(),this.nestedPopover.destroy(),this.nestedPopover.getElement().remove(),this.nestedPopover=null,(e=this.flipper)==null||e.activate(this.flippableElements),(t=this.nestedPopoverTriggerItem)==null||t.onChildrenClose())}showNestedPopoverForItem(e){var o;this.nestedPopover=new zn({searchable:e.isChildrenSearchable,items:e.children,nestingLevel:this.nestingLevel+1,flippable:e.isChildrenFlippable,messages:this.messages}),e.onChildrenOpen(),this.nestedPopover.on(Z.ClosedOnActivate,this.hide);const t=this.nestedPopover.getElement();return this.nodes.popover.appendChild(t),this.setTriggerItemPosition(t,e),t.style.setProperty(me.NestingLevel,this.nestedPopover.nestingLevel.toString()),this.nestedPopover.show(),(o=this.flipper)==null||o.deactivate(),this.nestedPopover}get shouldOpenBottom(){if(this.nodes.popover===void 0||this.nodes.popover===null)return!1;const e=this.nodes.popoverContainer.getBoundingClientRect(),t=this.scopeElement.getBoundingClientRect(),o=this.size.height,i=e.top+o,s=e.top-o,r=Math.min(window.innerHeight,t.bottom);return s{if(t instanceof le)return t.getElement();if(t instanceof Se)return t.getControls()}).flat().filter(t=>t!=null)}addSearch(){this.search=new os({items:this.itemsDefault,placeholder:this.messages.search}),this.search.on(De.Search,this.onSearch);const e=this.search.getElement();e.classList.add(P.search),this.nodes.popoverContainer.insertBefore(e,this.nodes.popoverContainer.firstChild)}toggleNothingFoundMessage(e){this.nodes.nothingFoundMessage.classList.toggle(P.nothingFoundMessageDisplayed,e)}};ss([fe],Vo.prototype,"size",1);let vt=Vo;class rs extends vt{constructor(e){const t=!ge();super({...e,class:P.popoverInline},{[_.Default]:{wrapperTag:"button",hint:{position:"top",alignment:"center",enabled:t}},[_.Html]:{hint:{position:"top",alignment:"center",enabled:t}}}),this.items.forEach(o=>{!(o instanceof le)&&!(o instanceof Se)||o.hasChildren&&o.isChildrenOpen&&this.showNestedItems(o)})}get offsetLeft(){return this.nodes.popoverContainer===null?0:this.nodes.popoverContainer.offsetLeft}show(){this.nestingLevel===0&&this.nodes.popover.style.setProperty(me.InlinePopoverWidth,this.size.width+"px"),super.show()}handleHover(){}setTriggerItemPosition(e,t){const o=t.getElement(),i=o?o.offsetLeft:0,s=this.offsetLeft+i;e.style.setProperty(me.TriggerItemLeft,s+"px")}showNestedItems(e){if(this.nestedPopoverTriggerItem===e){this.destroyNestedPopoverIfExists(),this.nestedPopoverTriggerItem=null;return}super.showNestedItems(e)}showNestedPopoverForItem(e){const t=super.showNestedPopoverForItem(e);return t.getElement().classList.add(P.getPopoverNestedClass(t.nestingLevel)),t}handleItemClick(e){var t;e!==this.nestedPopoverTriggerItem&&((t=this.nestedPopoverTriggerItem)==null||t.handleClick(),super.destroyNestedPopoverIfExists()),super.handleItemClick(e)}}const qo=class Me{constructor(){this.scrollPosition=null}lock(){rt?this.lockHard():document.body.classList.add(Me.CSS.scrollLocked)}unlock(){rt?this.unlockHard():document.body.classList.remove(Me.CSS.scrollLocked)}lockHard(){this.scrollPosition=window.pageYOffset,document.documentElement.style.setProperty("--window-scroll-offset",`${this.scrollPosition}px`),document.body.classList.add(Me.CSS.scrollLockedHard)}unlockHard(){document.body.classList.remove(Me.CSS.scrollLockedHard),this.scrollPosition!==null&&window.scrollTo(0,this.scrollPosition),this.scrollPosition=null}};qo.CSS={scrollLocked:"ce-scroll-locked",scrollLockedHard:"ce-scroll-locked--hard"};let as=qo;const kt=ie("ce-popover-header"),yt={root:kt(),text:kt("text"),backButton:kt("back-button")};class ls{constructor({text:e,onBackButtonClick:t}){this.listeners=new Ee,this.text=e,this.onBackButtonClick=t,this.nodes={root:d.make("div",[yt.root]),backButton:d.make("button",[yt.backButton]),text:d.make("div",[yt.text])},this.nodes.backButton.innerHTML=zi,this.nodes.root.appendChild(this.nodes.backButton),this.listeners.on(this.nodes.backButton,"click",this.onBackButtonClick),this.nodes.text.innerText=this.text,this.nodes.root.appendChild(this.nodes.text)}getElement(){return this.nodes.root}destroy(){this.nodes.root.remove(),this.listeners.destroy()}}class cs{constructor(){this.history=[]}push(e){this.history.push(e)}pop(){return this.history.pop()}get currentTitle(){return this.history.length===0?"":this.history[this.history.length-1].title}get currentItems(){return this.history.length===0?[]:this.history[this.history.length-1].items}reset(){for(;this.history.length>1;)this.pop()}}class Zo extends Xo{constructor(e){super(e,{[_.Default]:{hint:{enabled:!1}},[_.Html]:{hint:{enabled:!1}}}),this.scrollLocker=new as,this.history=new cs,this.isHidden=!0,this.nodes.overlay=d.make("div",[P.overlay,P.overlayHidden]),this.nodes.popover.insertBefore(this.nodes.overlay,this.nodes.popover.firstChild),this.listeners.on(this.nodes.overlay,"click",()=>{this.hide()}),this.history.push({items:e.items})}show(){this.nodes.overlay.classList.remove(P.overlayHidden),super.show(),this.scrollLocker.lock(),this.isHidden=!1}hide(){this.isHidden||(super.hide(),this.nodes.overlay.classList.add(P.overlayHidden),this.scrollLocker.unlock(),this.history.reset(),this.isHidden=!0)}destroy(){super.destroy(),this.scrollLocker.unlock()}showNestedItems(e){this.updateItemsAndHeader(e.children,e.title),this.history.push({title:e.title,items:e.children})}updateItemsAndHeader(e,t){if(this.header!==null&&this.header!==void 0&&(this.header.destroy(),this.header=null),t!==void 0){this.header=new ls({text:t,onBackButtonClick:()=>{this.history.pop(),this.updateItemsAndHeader(this.history.currentItems,this.history.currentTitle)}});const o=this.header.getElement();o!==null&&this.nodes.popoverContainer.insertBefore(o,this.nodes.popoverContainer.firstChild)}this.items.forEach(o=>{var i;return(i=o.getElement())==null?void 0:i.remove()}),this.items=this.buildItems(e),this.items.forEach(o=>{var s;const i=o.getElement();i!==null&&((s=this.nodes.items)==null||s.appendChild(i))})}}class ds extends E{constructor(){super(...arguments),this.opened=!1,this.selection=new b,this.popover=null,this.close=()=>{this.opened&&(this.opened=!1,b.isAtEditor||this.selection.restore(),this.selection.clearSaved(),!this.Editor.CrossBlockSelection.isCrossBlockSelectionStarted&&this.Editor.BlockManager.currentBlock&&this.Editor.BlockSelection.unselectBlock(this.Editor.BlockManager.currentBlock),this.eventsDispatcher.emit(this.events.closed),this.popover&&(this.popover.off(Z.Closed,this.onPopoverClose),this.popover.destroy(),this.popover.getElement().remove(),this.popover=null))},this.onPopoverClose=()=>{this.close()}}get events(){return{opened:"block-settings-opened",closed:"block-settings-closed"}}get CSS(){return{settings:"ce-settings"}}get flipper(){var e;if(this.popover!==null)return"flipper"in this.popover?(e=this.popover)==null?void 0:e.flipper:void 0}make(){this.nodes.wrapper=d.make("div",[this.CSS.settings]),this.eventsDispatcher.on(xe,this.close)}destroy(){this.removeAllNodes(),this.listeners.destroy(),this.eventsDispatcher.off(xe,this.close)}async open(e=this.Editor.BlockManager.currentBlock){var s;this.opened=!0,this.selection.save(),this.Editor.BlockSelection.selectBlock(e),this.Editor.BlockSelection.clearCache();const{toolTunes:t,commonTunes:o}=e.getTunes();this.eventsDispatcher.emit(this.events.opened);const i=ge()?Zo:vt;this.popover=new i({searchable:!0,items:await this.getTunesItems(e,o,t),scopeElement:this.Editor.API.methods.ui.nodes.redactor,messages:{nothingFound:H.ui(W.ui.popover,"Nothing found"),search:H.ui(W.ui.popover,"Filter")}}),this.popover.on(Z.Closed,this.onPopoverClose),(s=this.nodes.wrapper)==null||s.append(this.popover.getElement()),this.popover.show()}getElement(){return this.nodes.wrapper}async getTunesItems(e,t,o){const i=[];o!==void 0&&o.length>0&&(i.push(...o),i.push({type:_.Separator}));const s=Array.from(this.Editor.Tools.blockTools.values()),a=(await Po(e,s)).reduce((l,c)=>(c.toolbox.forEach(u=>{l.push({icon:u.icon,title:H.t(W.toolNames,u.title),name:c.name,closeOnActivate:!0,onActivate:async()=>{const{BlockManager:h,Caret:p,Toolbar:g}=this.Editor,f=await h.convert(e,c.name,u.data);g.close(),p.setToBlock(f,p.positions.END)}})}),l),[]);return a.length>0&&(i.push({icon:Uo,name:"convert-to",title:H.ui(W.ui.popover,"Convert to"),children:{searchable:!0,items:a}}),i.push({type:_.Separator})),i.push(...t),i.map(l=>this.resolveTuneAliases(l))}resolveTuneAliases(e){if(e.type===_.Separator||e.type===_.Html)return e;const t=ji(e,{label:"title"});return e.confirmation&&(t.confirmation=this.resolveTuneAliases(e.confirmation)),t}}var Go={exports:{}};/*! - * Library for handling keyboard shortcuts - * @copyright CodeX (https://codex.so) - * @license MIT - * @author CodeX (https://codex.so) - * @version 1.2.0 - */(function(n,e){(function(t,o){n.exports=o()})(window,function(){return function(t){var o={};function i(s){if(o[s])return o[s].exports;var r=o[s]={i:s,l:!1,exports:{}};return t[s].call(r.exports,r,r.exports,i),r.l=!0,r.exports}return i.m=t,i.c=o,i.d=function(s,r,a){i.o(s,r)||Object.defineProperty(s,r,{enumerable:!0,get:a})},i.r=function(s){typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(s,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(s,"__esModule",{value:!0})},i.t=function(s,r){if(1&r&&(s=i(s)),8&r||4&r&&typeof s=="object"&&s&&s.__esModule)return s;var a=Object.create(null);if(i.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:s}),2&r&&typeof s!="string")for(var l in s)i.d(a,l,(function(c){return s[c]}).bind(null,l));return a},i.n=function(s){var r=s&&s.__esModule?function(){return s.default}:function(){return s};return i.d(r,"a",r),r},i.o=function(s,r){return Object.prototype.hasOwnProperty.call(s,r)},i.p="",i(i.s=0)}([function(t,o,i){function s(l,c){for(var u=0;ur!==o);if(s.length===0){this.registeredShortcuts.delete(e);return}this.registeredShortcuts.set(e,s)}findShortcut(e,t){return(this.registeredShortcuts.get(e)||[]).find(({name:i})=>i===t)}}const be=new ps;var fs=Object.defineProperty,gs=Object.getOwnPropertyDescriptor,Jo=(n,e,t,o)=>{for(var i=o>1?void 0:o?gs(e,t):e,s=n.length-1,r;s>=0;s--)(r=n[s])&&(i=(o?r(e,t,i):r(i))||i);return o&&i&&fs(e,t,i),i},Fe=(n=>(n.Opened="toolbox-opened",n.Closed="toolbox-closed",n.BlockAdded="toolbox-block-added",n))(Fe||{});const wt=class Un extends we{constructor({api:e,tools:t,i18nLabels:o}){super(),this.opened=!1,this.listeners=new Ee,this.popover=null,this.handleMobileLayoutToggle=()=>{this.destroyPopover(),this.initPopover()},this.onPopoverClose=()=>{this.opened=!1,this.emit("toolbox-closed")},this.api=e,this.tools=t,this.i18nLabels=o,this.enableShortcuts(),this.nodes={toolbox:d.make("div",Un.CSS.toolbox)},this.initPopover(),this.api.events.on(xe,this.handleMobileLayoutToggle)}get isEmpty(){return this.toolsToBeDisplayed.length===0}static get CSS(){return{toolbox:"ce-toolbox"}}getElement(){return this.nodes.toolbox}hasFocus(){if(this.popover!==null)return"hasFocus"in this.popover?this.popover.hasFocus():void 0}destroy(){var e;super.destroy(),this.nodes&&this.nodes.toolbox&&this.nodes.toolbox.remove(),this.removeAllShortcuts(),(e=this.popover)==null||e.off(Z.Closed,this.onPopoverClose),this.listeners.destroy(),this.api.events.off(xe,this.handleMobileLayoutToggle)}toolButtonActivated(e,t){this.insertNewBlock(e,t)}open(){var e;this.isEmpty||((e=this.popover)==null||e.show(),this.opened=!0,this.emit("toolbox-opened"))}close(){var e;(e=this.popover)==null||e.hide(),this.opened=!1,this.emit("toolbox-closed")}toggle(){this.opened?this.close():this.open()}initPopover(){var t;const e=ge()?Zo:vt;this.popover=new e({scopeElement:this.api.ui.nodes.redactor,searchable:!0,messages:{nothingFound:this.i18nLabels.nothingFound,search:this.i18nLabels.filter},items:this.toolboxItemsToBeDisplayed}),this.popover.on(Z.Closed,this.onPopoverClose),(t=this.nodes.toolbox)==null||t.append(this.popover.getElement())}destroyPopover(){this.popover!==null&&(this.popover.hide(),this.popover.off(Z.Closed,this.onPopoverClose),this.popover.destroy(),this.popover=null),this.nodes.toolbox!==null&&(this.nodes.toolbox.innerHTML="")}get toolsToBeDisplayed(){const e=[];return this.tools.forEach(t=>{t.toolbox&&e.push(t)}),e}get toolboxItemsToBeDisplayed(){const e=(t,o,i=!0)=>({icon:t.icon,title:H.t(W.toolNames,t.title||Le(o.name)),name:o.name,onActivate:()=>{this.toolButtonActivated(o.name,t.data)},secondaryLabel:o.shortcut&&i?it(o.shortcut):""});return this.toolsToBeDisplayed.reduce((t,o)=>(Array.isArray(o.toolbox)?o.toolbox.forEach((i,s)=>{t.push(e(i,o,s===0))}):o.toolbox!==void 0&&t.push(e(o.toolbox,o)),t),[])}enableShortcuts(){this.toolsToBeDisplayed.forEach(e=>{const t=e.shortcut;t&&this.enableShortcutForTool(e.name,t)})}enableShortcutForTool(e,t){be.add({name:t,on:this.api.ui.nodes.redactor,handler:async o=>{o.preventDefault();const i=this.api.blocks.getCurrentBlockIndex(),s=this.api.blocks.getBlockByIndex(i);if(s)try{const r=await this.api.blocks.convert(s.id,e);this.api.caret.setToBlock(r,"end");return}catch{}this.insertNewBlock(e)}})}removeAllShortcuts(){this.toolsToBeDisplayed.forEach(e=>{const t=e.shortcut;t&&be.remove(this.api.ui.nodes.redactor,t)})}async insertNewBlock(e,t){const o=this.api.blocks.getCurrentBlockIndex(),i=this.api.blocks.getBlockByIndex(o);if(!i)return;const s=i.isEmpty?o:o+1;let r;if(t){const l=await this.api.blocks.composeBlockData(e);r=Object.assign(l,t)}const a=this.api.blocks.insert(e,r,void 0,s,void 0,i.isEmpty);a.call(te.APPEND_CALLBACK),this.api.caret.setToBlock(s),this.emit("toolbox-block-added",{block:a}),this.api.toolbar.close()}};Jo([fe],wt.prototype,"toolsToBeDisplayed",1),Jo([fe],wt.prototype,"toolboxItemsToBeDisplayed",1);let ms=wt;const Qo="block hovered";async function bs(n,e){const t=navigator.keyboard;if(!t)return e;try{return(await t.getLayoutMap()).get(n)||e}catch(o){return console.error(o),e}}class vs extends E{constructor({config:e,eventsDispatcher:t}){super({config:e,eventsDispatcher:t}),this.toolboxInstance=null}get CSS(){return{toolbar:"ce-toolbar",content:"ce-toolbar__content",actions:"ce-toolbar__actions",actionsOpened:"ce-toolbar__actions--opened",toolbarOpened:"ce-toolbar--opened",openedToolboxHolderModifier:"codex-editor--toolbox-opened",plusButton:"ce-toolbar__plus",plusButtonShortcut:"ce-toolbar__plus-shortcut",settingsToggler:"ce-toolbar__settings-btn",settingsTogglerHidden:"ce-toolbar__settings-btn--hidden"}}get opened(){return this.nodes.wrapper.classList.contains(this.CSS.toolbarOpened)}get toolbox(){var e;return{opened:(e=this.toolboxInstance)==null?void 0:e.opened,close:()=>{var t;(t=this.toolboxInstance)==null||t.close()},open:()=>{if(this.toolboxInstance===null){T("toolbox.open() called before initialization is finished","warn");return}this.Editor.BlockManager.currentBlock=this.hoveredBlock,this.toolboxInstance.open()},toggle:()=>{if(this.toolboxInstance===null){T("toolbox.toggle() called before initialization is finished","warn");return}this.toolboxInstance.toggle()},hasFocus:()=>{var t;return(t=this.toolboxInstance)==null?void 0:t.hasFocus()}}}get blockActions(){return{hide:()=>{this.nodes.actions.classList.remove(this.CSS.actionsOpened)},show:()=>{this.nodes.actions.classList.add(this.CSS.actionsOpened)}}}get blockTunesToggler(){return{hide:()=>this.nodes.settingsToggler.classList.add(this.CSS.settingsTogglerHidden),show:()=>this.nodes.settingsToggler.classList.remove(this.CSS.settingsTogglerHidden)}}toggleReadOnly(e){e?(this.destroy(),this.Editor.BlockSettings.destroy(),this.disableModuleBindings()):window.requestIdleCallback(()=>{this.drawUI(),this.enableModuleBindings()},{timeout:2e3})}moveAndOpen(e=this.Editor.BlockManager.currentBlock){if(this.toolboxInstance===null){T("Can't open Toolbar since Editor initialization is not finished yet","warn");return}if(this.toolboxInstance.opened&&this.toolboxInstance.close(),this.Editor.BlockSettings.opened&&this.Editor.BlockSettings.close(),!e)return;this.hoveredBlock=e;const t=e.holder,{isMobile:o}=this.Editor.UI;let i;const s=20,r=e.firstInput,a=t.getBoundingClientRect(),l=r!==void 0?r.getBoundingClientRect():null,c=l!==null?l.top-a.top:null,u=c!==null?c>s:void 0;if(o)i=t.offsetTop+t.offsetHeight;else if(r===void 0||u){const h=parseInt(window.getComputedStyle(e.pluginsContent).paddingTop);i=t.offsetTop+h}else{const h=ri(r),p=parseInt(window.getComputedStyle(this.nodes.plusButton).height,10),g=8;i=t.offsetTop+h-p+g+c}this.nodes.wrapper.style.top=`${Math.floor(i)}px`,this.Editor.BlockManager.blocks.length===1&&e.isEmpty?this.blockTunesToggler.hide():this.blockTunesToggler.show(),this.open()}close(){var e,t;this.Editor.ReadOnly.isEnabled||((e=this.nodes.wrapper)==null||e.classList.remove(this.CSS.toolbarOpened),this.blockActions.hide(),(t=this.toolboxInstance)==null||t.close(),this.Editor.BlockSettings.close(),this.reset())}reset(){this.nodes.wrapper.style.top="unset"}open(e=!0){this.nodes.wrapper.classList.add(this.CSS.toolbarOpened),e?this.blockActions.show():this.blockActions.hide()}async make(){this.nodes.wrapper=d.make("div",this.CSS.toolbar),["content","actions"].forEach(s=>{this.nodes[s]=d.make("div",this.CSS[s])}),d.append(this.nodes.wrapper,this.nodes.content),d.append(this.nodes.content,this.nodes.actions),this.nodes.plusButton=d.make("div",this.CSS.plusButton,{innerHTML:qi}),d.append(this.nodes.actions,this.nodes.plusButton),this.readOnlyMutableListeners.on(this.nodes.plusButton,"click",()=>{Ne(!0),this.plusButtonClicked()},!1);const e=d.make("div");e.appendChild(document.createTextNode(H.ui(W.ui.toolbar.toolbox,"Add"))),e.appendChild(d.make("div",this.CSS.plusButtonShortcut,{textContent:"/"})),Re(this.nodes.plusButton,e,{hidingDelay:400}),this.nodes.settingsToggler=d.make("span",this.CSS.settingsToggler,{innerHTML:Vi}),d.append(this.nodes.actions,this.nodes.settingsToggler);const t=d.make("div"),o=d.text(H.ui(W.ui.blockTunes.toggler,"Click to tune")),i=await bs("Slash","/");t.appendChild(o),t.appendChild(d.make("div",this.CSS.plusButtonShortcut,{textContent:it(`CMD + ${i}`)})),Re(this.nodes.settingsToggler,t,{hidingDelay:400}),d.append(this.nodes.actions,this.makeToolbox()),d.append(this.nodes.actions,this.Editor.BlockSettings.getElement()),d.append(this.Editor.UI.nodes.wrapper,this.nodes.wrapper)}makeToolbox(){return this.toolboxInstance=new ms({api:this.Editor.API.methods,tools:this.Editor.Tools.blockTools,i18nLabels:{filter:H.ui(W.ui.popover,"Filter"),nothingFound:H.ui(W.ui.popover,"Nothing found")}}),this.toolboxInstance.on(Fe.Opened,()=>{this.Editor.UI.nodes.wrapper.classList.add(this.CSS.openedToolboxHolderModifier)}),this.toolboxInstance.on(Fe.Closed,()=>{this.Editor.UI.nodes.wrapper.classList.remove(this.CSS.openedToolboxHolderModifier)}),this.toolboxInstance.on(Fe.BlockAdded,({block:e})=>{const{BlockManager:t,Caret:o}=this.Editor,i=t.getBlockById(e.id);i.inputs.length===0&&(i===t.lastBlock?(t.insertAtEnd(),o.setToBlock(t.lastBlock)):o.setToBlock(t.nextBlock))}),this.toolboxInstance.getElement()}plusButtonClicked(){var e;this.Editor.BlockManager.currentBlock=this.hoveredBlock,(e=this.toolboxInstance)==null||e.toggle()}enableModuleBindings(){this.readOnlyMutableListeners.on(this.nodes.settingsToggler,"mousedown",e=>{var t;e.stopPropagation(),this.settingsTogglerClicked(),(t=this.toolboxInstance)!=null&&t.opened&&this.toolboxInstance.close(),Ne(!0)},!0),ge()||this.eventsDispatcher.on(Qo,e=>{var t;this.Editor.BlockSettings.opened||(t=this.toolboxInstance)!=null&&t.opened||this.moveAndOpen(e.block)})}disableModuleBindings(){this.readOnlyMutableListeners.clearAll()}settingsTogglerClicked(){this.Editor.BlockManager.currentBlock=this.hoveredBlock,this.Editor.BlockSettings.opened?this.Editor.BlockSettings.close():this.Editor.BlockSettings.open(this.hoveredBlock)}drawUI(){this.Editor.BlockSettings.make(),this.make()}destroy(){this.removeAllNodes(),this.toolboxInstance&&this.toolboxInstance.destroy()}}var ce=(n=>(n[n.Block=0]="Block",n[n.Inline=1]="Inline",n[n.Tune=2]="Tune",n))(ce||{}),je=(n=>(n.Shortcut="shortcut",n.Toolbox="toolbox",n.EnabledInlineTools="inlineToolbar",n.EnabledBlockTunes="tunes",n.Config="config",n))(je||{}),en=(n=>(n.Shortcut="shortcut",n.SanitizeConfig="sanitize",n))(en||{}),ve=(n=>(n.IsEnabledLineBreaks="enableLineBreaks",n.Toolbox="toolbox",n.ConversionConfig="conversionConfig",n.IsReadOnlySupported="isReadOnlySupported",n.PasteConfig="pasteConfig",n))(ve||{}),He=(n=>(n.IsInline="isInline",n.Title="title",n.IsReadOnlySupported="isReadOnlySupported",n))(He||{}),Et=(n=>(n.IsTune="isTune",n))(Et||{});class xt{constructor({name:e,constructable:t,config:o,api:i,isDefault:s,isInternal:r=!1,defaultPlaceholder:a}){this.api=i,this.name=e,this.constructable=t,this.config=o,this.isDefault=s,this.isInternal=r,this.defaultPlaceholder=a}get settings(){const e=this.config.config||{};return this.isDefault&&!("placeholder"in e)&&this.defaultPlaceholder&&(e.placeholder=this.defaultPlaceholder),e}reset(){if(M(this.constructable.reset))return this.constructable.reset()}prepare(){if(M(this.constructable.prepare))return this.constructable.prepare({toolName:this.name,config:this.settings})}get shortcut(){const e=this.constructable.shortcut;return this.config.shortcut||e}get sanitizeConfig(){return this.constructable.sanitize||{}}isInline(){return this.type===ce.Inline}isBlock(){return this.type===ce.Block}isTune(){return this.type===ce.Tune}}class ks extends E{constructor({config:e,eventsDispatcher:t}){super({config:e,eventsDispatcher:t}),this.CSS={inlineToolbar:"ce-inline-toolbar"},this.opened=!1,this.popover=null,this.toolbarVerticalMargin=ge()?20:6,this.tools=new Map,window.requestIdleCallback(()=>{this.make()},{timeout:2e3})}async tryToShow(e=!1){e&&this.close(),this.allowedToShow()&&(await this.open(),this.Editor.Toolbar.close())}close(){var e,t;if(this.opened){for(const[o,i]of this.tools){const s=this.getToolShortcut(o.name);s!==void 0&&be.remove(this.Editor.UI.nodes.redactor,s),M(i.clear)&&i.clear()}this.tools=new Map,this.reset(),this.opened=!1,(e=this.popover)==null||e.hide(),(t=this.popover)==null||t.destroy(),this.popover=null}}containsNode(e){return this.nodes.wrapper===void 0?!1:this.nodes.wrapper.contains(e)}destroy(){var e;this.removeAllNodes(),(e=this.popover)==null||e.destroy(),this.popover=null}make(){this.nodes.wrapper=d.make("div",[this.CSS.inlineToolbar,...this.isRtl?[this.Editor.UI.CSS.editorRtlFix]:[]]),d.append(this.Editor.UI.nodes.wrapper,this.nodes.wrapper)}async open(){var t;if(this.opened)return;this.opened=!0,this.popover!==null&&this.popover.destroy(),this.createToolsInstances();const e=await this.getPopoverItems();this.popover=new rs({items:e,scopeElement:this.Editor.API.methods.ui.nodes.redactor,messages:{nothingFound:H.ui(W.ui.popover,"Nothing found"),search:H.ui(W.ui.popover,"Filter")}}),this.move(this.popover.size.width),(t=this.nodes.wrapper)==null||t.append(this.popover.getElement()),this.popover.show()}move(e){const t=b.rect,o=this.Editor.UI.nodes.wrapper.getBoundingClientRect(),i={x:t.x-o.x,y:t.y+t.height-o.top+this.toolbarVerticalMargin};i.x+e+o.x>this.Editor.UI.contentRect.right&&(i.x=this.Editor.UI.contentRect.right-e-o.x),this.nodes.wrapper.style.left=Math.floor(i.x)+"px",this.nodes.wrapper.style.top=Math.floor(i.y)+"px"}reset(){this.nodes.wrapper.style.left="0",this.nodes.wrapper.style.top="0"}allowedToShow(){const e=["IMG","INPUT"],t=b.get(),o=b.text;if(!t||!t.anchorNode||t.isCollapsed||o.length<1)return!1;const i=d.isElement(t.anchorNode)?t.anchorNode:t.anchorNode.parentElement;if(i===null||t!==null&&e.includes(i.tagName))return!1;const s=this.Editor.BlockManager.getBlock(t.anchorNode);return!s||this.getTools().some(c=>s.tool.inlineTools.has(c.name))===!1?!1:i.closest("[contenteditable]")!==null}getTools(){const e=this.Editor.BlockManager.currentBlock;return e?Array.from(e.tool.inlineTools.values()).filter(o=>!(this.Editor.ReadOnly.isEnabled&&o.isReadOnlySupported!==!0)):[]}createToolsInstances(){this.tools=new Map,this.getTools().forEach(t=>{const o=t.create();this.tools.set(t,o)})}async getPopoverItems(){const e=[];let t=0;for(const[o,i]of this.tools){const s=await i.render(),r=this.getToolShortcut(o.name);if(r!==void 0)try{this.enableShortcuts(o.name,r)}catch{}const a=r!==void 0?it(r):void 0,l=H.t(W.toolNames,o.title||Le(o.name));[s].flat().forEach(c=>{var h,p;const u={name:o.name,onActivate:()=>{this.toolClicked(i)},hint:{title:l,description:a}};if(d.isElement(c)){const g={...u,element:c,type:_.Html};if(M(i.renderActions)){const f=i.renderActions();g.children={isOpen:(h=i.checkState)==null?void 0:h.call(i,b.get()),isFlippable:!1,items:[{type:_.Html,element:f}]}}else(p=i.checkState)==null||p.call(i,b.get());e.push(g)}else if(c.type===_.Html)e.push({...u,...c,type:_.Html});else if(c.type===_.Separator)e.push({type:_.Separator});else{const g={...u,...c,type:_.Default};"children"in g&&t!==0&&e.push({type:_.Separator}),e.push(g),"children"in g&&t{var s;const{currentBlock:i}=this.Editor.BlockManager;i&&i.tool.enabledInlineTools&&(o.preventDefault(),(s=this.popover)==null||s.activateItemByName(e))},on:document})}toolClicked(e){var o;const t=b.range;(o=e.surround)==null||o.call(e,t),this.checkToolsState()}checkToolsState(){var e;(e=this.tools)==null||e.forEach(t=>{var o;(o=t.checkState)==null||o.call(t,b.get())})}get inlineTools(){const e={};return Array.from(this.Editor.Tools.inlineTools.entries()).forEach(([t,o])=>{e[t]=o.create()}),e}}function tn(){const n=window.getSelection();if(n===null)return[null,0];let e=n.focusNode,t=n.focusOffset;return e===null?[null,0]:(e.nodeType!==Node.TEXT_NODE&&e.childNodes.length>0&&(e.childNodes[t]?(e=e.childNodes[t],t=0):(e=e.childNodes[t-1],t=e.textContent.length)),[e,t])}function on(n,e,t,o){const i=document.createRange();o==="left"?(i.setStart(n,0),i.setEnd(e,t)):(i.setStart(e,t),i.setEnd(n,n.childNodes.length));const s=i.cloneContents(),r=document.createElement("div");r.appendChild(s);const a=r.textContent||"";return si(a)}function $e(n){const e=d.getDeepestNode(n);if(e===null||d.isEmpty(n))return!0;if(d.isNativeInput(e))return e.selectionEnd===0;if(d.isEmpty(n))return!0;const[t,o]=tn();return t===null?!1:on(n,t,o,"left")}function ze(n){const e=d.getDeepestNode(n,!0);if(e===null)return!0;if(d.isNativeInput(e))return e.selectionEnd===e.value.length;const[t,o]=tn();return t===null?!1:on(n,t,o,"right")}var nn={},Bt={},Ue={},de={},Ct={},Tt={};Object.defineProperty(Tt,"__esModule",{value:!0}),Tt.allInputsSelector=ys;function ys(){var n=["text","password","email","number","search","tel","url"];return"[contenteditable=true], textarea, input:not([type]), "+n.map(function(e){return'input[type="'.concat(e,'"]')}).join(", ")}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.allInputsSelector=void 0;var e=Tt;Object.defineProperty(n,"allInputsSelector",{enumerable:!0,get:function(){return e.allInputsSelector}})})(Ct);var ue={},St={};Object.defineProperty(St,"__esModule",{value:!0}),St.isNativeInput=ws;function ws(n){var e=["INPUT","TEXTAREA"];return n&&n.tagName?e.includes(n.tagName):!1}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isNativeInput=void 0;var e=St;Object.defineProperty(n,"isNativeInput",{enumerable:!0,get:function(){return e.isNativeInput}})})(ue);var sn={},It={};Object.defineProperty(It,"__esModule",{value:!0}),It.append=Es;function Es(n,e){Array.isArray(e)?e.forEach(function(t){n.appendChild(t)}):n.appendChild(e)}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.append=void 0;var e=It;Object.defineProperty(n,"append",{enumerable:!0,get:function(){return e.append}})})(sn);var Ot={},_t={};Object.defineProperty(_t,"__esModule",{value:!0}),_t.blockElements=xs;function xs(){return["address","article","aside","blockquote","canvas","div","dl","dt","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","li","main","nav","noscript","ol","output","p","pre","ruby","section","table","tbody","thead","tr","tfoot","ul","video"]}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.blockElements=void 0;var e=_t;Object.defineProperty(n,"blockElements",{enumerable:!0,get:function(){return e.blockElements}})})(Ot);var rn={},Mt={};Object.defineProperty(Mt,"__esModule",{value:!0}),Mt.calculateBaseline=Bs;function Bs(n){var e=window.getComputedStyle(n),t=parseFloat(e.fontSize),o=parseFloat(e.lineHeight)||t*1.2,i=parseFloat(e.paddingTop),s=parseFloat(e.borderTopWidth),r=parseFloat(e.marginTop),a=t*.8,l=(o-t)/2,c=r+s+i+l+a;return c}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.calculateBaseline=void 0;var e=Mt;Object.defineProperty(n,"calculateBaseline",{enumerable:!0,get:function(){return e.calculateBaseline}})})(rn);var an={},At={},Lt={},Pt={};Object.defineProperty(Pt,"__esModule",{value:!0}),Pt.isContentEditable=Cs;function Cs(n){return n.contentEditable==="true"}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isContentEditable=void 0;var e=Pt;Object.defineProperty(n,"isContentEditable",{enumerable:!0,get:function(){return e.isContentEditable}})})(Lt),Object.defineProperty(At,"__esModule",{value:!0}),At.canSetCaret=Is;var Ts=ue,Ss=Lt;function Is(n){var e=!0;if((0,Ts.isNativeInput)(n))switch(n.type){case"file":case"checkbox":case"radio":case"hidden":case"submit":case"button":case"image":case"reset":e=!1;break}else e=(0,Ss.isContentEditable)(n);return e}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.canSetCaret=void 0;var e=At;Object.defineProperty(n,"canSetCaret",{enumerable:!0,get:function(){return e.canSetCaret}})})(an);var We={},Nt={};function Os(n,e,t){const o=t.value!==void 0?"value":"get",i=t[o],s=`#${e}Cache`;if(t[o]=function(...r){return this[s]===void 0&&(this[s]=i.apply(this,r)),this[s]},o==="get"&&t.set){const r=t.set;t.set=function(a){delete n[s],r.apply(this,a)}}return t}function ln(){const n={win:!1,mac:!1,x11:!1,linux:!1},e=Object.keys(n).find(t=>window.navigator.appVersion.toLowerCase().indexOf(t)!==-1);return e!==void 0&&(n[e]=!0),n}function Rt(n){return n!=null&&n!==""&&(typeof n!="object"||Object.keys(n).length>0)}function _s(n){return!Rt(n)}const Ms=()=>typeof window<"u"&&window.navigator!==null&&Rt(window.navigator.platform)&&(/iP(ad|hone|od)/.test(window.navigator.platform)||window.navigator.platform==="MacIntel"&&window.navigator.maxTouchPoints>1);function As(n){const e=ln();return n=n.replace(/shift/gi,"⇧").replace(/backspace/gi,"⌫").replace(/enter/gi,"⏎").replace(/up/gi,"↑").replace(/left/gi,"→").replace(/down/gi,"↓").replace(/right/gi,"←").replace(/escape/gi,"⎋").replace(/insert/gi,"Ins").replace(/delete/gi,"␡").replace(/\+/gi,"+"),e.mac?n=n.replace(/ctrl|cmd/gi,"⌘").replace(/alt/gi,"⌥"):n=n.replace(/cmd/gi,"Ctrl").replace(/windows/gi,"WIN"),n}function Ls(n){return n[0].toUpperCase()+n.slice(1)}function Ps(n){const e=document.createElement("div");e.style.position="absolute",e.style.left="-999px",e.style.bottom="-999px",e.innerHTML=n,document.body.appendChild(e);const t=window.getSelection(),o=document.createRange();if(o.selectNode(e),t===null)throw new Error("Cannot copy text to clipboard");t.removeAllRanges(),t.addRange(o),document.execCommand("copy"),document.body.removeChild(e)}function Ns(n,e,t){let o;return(...i)=>{const s=this,r=()=>{o=void 0,t!==!0&&n.apply(s,i)},a=t===!0&&o!==void 0;window.clearTimeout(o),o=window.setTimeout(r,e),a&&n.apply(s,i)}}function se(n){return Object.prototype.toString.call(n).match(/\s([a-zA-Z]+)/)[1].toLowerCase()}function Rs(n){return se(n)==="boolean"}function cn(n){return se(n)==="function"||se(n)==="asyncfunction"}function Ds(n){return cn(n)&&/^\s*class\s+/.test(n.toString())}function Fs(n){return se(n)==="number"}function Ye(n){return se(n)==="object"}function js(n){return Promise.resolve(n)===n}function Hs(n){return se(n)==="string"}function $s(n){return se(n)==="undefined"}function Dt(n,...e){if(!e.length)return n;const t=e.shift();if(Ye(n)&&Ye(t))for(const o in t)Ye(t[o])?(n[o]===void 0&&Object.assign(n,{[o]:{}}),Dt(n[o],t[o])):Object.assign(n,{[o]:t[o]});return Dt(n,...e)}function zs(n,e,t){const o=`«${e}» is deprecated and will be removed in the next major release. Please use the «${t}» instead.`;n&&console.warn(o)}function Us(n){try{return new URL(n).href}catch{}return n.substring(0,2)==="//"?window.location.protocol+n:window.location.origin+n}function Ws(n){return n>47&&n<58||n===32||n===13||n===229||n>64&&n<91||n>95&&n<112||n>185&&n<193||n>218&&n<223}const Ys={BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,LEFT:37,UP:38,DOWN:40,RIGHT:39,DELETE:46,META:91,SLASH:191},Ks={LEFT:0,WHEEL:1,RIGHT:2,BACKWARD:3,FORWARD:4};let Xs=class{constructor(){this.completed=Promise.resolve()}add(e){return new Promise((t,o)=>{this.completed=this.completed.then(e).then(t).catch(o)})}};function Vs(n,e,t=void 0){let o,i,s,r=null,a=0;t||(t={});const l=function(){a=t.leading===!1?0:Date.now(),r=null,s=n.apply(o,i),r===null&&(o=i=null)};return function(){const c=Date.now();!a&&t.leading===!1&&(a=c);const u=e-(c-a);return o=this,i=arguments,u<=0||u>e?(r&&(clearTimeout(r),r=null),a=c,s=n.apply(o,i),r===null&&(o=i=null)):!r&&t.trailing!==!1&&(r=setTimeout(l,u)),s}}const Ft=Yn(Object.freeze(Object.defineProperty({__proto__:null,PromiseQueue:Xs,beautifyShortcut:As,cacheable:Os,capitalize:Ls,copyTextToClipboard:Ps,debounce:Ns,deepMerge:Dt,deprecationAssert:zs,getUserOS:ln,getValidUrl:Us,isBoolean:Rs,isClass:Ds,isEmpty:_s,isFunction:cn,isIosDevice:Ms,isNumber:Fs,isObject:Ye,isPrintableKey:Ws,isPromise:js,isString:Hs,isUndefined:$s,keyCodes:Ys,mouseButtons:Ks,notEmpty:Rt,throttle:Vs,typeOf:se},Symbol.toStringTag,{value:"Module"})));Object.defineProperty(Nt,"__esModule",{value:!0}),Nt.containsOnlyInlineElements=Gs;var qs=Ft,Zs=Ot;function Gs(n){var e;(0,qs.isString)(n)?(e=document.createElement("div"),e.innerHTML=n):e=n;var t=function(o){return!(0,Zs.blockElements)().includes(o.tagName.toLowerCase())&&Array.from(o.children).every(t)};return Array.from(e.children).every(t)}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.containsOnlyInlineElements=void 0;var e=Nt;Object.defineProperty(n,"containsOnlyInlineElements",{enumerable:!0,get:function(){return e.containsOnlyInlineElements}})})(We);var dn={},jt={},Ke={},Ht={};Object.defineProperty(Ht,"__esModule",{value:!0}),Ht.make=Js;function Js(n,e,t){var o;e===void 0&&(e=null),t===void 0&&(t={});var i=document.createElement(n);if(Array.isArray(e)){var s=e.filter(function(a){return a!==void 0});(o=i.classList).add.apply(o,s)}else e!==null&&i.classList.add(e);for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(i[r]=t[r]);return i}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.make=void 0;var e=Ht;Object.defineProperty(n,"make",{enumerable:!0,get:function(){return e.make}})})(Ke),Object.defineProperty(jt,"__esModule",{value:!0}),jt.fragmentToString=er;var Qs=Ke;function er(n){var e=(0,Qs.make)("div");return e.appendChild(n),e.innerHTML}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.fragmentToString=void 0;var e=jt;Object.defineProperty(n,"fragmentToString",{enumerable:!0,get:function(){return e.fragmentToString}})})(dn);var un={},$t={};Object.defineProperty($t,"__esModule",{value:!0}),$t.getContentLength=or;var tr=ue;function or(n){var e,t;return(0,tr.isNativeInput)(n)?n.value.length:n.nodeType===Node.TEXT_NODE?n.length:(t=(e=n.textContent)===null||e===void 0?void 0:e.length)!==null&&t!==void 0?t:0}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.getContentLength=void 0;var e=$t;Object.defineProperty(n,"getContentLength",{enumerable:!0,get:function(){return e.getContentLength}})})(un);var zt={},Ut={},hn=J&&J.__spreadArray||function(n,e,t){if(t||arguments.length===2)for(var o=0,i=e.length,s;o0;){var o=t.shift();if(o){if(n=o,(0,xr.isLeaf)(n)&&!(0,Br.isNodeEmpty)(n,e))return!1;t.push.apply(t,Array.from(n.childNodes))}}return!0}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isEmpty=void 0;var e=Gt;Object.defineProperty(n,"isEmpty",{enumerable:!0,get:function(){return e.isEmpty}})})(vn);var kn={},oo={};Object.defineProperty(oo,"__esModule",{value:!0}),oo.isFragment=Sr;var Tr=Ft;function Sr(n){return(0,Tr.isNumber)(n)?!1:!!n&&!!n.nodeType&&n.nodeType===Node.DOCUMENT_FRAGMENT_NODE}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isFragment=void 0;var e=oo;Object.defineProperty(n,"isFragment",{enumerable:!0,get:function(){return e.isFragment}})})(kn);var yn={},no={};Object.defineProperty(no,"__esModule",{value:!0}),no.isHTMLString=Or;var Ir=Ke;function Or(n){var e=(0,Ir.make)("div");return e.innerHTML=n,e.childElementCount>0}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isHTMLString=void 0;var e=no;Object.defineProperty(n,"isHTMLString",{enumerable:!0,get:function(){return e.isHTMLString}})})(yn);var wn={},io={};Object.defineProperty(io,"__esModule",{value:!0}),io.offset=_r;function _r(n){var e=n.getBoundingClientRect(),t=window.pageXOffset||document.documentElement.scrollLeft,o=window.pageYOffset||document.documentElement.scrollTop,i=e.top+o,s=e.left+t;return{top:i,left:s,bottom:i+e.height,right:s+e.width}}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.offset=void 0;var e=io;Object.defineProperty(n,"offset",{enumerable:!0,get:function(){return e.offset}})})(wn);var En={},so={};Object.defineProperty(so,"__esModule",{value:!0}),so.prepend=Mr;function Mr(n,e){Array.isArray(e)?(e=e.reverse(),e.forEach(function(t){return n.prepend(t)})):n.prepend(e)}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.prepend=void 0;var e=so;Object.defineProperty(n,"prepend",{enumerable:!0,get:function(){return e.prepend}})})(En),function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.prepend=n.offset=n.make=n.isLineBreakTag=n.isSingleTag=n.isNodeEmpty=n.isLeaf=n.isHTMLString=n.isFragment=n.isEmpty=n.isElement=n.isContentEditable=n.isCollapsedWhitespaces=n.findAllInputs=n.isNativeInput=n.allInputsSelector=n.getDeepestNode=n.getDeepestBlockElements=n.getContentLength=n.fragmentToString=n.containsOnlyInlineElements=n.canSetCaret=n.calculateBaseline=n.blockElements=n.append=void 0;var e=Ct;Object.defineProperty(n,"allInputsSelector",{enumerable:!0,get:function(){return e.allInputsSelector}});var t=ue;Object.defineProperty(n,"isNativeInput",{enumerable:!0,get:function(){return t.isNativeInput}});var o=sn;Object.defineProperty(n,"append",{enumerable:!0,get:function(){return o.append}});var i=Ot;Object.defineProperty(n,"blockElements",{enumerable:!0,get:function(){return i.blockElements}});var s=rn;Object.defineProperty(n,"calculateBaseline",{enumerable:!0,get:function(){return s.calculateBaseline}});var r=an;Object.defineProperty(n,"canSetCaret",{enumerable:!0,get:function(){return r.canSetCaret}});var a=We;Object.defineProperty(n,"containsOnlyInlineElements",{enumerable:!0,get:function(){return a.containsOnlyInlineElements}});var l=dn;Object.defineProperty(n,"fragmentToString",{enumerable:!0,get:function(){return l.fragmentToString}});var c=un;Object.defineProperty(n,"getContentLength",{enumerable:!0,get:function(){return c.getContentLength}});var u=zt;Object.defineProperty(n,"getDeepestBlockElements",{enumerable:!0,get:function(){return u.getDeepestBlockElements}});var h=fn;Object.defineProperty(n,"getDeepestNode",{enumerable:!0,get:function(){return h.getDeepestNode}});var p=mn;Object.defineProperty(n,"findAllInputs",{enumerable:!0,get:function(){return p.findAllInputs}});var g=bn;Object.defineProperty(n,"isCollapsedWhitespaces",{enumerable:!0,get:function(){return g.isCollapsedWhitespaces}});var f=Lt;Object.defineProperty(n,"isContentEditable",{enumerable:!0,get:function(){return f.isContentEditable}});var v=qt;Object.defineProperty(n,"isElement",{enumerable:!0,get:function(){return v.isElement}});var O=vn;Object.defineProperty(n,"isEmpty",{enumerable:!0,get:function(){return O.isEmpty}});var S=kn;Object.defineProperty(n,"isFragment",{enumerable:!0,get:function(){return S.isFragment}});var A=yn;Object.defineProperty(n,"isHTMLString",{enumerable:!0,get:function(){return A.isHTMLString}});var G=Jt;Object.defineProperty(n,"isLeaf",{enumerable:!0,get:function(){return G.isLeaf}});var j=eo;Object.defineProperty(n,"isNodeEmpty",{enumerable:!0,get:function(){return j.isNodeEmpty}});var U=Xe;Object.defineProperty(n,"isLineBreakTag",{enumerable:!0,get:function(){return U.isLineBreakTag}});var oe=Ve;Object.defineProperty(n,"isSingleTag",{enumerable:!0,get:function(){return oe.isSingleTag}});var he=Ke;Object.defineProperty(n,"make",{enumerable:!0,get:function(){return he.make}});var k=wn;Object.defineProperty(n,"offset",{enumerable:!0,get:function(){return k.offset}});var m=En;Object.defineProperty(n,"prepend",{enumerable:!0,get:function(){return m.prepend}})}(de);var Ze={};Object.defineProperty(Ze,"__esModule",{value:!0}),Ze.getContenteditableSlice=Lr;var Ar=de;function Lr(n,e,t,o,i){var s;i===void 0&&(i=!1);var r=document.createRange();if(o==="left"?(r.setStart(n,0),r.setEnd(e,t)):(r.setStart(e,t),r.setEnd(n,n.childNodes.length)),i===!0){var a=r.extractContents();return(0,Ar.fragmentToString)(a)}var l=r.cloneContents(),c=document.createElement("div");c.appendChild(l);var u=(s=c.textContent)!==null&&s!==void 0?s:"";return u}Object.defineProperty(Ue,"__esModule",{value:!0}),Ue.checkContenteditableSliceForEmptiness=Rr;var Pr=de,Nr=Ze;function Rr(n,e,t,o){var i=(0,Nr.getContenteditableSlice)(n,e,t,o);return(0,Pr.isCollapsedWhitespaces)(i)}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.checkContenteditableSliceForEmptiness=void 0;var e=Ue;Object.defineProperty(n,"checkContenteditableSliceForEmptiness",{enumerable:!0,get:function(){return e.checkContenteditableSliceForEmptiness}})})(Bt);var xn={};(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.getContenteditableSlice=void 0;var e=Ze;Object.defineProperty(n,"getContenteditableSlice",{enumerable:!0,get:function(){return e.getContenteditableSlice}})})(xn);var Bn={},ro={};Object.defineProperty(ro,"__esModule",{value:!0}),ro.focus=Fr;var Dr=de;function Fr(n,e){var t,o;if(e===void 0&&(e=!0),(0,Dr.isNativeInput)(n)){n.focus();var i=e?0:n.value.length;n.setSelectionRange(i,i)}else{var s=document.createRange(),r=window.getSelection();if(!r)return;var a=function(p){var g=document.createTextNode("");p.appendChild(g),s.setStart(g,0),s.setEnd(g,0)},l=function(p){return p!=null},c=n.childNodes,u=e?c[0]:c[c.length-1];if(l(u)){for(;l(u)&&u.nodeType!==Node.TEXT_NODE;)u=e?u.firstChild:u.lastChild;if(l(u)&&u.nodeType===Node.TEXT_NODE){var h=(o=(t=u.textContent)===null||t===void 0?void 0:t.length)!==null&&o!==void 0?o:0,i=e?0:h;s.setStart(u,i),s.setEnd(u,i)}else a(n)}else a(n);r.removeAllRanges(),r.addRange(s)}}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.focus=void 0;var e=ro;Object.defineProperty(n,"focus",{enumerable:!0,get:function(){return e.focus}})})(Bn);var ao={},Ge={};Object.defineProperty(Ge,"__esModule",{value:!0}),Ge.getCaretNodeAndOffset=jr;function jr(){var n=window.getSelection();if(n===null)return[null,0];var e=n.focusNode,t=n.focusOffset;return e===null?[null,0]:(e.nodeType!==Node.TEXT_NODE&&e.childNodes.length>0&&(e.childNodes[t]!==void 0?(e=e.childNodes[t],t=0):(e=e.childNodes[t-1],e.textContent!==null&&(t=e.textContent.length))),[e,t])}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.getCaretNodeAndOffset=void 0;var e=Ge;Object.defineProperty(n,"getCaretNodeAndOffset",{enumerable:!0,get:function(){return e.getCaretNodeAndOffset}})})(ao);var Cn={},Je={};Object.defineProperty(Je,"__esModule",{value:!0}),Je.getRange=Hr;function Hr(){var n=window.getSelection();return n&&n.rangeCount?n.getRangeAt(0):null}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.getRange=void 0;var e=Je;Object.defineProperty(n,"getRange",{enumerable:!0,get:function(){return e.getRange}})})(Cn);var Tn={},lo={};Object.defineProperty(lo,"__esModule",{value:!0}),lo.isCaretAtEndOfInput=Ur;var Sn=de,$r=ao,zr=Bt;function Ur(n){var e=(0,Sn.getDeepestNode)(n,!0);if(e===null)return!0;if((0,Sn.isNativeInput)(e))return e.selectionEnd===e.value.length;var t=(0,$r.getCaretNodeAndOffset)(),o=t[0],i=t[1];return o===null?!1:(0,zr.checkContenteditableSliceForEmptiness)(n,o,i,"right")}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isCaretAtEndOfInput=void 0;var e=lo;Object.defineProperty(n,"isCaretAtEndOfInput",{enumerable:!0,get:function(){return e.isCaretAtEndOfInput}})})(Tn);var In={},co={};Object.defineProperty(co,"__esModule",{value:!0}),co.isCaretAtStartOfInput=Kr;var Qe=de,Wr=Ge,Yr=Ue;function Kr(n){var e=(0,Qe.getDeepestNode)(n);if(e===null||(0,Qe.isEmpty)(n))return!0;if((0,Qe.isNativeInput)(e))return e.selectionEnd===0;if((0,Qe.isEmpty)(n))return!0;var t=(0,Wr.getCaretNodeAndOffset)(),o=t[0],i=t[1];return o===null?!1:(0,Yr.checkContenteditableSliceForEmptiness)(n,o,i,"left")}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.isCaretAtStartOfInput=void 0;var e=co;Object.defineProperty(n,"isCaretAtStartOfInput",{enumerable:!0,get:function(){return e.isCaretAtStartOfInput}})})(In);var On={},uo={};Object.defineProperty(uo,"__esModule",{value:!0}),uo.save=qr;var Xr=de,Vr=Je;function qr(){var n=(0,Vr.getRange)(),e=(0,Xr.make)("span");if(e.id="cursor",e.hidden=!0,!!n)return n.insertNode(e),function(){var o=window.getSelection();o&&(n.setStartAfter(e),n.setEndAfter(e),o.removeAllRanges(),o.addRange(n),setTimeout(function(){e.remove()},150))}}(function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.save=void 0;var e=uo;Object.defineProperty(n,"save",{enumerable:!0,get:function(){return e.save}})})(On),function(n){Object.defineProperty(n,"__esModule",{value:!0}),n.save=n.isCaretAtStartOfInput=n.isCaretAtEndOfInput=n.getRange=n.getCaretNodeAndOffset=n.focus=n.getContenteditableSlice=n.checkContenteditableSliceForEmptiness=void 0;var e=Bt;Object.defineProperty(n,"checkContenteditableSliceForEmptiness",{enumerable:!0,get:function(){return e.checkContenteditableSliceForEmptiness}});var t=xn;Object.defineProperty(n,"getContenteditableSlice",{enumerable:!0,get:function(){return t.getContenteditableSlice}});var o=Bn;Object.defineProperty(n,"focus",{enumerable:!0,get:function(){return o.focus}});var i=ao;Object.defineProperty(n,"getCaretNodeAndOffset",{enumerable:!0,get:function(){return i.getCaretNodeAndOffset}});var s=Cn;Object.defineProperty(n,"getRange",{enumerable:!0,get:function(){return s.getRange}});var r=Tn;Object.defineProperty(n,"isCaretAtEndOfInput",{enumerable:!0,get:function(){return r.isCaretAtEndOfInput}});var a=In;Object.defineProperty(n,"isCaretAtStartOfInput",{enumerable:!0,get:function(){return a.isCaretAtStartOfInput}});var l=On;Object.defineProperty(n,"save",{enumerable:!0,get:function(){return l.save}})}(nn);class Zr extends E{keydown(e){switch(this.beforeKeydownProcessing(e),e.keyCode){case y.BACKSPACE:this.backspace(e);break;case y.DELETE:this.delete(e);break;case y.ENTER:this.enter(e);break;case y.DOWN:case y.RIGHT:this.arrowRightAndDown(e);break;case y.UP:case y.LEFT:this.arrowLeftAndUp(e);break;case y.TAB:this.tabPressed(e);break}e.key==="/"&&!e.ctrlKey&&!e.metaKey&&this.slashPressed(e),e.code==="Slash"&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),this.commandSlashPressed())}beforeKeydownProcessing(e){this.needToolbarClosing(e)&&Eo(e.keyCode)&&(this.Editor.Toolbar.close(),e.ctrlKey||e.metaKey||e.altKey||e.shiftKey||this.Editor.BlockSelection.clearSelection(e))}keyup(e){e.shiftKey||this.Editor.UI.checkEmptiness()}dragOver(e){const t=this.Editor.BlockManager.getBlockByChildNode(e.target);t.dropTarget=!0}dragLeave(e){const t=this.Editor.BlockManager.getBlockByChildNode(e.target);t.dropTarget=!1}handleCommandC(e){const{BlockSelection:t}=this.Editor;t.anyBlockSelected&&t.copySelectedBlocks(e)}handleCommandX(e){const{BlockSelection:t,BlockManager:o,Caret:i}=this.Editor;t.anyBlockSelected&&t.copySelectedBlocks(e).then(()=>{const s=o.removeSelectedBlocks(),r=o.insertDefaultBlockAtIndex(s,!0);i.setToBlock(r,i.positions.START),t.clearSelection(e)})}tabPressed(e){const{InlineToolbar:t,Caret:o}=this.Editor;if(t.opened)return;(e.shiftKey?o.navigatePrevious(!0):o.navigateNext(!0))&&e.preventDefault()}commandSlashPressed(){this.Editor.BlockSelection.selectedBlocks.length>1||this.activateBlockSettings()}slashPressed(e){!this.Editor.UI.nodes.wrapper.contains(e.target)||!this.Editor.BlockManager.currentBlock.isEmpty||(e.preventDefault(),this.Editor.Caret.insertContentAtCaretPosition("/"),this.activateToolbox())}enter(e){const{BlockManager:t,UI:o}=this.Editor,i=t.currentBlock;if(i===void 0||i.tool.isLineBreaksEnabled||o.someToolbarOpened&&o.someFlipperButtonFocused||e.shiftKey&&!rt)return;let s=i;i.currentInput!==void 0&&$e(i.currentInput)&&!i.hasMedia?this.Editor.BlockManager.insertDefaultBlockAtIndex(this.Editor.BlockManager.currentBlockIndex):i.currentInput&&ze(i.currentInput)?s=this.Editor.BlockManager.insertDefaultBlockAtIndex(this.Editor.BlockManager.currentBlockIndex+1):s=this.Editor.BlockManager.split(),this.Editor.Caret.setToBlock(s),this.Editor.Toolbar.moveAndOpen(s),e.preventDefault()}backspace(e){const{BlockManager:t,Caret:o}=this.Editor,{currentBlock:i,previousBlock:s}=t;if(i===void 0||!b.isCollapsed||!i.currentInput||!$e(i.currentInput))return;if(e.preventDefault(),this.Editor.Toolbar.close(),!(i.currentInput===i.firstInput)){o.navigatePrevious();return}if(s===null)return;if(s.isEmpty){t.removeBlock(s);return}if(i.isEmpty){t.removeBlock(i);const l=t.currentBlock;o.setToBlock(l,o.positions.END);return}No(s,i)?this.mergeBlocks(s,i):o.setToBlock(s,o.positions.END)}delete(e){const{BlockManager:t,Caret:o}=this.Editor,{currentBlock:i,nextBlock:s}=t;if(!b.isCollapsed||!ze(i.currentInput))return;if(e.preventDefault(),this.Editor.Toolbar.close(),!(i.currentInput===i.lastInput)){o.navigateNext();return}if(s===null)return;if(s.isEmpty){t.removeBlock(s);return}if(i.isEmpty){t.removeBlock(i),o.setToBlock(s,o.positions.START);return}No(i,s)?this.mergeBlocks(i,s):o.setToBlock(s,o.positions.START)}mergeBlocks(e,t){const{BlockManager:o,Toolbar:i}=this.Editor;e.lastInput!==void 0&&(nn.focus(e.lastInput,!1),o.mergeBlocks(e,t).then(()=>{i.close()}))}arrowRightAndDown(e){const t=ae.usedKeys.includes(e.keyCode)&&(!e.shiftKey||e.keyCode===y.TAB);if(this.Editor.UI.someToolbarOpened&&t)return;this.Editor.Toolbar.close();const{currentBlock:o}=this.Editor.BlockManager,s=((o==null?void 0:o.currentInput)!==void 0?ze(o.currentInput):void 0)||this.Editor.BlockSelection.anyBlockSelected;if(e.shiftKey&&e.keyCode===y.DOWN&&s){this.Editor.CrossBlockSelection.toggleBlockSelectedState();return}if(e.keyCode===y.DOWN||e.keyCode===y.RIGHT&&!this.isRtl?this.Editor.Caret.navigateNext():this.Editor.Caret.navigatePrevious()){e.preventDefault();return}Ae(()=>{this.Editor.BlockManager.currentBlock&&this.Editor.BlockManager.currentBlock.updateCurrentInput()},20)(),this.Editor.BlockSelection.clearSelection(e)}arrowLeftAndUp(e){if(this.Editor.UI.someToolbarOpened){if(ae.usedKeys.includes(e.keyCode)&&(!e.shiftKey||e.keyCode===y.TAB))return;this.Editor.UI.closeAllToolbars()}this.Editor.Toolbar.close();const{currentBlock:t}=this.Editor.BlockManager,i=((t==null?void 0:t.currentInput)!==void 0?$e(t.currentInput):void 0)||this.Editor.BlockSelection.anyBlockSelected;if(e.shiftKey&&e.keyCode===y.UP&&i){this.Editor.CrossBlockSelection.toggleBlockSelectedState(!1);return}if(e.keyCode===y.UP||e.keyCode===y.LEFT&&!this.isRtl?this.Editor.Caret.navigatePrevious():this.Editor.Caret.navigateNext()){e.preventDefault();return}Ae(()=>{this.Editor.BlockManager.currentBlock&&this.Editor.BlockManager.currentBlock.updateCurrentInput()},20)(),this.Editor.BlockSelection.clearSelection(e)}needToolbarClosing(e){const t=e.keyCode===y.ENTER&&this.Editor.Toolbar.toolbox.opened,o=e.keyCode===y.ENTER&&this.Editor.BlockSettings.opened,i=e.keyCode===y.ENTER&&this.Editor.InlineToolbar.opened,s=e.keyCode===y.TAB;return!(e.shiftKey||s||t||o||i)}activateToolbox(){this.Editor.Toolbar.opened||this.Editor.Toolbar.moveAndOpen(),this.Editor.Toolbar.toolbox.open()}activateBlockSettings(){this.Editor.Toolbar.opened||this.Editor.Toolbar.moveAndOpen(),this.Editor.BlockSettings.opened||this.Editor.BlockSettings.open()}}class ho{constructor(e){this.blocks=[],this.workingArea=e}get length(){return this.blocks.length}get array(){return this.blocks}get nodes(){return xo(this.workingArea.children)}static set(e,t,o){return isNaN(Number(t))?(Reflect.set(e,t,o),!0):(e.insert(+t,o),!0)}static get(e,t){return isNaN(Number(t))?Reflect.get(e,t):e.get(+t)}push(e){this.blocks.push(e),this.insertToDOM(e)}swap(e,t){const o=this.blocks[t];d.swap(this.blocks[e].holder,o.holder),this.blocks[t]=this.blocks[e],this.blocks[e]=o}move(e,t){const o=this.blocks.splice(t,1)[0],i=e-1,s=Math.max(0,i),r=this.blocks[s];e>0?this.insertToDOM(o,"afterend",r):this.insertToDOM(o,"beforebegin",r),this.blocks.splice(e,0,o);const a=this.composeBlockEvent("move",{fromIndex:t,toIndex:e});o.call(te.MOVED,a)}insert(e,t,o=!1){if(!this.length){this.push(t);return}e>this.length&&(e=this.length),o&&(this.blocks[e].holder.remove(),this.blocks[e].call(te.REMOVED));const i=o?1:0;if(this.blocks.splice(e,i,t),e>0){const s=this.blocks[e-1];this.insertToDOM(t,"afterend",s)}else{const s=this.blocks[e+1];s?this.insertToDOM(t,"beforebegin",s):this.insertToDOM(t)}}replace(e,t){if(this.blocks[e]===void 0)throw Error("Incorrect index");this.blocks[e].holder.replaceWith(t.holder),this.blocks[e]=t}insertMany(e,t){const o=new DocumentFragment;for(const i of e)o.appendChild(i.holder);if(this.length>0){if(t>0){const i=Math.min(t-1,this.length-1);this.blocks[i].holder.after(o)}else t===0&&this.workingArea.prepend(o);this.blocks.splice(t,0,...e)}else this.blocks.push(...e),this.workingArea.appendChild(o);e.forEach(i=>i.call(te.RENDERED))}remove(e){isNaN(e)&&(e=this.length-1),this.blocks[e].holder.remove(),this.blocks[e].call(te.REMOVED),this.blocks.splice(e,1)}removeAll(){this.workingArea.innerHTML="",this.blocks.forEach(e=>e.call(te.REMOVED)),this.blocks.length=0}insertAfter(e,t){const o=this.blocks.indexOf(e);this.insert(o+1,t)}get(e){return this.blocks[e]}indexOf(e){return this.blocks.indexOf(e)}insertToDOM(e,t,o){t?o.holder.insertAdjacentElement(t,e.holder):this.workingArea.appendChild(e.holder),e.call(te.RENDERED)}composeBlockEvent(e,t){return new CustomEvent(e,{detail:t})}}const _n="block-removed",Mn="block-added",Gr="block-moved",An="block-changed";class Jr{constructor(){this.completed=Promise.resolve()}add(e){return new Promise((t,o)=>{this.completed=this.completed.then(e).then(t).catch(o)})}}class Qr extends E{constructor(){super(...arguments),this._currentBlockIndex=-1,this._blocks=null}get currentBlockIndex(){return this._currentBlockIndex}set currentBlockIndex(e){this._currentBlockIndex=e}get firstBlock(){return this._blocks[0]}get lastBlock(){return this._blocks[this._blocks.length-1]}get currentBlock(){return this._blocks[this.currentBlockIndex]}set currentBlock(e){this.currentBlockIndex=this.getBlockIndex(e)}get nextBlock(){return this.currentBlockIndex===this._blocks.length-1?null:this._blocks[this.currentBlockIndex+1]}get nextContentfulBlock(){return this.blocks.slice(this.currentBlockIndex+1).find(t=>!!t.inputs.length)}get previousContentfulBlock(){return this.blocks.slice(0,this.currentBlockIndex).reverse().find(t=>!!t.inputs.length)}get previousBlock(){return this.currentBlockIndex===0?null:this._blocks[this.currentBlockIndex-1]}get blocks(){return this._blocks.array}get isEditorEmpty(){return this.blocks.every(e=>e.isEmpty)}prepare(){const e=new ho(this.Editor.UI.nodes.redactor);this._blocks=new Proxy(e,{set:ho.set,get:ho.get}),this.listeners.on(document,"copy",t=>this.Editor.BlockEvents.handleCommandC(t))}toggleReadOnly(e){e?this.disableModuleBindings():this.enableModuleBindings()}composeBlock({tool:e,data:t={},id:o=void 0,tunes:i={}}){const s=this.Editor.ReadOnly.isEnabled,r=this.Editor.Tools.blockTools.get(e),a=new R({id:o,data:t,tool:r,api:this.Editor.API,readOnly:s,tunesData:i},this.eventsDispatcher);return s||window.requestIdleCallback(()=>{this.bindBlockEvents(a)},{timeout:2e3}),a}insert({id:e=void 0,tool:t=this.config.defaultBlock,data:o={},index:i,needToFocus:s=!0,replace:r=!1,tunes:a={}}={}){let l=i;l===void 0&&(l=this.currentBlockIndex+(r?0:1));const c=this.composeBlock({id:e,tool:t,data:o,tunes:a});return r&&this.blockDidMutated(_n,this.getBlockByIndex(l),{index:l}),this._blocks.insert(l,c,r),this.blockDidMutated(Mn,c,{index:l}),s?this.currentBlockIndex=l:l<=this.currentBlockIndex&&this.currentBlockIndex++,c}insertMany(e,t=0){this._blocks.insertMany(e,t)}async update(e,t,o){if(!t&&!o)return e;const i=await e.data,s=this.composeBlock({id:e.id,tool:e.name,data:Object.assign({},i,t??{}),tunes:o??e.tunes}),r=this.getBlockIndex(e);return this._blocks.replace(r,s),this.blockDidMutated(An,s,{index:r}),s}replace(e,t,o){const i=this.getBlockIndex(e);return this.insert({tool:t,data:o,index:i,replace:!0})}paste(e,t,o=!1){const i=this.insert({tool:e,replace:o});try{window.requestIdleCallback(()=>{i.call(te.ON_PASTE,t)})}catch(s){T(`${e}: onPaste callback call is failed`,"error",s)}return i}insertDefaultBlockAtIndex(e,t=!1){const o=this.composeBlock({tool:this.config.defaultBlock});return this._blocks[e]=o,this.blockDidMutated(Mn,o,{index:e}),t?this.currentBlockIndex=e:e<=this.currentBlockIndex&&this.currentBlockIndex++,o}insertAtEnd(){return this.currentBlockIndex=this.blocks.length-1,this.insert()}async mergeBlocks(e,t){let o;if(e.name===t.name&&e.mergeable){const i=await t.data;if(V(i)){console.error("Could not merge Block. Failed to extract original Block data.");return}const[s]=dt([i],e.tool.sanitizeConfig);o=s}else if(e.mergeable&&Pe(t,"export")&&Pe(e,"import")){const i=await t.exportDataAsString(),s=q(i,e.tool.sanitizeConfig);o=Ro(s,e.tool.conversionConfig)}o!==void 0&&(await e.mergeWith(o),this.removeBlock(t),this.currentBlockIndex=this._blocks.indexOf(e))}removeBlock(e,t=!0){return new Promise(o=>{const i=this._blocks.indexOf(e);if(!this.validateIndex(i))throw new Error("Can't find a Block to remove");e.destroy(),this._blocks.remove(i),this.blockDidMutated(_n,e,{index:i}),this.currentBlockIndex>=i&&this.currentBlockIndex--,this.blocks.length?i===0&&(this.currentBlockIndex=0):(this.unsetCurrentBlock(),t&&this.insert()),o()})}removeSelectedBlocks(){let e;for(let t=this.blocks.length-1;t>=0;t--)this.blocks[t].selected&&(this.removeBlock(this.blocks[t]),e=t);return e}removeAllBlocks(){for(let e=this.blocks.length-1;e>=0;e--)this._blocks.remove(e);this.unsetCurrentBlock(),this.insert(),this.currentBlock.firstInput.focus()}split(){const e=this.Editor.Caret.extractFragmentFromCaretPosition(),t=d.make("div");t.appendChild(e);const o={text:d.isEmpty(t)?"":t.innerHTML};return this.insert({data:o})}getBlockByIndex(e){return e===-1&&(e=this._blocks.length-1),this._blocks[e]}getBlockIndex(e){return this._blocks.indexOf(e)}getBlockById(e){return this._blocks.array.find(t=>t.id===e)}getBlock(e){d.isElement(e)||(e=e.parentNode);const t=this._blocks.nodes,o=e.closest(`.${R.CSS.wrapper}`),i=t.indexOf(o);if(i>=0)return this._blocks[i]}setCurrentBlockByChildNode(e){d.isElement(e)||(e=e.parentNode);const t=e.closest(`.${R.CSS.wrapper}`);if(!t)return;const o=t.closest(`.${this.Editor.UI.CSS.editorWrapper}`);if(o!=null&&o.isEqualNode(this.Editor.UI.nodes.wrapper))return this.currentBlockIndex=this._blocks.nodes.indexOf(t),this.currentBlock.updateCurrentInput(),this.currentBlock}getBlockByChildNode(e){if(!e||!(e instanceof Node))return;d.isElement(e)||(e=e.parentNode);const t=e.closest(`.${R.CSS.wrapper}`);return this.blocks.find(o=>o.holder===t)}swap(e,t){this._blocks.swap(e,t),this.currentBlockIndex=t}move(e,t=this.currentBlockIndex){if(isNaN(e)||isNaN(t)){T("Warning during 'move' call: incorrect indices provided.","warn");return}if(!this.validateIndex(e)||!this.validateIndex(t)){T("Warning during 'move' call: indices cannot be lower than 0 or greater than the amount of blocks.","warn");return}this._blocks.move(e,t),this.currentBlockIndex=e,this.blockDidMutated(Gr,this.currentBlock,{fromIndex:t,toIndex:e})}async convert(e,t,o){if(!await e.save())throw new Error("Could not convert Block. Failed to extract original Block data.");const s=this.Editor.Tools.blockTools.get(t);if(!s)throw new Error(`Could not convert Block. Tool «${t}» not found.`);const r=await e.exportDataAsString(),a=q(r,s.sanitizeConfig);let l=Ro(a,s.conversionConfig,s.settings);return o&&(l=Object.assign(l,o)),this.replace(e,s.name,l)}unsetCurrentBlock(){this.currentBlockIndex=-1}async clear(e=!1){const t=new Jr;this.blocks.forEach(o=>{t.add(async()=>{await this.removeBlock(o,!1)})}),await t.completed,this.unsetCurrentBlock(),e&&this.insert(),this.Editor.UI.checkEmptiness()}async destroy(){await Promise.all(this.blocks.map(e=>e.destroy()))}bindBlockEvents(e){const{BlockEvents:t}=this.Editor;this.readOnlyMutableListeners.on(e.holder,"keydown",o=>{t.keydown(o)}),this.readOnlyMutableListeners.on(e.holder,"keyup",o=>{t.keyup(o)}),this.readOnlyMutableListeners.on(e.holder,"dragover",o=>{t.dragOver(o)}),this.readOnlyMutableListeners.on(e.holder,"dragleave",o=>{t.dragLeave(o)}),e.on("didMutated",o=>this.blockDidMutated(An,o,{index:this.getBlockIndex(o)}))}disableModuleBindings(){this.readOnlyMutableListeners.clearAll()}enableModuleBindings(){this.readOnlyMutableListeners.on(document,"cut",e=>this.Editor.BlockEvents.handleCommandX(e)),this.blocks.forEach(e=>{this.bindBlockEvents(e)})}validateIndex(e){return!(e<0||e>=this._blocks.length)}blockDidMutated(e,t,o){const i=new CustomEvent(e,{detail:{target:new ee(t),...o}});return this.eventsDispatcher.emit(_o,{event:i}),t}}class ea extends E{constructor(){super(...arguments),this.anyBlockSelectedCache=null,this.needToSelectAll=!1,this.nativeInputSelected=!1,this.readyToBlockSelection=!1}get sanitizerConfig(){return{p:{},h1:{},h2:{},h3:{},h4:{},h5:{},h6:{},ol:{},ul:{},li:{},br:!0,img:{src:!0,width:!0,height:!0},a:{href:!0},b:{},i:{},u:{}}}get allBlocksSelected(){const{BlockManager:e}=this.Editor;return e.blocks.every(t=>t.selected===!0)}set allBlocksSelected(e){const{BlockManager:t}=this.Editor;t.blocks.forEach(o=>{o.selected=e}),this.clearCache()}get anyBlockSelected(){const{BlockManager:e}=this.Editor;return this.anyBlockSelectedCache===null&&(this.anyBlockSelectedCache=e.blocks.some(t=>t.selected===!0)),this.anyBlockSelectedCache}get selectedBlocks(){return this.Editor.BlockManager.blocks.filter(e=>e.selected)}prepare(){this.selection=new b,be.add({name:"CMD+A",handler:e=>{const{BlockManager:t,ReadOnly:o}=this.Editor;if(o.isEnabled){e.preventDefault(),this.selectAllBlocks();return}t.currentBlock&&this.handleCommandA(e)},on:this.Editor.UI.nodes.redactor})}toggleReadOnly(){b.get().removeAllRanges(),this.allBlocksSelected=!1}unSelectBlockByIndex(e){const{BlockManager:t}=this.Editor;let o;isNaN(e)?o=t.currentBlock:o=t.getBlockByIndex(e),o.selected=!1,this.clearCache()}clearSelection(e,t=!1){const{BlockManager:o,Caret:i,RectangleSelection:s}=this.Editor;this.needToSelectAll=!1,this.nativeInputSelected=!1,this.readyToBlockSelection=!1;const r=e&&e instanceof KeyboardEvent,a=r&&Eo(e.keyCode);if(this.anyBlockSelected&&r&&a&&!b.isSelectionExists){const l=o.removeSelectedBlocks();o.insertDefaultBlockAtIndex(l,!0),i.setToBlock(o.currentBlock),Ae(()=>{const c=e.key;i.insertContentAtCaretPosition(c.length>1?"":c)},20)()}if(this.Editor.CrossBlockSelection.clear(e),!this.anyBlockSelected||s.isRectActivated()){this.Editor.RectangleSelection.clearSelection();return}t&&this.selection.restore(),this.allBlocksSelected=!1}copySelectedBlocks(e){e.preventDefault();const t=d.make("div");this.selectedBlocks.forEach(s=>{const r=q(s.holder.innerHTML,this.sanitizerConfig),a=d.make("p");a.innerHTML=r,t.appendChild(a)});const o=Array.from(t.childNodes).map(s=>s.textContent).join(` - -`),i=t.innerHTML;return e.clipboardData.setData("text/plain",o),e.clipboardData.setData("text/html",i),Promise.all(this.selectedBlocks.map(s=>s.save())).then(s=>{try{e.clipboardData.setData(this.Editor.Paste.MIME_TYPE,JSON.stringify(s))}catch{}})}selectBlockByIndex(e){const{BlockManager:t}=this.Editor,o=t.getBlockByIndex(e);o!==void 0&&this.selectBlock(o)}selectBlock(e){this.selection.save(),b.get().removeAllRanges(),e.selected=!0,this.clearCache(),this.Editor.InlineToolbar.close()}unselectBlock(e){e.selected=!1,this.clearCache()}clearCache(){this.anyBlockSelectedCache=null}destroy(){be.remove(this.Editor.UI.nodes.redactor,"CMD+A")}handleCommandA(e){if(this.Editor.RectangleSelection.clearSelection(),d.isNativeInput(e.target)&&!this.readyToBlockSelection){this.readyToBlockSelection=!0;return}const t=this.Editor.BlockManager.getBlock(e.target),o=t.inputs;if(o.length>1&&!this.readyToBlockSelection){this.readyToBlockSelection=!0;return}if(o.length===1&&!this.needToSelectAll){this.needToSelectAll=!0;return}this.needToSelectAll?(e.preventDefault(),this.selectAllBlocks(),this.needToSelectAll=!1,this.readyToBlockSelection=!1):this.readyToBlockSelection&&(e.preventDefault(),this.selectBlock(t),this.needToSelectAll=!0)}selectAllBlocks(){this.selection.save(),b.get().removeAllRanges(),this.allBlocksSelected=!0,this.Editor.InlineToolbar.close()}}class et extends E{get positions(){return{START:"start",END:"end",DEFAULT:"default"}}static get CSS(){return{shadowCaret:"cdx-shadow-caret"}}setToBlock(e,t=this.positions.DEFAULT,o=0){var c;const{BlockManager:i,BlockSelection:s}=this.Editor;if(s.clearSelection(),!e.focusable){(c=window.getSelection())==null||c.removeAllRanges(),s.selectBlock(e),i.currentBlock=e;return}let r;switch(t){case this.positions.START:r=e.firstInput;break;case this.positions.END:r=e.lastInput;break;default:r=e.currentInput}if(!r)return;const a=d.getDeepestNode(r,t===this.positions.END),l=d.getContentLength(a);switch(!0){case t===this.positions.START:o=0;break;case t===this.positions.END:case o>l:o=l;break}this.set(a,o),i.setCurrentBlockByChildNode(e.holder),i.currentBlock.currentInput=r}setToInput(e,t=this.positions.DEFAULT,o=0){const{currentBlock:i}=this.Editor.BlockManager,s=d.getDeepestNode(e);switch(t){case this.positions.START:this.set(s,0);break;case this.positions.END:this.set(s,d.getContentLength(s));break;default:o&&this.set(s,o)}i.currentInput=e}set(e,t=0){const{top:i,bottom:s}=b.setCursor(e,t),{innerHeight:r}=window;i<0?window.scrollBy(0,i-30):s>r&&window.scrollBy(0,s-r+30)}setToTheLastBlock(){const e=this.Editor.BlockManager.lastBlock;if(e)if(e.tool.isDefault&&e.isEmpty)this.setToBlock(e);else{const t=this.Editor.BlockManager.insertAtEnd();this.setToBlock(t)}}extractFragmentFromCaretPosition(){const e=b.get();if(e.rangeCount){const t=e.getRangeAt(0),o=this.Editor.BlockManager.currentBlock.currentInput;if(t.deleteContents(),o)if(d.isNativeInput(o)){const i=o,s=document.createDocumentFragment(),r=i.value.substring(0,i.selectionStart),a=i.value.substring(i.selectionStart);return s.textContent=a,i.value=r,s}else{const i=t.cloneRange();return i.selectNodeContents(o),i.setStart(t.endContainer,t.endOffset),i.extractContents()}}}navigateNext(e=!1){const{BlockManager:t}=this.Editor,{currentBlock:o,nextBlock:i}=t;if(o===void 0)return!1;const{nextInput:s,currentInput:r}=o,a=r!==void 0?ze(r):void 0;let l=i;const c=e||a||!o.focusable;if(s&&c)return this.setToInput(s,this.positions.START),!0;if(l===null){if(o.tool.isDefault||!c)return!1;l=t.insertAtEnd()}return c?(this.setToBlock(l,this.positions.START),!0):!1}navigatePrevious(e=!1){const{currentBlock:t,previousBlock:o}=this.Editor.BlockManager;if(!t)return!1;const{previousInput:i,currentInput:s}=t,r=s!==void 0?$e(s):void 0,a=e||r||!t.focusable;return i&&a?(this.setToInput(i,this.positions.END),!0):o!==null&&a?(this.setToBlock(o,this.positions.END),!0):!1}createShadow(e){const t=document.createElement("span");t.classList.add(et.CSS.shadowCaret),e.insertAdjacentElement("beforeend",t)}restoreCaret(e){const t=e.querySelector(`.${et.CSS.shadowCaret}`);if(!t)return;new b().expandToTag(t);const i=document.createRange();i.selectNode(t),i.extractContents()}insertContentAtCaretPosition(e){const t=document.createDocumentFragment(),o=document.createElement("div"),i=b.get(),s=b.range;o.innerHTML=e,Array.from(o.childNodes).forEach(c=>t.appendChild(c)),t.childNodes.length===0&&t.appendChild(new Text);const r=t.lastChild;s.deleteContents(),s.insertNode(t);const a=document.createRange(),l=r.nodeType===Node.TEXT_NODE?r:r.firstChild;l!==null&&l.textContent!==null&&a.setStart(l,l.textContent.length),i.removeAllRanges(),i.addRange(a)}}class ta extends E{constructor(){super(...arguments),this.onMouseUp=()=>{this.listeners.off(document,"mouseover",this.onMouseOver),this.listeners.off(document,"mouseup",this.onMouseUp)},this.onMouseOver=e=>{const{BlockManager:t,BlockSelection:o}=this.Editor;if(e.relatedTarget===null&&e.target===null)return;const i=t.getBlockByChildNode(e.relatedTarget)||this.lastSelectedBlock,s=t.getBlockByChildNode(e.target);if(!(!i||!s)&&s!==i){if(i===this.firstSelectedBlock){b.get().removeAllRanges(),i.selected=!0,s.selected=!0,o.clearCache();return}if(s===this.firstSelectedBlock){i.selected=!1,s.selected=!1,o.clearCache();return}this.Editor.InlineToolbar.close(),this.toggleBlocksSelectedState(i,s),this.lastSelectedBlock=s}}}async prepare(){this.listeners.on(document,"mousedown",e=>{this.enableCrossBlockSelection(e)})}watchSelection(e){if(e.button!==Xn.LEFT)return;const{BlockManager:t}=this.Editor;this.firstSelectedBlock=t.getBlock(e.target),this.lastSelectedBlock=this.firstSelectedBlock,this.listeners.on(document,"mouseover",this.onMouseOver),this.listeners.on(document,"mouseup",this.onMouseUp)}get isCrossBlockSelectionStarted(){return!!this.firstSelectedBlock&&!!this.lastSelectedBlock&&this.firstSelectedBlock!==this.lastSelectedBlock}toggleBlockSelectedState(e=!0){const{BlockManager:t,BlockSelection:o}=this.Editor;this.lastSelectedBlock||(this.lastSelectedBlock=this.firstSelectedBlock=t.currentBlock),this.firstSelectedBlock===this.lastSelectedBlock&&(this.firstSelectedBlock.selected=!0,o.clearCache(),b.get().removeAllRanges());const i=t.blocks.indexOf(this.lastSelectedBlock)+(e?1:-1),s=t.blocks[i];s&&(this.lastSelectedBlock.selected!==s.selected?(s.selected=!0,o.clearCache()):(this.lastSelectedBlock.selected=!1,o.clearCache()),this.lastSelectedBlock=s,this.Editor.InlineToolbar.close(),s.holder.scrollIntoView({block:"nearest"}))}clear(e){const{BlockManager:t,BlockSelection:o,Caret:i}=this.Editor,s=t.blocks.indexOf(this.firstSelectedBlock),r=t.blocks.indexOf(this.lastSelectedBlock);if(o.anyBlockSelected&&s>-1&&r>-1&&e&&e instanceof KeyboardEvent)switch(e.keyCode){case y.DOWN:case y.RIGHT:i.setToBlock(t.blocks[Math.max(s,r)],i.positions.END);break;case y.UP:case y.LEFT:i.setToBlock(t.blocks[Math.min(s,r)],i.positions.START);break;default:i.setToBlock(t.blocks[Math.max(s,r)],i.positions.END)}this.firstSelectedBlock=this.lastSelectedBlock=null}enableCrossBlockSelection(e){const{UI:t}=this.Editor;b.isCollapsed||this.Editor.BlockSelection.clearSelection(e),t.nodes.redactor.contains(e.target)?this.watchSelection(e):this.Editor.BlockSelection.clearSelection(e)}toggleBlocksSelectedState(e,t){const{BlockManager:o,BlockSelection:i}=this.Editor,s=o.blocks.indexOf(e),r=o.blocks.indexOf(t),a=e.selected!==t.selected;for(let l=Math.min(s,r);l<=Math.max(s,r);l++){const c=o.blocks[l];c!==this.firstSelectedBlock&&c!==(a?e:t)&&(o.blocks[l].selected=!o.blocks[l].selected,i.clearCache())}}}class oa extends E{constructor(){super(...arguments),this.isStartedAtEditor=!1}toggleReadOnly(e){e?this.disableModuleBindings():this.enableModuleBindings()}enableModuleBindings(){const{UI:e}=this.Editor;this.readOnlyMutableListeners.on(e.nodes.holder,"drop",async t=>{await this.processDrop(t)},!0),this.readOnlyMutableListeners.on(e.nodes.holder,"dragstart",()=>{this.processDragStart()}),this.readOnlyMutableListeners.on(e.nodes.holder,"dragover",t=>{this.processDragOver(t)},!0)}disableModuleBindings(){this.readOnlyMutableListeners.clearAll()}async processDrop(e){const{BlockManager:t,Paste:o,Caret:i}=this.Editor;e.preventDefault(),t.blocks.forEach(r=>{r.dropTarget=!1}),b.isAtEditor&&!b.isCollapsed&&this.isStartedAtEditor&&document.execCommand("delete"),this.isStartedAtEditor=!1;const s=t.setCurrentBlockByChildNode(e.target);if(s)this.Editor.Caret.setToBlock(s,i.positions.END);else{const r=t.setCurrentBlockByChildNode(t.lastBlock.holder);this.Editor.Caret.setToBlock(r,i.positions.END)}await o.processDataTransfer(e.dataTransfer,!0)}processDragStart(){b.isAtEditor&&!b.isCollapsed&&(this.isStartedAtEditor=!0),this.Editor.InlineToolbar.close()}processDragOver(e){e.preventDefault()}}const na=180,ia=400;class sa extends E{constructor({config:e,eventsDispatcher:t}){super({config:e,eventsDispatcher:t}),this.disabled=!1,this.batchingTimeout=null,this.batchingOnChangeQueue=new Map,this.batchTime=ia,this.mutationObserver=new MutationObserver(o=>{this.redactorChanged(o)}),this.eventsDispatcher.on(_o,o=>{this.particularBlockChanged(o.event)}),this.eventsDispatcher.on(Mo,()=>{this.disable()}),this.eventsDispatcher.on(Ao,()=>{this.enable()})}enable(){this.mutationObserver.observe(this.Editor.UI.nodes.redactor,{childList:!0,subtree:!0,characterData:!0,attributes:!0}),this.disabled=!1}disable(){this.mutationObserver.disconnect(),this.disabled=!0}particularBlockChanged(e){this.disabled||!M(this.config.onChange)||(this.batchingOnChangeQueue.set(`block:${e.detail.target.id}:event:${e.type}`,e),this.batchingTimeout&&clearTimeout(this.batchingTimeout),this.batchingTimeout=setTimeout(()=>{let t;this.batchingOnChangeQueue.size===1?t=this.batchingOnChangeQueue.values().next().value:t=Array.from(this.batchingOnChangeQueue.values()),this.config.onChange&&this.config.onChange(this.Editor.API.methods,t),this.batchingOnChangeQueue.clear()},this.batchTime))}redactorChanged(e){this.eventsDispatcher.emit(at,{mutations:e})}}const Ln=class Wn extends E{constructor(){super(...arguments),this.MIME_TYPE="application/x-editor-js",this.toolsTags={},this.tagsByTool={},this.toolsPatterns=[],this.toolsFiles={},this.exceptionList=[],this.processTool=e=>{try{const t=e.create({},{},!1);if(e.pasteConfig===!1){this.exceptionList.push(e.name);return}if(!M(t.onPaste))return;this.getTagsConfig(e),this.getFilesConfig(e),this.getPatternsConfig(e)}catch(t){T(`Paste handling for «${e.name}» Tool hasn't been set up because of the error`,"warn",t)}},this.handlePasteEvent=async e=>{const{BlockManager:t,Toolbar:o}=this.Editor,i=t.setCurrentBlockByChildNode(e.target);!i||this.isNativeBehaviour(e.target)&&!e.clipboardData.types.includes("Files")||i&&this.exceptionList.includes(i.name)||(e.preventDefault(),this.processDataTransfer(e.clipboardData),o.close())}}async prepare(){this.processTools()}toggleReadOnly(e){e?this.unsetCallback():this.setCallback()}async processDataTransfer(e,t=!1){const{Tools:o}=this.Editor,i=e.types;if((i.includes?i.includes("Files"):i.contains("Files"))&&!V(this.toolsFiles)){await this.processFiles(e.files);return}const r=e.getData(this.MIME_TYPE),a=e.getData("text/plain");let l=e.getData("text/html");if(r)try{this.insertEditorJSData(JSON.parse(r));return}catch{}t&&a.trim()&&l.trim()&&(l="

            "+(l.trim()?l:a)+"

            ");const c=Object.keys(this.toolsTags).reduce((p,g)=>(p[g.toLowerCase()]=this.toolsTags[g].sanitizationConfig??{},p),{}),u=Object.assign({},c,o.getAllInlineToolsSanitizeConfig(),{br:{}}),h=q(l,u);!h.trim()||h.trim()===a||!d.isHTMLString(h)?await this.processText(a):await this.processText(h,!0)}async processText(e,t=!1){const{Caret:o,BlockManager:i}=this.Editor,s=t?this.processHTML(e):this.processPlain(e);if(!s.length)return;if(s.length===1){s[0].isBlock?this.processSingleBlock(s.pop()):this.processInlinePaste(s.pop());return}const a=i.currentBlock&&i.currentBlock.tool.isDefault&&i.currentBlock.isEmpty;s.map(async(l,c)=>this.insertBlock(l,c===0&&a)),i.currentBlock&&o.setToBlock(i.currentBlock,o.positions.END)}setCallback(){this.listeners.on(this.Editor.UI.nodes.holder,"paste",this.handlePasteEvent)}unsetCallback(){this.listeners.off(this.Editor.UI.nodes.holder,"paste",this.handlePasteEvent)}processTools(){const e=this.Editor.Tools.blockTools;Array.from(e.values()).forEach(this.processTool)}collectTagNames(e){return Q(e)?[e]:N(e)?Object.keys(e):[]}getTagsConfig(e){if(e.pasteConfig===!1)return;const t=e.pasteConfig.tags||[],o=[];t.forEach(i=>{const s=this.collectTagNames(i);o.push(...s),s.forEach(r=>{if(Object.prototype.hasOwnProperty.call(this.toolsTags,r)){T(`Paste handler for «${e.name}» Tool on «${r}» tag is skipped because it is already used by «${this.toolsTags[r].tool.name}» Tool.`,"warn");return}const a=N(i)?i[r]:null;this.toolsTags[r.toUpperCase()]={tool:e,sanitizationConfig:a}})}),this.tagsByTool[e.name]=o.map(i=>i.toUpperCase())}getFilesConfig(e){if(e.pasteConfig===!1)return;const{files:t={}}=e.pasteConfig;let{extensions:o,mimeTypes:i}=t;!o&&!i||(o&&!Array.isArray(o)&&(T(`«extensions» property of the onDrop config for «${e.name}» Tool should be an array`),o=[]),i&&!Array.isArray(i)&&(T(`«mimeTypes» property of the onDrop config for «${e.name}» Tool should be an array`),i=[]),i&&(i=i.filter(s=>Jn(s)?!0:(T(`MIME type value «${s}» for the «${e.name}» Tool is not a valid MIME type`,"warn"),!1))),this.toolsFiles[e.name]={extensions:o||[],mimeTypes:i||[]})}getPatternsConfig(e){e.pasteConfig===!1||!e.pasteConfig.patterns||V(e.pasteConfig.patterns)||Object.entries(e.pasteConfig.patterns).forEach(([t,o])=>{o instanceof RegExp||T(`Pattern ${o} for «${e.name}» Tool is skipped because it should be a Regexp instance.`,"warn"),this.toolsPatterns.push({key:t,pattern:o,tool:e})})}isNativeBehaviour(e){return d.isNativeInput(e)}async processFiles(e){const{BlockManager:t}=this.Editor;let o;o=await Promise.all(Array.from(e).map(r=>this.processFile(r))),o=o.filter(r=>!!r);const s=t.currentBlock.tool.isDefault&&t.currentBlock.isEmpty;o.forEach((r,a)=>{t.paste(r.type,r.event,a===0&&s)})}async processFile(e){const t=Gn(e),o=Object.entries(this.toolsFiles).find(([r,{mimeTypes:a,extensions:l}])=>{const[c,u]=e.type.split("/"),h=l.find(g=>g.toLowerCase()===t.toLowerCase()),p=a.find(g=>{const[f,v]=g.split("/");return f===c&&(v===u||v==="*")});return!!h||!!p});if(!o)return;const[i]=o;return{event:this.composePasteEvent("file",{file:e}),type:i}}processHTML(e){const{Tools:t}=this.Editor,o=d.make("DIV");return o.innerHTML=e,this.getNodes(o).map(s=>{let r,a=t.defaultTool,l=!1;switch(s.nodeType){case Node.DOCUMENT_FRAGMENT_NODE:r=d.make("div"),r.appendChild(s);break;case Node.ELEMENT_NODE:r=s,l=!0,this.toolsTags[r.tagName]&&(a=this.toolsTags[r.tagName].tool);break}const{tags:c}=a.pasteConfig||{tags:[]},u=c.reduce((g,f)=>(this.collectTagNames(f).forEach(O=>{const S=N(f)?f[O]:null;g[O.toLowerCase()]=S||{}}),g),{}),h=Object.assign({},u,a.baseSanitizeConfig);if(r.tagName.toLowerCase()==="table"){const g=q(r.outerHTML,h);r=d.make("div",void 0,{innerHTML:g}).firstChild}else r.innerHTML=q(r.innerHTML,h);const p=this.composePasteEvent("tag",{data:r});return{content:r,isBlock:l,tool:a.name,event:p}}).filter(s=>{const r=d.isEmpty(s.content),a=d.isSingleTag(s.content);return!r||a})}processPlain(e){const{defaultBlock:t}=this.config;if(!e)return[];const o=t;return e.split(/\r?\n/).filter(i=>i.trim()).map(i=>{const s=d.make("div");s.textContent=i;const r=this.composePasteEvent("tag",{data:s});return{content:s,tool:o,isBlock:!1,event:r}})}async processSingleBlock(e){const{Caret:t,BlockManager:o}=this.Editor,{currentBlock:i}=o;if(!i||e.tool!==i.name||!d.containsOnlyInlineElements(e.content.innerHTML)){this.insertBlock(e,(i==null?void 0:i.tool.isDefault)&&i.isEmpty);return}t.insertContentAtCaretPosition(e.content.innerHTML)}async processInlinePaste(e){const{BlockManager:t,Caret:o}=this.Editor,{content:i}=e;if(t.currentBlock&&t.currentBlock.tool.isDefault&&i.textContent.length{const s=i.pattern.exec(e);return s?e===s.shift():!1});return t?{event:this.composePasteEvent("pattern",{key:t.key,data:e}),tool:t.tool.name}:void 0}insertBlock(e,t=!1){const{BlockManager:o,Caret:i}=this.Editor,{currentBlock:s}=o;let r;if(t&&s&&s.isEmpty){r=o.paste(e.tool,e.event,!0),i.setToBlock(r,i.positions.END);return}r=o.paste(e.tool,e.event),i.setToBlock(r,i.positions.END)}insertEditorJSData(e){const{BlockManager:t,Caret:o,Tools:i}=this.Editor;dt(e,r=>i.blockTools.get(r).sanitizeConfig).forEach(({tool:r,data:a},l)=>{let c=!1;l===0&&(c=t.currentBlock&&t.currentBlock.tool.isDefault&&t.currentBlock.isEmpty);const u=t.insert({tool:r,data:a,replace:c});o.setToBlock(u,o.positions.END)})}processElementNode(e,t,o){const i=Object.keys(this.toolsTags),s=e,{tool:r}=this.toolsTags[s.tagName]||{},a=this.tagsByTool[r==null?void 0:r.name]||[],l=i.includes(s.tagName),c=d.blockElements.includes(s.tagName.toLowerCase()),u=Array.from(s.children).some(({tagName:p})=>i.includes(p)&&!a.includes(p)),h=Array.from(s.children).some(({tagName:p})=>d.blockElements.includes(p.toLowerCase()));if(!c&&!l&&!u)return o.appendChild(s),[...t,o];if(l&&!u||c&&!h&&!u)return[...t,o,s]}getNodes(e){const t=Array.from(e.childNodes);let o;const i=(s,r)=>{if(d.isEmpty(r)&&!d.isSingleTag(r))return s;const a=s[s.length-1];let l=new DocumentFragment;switch(a&&d.isFragment(a)&&(l=s.pop()),r.nodeType){case Node.ELEMENT_NODE:if(o=this.processElementNode(r,s,l),o)return o;break;case Node.TEXT_NODE:return l.appendChild(r),[...s,l];default:return[...s,l]}return[...s,...Array.from(r.childNodes).reduce(i,[])]};return t.reduce(i,[])}composePasteEvent(e,t){return new CustomEvent(e,{detail:t})}};Ln.PATTERN_PROCESSING_MAX_LENGTH=450;let ra=Ln;class aa extends E{constructor(){super(...arguments),this.toolsDontSupportReadOnly=[],this.readOnlyEnabled=!1}get isEnabled(){return this.readOnlyEnabled}async prepare(){const{Tools:e}=this.Editor,{blockTools:t}=e,o=[];Array.from(t.entries()).forEach(([i,s])=>{s.isReadOnlySupported||o.push(i)}),this.toolsDontSupportReadOnly=o,this.config.readOnly&&o.length>0&&this.throwCriticalError(),this.toggle(this.config.readOnly,!0)}async toggle(e=!this.readOnlyEnabled,t=!1){e&&this.toolsDontSupportReadOnly.length>0&&this.throwCriticalError();const o=this.readOnlyEnabled;this.readOnlyEnabled=e;for(const s in this.Editor)this.Editor[s].toggleReadOnly&&this.Editor[s].toggleReadOnly(e);if(o===e)return this.readOnlyEnabled;if(t)return this.readOnlyEnabled;this.Editor.ModificationsObserver.disable();const i=await this.Editor.Saver.save();return await this.Editor.BlockManager.clear(),await this.Editor.Renderer.render(i.blocks),this.Editor.ModificationsObserver.enable(),this.readOnlyEnabled}throwCriticalError(){throw new Oo(`To enable read-only mode all connected tools should support it. Tools ${this.toolsDontSupportReadOnly.join(", ")} don't support read-only mode.`)}}class Ie extends E{constructor(){super(...arguments),this.isRectSelectionActivated=!1,this.SCROLL_SPEED=3,this.HEIGHT_OF_SCROLL_ZONE=40,this.BOTTOM_SCROLL_ZONE=1,this.TOP_SCROLL_ZONE=2,this.MAIN_MOUSE_BUTTON=0,this.mousedown=!1,this.isScrolling=!1,this.inScrollZone=null,this.startX=0,this.startY=0,this.mouseX=0,this.mouseY=0,this.stackOfSelected=[],this.listenerIds=[]}static get CSS(){return{overlay:"codex-editor-overlay",overlayContainer:"codex-editor-overlay__container",rect:"codex-editor-overlay__rectangle",topScrollZone:"codex-editor-overlay__scroll-zone--top",bottomScrollZone:"codex-editor-overlay__scroll-zone--bottom"}}prepare(){this.enableModuleBindings()}startSelection(e,t){const o=document.elementFromPoint(e-window.pageXOffset,t-window.pageYOffset);o.closest(`.${this.Editor.Toolbar.CSS.toolbar}`)||(this.Editor.BlockSelection.allBlocksSelected=!1,this.clearSelection(),this.stackOfSelected=[]);const s=[`.${R.CSS.content}`,`.${this.Editor.Toolbar.CSS.toolbar}`,`.${this.Editor.InlineToolbar.CSS.inlineToolbar}`],r=o.closest("."+this.Editor.UI.CSS.editorWrapper),a=s.some(l=>!!o.closest(l));!r||a||(this.mousedown=!0,this.startX=e,this.startY=t)}endSelection(){this.mousedown=!1,this.startX=0,this.startY=0,this.overlayRectangle.style.display="none"}isRectActivated(){return this.isRectSelectionActivated}clearSelection(){this.isRectSelectionActivated=!1}enableModuleBindings(){const{container:e}=this.genHTML();this.listeners.on(e,"mousedown",t=>{this.processMouseDown(t)},!1),this.listeners.on(document.body,"mousemove",ot(t=>{this.processMouseMove(t)},10),{passive:!0}),this.listeners.on(document.body,"mouseleave",()=>{this.processMouseLeave()}),this.listeners.on(window,"scroll",ot(t=>{this.processScroll(t)},10),{passive:!0}),this.listeners.on(document.body,"mouseup",()=>{this.processMouseUp()},!1)}processMouseDown(e){if(e.button!==this.MAIN_MOUSE_BUTTON)return;e.target.closest(d.allInputsSelector)!==null||this.startSelection(e.pageX,e.pageY)}processMouseMove(e){this.changingRectangle(e),this.scrollByZones(e.clientY)}processMouseLeave(){this.clearSelection(),this.endSelection()}processScroll(e){this.changingRectangle(e)}processMouseUp(){this.clearSelection(),this.endSelection()}scrollByZones(e){if(this.inScrollZone=null,e<=this.HEIGHT_OF_SCROLL_ZONE&&(this.inScrollZone=this.TOP_SCROLL_ZONE),document.documentElement.clientHeight-e<=this.HEIGHT_OF_SCROLL_ZONE&&(this.inScrollZone=this.BOTTOM_SCROLL_ZONE),!this.inScrollZone){this.isScrolling=!1;return}this.isScrolling||(this.scrollVertical(this.inScrollZone===this.TOP_SCROLL_ZONE?-this.SCROLL_SPEED:this.SCROLL_SPEED),this.isScrolling=!0)}genHTML(){const{UI:e}=this.Editor,t=e.nodes.holder.querySelector("."+e.CSS.editorWrapper),o=d.make("div",Ie.CSS.overlay,{}),i=d.make("div",Ie.CSS.overlayContainer,{}),s=d.make("div",Ie.CSS.rect,{});return i.appendChild(s),o.appendChild(i),t.appendChild(o),this.overlayRectangle=s,{container:t,overlay:o}}scrollVertical(e){if(!(this.inScrollZone&&this.mousedown))return;const t=window.pageYOffset;window.scrollBy(0,e),this.mouseY+=window.pageYOffset-t,setTimeout(()=>{this.scrollVertical(e)},0)}changingRectangle(e){if(!this.mousedown)return;e.pageY!==void 0&&(this.mouseX=e.pageX,this.mouseY=e.pageY);const{rightPos:t,leftPos:o,index:i}=this.genInfoForMouseSelection(),s=this.startX>t&&this.mouseX>t,r=this.startX=this.startY?(this.overlayRectangle.style.top=`${this.startY-window.pageYOffset}px`,this.overlayRectangle.style.bottom=`calc(100% - ${this.mouseY-window.pageYOffset}px`):(this.overlayRectangle.style.bottom=`calc(100% - ${this.startY-window.pageYOffset}px`,this.overlayRectangle.style.top=`${this.mouseY-window.pageYOffset}px`),this.mouseX>=this.startX?(this.overlayRectangle.style.left=`${this.startX-window.pageXOffset}px`,this.overlayRectangle.style.right=`calc(100% - ${this.mouseX-window.pageXOffset}px`):(this.overlayRectangle.style.right=`calc(100% - ${this.startX-window.pageXOffset}px`,this.overlayRectangle.style.left=`${this.mouseX-window.pageXOffset}px`)}genInfoForMouseSelection(){const t=document.body.offsetWidth/2,o=this.mouseY-window.pageYOffset,i=document.elementFromPoint(t,o),s=this.Editor.BlockManager.getBlockByChildNode(i);let r;s!==void 0&&(r=this.Editor.BlockManager.blocks.findIndex(h=>h.holder===s.holder));const a=this.Editor.BlockManager.lastBlock.holder.querySelector("."+R.CSS.content),l=Number.parseInt(window.getComputedStyle(a).width,10)/2,c=t-l,u=t+l;return{index:r,leftPos:c,rightPos:u}}addBlockInSelection(e){this.rectCrossesBlocks&&this.Editor.BlockSelection.selectBlockByIndex(e),this.stackOfSelected.push(e)}trySelectNextBlock(e){const t=this.stackOfSelected[this.stackOfSelected.length-1]===e,o=this.stackOfSelected.length,i=1,s=-1,r=0;if(t)return;const a=this.stackOfSelected[o-1]-this.stackOfSelected[o-2]>0;let l=r;o>1&&(l=a?i:s);const c=e>this.stackOfSelected[o-1]&&l===i,u=ethis.stackOfSelected[o-1]||this.stackOfSelected[o-1]===void 0)){let v=this.stackOfSelected[o-1]+1||e;for(v;v<=e;v++)this.addBlockInSelection(v);return}if(!p&&e=e;v--)this.addBlockInSelection(v);return}if(!p)return;let g=o-1,f;for(e>this.stackOfSelected[o-1]?f=()=>e>this.stackOfSelected[g]:f=()=>e{const{Tools:o,BlockManager:i}=this.Editor;if(e.length===0)i.insert();else{const s=e.map(({type:r,data:a,tunes:l,id:c})=>{o.available.has(r)===!1&&(X(`Tool «${r}» is not found. Check 'tools' property at the Editor.js config.`,"warn"),a=this.composeStubDataForTool(r,a,c),r=o.stubTool);let u;try{u=i.composeBlock({id:c,tool:r,data:a,tunes:l})}catch(h){T(`Block «${r}» skipped because of plugins error`,"error",{data:a,error:h}),a=this.composeStubDataForTool(r,a,c),r=o.stubTool,u=i.composeBlock({id:c,tool:r,data:a,tunes:l})}return u});i.insertMany(s)}window.requestIdleCallback(()=>{t()},{timeout:2e3})})}composeStubDataForTool(e,t,o){const{Tools:i}=this.Editor;let s=e;if(i.unavailable.has(e)){const r=i.unavailable.get(e).toolbox;r!==void 0&&r[0].title!==void 0&&(s=r[0].title)}return{savedData:{id:o,type:e,data:t},title:s}}}class ca extends E{async save(){const{BlockManager:e,Tools:t}=this.Editor,o=e.blocks,i=[];try{o.forEach(a=>{i.push(this.getSavedData(a))});const s=await Promise.all(i),r=await dt(s,a=>t.blockTools.get(a).sanitizeConfig);return this.makeOutput(r)}catch(s){X("Saving failed due to the Error %o","error",s)}}async getSavedData(e){const t=await e.save(),o=t&&await e.validate(t.data);return{...t,isValid:o}}makeOutput(e){const t=[];return e.forEach(({id:o,tool:i,data:s,tunes:r,isValid:a})=>{if(!a){T(`Block «${i}» skipped because saved data is invalid`);return}if(i===this.Editor.Tools.stubTool){t.push(s);return}const l={id:o,type:i,data:s,...!V(r)&&{tunes:r}};t.push(l)}),{time:+new Date,blocks:t,version:"2.31.0-rc.9"}}}(function(){try{if(typeof document<"u"){var n=document.createElement("style");n.appendChild(document.createTextNode(".ce-paragraph{line-height:1.6em;outline:none}.ce-block:only-of-type .ce-paragraph[data-placeholder-active]:empty:before,.ce-block:only-of-type .ce-paragraph[data-placeholder-active][data-empty=true]:before{content:attr(data-placeholder-active)}.ce-paragraph p:first-of-type{margin-top:0}.ce-paragraph p:last-of-type{margin-bottom:0}")),document.head.appendChild(n)}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})();const da='';function ua(n){const e=document.createElement("div");e.innerHTML=n.trim();const t=document.createDocumentFragment();return t.append(...Array.from(e.childNodes)),t}/** - * Base Paragraph Block for the Editor.js. - * Represents a regular text block - * - * @author CodeX (team@codex.so) - * @copyright CodeX 2018 - * @license The MIT License (MIT) - */class po{static get DEFAULT_PLACEHOLDER(){return""}constructor({data:e,config:t,api:o,readOnly:i}){this.api=o,this.readOnly=i,this._CSS={block:this.api.styles.block,wrapper:"ce-paragraph"},this.readOnly||(this.onKeyUp=this.onKeyUp.bind(this)),this._placeholder=t.placeholder?t.placeholder:po.DEFAULT_PLACEHOLDER,this._data=e??{},this._element=null,this._preserveBlank=t.preserveBlank??!1}onKeyUp(e){if(e.code!=="Backspace"&&e.code!=="Delete"||!this._element)return;const{textContent:t}=this._element;t===""&&(this._element.innerHTML="")}drawView(){const e=document.createElement("DIV");return e.classList.add(this._CSS.wrapper,this._CSS.block),e.contentEditable="false",e.dataset.placeholderActive=this.api.i18n.t(this._placeholder),this._data.text&&(e.innerHTML=this._data.text),this.readOnly||(e.contentEditable="true",e.addEventListener("keyup",this.onKeyUp)),e}render(){return this._element=this.drawView(),this._element}merge(e){if(!this._element)return;this._data.text+=e.text;const t=ua(e.text);this._element.appendChild(t),this._element.normalize()}validate(e){return!(e.text.trim()===""&&!this._preserveBlank)}save(e){return{text:e.innerHTML}}onPaste(e){const t={text:e.detail.data.innerHTML};this._data=t,window.requestAnimationFrame(()=>{this._element&&(this._element.innerHTML=this._data.text||"")})}static get conversionConfig(){return{export:"text",import:"text"}}static get sanitize(){return{text:{br:!0}}}static get isReadOnlySupported(){return!0}static get pasteConfig(){return{tags:["P"]}}static get toolbox(){return{icon:da,title:"Text"}}}class fo{constructor(){this.commandName="bold"}static get sanitize(){return{b:{}}}render(){return{icon:Hi,name:"bold",onActivate:()=>{document.execCommand(this.commandName)},isActive:()=>document.queryCommandState(this.commandName)}}get shortcut(){return"CMD+B"}}fo.isInline=!0,fo.title="Bold";class go{constructor(){this.commandName="italic",this.CSS={button:"ce-inline-tool",buttonActive:"ce-inline-tool--active",buttonModifier:"ce-inline-tool--italic"},this.nodes={button:null}}static get sanitize(){return{i:{}}}render(){return this.nodes.button=document.createElement("button"),this.nodes.button.type="button",this.nodes.button.classList.add(this.CSS.button,this.CSS.buttonModifier),this.nodes.button.innerHTML=Xi,this.nodes.button}surround(){document.execCommand(this.commandName)}checkState(){const e=document.queryCommandState(this.commandName);return this.nodes.button.classList.toggle(this.CSS.buttonActive,e),e}get shortcut(){return"CMD+I"}}go.isInline=!0,go.title="Italic";class mo{constructor({api:e}){this.commandLink="createLink",this.commandUnlink="unlink",this.ENTER_KEY=13,this.CSS={button:"ce-inline-tool",buttonActive:"ce-inline-tool--active",buttonModifier:"ce-inline-tool--link",buttonUnlink:"ce-inline-tool--unlink",input:"ce-inline-tool-input",inputShowed:"ce-inline-tool-input--showed"},this.nodes={button:null,input:null},this.inputOpened=!1,this.toolbar=e.toolbar,this.inlineToolbar=e.inlineToolbar,this.notifier=e.notifier,this.i18n=e.i18n,this.selection=new b}static get sanitize(){return{a:{href:!0,target:"_blank",rel:"nofollow"}}}render(){return this.nodes.button=document.createElement("button"),this.nodes.button.type="button",this.nodes.button.classList.add(this.CSS.button,this.CSS.buttonModifier),this.nodes.button.innerHTML=zo,this.nodes.button}renderActions(){return this.nodes.input=document.createElement("input"),this.nodes.input.placeholder=this.i18n.t("Add a link"),this.nodes.input.enterKeyHint="done",this.nodes.input.classList.add(this.CSS.input),this.nodes.input.addEventListener("keydown",e=>{e.keyCode===this.ENTER_KEY&&this.enterPressed(e)}),this.nodes.input}surround(e){if(e){this.inputOpened?(this.selection.restore(),this.selection.removeFakeBackground()):(this.selection.setFakeBackground(),this.selection.save());const t=this.selection.findParentTag("A");if(t){this.selection.expandToTag(t),this.unlink(),this.closeActions(),this.checkState(),this.toolbar.close();return}}this.toggleActions()}checkState(){const e=this.selection.findParentTag("A");if(e){this.nodes.button.innerHTML=Gi,this.nodes.button.classList.add(this.CSS.buttonUnlink),this.nodes.button.classList.add(this.CSS.buttonActive),this.openActions();const t=e.getAttribute("href");this.nodes.input.value=t!=="null"?t:"",this.selection.save()}else this.nodes.button.innerHTML=zo,this.nodes.button.classList.remove(this.CSS.buttonUnlink),this.nodes.button.classList.remove(this.CSS.buttonActive);return!!e}clear(){this.closeActions()}get shortcut(){return"CMD+K"}toggleActions(){this.inputOpened?this.closeActions(!1):this.openActions(!0)}openActions(e=!1){this.nodes.input.classList.add(this.CSS.inputShowed),e&&this.nodes.input.focus(),this.inputOpened=!0}closeActions(e=!0){if(this.selection.isFakeBackgroundEnabled){const t=new b;t.save(),this.selection.restore(),this.selection.removeFakeBackground(),t.restore()}this.nodes.input.classList.remove(this.CSS.inputShowed),this.nodes.input.value="",e&&this.selection.clearSaved(),this.inputOpened=!1}enterPressed(e){let t=this.nodes.input.value||"";if(!t.trim()){this.selection.restore(),this.unlink(),e.preventDefault(),this.closeActions();return}if(!this.validateURL(t)){this.notifier.show({message:"Pasted link is not valid.",style:"error"}),T("Incorrect Link pasted","warn",t);return}t=this.prepareLink(t),this.selection.restore(),this.selection.removeFakeBackground(),this.insertLink(t),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation(),this.selection.collapseToEnd(),this.inlineToolbar.close()}validateURL(e){return!/\s/.test(e)}prepareLink(e){return e=e.trim(),e=this.addProtocol(e),e}addProtocol(e){if(/^(\w+):(\/\/)?/.test(e))return e;const t=/^\/[^/\s]/.test(e),o=e.substring(0,1)==="#",i=/^\/\/[^/\s]/.test(e);return!t&&!o&&!i&&(e="http://"+e),e}insertLink(e){const t=this.selection.findParentTag("A");t&&this.selection.expandToTag(t),document.execCommand(this.commandLink,!1,e)}unlink(){document.execCommand(this.commandUnlink)}}mo.isInline=!0,mo.title="Link";class Pn{constructor({api:e}){this.i18nAPI=e.i18n,this.blocksAPI=e.blocks,this.selectionAPI=e.selection,this.toolsAPI=e.tools,this.caretAPI=e.caret}async render(){const e=b.get(),t=this.blocksAPI.getBlockByElement(e.anchorNode);if(t===void 0)return[];const o=this.toolsAPI.getBlockTools(),i=await Po(t,o);if(i.length===0)return[];const s=i.reduce((c,u)=>{var h;return(h=u.toolbox)==null||h.forEach(p=>{c.push({icon:p.icon,title:H.t(W.toolNames,p.title),name:u.name,closeOnActivate:!0,onActivate:async()=>{const g=await this.blocksAPI.convert(t.id,u.name,p.data);this.caretAPI.setToBlock(g,"end")}})}),c},[]),r=await t.getActiveToolboxEntry(),a=r!==void 0?r.icon:Uo,l=!ge();return{icon:a,name:"convert-to",hint:{title:this.i18nAPI.t("Convert to")},children:{searchable:l,items:s,onOpen:()=>{l&&(this.selectionAPI.setFakeBackground(),this.selectionAPI.save())},onClose:()=>{l&&(this.selectionAPI.restore(),this.selectionAPI.removeFakeBackground())}}}}}Pn.isInline=!0;class Nn{constructor({data:e,api:t}){this.CSS={wrapper:"ce-stub",info:"ce-stub__info",title:"ce-stub__title",subtitle:"ce-stub__subtitle"},this.api=t,this.title=e.title||this.api.i18n.t("Error"),this.subtitle=this.api.i18n.t("The block can not be displayed correctly."),this.savedData=e.savedData,this.wrapper=this.make()}render(){return this.wrapper}save(){return this.savedData}make(){const e=d.make("div",this.CSS.wrapper),t=Ji,o=d.make("div",this.CSS.info),i=d.make("div",this.CSS.title,{textContent:this.title}),s=d.make("div",this.CSS.subtitle,{textContent:this.subtitle});return e.innerHTML=t,o.appendChild(i),o.appendChild(s),e.appendChild(o),e}}Nn.isReadOnlySupported=!0;class ha extends xt{constructor(){super(...arguments),this.type=ce.Inline}get title(){return this.constructable[He.Title]}create(){return new this.constructable({api:this.api,config:this.settings})}get isReadOnlySupported(){return this.constructable[He.IsReadOnlySupported]??!1}}class pa extends xt{constructor(){super(...arguments),this.type=ce.Tune}create(e,t){return new this.constructable({api:this.api,config:this.settings,block:t,data:e})}}class F extends Map{get blockTools(){const e=Array.from(this.entries()).filter(([,t])=>t.isBlock());return new F(e)}get inlineTools(){const e=Array.from(this.entries()).filter(([,t])=>t.isInline());return new F(e)}get blockTunes(){const e=Array.from(this.entries()).filter(([,t])=>t.isTune());return new F(e)}get internalTools(){const e=Array.from(this.entries()).filter(([,t])=>t.isInternal);return new F(e)}get externalTools(){const e=Array.from(this.entries()).filter(([,t])=>!t.isInternal);return new F(e)}}var fa=Object.defineProperty,ga=Object.getOwnPropertyDescriptor,Rn=(n,e,t,o)=>{for(var i=o>1?void 0:o?ga(e,t):e,s=n.length-1,r;s>=0;s--)(r=n[s])&&(i=(o?r(e,t,i):r(i))||i);return o&&i&&fa(e,t,i),i};class bo extends xt{constructor(){super(...arguments),this.type=ce.Block,this.inlineTools=new F,this.tunes=new F}create(e,t,o){return new this.constructable({data:e,block:t,readOnly:o,api:this.api,config:this.settings})}get isReadOnlySupported(){return this.constructable[ve.IsReadOnlySupported]===!0}get isLineBreaksEnabled(){return this.constructable[ve.IsEnabledLineBreaks]}get toolbox(){const e=this.constructable[ve.Toolbox],t=this.config[je.Toolbox];if(!V(e)&&t!==!1)return t?Array.isArray(e)?Array.isArray(t)?t.map((o,i)=>{const s=e[i];return s?{...s,...o}:o}):[t]:Array.isArray(t)?t:[{...e,...t}]:Array.isArray(e)?e:[e]}get conversionConfig(){return this.constructable[ve.ConversionConfig]}get enabledInlineTools(){return this.config[je.EnabledInlineTools]||!1}get enabledBlockTunes(){return this.config[je.EnabledBlockTunes]}get pasteConfig(){return this.constructable[ve.PasteConfig]??{}}get sanitizeConfig(){const e=super.sanitizeConfig,t=this.baseSanitizeConfig;if(V(e))return t;const o={};for(const i in e)if(Object.prototype.hasOwnProperty.call(e,i)){const s=e[i];N(s)?o[i]=Object.assign({},t,s):o[i]=s}return o}get baseSanitizeConfig(){const e={};return Array.from(this.inlineTools.values()).forEach(t=>Object.assign(e,t.sanitizeConfig)),Array.from(this.tunes.values()).forEach(t=>Object.assign(e,t.sanitizeConfig)),e}}Rn([fe],bo.prototype,"sanitizeConfig",1),Rn([fe],bo.prototype,"baseSanitizeConfig",1);class ma{constructor(e,t,o){this.api=o,this.config=e,this.editorConfig=t}get(e){const{class:t,isInternal:o=!1,...i}=this.config[e],s=this.getConstructor(t),r=t[Et.IsTune];return new s({name:e,constructable:t,config:i,api:this.api.getMethodsForTool(e,r),isDefault:e===this.editorConfig.defaultBlock,defaultPlaceholder:this.editorConfig.placeholder,isInternal:o})}getConstructor(e){switch(!0){case e[He.IsInline]:return ha;case e[Et.IsTune]:return pa;default:return bo}}}class Dn{constructor({api:e}){this.CSS={animation:"wobble"},this.api=e}render(){return{icon:$i,title:this.api.i18n.t("Move down"),onActivate:()=>this.handleClick(),name:"move-down"}}handleClick(){const e=this.api.blocks.getCurrentBlockIndex(),t=this.api.blocks.getBlockByIndex(e+1);if(!t)throw new Error("Unable to move Block down since it is already the last");const o=t.holder,i=o.getBoundingClientRect();let s=Math.abs(window.innerHeight-o.offsetHeight);i.topthis.handleClick()}}}handleClick(){this.api.blocks.delete()}}Fn.isTune=!0;class jn{constructor({api:e}){this.CSS={animation:"wobble"},this.api=e}render(){return{icon:Wi,title:this.api.i18n.t("Move up"),onActivate:()=>this.handleClick(),name:"move-up"}}handleClick(){const e=this.api.blocks.getCurrentBlockIndex(),t=this.api.blocks.getBlockByIndex(e),o=this.api.blocks.getBlockByIndex(e-1);if(e===0||!t||!o)throw new Error("Unable to move Block up since it is already the first");const i=t.holder,s=o.holder,r=i.getBoundingClientRect(),a=s.getBoundingClientRect();let l;a.top>0?l=Math.abs(r.top)-Math.abs(a.top):l=Math.abs(r.top)+a.height,window.scrollBy(0,-1*l),this.api.blocks.move(e-1),this.api.toolbar.toggleBlockSettings(!0)}}jn.isTune=!0;var ba=Object.defineProperty,va=Object.getOwnPropertyDescriptor,ka=(n,e,t,o)=>{for(var i=o>1?void 0:o?va(e,t):e,s=n.length-1,r;s>=0;s--)(r=n[s])&&(i=(o?r(e,t,i):r(i))||i);return o&&i&&ba(e,t,i),i};class Hn extends E{constructor(){super(...arguments),this.stubTool="stub",this.toolsAvailable=new F,this.toolsUnavailable=new F}get available(){return this.toolsAvailable}get unavailable(){return this.toolsUnavailable}get inlineTools(){return this.available.inlineTools}get blockTools(){return this.available.blockTools}get blockTunes(){return this.available.blockTunes}get defaultTool(){return this.blockTools.get(this.config.defaultBlock)}get internal(){return this.available.internalTools}async prepare(){if(this.validateTools(),this.config.tools=nt({},this.internalTools,this.config.tools),!Object.prototype.hasOwnProperty.call(this.config,"tools")||Object.keys(this.config.tools).length===0)throw Error("Can't start without tools");const e=this.prepareConfig();this.factory=new ma(e,this.config,this.Editor.API);const t=this.getListOfPrepareFunctions(e);if(t.length===0)return Promise.resolve();await Zn(t,o=>{this.toolPrepareMethodSuccess(o)},o=>{this.toolPrepareMethodFallback(o)}),this.prepareBlockTools()}getAllInlineToolsSanitizeConfig(){const e={};return Array.from(this.inlineTools.values()).forEach(t=>{Object.assign(e,t.sanitizeConfig)}),e}destroy(){Object.values(this.available).forEach(async e=>{M(e.reset)&&await e.reset()})}get internalTools(){return{convertTo:{class:Pn,isInternal:!0},link:{class:mo,isInternal:!0},bold:{class:fo,isInternal:!0},italic:{class:go,isInternal:!0},paragraph:{class:po,inlineToolbar:!0,isInternal:!0},stub:{class:Nn,isInternal:!0},moveUp:{class:jn,isInternal:!0},delete:{class:Fn,isInternal:!0},moveDown:{class:Dn,isInternal:!0}}}toolPrepareMethodSuccess(e){const t=this.factory.get(e.toolName);if(t.isInline()){const i=["render"].filter(s=>!t.create()[s]);if(i.length){T(`Incorrect Inline Tool: ${t.name}. Some of required methods is not implemented %o`,"warn",i),this.toolsUnavailable.set(t.name,t);return}}this.toolsAvailable.set(t.name,t)}toolPrepareMethodFallback(e){this.toolsUnavailable.set(e.toolName,this.factory.get(e.toolName))}getListOfPrepareFunctions(e){const t=[];return Object.entries(e).forEach(([o,i])=>{t.push({function:M(i.class.prepare)?i.class.prepare:()=>{},data:{toolName:o,config:i.config}})}),t}prepareBlockTools(){Array.from(this.blockTools.values()).forEach(e=>{this.assignInlineToolsToBlockTool(e),this.assignBlockTunesToBlockTool(e)})}assignInlineToolsToBlockTool(e){if(this.config.inlineToolbar!==!1){if(e.enabledInlineTools===!0){e.inlineTools=new F(Array.isArray(this.config.inlineToolbar)?this.config.inlineToolbar.map(t=>[t,this.inlineTools.get(t)]):Array.from(this.inlineTools.entries()));return}Array.isArray(e.enabledInlineTools)&&(e.inlineTools=new F(["convertTo",...e.enabledInlineTools].map(t=>[t,this.inlineTools.get(t)])))}}assignBlockTunesToBlockTool(e){if(e.enabledBlockTunes!==!1){if(Array.isArray(e.enabledBlockTunes)){const t=new F(e.enabledBlockTunes.map(o=>[o,this.blockTunes.get(o)]));e.tunes=new F([...t,...this.blockTunes.internalTools]);return}if(Array.isArray(this.config.tunes)){const t=new F(this.config.tunes.map(o=>[o,this.blockTunes.get(o)]));e.tunes=new F([...t,...this.blockTunes.internalTools]);return}e.tunes=this.blockTunes.internalTools}}validateTools(){for(const e in this.config.tools)if(Object.prototype.hasOwnProperty.call(this.config.tools,e)){if(e in this.internalTools)return;const t=this.config.tools[e];if(!M(t)&&!M(t.class))throw Error(`Tool «${e}» must be a constructor function or an object with function in the «class» property`)}}prepareConfig(){const e={};for(const t in this.config.tools)N(this.config.tools[t])?e[t]=this.config.tools[t]:e[t]={class:this.config.tools[t]};return e}}ka([fe],Hn.prototype,"getAllInlineToolsSanitizeConfig",1);const ya=`:root{--selectionColor: #e1f2ff;--inlineSelectionColor: #d4ecff;--bg-light: #eff2f5;--grayText: #707684;--color-dark: #1D202B;--color-active-icon: #388AE5;--color-gray-border: rgba(201, 201, 204, .48);--content-width: 650px;--narrow-mode-right-padding: 50px;--toolbox-buttons-size: 26px;--toolbox-buttons-size--mobile: 36px;--icon-size: 20px;--icon-size--mobile: 28px;--block-padding-vertical: .4em;--color-line-gray: #EFF0F1 }.codex-editor{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;z-index:1}.codex-editor .hide{display:none}.codex-editor__redactor [contenteditable]:empty:after{content:"\\feff"}@media (min-width: 651px){.codex-editor--narrow .codex-editor__redactor{margin-right:50px}}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .codex-editor__redactor{margin-left:50px;margin-right:0}}@media (min-width: 651px){.codex-editor--narrow .ce-toolbar__actions{right:-5px}}.codex-editor-copyable{position:absolute;height:1px;width:1px;top:-400%;opacity:.001}.codex-editor-overlay{position:fixed;top:0;left:0;right:0;bottom:0;z-index:999;pointer-events:none;overflow:hidden}.codex-editor-overlay__container{position:relative;pointer-events:auto;z-index:0}.codex-editor-overlay__rectangle{position:absolute;pointer-events:none;background-color:#2eaadc33;border:1px solid transparent}.codex-editor svg{max-height:100%}.codex-editor path{stroke:currentColor}.codex-editor ::-moz-selection{background-color:#d4ecff}.codex-editor ::selection{background-color:#d4ecff}.codex-editor--toolbox-opened [contentEditable=true][data-placeholder]:focus:before{opacity:0!important}.ce-scroll-locked{overflow:hidden}.ce-scroll-locked--hard{overflow:hidden;top:calc(-1 * var(--window-scroll-offset));position:fixed;width:100%}.ce-toolbar{position:absolute;left:0;right:0;top:0;-webkit-transition:opacity .1s ease;transition:opacity .1s ease;will-change:opacity,top;display:none}.ce-toolbar--opened{display:block}.ce-toolbar__content{max-width:650px;margin:0 auto;position:relative}.ce-toolbar__plus{color:#1d202b;cursor:pointer;width:26px;height:26px;border-radius:7px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-ms-flex-negative:0;flex-shrink:0}@media (max-width: 650px){.ce-toolbar__plus{width:36px;height:36px}}@media (hover: hover){.ce-toolbar__plus:hover{background-color:#eff2f5}}.ce-toolbar__plus--active{background-color:#eff2f5;-webkit-animation:bounceIn .75s 1;animation:bounceIn .75s 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.ce-toolbar__plus-shortcut{opacity:.6;word-spacing:-2px;margin-top:5px}@media (max-width: 650px){.ce-toolbar__plus{position:absolute;background-color:#fff;border:1px solid #E8E8EB;-webkit-box-shadow:0 3px 15px -3px rgba(13,20,33,.13);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;z-index:2;position:static}.ce-toolbar__plus--left-oriented:before{left:15px;margin-left:0}.ce-toolbar__plus--right-oriented:before{left:auto;right:15px;margin-left:0}}.ce-toolbar__actions{position:absolute;right:100%;opacity:0;display:-webkit-box;display:-ms-flexbox;display:flex;padding-right:5px}.ce-toolbar__actions--opened{opacity:1}@media (max-width: 650px){.ce-toolbar__actions{right:auto}}.ce-toolbar__settings-btn{color:#1d202b;width:26px;height:26px;border-radius:7px;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;margin-left:3px;cursor:pointer;user-select:none}@media (max-width: 650px){.ce-toolbar__settings-btn{width:36px;height:36px}}@media (hover: hover){.ce-toolbar__settings-btn:hover{background-color:#eff2f5}}.ce-toolbar__settings-btn--active{background-color:#eff2f5;-webkit-animation:bounceIn .75s 1;animation:bounceIn .75s 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@media (min-width: 651px){.ce-toolbar__settings-btn{width:24px}}.ce-toolbar__settings-btn--hidden{display:none}@media (max-width: 650px){.ce-toolbar__settings-btn{position:absolute;background-color:#fff;border:1px solid #E8E8EB;-webkit-box-shadow:0 3px 15px -3px rgba(13,20,33,.13);box-shadow:0 3px 15px -3px #0d142121;border-radius:6px;z-index:2;position:static}.ce-toolbar__settings-btn--left-oriented:before{left:15px;margin-left:0}.ce-toolbar__settings-btn--right-oriented:before{left:auto;right:15px;margin-left:0}}.ce-toolbar__plus svg,.ce-toolbar__settings-btn svg{width:24px;height:24px}@media (min-width: 651px){.codex-editor--narrow .ce-toolbar__plus{left:5px}}@media (min-width: 651px){.codex-editor--narrow .ce-toolbox .ce-popover{right:0;left:auto;left:initial}}.ce-inline-toolbar{--y-offset: 8px;--color-background-icon-active: rgba(56, 138, 229, .1);--color-text-icon-active: #388AE5;--color-text-primary: black;position:absolute;visibility:hidden;-webkit-transition:opacity .25s ease;transition:opacity .25s ease;will-change:opacity,left,top;top:0;left:0;z-index:3;opacity:1;visibility:visible}.ce-inline-toolbar [hidden]{display:none!important}.ce-inline-toolbar__toggler-and-button-wrapper{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;padding:0 6px}.ce-inline-toolbar__buttons{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-inline-toolbar__dropdown{display:-webkit-box;display:-ms-flexbox;display:flex;padding:6px;margin:0 6px 0 -6px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;border-right:1px solid rgba(201,201,204,.48);-webkit-box-sizing:border-box;box-sizing:border-box}@media (hover: hover){.ce-inline-toolbar__dropdown:hover{background:#eff2f5}}.ce-inline-toolbar__dropdown--hidden{display:none}.ce-inline-toolbar__dropdown-content,.ce-inline-toolbar__dropdown-arrow{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-inline-toolbar__dropdown-content svg,.ce-inline-toolbar__dropdown-arrow svg{width:20px;height:20px}.ce-inline-toolbar__shortcut{opacity:.6;word-spacing:-3px;margin-top:3px}.ce-inline-tool{color:var(--color-text-primary);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:0;border-radius:4px;line-height:normal;height:100%;padding:0;width:28px;background-color:transparent;cursor:pointer}@media (max-width: 650px){.ce-inline-tool{width:36px;height:36px}}@media (hover: hover){.ce-inline-tool:hover{background-color:#f8f8f8}}.ce-inline-tool svg{display:block;width:20px;height:20px}@media (max-width: 650px){.ce-inline-tool svg{width:28px;height:28px}}.ce-inline-tool--link .icon--unlink,.ce-inline-tool--unlink .icon--link{display:none}.ce-inline-tool--unlink .icon--unlink{display:inline-block;margin-bottom:-1px}.ce-inline-tool-input{background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:4px 8px;font-size:14px;line-height:22px;outline:none;margin:0;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box;display:none;font-weight:500;-webkit-appearance:none;font-family:inherit}@media (max-width: 650px){.ce-inline-tool-input{font-size:15px;font-weight:500}}.ce-inline-tool-input::-webkit-input-placeholder{color:#707684}.ce-inline-tool-input::-moz-placeholder{color:#707684}.ce-inline-tool-input:-ms-input-placeholder{color:#707684}.ce-inline-tool-input::-ms-input-placeholder{color:#707684}.ce-inline-tool-input::placeholder{color:#707684}.ce-inline-tool-input--showed{display:block}.ce-inline-tool--active{background:var(--color-background-icon-active);color:var(--color-text-icon-active)}@-webkit-keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.ce-block{-webkit-animation:fade-in .3s ease;animation:fade-in .3s ease;-webkit-animation-fill-mode:none;animation-fill-mode:none;-webkit-animation-fill-mode:initial;animation-fill-mode:initial}.ce-block:first-of-type{margin-top:0}.ce-block--selected .ce-block__content{background:#e1f2ff}.ce-block--selected .ce-block__content [contenteditable]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ce-block--selected .ce-block__content img,.ce-block--selected .ce-block__content .ce-stub{opacity:.55}.ce-block--stretched .ce-block__content{max-width:none}.ce-block__content{position:relative;max-width:650px;margin:0 auto;-webkit-transition:background-color .15s ease;transition:background-color .15s ease}.ce-block--drop-target .ce-block__content:before{content:"";position:absolute;top:100%;left:-20px;margin-top:-1px;height:8px;width:8px;border:solid #388AE5;border-width:1px 1px 0 0;-webkit-transform-origin:right;transform-origin:right;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.ce-block--drop-target .ce-block__content:after{content:"";position:absolute;top:100%;height:1px;width:100%;color:#388ae5;background:repeating-linear-gradient(90deg,#388AE5,#388AE5 1px,#fff 1px,#fff 6px)}.ce-block a{cursor:pointer;-webkit-text-decoration:underline;text-decoration:underline}.ce-block b{font-weight:700}.ce-block i{font-style:italic}@-webkit-keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}20%{-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}60%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes bounceIn{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}20%{-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}60%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@-webkit-keyframes selectionBounce{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}50%{-webkit-transform:scale3d(1.01,1.01,1.01);transform:scale3d(1.01,1.01,1.01)}70%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes selectionBounce{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}50%{-webkit-transform:scale3d(1.01,1.01,1.01);transform:scale3d(1.01,1.01,1.01)}70%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@-webkit-keyframes buttonClicked{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.95,.95,.95);transform:scale3d(.95,.95,.95)}60%{-webkit-transform:scale3d(1.02,1.02,1.02);transform:scale3d(1.02,1.02,1.02)}80%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}@keyframes buttonClicked{0%,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{-webkit-transform:scale3d(.95,.95,.95);transform:scale3d(.95,.95,.95)}60%{-webkit-transform:scale3d(1.02,1.02,1.02);transform:scale3d(1.02,1.02,1.02)}80%{-webkit-transform:scale3d(1,1,1);transform:scaleZ(1)}}.cdx-block{padding:.4em 0}.cdx-block::-webkit-input-placeholder{line-height:normal!important}.cdx-input{border:1px solid rgba(201,201,204,.48);-webkit-box-shadow:inset 0 1px 2px 0 rgba(35,44,72,.06);box-shadow:inset 0 1px 2px #232c480f;border-radius:3px;padding:10px 12px;outline:none;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.cdx-input[data-placeholder]:before{position:static!important}.cdx-input[data-placeholder]:before{display:inline-block;width:0;white-space:nowrap;pointer-events:none}.cdx-settings-button{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;border-radius:3px;cursor:pointer;border:0;outline:none;background-color:transparent;vertical-align:bottom;color:inherit;margin:0;min-width:26px;min-height:26px}.cdx-settings-button--focused{background:rgba(34,186,255,.08)!important}.cdx-settings-button--focused{-webkit-box-shadow:inset 0 0 0px 1px rgba(7,161,227,.08);box-shadow:inset 0 0 0 1px #07a1e314}.cdx-settings-button--focused-animated{-webkit-animation-name:buttonClicked;animation-name:buttonClicked;-webkit-animation-duration:.25s;animation-duration:.25s}.cdx-settings-button--active{color:#388ae5}.cdx-settings-button svg{width:auto;height:auto}@media (max-width: 650px){.cdx-settings-button svg{width:28px;height:28px}}@media (max-width: 650px){.cdx-settings-button{width:36px;height:36px;border-radius:8px}}@media (hover: hover){.cdx-settings-button:hover{background-color:#eff2f5}}.cdx-loader{position:relative;border:1px solid rgba(201,201,204,.48)}.cdx-loader:before{content:"";position:absolute;left:50%;top:50%;width:18px;height:18px;margin:-11px 0 0 -11px;border:2px solid rgba(201,201,204,.48);border-left-color:#388ae5;border-radius:50%;-webkit-animation:cdxRotation 1.2s infinite linear;animation:cdxRotation 1.2s infinite linear}@-webkit-keyframes cdxRotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes cdxRotation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.cdx-button{padding:13px;border-radius:3px;border:1px solid rgba(201,201,204,.48);font-size:14.9px;background:#fff;-webkit-box-shadow:0 2px 2px 0 rgba(18,30,57,.04);box-shadow:0 2px 2px #121e390a;color:#707684;text-align:center;cursor:pointer}@media (hover: hover){.cdx-button:hover{background:#FBFCFE;-webkit-box-shadow:0 1px 3px 0 rgba(18,30,57,.08);box-shadow:0 1px 3px #121e3914}}.cdx-button svg{height:20px;margin-right:.2em;margin-top:-2px}.ce-stub{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:12px 18px;margin:10px 0;border-radius:10px;background:#eff2f5;border:1px solid #EFF0F1;color:#707684;font-size:14px}.ce-stub svg{width:20px;height:20px}.ce-stub__info{margin-left:14px}.ce-stub__title{font-weight:500;text-transform:capitalize}.codex-editor.codex-editor--rtl{direction:rtl}.codex-editor.codex-editor--rtl .cdx-list{padding-left:0;padding-right:40px}.codex-editor.codex-editor--rtl .ce-toolbar__plus{right:-26px;left:auto}.codex-editor.codex-editor--rtl .ce-toolbar__actions{right:auto;left:-26px}@media (max-width: 650px){.codex-editor.codex-editor--rtl .ce-toolbar__actions{margin-left:0;margin-right:auto;padding-right:0;padding-left:10px}}.codex-editor.codex-editor--rtl .ce-settings{left:5px;right:auto}.codex-editor.codex-editor--rtl .ce-settings:before{right:auto;left:25px}.codex-editor.codex-editor--rtl .ce-settings__button:not(:nth-child(3n+3)){margin-left:3px;margin-right:0}.codex-editor.codex-editor--rtl .ce-conversion-tool__icon{margin-right:0;margin-left:10px}.codex-editor.codex-editor--rtl .ce-inline-toolbar__dropdown{border-right:0px solid transparent;border-left:1px solid rgba(201,201,204,.48);margin:0 -6px 0 6px}.codex-editor.codex-editor--rtl .ce-inline-toolbar__dropdown .icon--toggler-down{margin-left:0;margin-right:4px}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .ce-toolbar__plus{left:0;right:5px}}@media (min-width: 651px){.codex-editor--narrow.codex-editor--rtl .ce-toolbar__actions{left:-5px}}.cdx-search-field{--icon-margin-right: 10px;background:#F8F8F8;border:1px solid rgba(226,226,229,.2);border-radius:6px;padding:2px;display:grid;grid-template-columns:auto auto 1fr;grid-template-rows:auto}.cdx-search-field__icon{width:26px;height:26px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-right:var(--icon-margin-right)}.cdx-search-field__icon svg{width:20px;height:20px;color:#707684}.cdx-search-field__input{font-size:14px;outline:none;font-weight:500;font-family:inherit;border:0;background:transparent;margin:0;padding:0;line-height:22px;min-width:calc(100% - 26px - var(--icon-margin-right))}.cdx-search-field__input::-webkit-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::-moz-placeholder{color:#707684;font-weight:500}.cdx-search-field__input:-ms-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::-ms-input-placeholder{color:#707684;font-weight:500}.cdx-search-field__input::placeholder{color:#707684;font-weight:500}.ce-popover{--border-radius: 6px;--width: 200px;--max-height: 270px;--padding: 6px;--offset-from-target: 8px;--color-border: #EFF0F1;--color-shadow: rgba(13, 20, 33, .1);--color-background: white;--color-text-primary: black;--color-text-secondary: #707684;--color-border-icon: rgba(201, 201, 204, .48);--color-border-icon-disabled: #EFF0F1;--color-text-icon-active: #388AE5;--color-background-icon-active: rgba(56, 138, 229, .1);--color-background-item-focus: rgba(34, 186, 255, .08);--color-shadow-item-focus: rgba(7, 161, 227, .08);--color-background-item-hover: #F8F8F8;--color-background-item-confirm: #E24A4A;--color-background-item-confirm-hover: #CE4343;--popover-top: calc(100% + var(--offset-from-target));--popover-left: 0;--nested-popover-overlap: 4px;--icon-size: 20px;--item-padding: 3px;--item-height: calc(var(--icon-size) + 2 * var(--item-padding))}.ce-popover__container{min-width:var(--width);width:var(--width);max-height:var(--max-height);border-radius:var(--border-radius);overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:0px 3px 15px -3px var(--color-shadow);box-shadow:0 3px 15px -3px var(--color-shadow);position:absolute;left:var(--popover-left);top:var(--popover-top);background:var(--color-background);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;z-index:4;opacity:0;max-height:0;pointer-events:none;padding:0;border:none}.ce-popover--opened>.ce-popover__container{opacity:1;padding:var(--padding);max-height:var(--max-height);pointer-events:auto;-webkit-animation:panelShowing .1s ease;animation:panelShowing .1s ease;border:1px solid var(--color-border)}@media (max-width: 650px){.ce-popover--opened>.ce-popover__container{-webkit-animation:panelShowingMobile .25s ease;animation:panelShowingMobile .25s ease}}.ce-popover--open-top .ce-popover__container{--popover-top: calc(-1 * (var(--offset-from-target) + var(--popover-height)))}.ce-popover--open-left .ce-popover__container{--popover-left: calc(-1 * var(--width) + 100%)}.ce-popover__items{overflow-y:auto;-ms-scroll-chaining:none;overscroll-behavior:contain}@media (max-width: 650px){.ce-popover__overlay{position:fixed;top:0;bottom:0;left:0;right:0;background:#1D202B;z-index:3;opacity:.5;-webkit-transition:opacity .12s ease-in;transition:opacity .12s ease-in;will-change:opacity;visibility:visible}}.ce-popover__overlay--hidden{display:none}@media (max-width: 650px){.ce-popover .ce-popover__container{--offset: 5px;position:fixed;max-width:none;min-width:calc(100% - var(--offset) * 2);left:var(--offset);right:var(--offset);bottom:calc(var(--offset) + env(safe-area-inset-bottom));top:auto;border-radius:10px}}.ce-popover__search{margin-bottom:5px}.ce-popover__nothing-found-message{color:#707684;display:none;cursor:default;padding:3px;font-size:14px;line-height:20px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ce-popover__nothing-found-message--displayed{display:block}.ce-popover--nested .ce-popover__container{--popover-left: calc(var(--nesting-level) * (var(--width) - var(--nested-popover-overlap)));top:calc(var(--trigger-item-top) - var(--nested-popover-overlap));position:absolute}.ce-popover--open-top.ce-popover--nested .ce-popover__container{top:calc(var(--trigger-item-top) - var(--popover-height) + var(--item-height) + var(--offset-from-target) + var(--nested-popover-overlap))}.ce-popover--open-left .ce-popover--nested .ce-popover__container{--popover-left: calc(-1 * (var(--nesting-level) + 1) * var(--width) + 100%)}.ce-popover-item-separator{padding:4px 3px}.ce-popover-item-separator--hidden{display:none}.ce-popover-item-separator__line{height:1px;background:var(--color-border);width:100%}.ce-popover-item-html--hidden{display:none}.ce-popover-item{--border-radius: 6px;border-radius:var(--border-radius);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:var(--item-padding);color:var(--color-text-primary);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:none;background:transparent}@media (max-width: 650px){.ce-popover-item{padding:4px}}.ce-popover-item:not(:last-of-type){margin-bottom:1px}.ce-popover-item__icon{width:26px;height:26px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.ce-popover-item__icon svg{width:20px;height:20px}@media (max-width: 650px){.ce-popover-item__icon{width:36px;height:36px;border-radius:8px}.ce-popover-item__icon svg{width:28px;height:28px}}.ce-popover-item__icon--tool{margin-right:4px}.ce-popover-item__title{font-size:14px;line-height:20px;font-weight:500;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-right:auto}@media (max-width: 650px){.ce-popover-item__title{font-size:16px}}.ce-popover-item__secondary-title{color:var(--color-text-secondary);font-size:12px;white-space:nowrap;letter-spacing:-.1em;padding-right:5px;opacity:.6}@media (max-width: 650px){.ce-popover-item__secondary-title{display:none}}.ce-popover-item--active{background:var(--color-background-icon-active);color:var(--color-text-icon-active)}.ce-popover-item--disabled{color:var(--color-text-secondary);cursor:default;pointer-events:none}.ce-popover-item--focused:not(.ce-popover-item--no-focus){background:var(--color-background-item-focus)!important}.ce-popover-item--hidden{display:none}@media (hover: hover){.ce-popover-item:hover{cursor:pointer}.ce-popover-item:hover:not(.ce-popover-item--no-hover){background-color:var(--color-background-item-hover)}}.ce-popover-item--confirmation{background:var(--color-background-item-confirm)}.ce-popover-item--confirmation .ce-popover-item__title,.ce-popover-item--confirmation .ce-popover-item__icon{color:#fff}@media (hover: hover){.ce-popover-item--confirmation:not(.ce-popover-item--no-hover):hover{background:var(--color-background-item-confirm-hover)}}.ce-popover-item--confirmation:not(.ce-popover-item--no-focus).ce-popover-item--focused{background:var(--color-background-item-confirm-hover)!important}@-webkit-keyframes panelShowing{0%{opacity:0;-webkit-transform:translateY(-8px) scale(.9);transform:translateY(-8px) scale(.9)}70%{opacity:1;-webkit-transform:translateY(2px);transform:translateY(2px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes panelShowing{0%{opacity:0;-webkit-transform:translateY(-8px) scale(.9);transform:translateY(-8px) scale(.9)}70%{opacity:1;-webkit-transform:translateY(2px);transform:translateY(2px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes panelShowingMobile{0%{opacity:0;-webkit-transform:translateY(14px) scale(.98);transform:translateY(14px) scale(.98)}70%{opacity:1;-webkit-transform:translateY(-4px);transform:translateY(-4px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes panelShowingMobile{0%{opacity:0;-webkit-transform:translateY(14px) scale(.98);transform:translateY(14px) scale(.98)}70%{opacity:1;-webkit-transform:translateY(-4px);transform:translateY(-4px)}to{-webkit-transform:translateY(0);transform:translateY(0)}}.wobble{-webkit-animation-name:wobble;animation-name:wobble;-webkit-animation-duration:.4s;animation-duration:.4s}@-webkit-keyframes wobble{0%{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-9%,0,0);transform:translate3d(-9%,0,0)}30%{-webkit-transform:translate3d(9%,0,0);transform:translate3d(9%,0,0)}45%{-webkit-transform:translate3d(-4%,0,0);transform:translate3d(-4%,0,0)}60%{-webkit-transform:translate3d(4%,0,0);transform:translate3d(4%,0,0)}75%{-webkit-transform:translate3d(-1%,0,0);transform:translate3d(-1%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}}@keyframes wobble{0%{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}15%{-webkit-transform:translate3d(-9%,0,0);transform:translate3d(-9%,0,0)}30%{-webkit-transform:translate3d(9%,0,0);transform:translate3d(9%,0,0)}45%{-webkit-transform:translate3d(-4%,0,0);transform:translate3d(-4%,0,0)}60%{-webkit-transform:translate3d(4%,0,0);transform:translate3d(4%,0,0)}75%{-webkit-transform:translate3d(-1%,0,0);transform:translate3d(-1%,0,0)}to{-webkit-transform:translate3d(0,0,0);transform:translateZ(0)}}.ce-popover-header{margin-bottom:8px;margin-top:4px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ce-popover-header__text{font-size:18px;font-weight:600}.ce-popover-header__back-button{border:0;background:transparent;width:36px;height:36px;color:var(--color-text-primary)}.ce-popover-header__back-button svg{display:block;width:28px;height:28px}.ce-popover--inline{--height: 38px;--height-mobile: 46px;--container-padding: 4px;position:relative}.ce-popover--inline .ce-popover__custom-content{margin-bottom:0}.ce-popover--inline .ce-popover__items{display:-webkit-box;display:-ms-flexbox;display:flex}.ce-popover--inline .ce-popover__container{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;padding:var(--container-padding);height:var(--height);top:0;min-width:-webkit-max-content;min-width:-moz-max-content;min-width:max-content;width:-webkit-max-content;width:-moz-max-content;width:max-content;-webkit-animation:none;animation:none}@media (max-width: 650px){.ce-popover--inline .ce-popover__container{height:var(--height-mobile);position:absolute}}.ce-popover--inline .ce-popover-item-separator{padding:0 4px}.ce-popover--inline .ce-popover-item-separator__line{height:100%;width:1px}.ce-popover--inline .ce-popover-item{border-radius:4px;padding:4px}.ce-popover--inline .ce-popover-item__icon--tool{-webkit-box-shadow:none;box-shadow:none;background:transparent;margin-right:0}.ce-popover--inline .ce-popover-item__icon{width:auto;width:initial;height:auto;height:initial}.ce-popover--inline .ce-popover-item__icon svg{width:20px;height:20px}@media (max-width: 650px){.ce-popover--inline .ce-popover-item__icon svg{width:28px;height:28px}}.ce-popover--inline .ce-popover-item:not(:last-of-type){margin-bottom:0;margin-bottom:initial}.ce-popover--inline .ce-popover-item-html{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.ce-popover--inline .ce-popover-item__icon--chevron-right{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.ce-popover--inline .ce-popover--nested-level-1 .ce-popover__container{--offset: 3px;left:0;top:calc(var(--height) + var(--offset))}@media (max-width: 650px){.ce-popover--inline .ce-popover--nested-level-1 .ce-popover__container{top:calc(var(--height-mobile) + var(--offset))}}.ce-popover--inline .ce-popover--nested .ce-popover__container{min-width:var(--width);width:var(--width);height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;padding:6px;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.ce-popover--inline .ce-popover--nested .ce-popover__items{display:block;width:100%}.ce-popover--inline .ce-popover--nested .ce-popover-item{border-radius:6px;padding:3px}@media (max-width: 650px){.ce-popover--inline .ce-popover--nested .ce-popover-item{padding:4px}}.ce-popover--inline .ce-popover--nested .ce-popover-item__icon--tool{margin-right:4px}.ce-popover--inline .ce-popover--nested .ce-popover-item__icon{width:26px;height:26px}.ce-popover--inline .ce-popover--nested .ce-popover-item-separator{padding:4px 3px}.ce-popover--inline .ce-popover--nested .ce-popover-item-separator__line{width:100%;height:1px}.codex-editor [data-placeholder]:empty:before,.codex-editor [data-placeholder][data-empty=true]:before{pointer-events:none;color:#707684;cursor:text;content:attr(data-placeholder)}.codex-editor [data-placeholder-active]:empty:before,.codex-editor [data-placeholder-active][data-empty=true]:before{pointer-events:none;color:#707684;cursor:text}.codex-editor [data-placeholder-active]:empty:focus:before,.codex-editor [data-placeholder-active][data-empty=true]:focus:before{content:attr(data-placeholder-active)} -`;class wa extends E{constructor(){super(...arguments),this.isMobile=!1,this.contentRectCache=null,this.resizeDebouncer=Bo(()=>{this.windowResize()},200),this.selectionChangeDebounced=Bo(()=>{this.selectionChanged()},na),this.documentTouchedListener=e=>{this.documentTouched(e)}}get CSS(){return{editorWrapper:"codex-editor",editorWrapperNarrow:"codex-editor--narrow",editorZone:"codex-editor__redactor",editorZoneHidden:"codex-editor__redactor--hidden",editorEmpty:"codex-editor--empty",editorRtlFix:"codex-editor--rtl"}}get contentRect(){if(this.contentRectCache!==null)return this.contentRectCache;const e=this.nodes.wrapper.querySelector(`.${R.CSS.content}`);return e?(this.contentRectCache=e.getBoundingClientRect(),this.contentRectCache):{width:650,left:0,right:0}}async prepare(){this.setIsMobile(),this.make(),this.loadStyles()}toggleReadOnly(e){e?this.unbindReadOnlySensitiveListeners():window.requestIdleCallback(()=>{this.bindReadOnlySensitiveListeners()},{timeout:2e3})}checkEmptiness(){const{BlockManager:e}=this.Editor;this.nodes.wrapper.classList.toggle(this.CSS.editorEmpty,e.isEditorEmpty)}get someToolbarOpened(){const{Toolbar:e,BlockSettings:t,InlineToolbar:o}=this.Editor;return!!(t.opened||o.opened||e.toolbox.opened)}get someFlipperButtonFocused(){return this.Editor.Toolbar.toolbox.hasFocus()?!0:Object.entries(this.Editor).filter(([e,t])=>t.flipper instanceof ae).some(([e,t])=>t.flipper.hasFocus())}destroy(){this.nodes.holder.innerHTML="",this.unbindReadOnlyInsensitiveListeners()}closeAllToolbars(){const{Toolbar:e,BlockSettings:t,InlineToolbar:o}=this.Editor;t.close(),o.close(),e.toolbox.close()}setIsMobile(){const e=window.innerWidth{this.redactorClicked(e)},!1),this.readOnlyMutableListeners.on(document,"keydown",e=>{this.documentKeydown(e)},!0),this.readOnlyMutableListeners.on(document,"mousedown",e=>{this.documentClicked(e)},!0),this.watchBlockHoveredEvents(),this.enableInputsEmptyMark()}watchBlockHoveredEvents(){let e;this.readOnlyMutableListeners.on(this.nodes.redactor,"mousemove",ot(t=>{const o=t.target.closest(".ce-block");this.Editor.BlockSelection.anyBlockSelected||o&&e!==o&&(e=o,this.eventsDispatcher.emit(Qo,{block:this.Editor.BlockManager.getBlockByChildNode(o)}))},20),{passive:!0})}unbindReadOnlySensitiveListeners(){this.readOnlyMutableListeners.clearAll()}windowResize(){this.contentRectCache=null,this.setIsMobile()}documentKeydown(e){switch(e.keyCode){case y.ENTER:this.enterPressed(e);break;case y.BACKSPACE:case y.DELETE:this.backspacePressed(e);break;case y.ESC:this.escapePressed(e);break;default:this.defaultBehaviour(e);break}}defaultBehaviour(e){const{currentBlock:t}=this.Editor.BlockManager,o=e.target.closest(`.${this.CSS.editorWrapper}`),i=e.altKey||e.ctrlKey||e.metaKey||e.shiftKey;if(t!==void 0&&o===null){this.Editor.BlockEvents.keydown(e);return}o||t&&i||(this.Editor.BlockManager.unsetCurrentBlock(),this.Editor.Toolbar.close())}backspacePressed(e){const{BlockManager:t,BlockSelection:o,Caret:i}=this.Editor;if(o.anyBlockSelected&&!b.isSelectionExists){const s=t.removeSelectedBlocks(),r=t.insertDefaultBlockAtIndex(s,!0);i.setToBlock(r,i.positions.START),o.clearSelection(e),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation()}}escapePressed(e){this.Editor.BlockSelection.clearSelection(e),this.Editor.Toolbar.toolbox.opened?(this.Editor.Toolbar.toolbox.close(),this.Editor.Caret.setToBlock(this.Editor.BlockManager.currentBlock,this.Editor.Caret.positions.END)):this.Editor.BlockSettings.opened?this.Editor.BlockSettings.close():this.Editor.InlineToolbar.opened?this.Editor.InlineToolbar.close():this.Editor.Toolbar.close()}enterPressed(e){const{BlockManager:t,BlockSelection:o}=this.Editor;if(this.someToolbarOpened)return;const i=t.currentBlockIndex>=0;if(o.anyBlockSelected&&!b.isSelectionExists){o.clearSelection(e),e.preventDefault(),e.stopImmediatePropagation(),e.stopPropagation();return}if(!this.someToolbarOpened&&i&&e.target.tagName==="BODY"){const s=this.Editor.BlockManager.insert();e.preventDefault(),this.Editor.Caret.setToBlock(s),this.Editor.Toolbar.moveAndOpen(s)}this.Editor.BlockSelection.clearSelection(e)}documentClicked(e){var a,l;if(!e.isTrusted)return;const t=e.target;this.nodes.holder.contains(t)||b.isAtEditor||(this.Editor.BlockManager.unsetCurrentBlock(),this.Editor.Toolbar.close());const i=(a=this.Editor.BlockSettings.nodes.wrapper)==null?void 0:a.contains(t),s=(l=this.Editor.Toolbar.nodes.settingsToggler)==null?void 0:l.contains(t),r=i||s;if(this.Editor.BlockSettings.opened&&!r){this.Editor.BlockSettings.close();const c=this.Editor.BlockManager.getBlockByChildNode(t);this.Editor.Toolbar.moveAndOpen(c)}this.Editor.BlockSelection.clearSelection(e)}documentTouched(e){let t=e.target;if(t===this.nodes.redactor){const o=e instanceof MouseEvent?e.clientX:e.touches[0].clientX,i=e instanceof MouseEvent?e.clientY:e.touches[0].clientY;t=document.elementFromPoint(o,i)}try{this.Editor.BlockManager.setCurrentBlockByChildNode(t)}catch{this.Editor.RectangleSelection.isRectActivated()||this.Editor.Caret.setToTheLastBlock()}this.Editor.ReadOnly.isEnabled||this.Editor.Toolbar.moveAndOpen()}redactorClicked(e){if(!b.isCollapsed)return;const t=e.target,o=e.metaKey||e.ctrlKey;if(d.isAnchor(t)&&o){e.stopImmediatePropagation(),e.stopPropagation();const i=t.getAttribute("href"),s=ei(i);oi(s);return}this.processBottomZoneClick(e)}processBottomZoneClick(e){const t=this.Editor.BlockManager.getBlockByIndex(-1),o=d.offset(t.holder).bottom,i=e.pageY,{BlockSelection:s}=this.Editor;if(e.target instanceof Element&&e.target.isEqualNode(this.nodes.redactor)&&!s.anyBlockSelected&&o{t=i,o=s}),Promise.resolve().then(async()=>{this.configuration=e,this.validate(),this.init(),await this.start(),await this.render();const{BlockManager:i,Caret:s,UI:r,ModificationsObserver:a}=this.moduleInstances;r.checkEmptiness(),a.enable(),this.configuration.autofocus===!0&&this.configuration.readOnly!==!0&&s.setToBlock(i.blocks[0],s.positions.START),t()}).catch(i=>{T(`Editor.js is not ready because of ${i}`,"error"),o(i)})}set configuration(e){var o,i;N(e)?this.config={...e}:this.config={holder:e},st(!!this.config.holderId,"config.holderId","config.holder"),this.config.holderId&&!this.config.holder&&(this.config.holder=this.config.holderId,this.config.holderId=null),this.config.holder==null&&(this.config.holder="editorjs"),this.config.logLevel||(this.config.logLevel=ko.VERBOSE),Vn(this.config.logLevel),st(!!this.config.initialBlock,"config.initialBlock","config.defaultBlock"),this.config.defaultBlock=this.config.defaultBlock||this.config.initialBlock||"paragraph",this.config.minHeight=this.config.minHeight!==void 0?this.config.minHeight:300;const t={type:this.config.defaultBlock,data:{}};this.config.placeholder=this.config.placeholder||!1,this.config.sanitizer=this.config.sanitizer||{p:!0,b:!0,a:!0},this.config.hideToolbar=this.config.hideToolbar?this.config.hideToolbar:!1,this.config.tools=this.config.tools||{},this.config.i18n=this.config.i18n||{},this.config.data=this.config.data||{blocks:[]},this.config.onReady=this.config.onReady||(()=>{}),this.config.onChange=this.config.onChange||(()=>{}),this.config.inlineToolbar=this.config.inlineToolbar!==void 0?this.config.inlineToolbar:!0,(V(this.config.data)||!this.config.data.blocks||this.config.data.blocks.length===0)&&(this.config.data={blocks:[t]}),this.config.readOnly=this.config.readOnly||!1,(o=this.config.i18n)!=null&&o.messages&&H.setDictionary(this.config.i18n.messages),this.config.i18n.direction=((i=this.config.i18n)==null?void 0:i.direction)||"ltr"}get configuration(){return this.config}validate(){const{holderId:e,holder:t}=this.config;if(e&&t)throw Error("«holderId» and «holder» param can't assign at the same time.");if(Q(t)&&!d.get(t))throw Error(`element with ID «${t}» is missing. Pass correct holder's ID.`);if(t&&N(t)&&!d.isElement(t))throw Error("«holder» value must be an Element node")}init(){this.constructModules(),this.configureModules()}async start(){await["Tools","UI","BlockManager","Paste","BlockSelection","RectangleSelection","CrossBlockSelection","ReadOnly"].reduce((t,o)=>t.then(async()=>{try{await this.moduleInstances[o].prepare()}catch(i){if(i instanceof Oo)throw new Error(i.message);T(`Module ${o} was skipped because of %o`,"warn",i)}}),Promise.resolve())}render(){return this.moduleInstances.Renderer.render(this.config.data.blocks)}constructModules(){Object.entries(Ea).forEach(([e,t])=>{try{this.moduleInstances[e]=new t({config:this.configuration,eventsDispatcher:this.eventsDispatcher})}catch(o){T("[constructModules]",`Module ${e} skipped because`,"error",o)}})}configureModules(){for(const e in this.moduleInstances)Object.prototype.hasOwnProperty.call(this.moduleInstances,e)&&(this.moduleInstances[e].state=this.getModulesDiff(e))}getModulesDiff(e){const t={};for(const o in this.moduleInstances)o!==e&&(t[o]=this.moduleInstances[o]);return t}}/** - * Editor.js - * - * @license Apache-2.0 - * @see Editor.js - * @author CodeX Team - */class Ba{static get version(){return"2.31.0-rc.9"}constructor(e){let t=()=>{};N(e)&&M(e.onReady)&&(t=e.onReady);const o=new xa(e);this.isReady=o.isReady.then(()=>{this.exportAPI(o),t()})}exportAPI(e){const t=["configuration"],o=()=>{Object.values(e.moduleInstances).forEach(s=>{M(s.destroy)&&s.destroy(),s.listeners.removeAll()}),Ri(),e=null;for(const s in this)Object.prototype.hasOwnProperty.call(this,s)&&delete this[s];Object.setPrototypeOf(this,null)};t.forEach(s=>{this[s]=e[s]}),this.destroy=o,Object.setPrototypeOf(this,e.moduleInstances.API.methods),delete this.exportAPI,Object.entries({blocks:{clear:"clear",render:"render"},caret:{focus:"focus"},events:{on:"on",off:"off",emit:"emit"},saver:{save:"save"}}).forEach(([s,r])=>{Object.entries(r).forEach(([a,l])=>{this[l]=e.moduleInstances.API.methods[s][a]})})}}return Ba}); diff --git a/plugins/tiddlywiki/editorjs/files/header.umd.js b/plugins/tiddlywiki/editorjs/files/header.umd.js deleted file mode 100644 index df5649345..000000000 --- a/plugins/tiddlywiki/editorjs/files/header.umd.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Skipped minification because the original files appears to be already minified. - * Original file: /npm/@editorjs/header@2.8.8/dist/header.umd.js - * - * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files - */ -(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(".ce-header{padding:.6em 0 3px;margin:0;line-height:1.25em;outline:none}.ce-header p,.ce-header div{padding:0!important;margin:0!important}")),document.head.appendChild(e)}}catch(n){console.error("vite-plugin-css-injected-by-js",n)}})(); -(function(n,s){typeof exports=="object"&&typeof module<"u"?module.exports=s():typeof define=="function"&&define.amd?define(s):(n=typeof globalThis<"u"?globalThis:n||self,n.Header=s())})(this,function(){"use strict";const n="",s='',a='',h='',d='',u='',g='',c='';/** - * Header block for the Editor.js. - * - * @author CodeX (team@ifmo.su) - * @copyright CodeX 2018 - * @license MIT - * @version 2.0.0 - */class v{constructor({data:e,config:t,api:i,readOnly:r}){this.api=i,this.readOnly=r,this._settings=t,this._data=this.normalizeData(e),this._element=this.getTag()}get _CSS(){return{block:this.api.styles.block,wrapper:"ce-header"}}isHeaderData(e){return e.text!==void 0}normalizeData(e){const t={text:"",level:this.defaultLevel.number};return this.isHeaderData(e)&&(t.text=e.text||"",e.level!==void 0&&!isNaN(parseInt(e.level.toString()))&&(t.level=parseInt(e.level.toString()))),t}render(){return this._element}renderSettings(){return this.levels.map(e=>({icon:e.svg,label:this.api.i18n.t(`Heading ${e.number}`),onActivate:()=>this.setLevel(e.number),closeOnActivate:!0,isActive:this.currentLevel.number===e.number,render:()=>document.createElement("div")}))}setLevel(e){this.data={level:e,text:this.data.text}}merge(e){this._element.insertAdjacentHTML("beforeend",e.text)}validate(e){return e.text.trim()!==""}save(e){return{text:e.innerHTML,level:this.currentLevel.number}}static get conversionConfig(){return{export:"text",import:"text"}}static get sanitize(){return{level:!1,text:{}}}static get isReadOnlySupported(){return!0}get data(){return this._data.text=this._element.innerHTML,this._data.level=this.currentLevel.number,this._data}set data(e){if(this._data=this.normalizeData(e),e.level!==void 0&&this._element.parentNode){const t=this.getTag();t.innerHTML=this._element.innerHTML,this._element.parentNode.replaceChild(t,this._element),this._element=t}e.text!==void 0&&(this._element.innerHTML=this._data.text||"")}getTag(){const e=document.createElement(this.currentLevel.tag);return e.innerHTML=this._data.text||"",e.classList.add(this._CSS.wrapper),e.contentEditable=this.readOnly?"false":"true",e.dataset.placeholder=this.api.i18n.t(this._settings.placeholder||""),e}get currentLevel(){let e=this.levels.find(t=>t.number===this._data.level);return e||(e=this.defaultLevel),e}get defaultLevel(){if(this._settings.defaultLevel){const e=this.levels.find(t=>t.number===this._settings.defaultLevel);if(e)return e;console.warn("(ง'̀-'́)ง Heading Tool: the default level specified was not found in available levels")}return this.levels[1]}get levels(){const e=[{number:1,tag:"H1",svg:s},{number:2,tag:"H2",svg:a},{number:3,tag:"H3",svg:h},{number:4,tag:"H4",svg:d},{number:5,tag:"H5",svg:u},{number:6,tag:"H6",svg:g}];return this._settings.levels?e.filter(t=>this._settings.levels.includes(t.number)):e}onPaste(e){const t=e.detail;if("data"in t){const i=t.data;let r=this.defaultLevel.number;switch(i.tagName){case"H1":r=1;break;case"H2":r=2;break;case"H3":r=3;break;case"H4":r=4;break;case"H5":r=5;break;case"H6":r=6;break}this._settings.levels&&(r=this._settings.levels.reduce((o,l)=>Math.abs(l-r) - -Downloaded from Github releases: - -* [ext[EditorJs|https://github.com/codex-team/editor.js/releases]]: 2.31.0-rc.9 - -Downloaded from JsDelivr CDN: - -* [ext[Heading|https://github.com/editor-js/header]]: 2.8.8 -* [ext[List|https://github.com/editor-js/list]]: 2.0.6 diff --git a/plugins/tiddlywiki/editorjs/widget.js b/plugins/tiddlywiki/editorjs/widget.js deleted file mode 100644 index caecb4ad4..000000000 --- a/plugins/tiddlywiki/editorjs/widget.js +++ /dev/null @@ -1,90 +0,0 @@ -/*\ -title: $:/plugins/tiddlywiki/editorjs/widget.js -type: application/javascript -module-type: widget - -Text node widget - -\*/ - -"use strict"; - -var Widget = require("$:/core/modules/widgets/widget.js").widget; -var debounce = require("$:/core/modules/utils/debounce.js").debounce; - -var EditorJSWidget = function(parseTreeNode,options) { - this.initialise(parseTreeNode,options); -}; - -/* -Inherit from the base widget class -*/ -EditorJSWidget.prototype = new Widget(); - -/* -Render this widget into the DOM -*/ -EditorJSWidget.prototype.render = function(parent,nextSibling) { - this.parentDomNode = parent; - this.computeAttributes(); - this.execute(); - var container = $tw.utils.domMaker('div', { - class: 'tc-editorjs-container', - }); - var EditorJS = require("$:/plugins/tiddlywiki/editorjs/lib/editorjs.js"); - var List = require("$:/plugins/tiddlywiki/editorjs/lib/editorjs-list.js"); - var Header = require("$:/plugins/tiddlywiki/editorjs/lib/header.js"); - const editor = new EditorJS({ - holder: container, - tools: { - list: List, - header: Header - }, - onChange: this.debouncedSaveEditorContent.bind(this) - }); - this.editor = editor; - - editor.isReady - .then(() => { - console.log('Editor.js is ready to work!', editor.onChange); - }) - .catch((reason) => { - console.log('Editor.js initialization failed because of', reason) - }); - - parent.insertBefore(container,nextSibling); - this.domNodes.push(container); -}; - -EditorJSWidget.prototype.saveEditorContent = function() { - this.editor.save().then((outputData) => { - console.log('Article data: ', outputData) - }).catch((error) => { - console.log('Saving failed: ', error) - }); -} - -// Debounced save function for performance -EditorJSWidget.prototype.debouncedSaveEditorContent = debounce(EditorJSWidget.prototype.saveEditorContent, 300); - -/* -Compute the internal state of the widget -*/ -EditorJSWidget.prototype.execute = function() { - // Nothing to do for a text node -}; - -/* -Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering -*/ -EditorJSWidget.prototype.refresh = function(changedTiddlers) { - var changedAttributes = this.computeAttributes(); - if(changedAttributes.text) { - this.refreshSelf(); - return true; - } else { - return false; - } -}; - -exports.editorjs = EditorJSWidget; diff --git a/plugins/tiddlywiki/editorjs/ast/wikiAstFromEditorJSAst.js b/plugins/tiddlywiki/prosemirror/ast/wikiAstFromEditorJSAst.js similarity index 88% rename from plugins/tiddlywiki/editorjs/ast/wikiAstFromEditorJSAst.js rename to plugins/tiddlywiki/prosemirror/ast/wikiAstFromEditorJSAst.js index eeb26bd7f..00bd23701 100644 --- a/plugins/tiddlywiki/editorjs/ast/wikiAstFromEditorJSAst.js +++ b/plugins/tiddlywiki/prosemirror/ast/wikiAstFromEditorJSAst.js @@ -1,9 +1,9 @@ /*\ -title: $:/plugins/tiddlywiki/editorjs/ast/wikiAstFromEditorJSAst.js +title: $:/plugins/tiddlywiki/prosemirror/ast/wikiAstFromProsemirrorAst.js type: application/javascript module-type: library -Get the EditorJS AST from a Wiki AST +Get the Prosemirror AST from a Wiki AST \*/ @@ -30,11 +30,11 @@ const builders = { set, }; -function wikiAstFromEditorJSAst(input) { +function wikiAstFromProsemirrorAst(input) { return convertNodes(builders, Array.isArray(input) ? input : [input]); } -exports.wikiAstFromEditorJSAst = wikiAstFromEditorJSAst; +exports.wikiAstFromProsemirrorAst = wikiAstFromProsemirrorAst; function convertNodes(builders, nodes) { if (nodes === undefined || nodes.length === 0) { diff --git a/plugins/tiddlywiki/editorjs/ast/wikiAstToEditorJSAst.js b/plugins/tiddlywiki/prosemirror/ast/wikiAstToEditorJSAst.js similarity index 74% rename from plugins/tiddlywiki/editorjs/ast/wikiAstToEditorJSAst.js rename to plugins/tiddlywiki/prosemirror/ast/wikiAstToEditorJSAst.js index 37e953580..3d5b9c0e3 100644 --- a/plugins/tiddlywiki/editorjs/ast/wikiAstToEditorJSAst.js +++ b/plugins/tiddlywiki/prosemirror/ast/wikiAstToEditorJSAst.js @@ -1,16 +1,16 @@ /*\ -title: $:/plugins/tiddlywiki/editorjs/ast/wikiAstToEditorJSAst.js +title: $:/plugins/tiddlywiki/prosemirror/ast/wikiAstToProsemirrorAst.js type: application/javascript module-type: library -Get the EditorJS AST from a Wiki AST +Get the Prosemirror AST from a Wiki AST \*/ -function wikiAstToEditorJSAst(node, options) { +function wikiAstToProsemirrorAst(node, options) { return convertNodes({ ...initialContext, ...options }, Array.isArray(node) ? node : [node]); } -exports.wikiAstToEditorJSAst = wikiAstToEditorJSAst; +exports.wikiAstToProsemirrorAst = wikiAstToProsemirrorAst; const initialContext = { builders, @@ -23,21 +23,21 @@ function convertNodes(context, nodes) { } return nodes.reduce((accumulator, node) => { - return [...accumulator, ...editorJSNode(context, node)]; + return [...accumulator, ...prosemirrorNode(context, node)]; }, []); } -function editorJSNode(context, node) { +function prosemirrorNode(context, node) { const id = context.idCreator?.(); const withId = (nodeToAddId) => (id === undefined ? nodeToAddId : { ...nodeToAddId, id }); if ('rule' in node && node.rule !== undefined && node.rule in context.builders) { const builder = context.builders[node.rule]; if (typeof builder === 'function') { // basic elements - const builtEditorJSNodeOrNodes = builder(context, node); - return Array.isArray(builtEditorJSNodeOrNodes) - ? builtEditorJSNodeOrNodes.map((child) => withId(child)) - : ([withId(builtEditorJSNodeOrNodes)]); + const builtProsemirrorNodeOrNodes = builder(context, node); + return Array.isArray(builtProsemirrorNodeOrNodes) + ? builtProsemirrorNodeOrNodes.map((child) => withId(child)) + : ([withId(builtProsemirrorNodeOrNodes)]); } } else if ('text' in node) { // text node diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-example-setup.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-example-setup.cjs new file mode 100644 index 000000000..2bab07c32 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-example-setup.cjs @@ -0,0 +1,469 @@ +'use strict'; + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } +function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } +function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var prosemirrorKeymap = require('prosemirror-keymap'); +var prosemirrorHistory = require('prosemirror-history'); +var prosemirrorCommands = require('prosemirror-commands'); +var prosemirrorState = require('prosemirror-state'); +var prosemirrorDropcursor = require('prosemirror-dropcursor'); +var prosemirrorGapcursor = require('prosemirror-gapcursor'); +var prosemirrorMenu = require('prosemirror-menu'); +var prosemirrorSchemaList = require('prosemirror-schema-list'); +var prosemirrorInputrules = require('prosemirror-inputrules'); +var prefix = "ProseMirror-prompt"; +function openPrompt(options) { + var wrapper = document.body.appendChild(document.createElement("div")); + wrapper.className = prefix; + var mouseOutside = function mouseOutside(e) { + if (!wrapper.contains(e.target)) close(); + }; + setTimeout(function () { + return window.addEventListener("mousedown", mouseOutside); + }, 50); + var close = function close() { + window.removeEventListener("mousedown", mouseOutside); + if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper); + }; + var domFields = []; + for (var name in options.fields) domFields.push(options.fields[name].render()); + var submitButton = document.createElement("button"); + submitButton.type = "submit"; + submitButton.className = prefix + "-submit"; + submitButton.textContent = "OK"; + var cancelButton = document.createElement("button"); + cancelButton.type = "button"; + cancelButton.className = prefix + "-cancel"; + cancelButton.textContent = "Cancel"; + cancelButton.addEventListener("click", close); + var form = wrapper.appendChild(document.createElement("form")); + if (options.title) form.appendChild(document.createElement("h5")).textContent = options.title; + domFields.forEach(function (field) { + form.appendChild(document.createElement("div")).appendChild(field); + }); + var buttons = form.appendChild(document.createElement("div")); + buttons.className = prefix + "-buttons"; + buttons.appendChild(submitButton); + buttons.appendChild(document.createTextNode(" ")); + buttons.appendChild(cancelButton); + var box = wrapper.getBoundingClientRect(); + wrapper.style.top = (window.innerHeight - box.height) / 2 + "px"; + wrapper.style.left = (window.innerWidth - box.width) / 2 + "px"; + var submit = function submit() { + var params = getValues(options.fields, domFields); + if (params) { + close(); + options.callback(params); + } + }; + form.addEventListener("submit", function (e) { + e.preventDefault(); + submit(); + }); + form.addEventListener("keydown", function (e) { + if (e.keyCode == 27) { + e.preventDefault(); + close(); + } else if (e.keyCode == 13 && !(e.ctrlKey || e.metaKey || e.shiftKey)) { + e.preventDefault(); + submit(); + } else if (e.keyCode == 9) { + window.setTimeout(function () { + if (!wrapper.contains(document.activeElement)) close(); + }, 500); + } + }); + var input = form.elements[0]; + if (input) input.focus(); +} +function getValues(fields, domFields) { + var result = Object.create(null), + i = 0; + for (var name in fields) { + var field = fields[name], + dom = domFields[i++]; + var value = field.read(dom), + bad = field.validate(value); + if (bad) { + reportInvalid(dom, bad); + return null; + } + result[name] = field.clean(value); + } + return result; +} +function reportInvalid(dom, message) { + var parent = dom.parentNode; + var msg = parent.appendChild(document.createElement("div")); + msg.style.left = dom.offsetLeft + dom.offsetWidth + 2 + "px"; + msg.style.top = dom.offsetTop - 5 + "px"; + msg.className = "ProseMirror-invalid"; + msg.textContent = message; + setTimeout(function () { + return parent.removeChild(msg); + }, 1500); +} +var Field = function () { + function Field(options) { + _classCallCheck(this, Field); + this.options = options; + } + _createClass(Field, [{ + key: "read", + value: function read(dom) { + return dom.value; + } + }, { + key: "validateType", + value: function validateType(value) { + return null; + } + }, { + key: "validate", + value: function validate(value) { + if (!value && this.options.required) return "Required field"; + return this.validateType(value) || (this.options.validate ? this.options.validate(value) : null); + } + }, { + key: "clean", + value: function clean(value) { + return this.options.clean ? this.options.clean(value) : value; + } + }]); + return Field; +}(); +var TextField = function (_Field) { + _inherits(TextField, _Field); + var _super = _createSuper(TextField); + function TextField() { + _classCallCheck(this, TextField); + return _super.apply(this, arguments); + } + _createClass(TextField, [{ + key: "render", + value: function render() { + var input = document.createElement("input"); + input.type = "text"; + input.placeholder = this.options.label; + input.value = this.options.value || ""; + input.autocomplete = "off"; + return input; + } + }]); + return TextField; +}(Field); +function canInsert(state, nodeType) { + var $from = state.selection.$from; + for (var d = $from.depth; d >= 0; d--) { + var index = $from.index(d); + if ($from.node(d).canReplaceWith(index, index, nodeType)) return true; + } + return false; +} +function insertImageItem(nodeType) { + return new prosemirrorMenu.MenuItem({ + title: "Insert image", + label: "Image", + enable: function enable(state) { + return canInsert(state, nodeType); + }, + run: function run(state, _, view) { + var _state$selection = state.selection, + from = _state$selection.from, + to = _state$selection.to, + attrs = null; + if (state.selection instanceof prosemirrorState.NodeSelection && state.selection.node.type == nodeType) attrs = state.selection.node.attrs; + openPrompt({ + title: "Insert image", + fields: { + src: new TextField({ + label: "Location", + required: true, + value: attrs && attrs.src + }), + title: new TextField({ + label: "Title", + value: attrs && attrs.title + }), + alt: new TextField({ + label: "Description", + value: attrs ? attrs.alt : state.doc.textBetween(from, to, " ") + }) + }, + callback: function callback(attrs) { + view.dispatch(view.state.tr.replaceSelectionWith(nodeType.createAndFill(attrs))); + view.focus(); + } + }); + } + }); +} +function cmdItem(cmd, options) { + var passedOptions = { + label: options.title, + run: cmd + }; + for (var prop in options) passedOptions[prop] = options[prop]; + if (!options.enable && !options.select) passedOptions[options.enable ? "enable" : "select"] = function (state) { + return cmd(state); + }; + return new prosemirrorMenu.MenuItem(passedOptions); +} +function markActive(state, type) { + var _state$selection2 = state.selection, + from = _state$selection2.from, + $from = _state$selection2.$from, + to = _state$selection2.to, + empty = _state$selection2.empty; + if (empty) return !!type.isInSet(state.storedMarks || $from.marks());else return state.doc.rangeHasMark(from, to, type); +} +function markItem(markType, options) { + var passedOptions = { + active: function active(state) { + return markActive(state, markType); + } + }; + for (var prop in options) passedOptions[prop] = options[prop]; + return cmdItem(prosemirrorCommands.toggleMark(markType), passedOptions); +} +function linkItem(markType) { + return new prosemirrorMenu.MenuItem({ + title: "Add or remove link", + icon: prosemirrorMenu.icons.link, + active: function active(state) { + return markActive(state, markType); + }, + enable: function enable(state) { + return !state.selection.empty; + }, + run: function run(state, dispatch, view) { + if (markActive(state, markType)) { + prosemirrorCommands.toggleMark(markType)(state, dispatch); + return true; + } + openPrompt({ + title: "Create a link", + fields: { + href: new TextField({ + label: "Link target", + required: true + }), + title: new TextField({ + label: "Title" + }) + }, + callback: function callback(attrs) { + prosemirrorCommands.toggleMark(markType, attrs)(view.state, view.dispatch); + view.focus(); + } + }); + } + }); +} +function wrapListItem(nodeType, options) { + return cmdItem(prosemirrorSchemaList.wrapInList(nodeType, options.attrs), options); +} +function buildMenuItems(schema) { + var r = {}; + var mark; + if (mark = schema.marks.strong) r.toggleStrong = markItem(mark, { + title: "Toggle strong style", + icon: prosemirrorMenu.icons.strong + }); + if (mark = schema.marks.em) r.toggleEm = markItem(mark, { + title: "Toggle emphasis", + icon: prosemirrorMenu.icons.em + }); + if (mark = schema.marks.code) r.toggleCode = markItem(mark, { + title: "Toggle code font", + icon: prosemirrorMenu.icons.code + }); + if (mark = schema.marks.link) r.toggleLink = linkItem(mark); + var node; + if (node = schema.nodes.image) r.insertImage = insertImageItem(node); + if (node = schema.nodes.bullet_list) r.wrapBulletList = wrapListItem(node, { + title: "Wrap in bullet list", + icon: prosemirrorMenu.icons.bulletList + }); + if (node = schema.nodes.ordered_list) r.wrapOrderedList = wrapListItem(node, { + title: "Wrap in ordered list", + icon: prosemirrorMenu.icons.orderedList + }); + if (node = schema.nodes.blockquote) r.wrapBlockQuote = prosemirrorMenu.wrapItem(node, { + title: "Wrap in block quote", + icon: prosemirrorMenu.icons.blockquote + }); + if (node = schema.nodes.paragraph) r.makeParagraph = prosemirrorMenu.blockTypeItem(node, { + title: "Change to paragraph", + label: "Plain" + }); + if (node = schema.nodes.code_block) r.makeCodeBlock = prosemirrorMenu.blockTypeItem(node, { + title: "Change to code block", + label: "Code" + }); + if (node = schema.nodes.heading) for (var i = 1; i <= 10; i++) r["makeHead" + i] = prosemirrorMenu.blockTypeItem(node, { + title: "Change to heading " + i, + label: "Level " + i, + attrs: { + level: i + } + }); + if (node = schema.nodes.horizontal_rule) { + var hr = node; + r.insertHorizontalRule = new prosemirrorMenu.MenuItem({ + title: "Insert horizontal rule", + label: "Horizontal rule", + enable: function enable(state) { + return canInsert(state, hr); + }, + run: function run(state, dispatch) { + dispatch(state.tr.replaceSelectionWith(hr.create())); + } + }); + } + var cut = function cut(arr) { + return arr.filter(function (x) { + return x; + }); + }; + r.insertMenu = new prosemirrorMenu.Dropdown(cut([r.insertImage, r.insertHorizontalRule]), { + label: "Insert" + }); + r.typeMenu = new prosemirrorMenu.Dropdown(cut([r.makeParagraph, r.makeCodeBlock, r.makeHead1 && new prosemirrorMenu.DropdownSubmenu(cut([r.makeHead1, r.makeHead2, r.makeHead3, r.makeHead4, r.makeHead5, r.makeHead6]), { + label: "Heading" + })]), { + label: "Type..." + }); + r.inlineMenu = [cut([r.toggleStrong, r.toggleEm, r.toggleCode, r.toggleLink])]; + r.blockMenu = [cut([r.wrapBulletList, r.wrapOrderedList, r.wrapBlockQuote, prosemirrorMenu.joinUpItem, prosemirrorMenu.liftItem, prosemirrorMenu.selectParentNodeItem])]; + r.fullMenu = r.inlineMenu.concat([[r.insertMenu, r.typeMenu]], [[prosemirrorMenu.undoItem, prosemirrorMenu.redoItem]], r.blockMenu); + return r; +} +var mac = typeof navigator != "undefined" ? /Mac|iP(hone|[oa]d)/.test(navigator.platform) : false; +function buildKeymap(schema, mapKeys) { + var keys = {}, + type; + function bind(key, cmd) { + if (mapKeys) { + var mapped = mapKeys[key]; + if (mapped === false) return; + if (mapped) key = mapped; + } + keys[key] = cmd; + } + bind("Mod-z", prosemirrorHistory.undo); + bind("Shift-Mod-z", prosemirrorHistory.redo); + bind("Backspace", prosemirrorInputrules.undoInputRule); + if (!mac) bind("Mod-y", prosemirrorHistory.redo); + bind("Alt-ArrowUp", prosemirrorCommands.joinUp); + bind("Alt-ArrowDown", prosemirrorCommands.joinDown); + bind("Mod-BracketLeft", prosemirrorCommands.lift); + bind("Escape", prosemirrorCommands.selectParentNode); + if (type = schema.marks.strong) { + bind("Mod-b", prosemirrorCommands.toggleMark(type)); + bind("Mod-B", prosemirrorCommands.toggleMark(type)); + } + if (type = schema.marks.em) { + bind("Mod-i", prosemirrorCommands.toggleMark(type)); + bind("Mod-I", prosemirrorCommands.toggleMark(type)); + } + if (type = schema.marks.code) bind("Mod-`", prosemirrorCommands.toggleMark(type)); + if (type = schema.nodes.bullet_list) bind("Shift-Ctrl-8", prosemirrorSchemaList.wrapInList(type)); + if (type = schema.nodes.ordered_list) bind("Shift-Ctrl-9", prosemirrorSchemaList.wrapInList(type)); + if (type = schema.nodes.blockquote) bind("Ctrl->", prosemirrorCommands.wrapIn(type)); + if (type = schema.nodes.hard_break) { + var br = type, + cmd = prosemirrorCommands.chainCommands(prosemirrorCommands.exitCode, function (state, dispatch) { + if (dispatch) dispatch(state.tr.replaceSelectionWith(br.create()).scrollIntoView()); + return true; + }); + bind("Mod-Enter", cmd); + bind("Shift-Enter", cmd); + if (mac) bind("Ctrl-Enter", cmd); + } + if (type = schema.nodes.list_item) { + bind("Enter", prosemirrorSchemaList.splitListItem(type)); + bind("Mod-[", prosemirrorSchemaList.liftListItem(type)); + bind("Mod-]", prosemirrorSchemaList.sinkListItem(type)); + } + if (type = schema.nodes.paragraph) bind("Shift-Ctrl-0", prosemirrorCommands.setBlockType(type)); + if (type = schema.nodes.code_block) bind("Shift-Ctrl-\\", prosemirrorCommands.setBlockType(type)); + if (type = schema.nodes.heading) for (var i = 1; i <= 6; i++) bind("Shift-Ctrl-" + i, prosemirrorCommands.setBlockType(type, { + level: i + })); + if (type = schema.nodes.horizontal_rule) { + var hr = type; + bind("Mod-_", function (state, dispatch) { + if (dispatch) dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView()); + return true; + }); + } + return keys; +} +function blockQuoteRule(nodeType) { + return prosemirrorInputrules.wrappingInputRule(/^\s*>\s$/, nodeType); +} +function orderedListRule(nodeType) { + return prosemirrorInputrules.wrappingInputRule(/^(\d+)\.\s$/, nodeType, function (match) { + return { + order: +match[1] + }; + }, function (match, node) { + return node.childCount + node.attrs.order == +match[1]; + }); +} +function bulletListRule(nodeType) { + return prosemirrorInputrules.wrappingInputRule(/^\s*([-+*])\s$/, nodeType); +} +function codeBlockRule(nodeType) { + return prosemirrorInputrules.textblockTypeInputRule(/^```$/, nodeType); +} +function headingRule(nodeType, maxLevel) { + return prosemirrorInputrules.textblockTypeInputRule(new RegExp("^(#{1," + maxLevel + "})\\s$"), nodeType, function (match) { + return { + level: match[1].length + }; + }); +} +function buildInputRules(schema) { + var rules = prosemirrorInputrules.smartQuotes.concat(prosemirrorInputrules.ellipsis, prosemirrorInputrules.emDash), + type; + if (type = schema.nodes.blockquote) rules.push(blockQuoteRule(type)); + if (type = schema.nodes.ordered_list) rules.push(orderedListRule(type)); + if (type = schema.nodes.bullet_list) rules.push(bulletListRule(type)); + if (type = schema.nodes.code_block) rules.push(codeBlockRule(type)); + if (type = schema.nodes.heading) rules.push(headingRule(type, 6)); + return prosemirrorInputrules.inputRules({ + rules: rules + }); +} +function exampleSetup(options) { + var plugins = [buildInputRules(options.schema), prosemirrorKeymap.keymap(buildKeymap(options.schema, options.mapKeys)), prosemirrorKeymap.keymap(prosemirrorCommands.baseKeymap), prosemirrorDropcursor.dropCursor(), prosemirrorGapcursor.gapCursor()]; + if (options.menuBar !== false) plugins.push(prosemirrorMenu.menuBar({ + floating: options.floatingMenu !== false, + content: options.menuContent || buildMenuItems(options.schema).fullMenu + })); + if (options.history !== false) plugins.push(prosemirrorHistory.history()); + return plugins.concat(new prosemirrorState.Plugin({ + props: { + attributes: { + "class": "ProseMirror-example-setup-style" + } + } + })); +} +exports.buildInputRules = buildInputRules; +exports.buildKeymap = buildKeymap; +exports.buildMenuItems = buildMenuItems; +exports.exampleSetup = exampleSetup; diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-model.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-model.cjs new file mode 100644 index 000000000..ab159513a --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-model.cjs @@ -0,0 +1,2893 @@ +'use strict'; + +function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } +function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } +function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } +function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get.bind(); } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); } +function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } +function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } +function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); } +function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct.bind(); } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } +function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } +function _isNativeFunction(fn) { try { return Function.toString.call(fn).indexOf("[native code]") !== -1; } catch (e) { return typeof fn === "function"; } } +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var OrderedMap = require('orderedmap'); +function _findDiffStart(a, b, pos) { + for (var i = 0;; i++) { + if (i == a.childCount || i == b.childCount) return a.childCount == b.childCount ? null : pos; + var childA = a.child(i), + childB = b.child(i); + if (childA == childB) { + pos += childA.nodeSize; + continue; + } + if (!childA.sameMarkup(childB)) return pos; + if (childA.isText && childA.text != childB.text) { + for (var j = 0; childA.text[j] == childB.text[j]; j++) pos++; + return pos; + } + if (childA.content.size || childB.content.size) { + var inner = _findDiffStart(childA.content, childB.content, pos + 1); + if (inner != null) return inner; + } + pos += childA.nodeSize; + } +} +function _findDiffEnd(a, b, posA, posB) { + for (var iA = a.childCount, iB = b.childCount;;) { + if (iA == 0 || iB == 0) return iA == iB ? null : { + a: posA, + b: posB + }; + var childA = a.child(--iA), + childB = b.child(--iB), + size = childA.nodeSize; + if (childA == childB) { + posA -= size; + posB -= size; + continue; + } + if (!childA.sameMarkup(childB)) return { + a: posA, + b: posB + }; + if (childA.isText && childA.text != childB.text) { + var same = 0, + minSize = Math.min(childA.text.length, childB.text.length); + while (same < minSize && childA.text[childA.text.length - same - 1] == childB.text[childB.text.length - same - 1]) { + same++; + posA--; + posB--; + } + return { + a: posA, + b: posB + }; + } + if (childA.content.size || childB.content.size) { + var inner = _findDiffEnd(childA.content, childB.content, posA - 1, posB - 1); + if (inner) return inner; + } + posA -= size; + posB -= size; + } +} +var Fragment = function () { + function Fragment(content, size) { + _classCallCheck(this, Fragment); + this.content = content; + this.size = size || 0; + if (size == null) for (var i = 0; i < content.length; i++) this.size += content[i].nodeSize; + } + _createClass(Fragment, [{ + key: "nodesBetween", + value: function nodesBetween(from, to, f) { + var nodeStart = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; + var parent = arguments.length > 4 ? arguments[4] : undefined; + for (var i = 0, pos = 0; pos < to; i++) { + var child = this.content[i], + end = pos + child.nodeSize; + if (end > from && f(child, nodeStart + pos, parent || null, i) !== false && child.content.size) { + var start = pos + 1; + child.nodesBetween(Math.max(0, from - start), Math.min(child.content.size, to - start), f, nodeStart + start); + } + pos = end; + } + } + }, { + key: "descendants", + value: function descendants(f) { + this.nodesBetween(0, this.size, f); + } + }, { + key: "textBetween", + value: function textBetween(from, to, blockSeparator, leafText) { + var text = "", + first = true; + this.nodesBetween(from, to, function (node, pos) { + var nodeText = node.isText ? node.text.slice(Math.max(from, pos) - pos, to - pos) : !node.isLeaf ? "" : leafText ? typeof leafText === "function" ? leafText(node) : leafText : node.type.spec.leafText ? node.type.spec.leafText(node) : ""; + if (node.isBlock && (node.isLeaf && nodeText || node.isTextblock) && blockSeparator) { + if (first) first = false;else text += blockSeparator; + } + text += nodeText; + }, 0); + return text; + } + }, { + key: "append", + value: function append(other) { + if (!other.size) return this; + if (!this.size) return other; + var last = this.lastChild, + first = other.firstChild, + content = this.content.slice(), + i = 0; + if (last.isText && last.sameMarkup(first)) { + content[content.length - 1] = last.withText(last.text + first.text); + i = 1; + } + for (; i < other.content.length; i++) content.push(other.content[i]); + return new Fragment(content, this.size + other.size); + } + }, { + key: "cut", + value: function cut(from) { + var to = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.size; + if (from == 0 && to == this.size) return this; + var result = [], + size = 0; + if (to > from) for (var i = 0, pos = 0; pos < to; i++) { + var child = this.content[i], + end = pos + child.nodeSize; + if (end > from) { + if (pos < from || end > to) { + if (child.isText) child = child.cut(Math.max(0, from - pos), Math.min(child.text.length, to - pos));else child = child.cut(Math.max(0, from - pos - 1), Math.min(child.content.size, to - pos - 1)); + } + result.push(child); + size += child.nodeSize; + } + pos = end; + } + return new Fragment(result, size); + } + }, { + key: "cutByIndex", + value: function cutByIndex(from, to) { + if (from == to) return Fragment.empty; + if (from == 0 && to == this.content.length) return this; + return new Fragment(this.content.slice(from, to)); + } + }, { + key: "replaceChild", + value: function replaceChild(index, node) { + var current = this.content[index]; + if (current == node) return this; + var copy = this.content.slice(); + var size = this.size + node.nodeSize - current.nodeSize; + copy[index] = node; + return new Fragment(copy, size); + } + }, { + key: "addToStart", + value: function addToStart(node) { + return new Fragment([node].concat(this.content), this.size + node.nodeSize); + } + }, { + key: "addToEnd", + value: function addToEnd(node) { + return new Fragment(this.content.concat(node), this.size + node.nodeSize); + } + }, { + key: "eq", + value: function eq(other) { + if (this.content.length != other.content.length) return false; + for (var i = 0; i < this.content.length; i++) if (!this.content[i].eq(other.content[i])) return false; + return true; + } + }, { + key: "firstChild", + get: function get() { + return this.content.length ? this.content[0] : null; + } + }, { + key: "lastChild", + get: function get() { + return this.content.length ? this.content[this.content.length - 1] : null; + } + }, { + key: "childCount", + get: function get() { + return this.content.length; + } + }, { + key: "child", + value: function child(index) { + var found = this.content[index]; + if (!found) throw new RangeError("Index " + index + " out of range for " + this); + return found; + } + }, { + key: "maybeChild", + value: function maybeChild(index) { + return this.content[index] || null; + } + }, { + key: "forEach", + value: function forEach(f) { + for (var i = 0, p = 0; i < this.content.length; i++) { + var child = this.content[i]; + f(child, p, i); + p += child.nodeSize; + } + } + }, { + key: "findDiffStart", + value: function findDiffStart(other) { + var pos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + return _findDiffStart(this, other, pos); + } + }, { + key: "findDiffEnd", + value: function findDiffEnd(other) { + var pos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.size; + var otherPos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : other.size; + return _findDiffEnd(this, other, pos, otherPos); + } + }, { + key: "findIndex", + value: function findIndex(pos) { + var round = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; + if (pos == 0) return retIndex(0, pos); + if (pos == this.size) return retIndex(this.content.length, pos); + if (pos > this.size || pos < 0) throw new RangeError("Position ".concat(pos, " outside of fragment (").concat(this, ")")); + for (var i = 0, curPos = 0;; i++) { + var cur = this.child(i), + end = curPos + cur.nodeSize; + if (end >= pos) { + if (end == pos || round > 0) return retIndex(i + 1, end); + return retIndex(i, curPos); + } + curPos = end; + } + } + }, { + key: "toString", + value: function toString() { + return "<" + this.toStringInner() + ">"; + } + }, { + key: "toStringInner", + value: function toStringInner() { + return this.content.join(", "); + } + }, { + key: "toJSON", + value: function toJSON() { + return this.content.length ? this.content.map(function (n) { + return n.toJSON(); + }) : null; + } + }], [{ + key: "fromJSON", + value: function fromJSON(schema, value) { + if (!value) return Fragment.empty; + if (!Array.isArray(value)) throw new RangeError("Invalid input for Fragment.fromJSON"); + return new Fragment(value.map(schema.nodeFromJSON)); + } + }, { + key: "fromArray", + value: function fromArray(array) { + if (!array.length) return Fragment.empty; + var joined, + size = 0; + for (var i = 0; i < array.length; i++) { + var node = array[i]; + size += node.nodeSize; + if (i && node.isText && array[i - 1].sameMarkup(node)) { + if (!joined) joined = array.slice(0, i); + joined[joined.length - 1] = node.withText(joined[joined.length - 1].text + node.text); + } else if (joined) { + joined.push(node); + } + } + return new Fragment(joined || array, size); + } + }, { + key: "from", + value: function from(nodes) { + if (!nodes) return Fragment.empty; + if (nodes instanceof Fragment) return nodes; + if (Array.isArray(nodes)) return this.fromArray(nodes); + if (nodes.attrs) return new Fragment([nodes], nodes.nodeSize); + throw new RangeError("Can not convert " + nodes + " to a Fragment" + (nodes.nodesBetween ? " (looks like multiple versions of prosemirror-model were loaded)" : "")); + } + }]); + return Fragment; +}(); +Fragment.empty = new Fragment([], 0); +var found = { + index: 0, + offset: 0 +}; +function retIndex(index, offset) { + found.index = index; + found.offset = offset; + return found; +} +function compareDeep(a, b) { + if (a === b) return true; + if (!(a && _typeof(a) == "object") || !(b && _typeof(b) == "object")) return false; + var array = Array.isArray(a); + if (Array.isArray(b) != array) return false; + if (array) { + if (a.length != b.length) return false; + for (var i = 0; i < a.length; i++) if (!compareDeep(a[i], b[i])) return false; + } else { + for (var p in a) if (!(p in b) || !compareDeep(a[p], b[p])) return false; + for (var _p in b) if (!(_p in a)) return false; + } + return true; +} +var Mark = function () { + function Mark(type, attrs) { + _classCallCheck(this, Mark); + this.type = type; + this.attrs = attrs; + } + _createClass(Mark, [{ + key: "addToSet", + value: function addToSet(set) { + var copy, + placed = false; + for (var i = 0; i < set.length; i++) { + var other = set[i]; + if (this.eq(other)) return set; + if (this.type.excludes(other.type)) { + if (!copy) copy = set.slice(0, i); + } else if (other.type.excludes(this.type)) { + return set; + } else { + if (!placed && other.type.rank > this.type.rank) { + if (!copy) copy = set.slice(0, i); + copy.push(this); + placed = true; + } + if (copy) copy.push(other); + } + } + if (!copy) copy = set.slice(); + if (!placed) copy.push(this); + return copy; + } + }, { + key: "removeFromSet", + value: function removeFromSet(set) { + for (var i = 0; i < set.length; i++) if (this.eq(set[i])) return set.slice(0, i).concat(set.slice(i + 1)); + return set; + } + }, { + key: "isInSet", + value: function isInSet(set) { + for (var i = 0; i < set.length; i++) if (this.eq(set[i])) return true; + return false; + } + }, { + key: "eq", + value: function eq(other) { + return this == other || this.type == other.type && compareDeep(this.attrs, other.attrs); + } + }, { + key: "toJSON", + value: function toJSON() { + var obj = { + type: this.type.name + }; + for (var _ in this.attrs) { + obj.attrs = this.attrs; + break; + } + return obj; + } + }], [{ + key: "fromJSON", + value: function fromJSON(schema, json) { + if (!json) throw new RangeError("Invalid input for Mark.fromJSON"); + var type = schema.marks[json.type]; + if (!type) throw new RangeError("There is no mark type ".concat(json.type, " in this schema")); + var mark = type.create(json.attrs); + type.checkAttrs(mark.attrs); + return mark; + } + }, { + key: "sameSet", + value: function sameSet(a, b) { + if (a == b) return true; + if (a.length != b.length) return false; + for (var i = 0; i < a.length; i++) if (!a[i].eq(b[i])) return false; + return true; + } + }, { + key: "setFrom", + value: function setFrom(marks) { + if (!marks || Array.isArray(marks) && marks.length == 0) return Mark.none; + if (marks instanceof Mark) return [marks]; + var copy = marks.slice(); + copy.sort(function (a, b) { + return a.type.rank - b.type.rank; + }); + return copy; + } + }]); + return Mark; +}(); +Mark.none = []; +var ReplaceError = function (_Error) { + _inherits(ReplaceError, _Error); + var _super = _createSuper(ReplaceError); + function ReplaceError() { + _classCallCheck(this, ReplaceError); + return _super.apply(this, arguments); + } + return _createClass(ReplaceError); +}(_wrapNativeSuper(Error)); +var Slice = function () { + function Slice(content, openStart, openEnd) { + _classCallCheck(this, Slice); + this.content = content; + this.openStart = openStart; + this.openEnd = openEnd; + } + _createClass(Slice, [{ + key: "size", + get: function get() { + return this.content.size - this.openStart - this.openEnd; + } + }, { + key: "insertAt", + value: function insertAt(pos, fragment) { + var content = insertInto(this.content, pos + this.openStart, fragment); + return content && new Slice(content, this.openStart, this.openEnd); + } + }, { + key: "removeBetween", + value: function removeBetween(from, to) { + return new Slice(removeRange(this.content, from + this.openStart, to + this.openStart), this.openStart, this.openEnd); + } + }, { + key: "eq", + value: function eq(other) { + return this.content.eq(other.content) && this.openStart == other.openStart && this.openEnd == other.openEnd; + } + }, { + key: "toString", + value: function toString() { + return this.content + "(" + this.openStart + "," + this.openEnd + ")"; + } + }, { + key: "toJSON", + value: function toJSON() { + if (!this.content.size) return null; + var json = { + content: this.content.toJSON() + }; + if (this.openStart > 0) json.openStart = this.openStart; + if (this.openEnd > 0) json.openEnd = this.openEnd; + return json; + } + }], [{ + key: "fromJSON", + value: function fromJSON(schema, json) { + if (!json) return Slice.empty; + var openStart = json.openStart || 0, + openEnd = json.openEnd || 0; + if (typeof openStart != "number" || typeof openEnd != "number") throw new RangeError("Invalid input for Slice.fromJSON"); + return new Slice(Fragment.fromJSON(schema, json.content), openStart, openEnd); + } + }, { + key: "maxOpen", + value: function maxOpen(fragment) { + var openIsolating = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var openStart = 0, + openEnd = 0; + for (var n = fragment.firstChild; n && !n.isLeaf && (openIsolating || !n.type.spec.isolating); n = n.firstChild) openStart++; + for (var _n = fragment.lastChild; _n && !_n.isLeaf && (openIsolating || !_n.type.spec.isolating); _n = _n.lastChild) openEnd++; + return new Slice(fragment, openStart, openEnd); + } + }]); + return Slice; +}(); +Slice.empty = new Slice(Fragment.empty, 0, 0); +function removeRange(content, from, to) { + var _content$findIndex = content.findIndex(from), + index = _content$findIndex.index, + offset = _content$findIndex.offset, + child = content.maybeChild(index); + var _content$findIndex2 = content.findIndex(to), + indexTo = _content$findIndex2.index, + offsetTo = _content$findIndex2.offset; + if (offset == from || child.isText) { + if (offsetTo != to && !content.child(indexTo).isText) throw new RangeError("Removing non-flat range"); + return content.cut(0, from).append(content.cut(to)); + } + if (index != indexTo) throw new RangeError("Removing non-flat range"); + return content.replaceChild(index, child.copy(removeRange(child.content, from - offset - 1, to - offset - 1))); +} +function insertInto(content, dist, insert, parent) { + var _content$findIndex3 = content.findIndex(dist), + index = _content$findIndex3.index, + offset = _content$findIndex3.offset, + child = content.maybeChild(index); + if (offset == dist || child.isText) { + if (parent && !parent.canReplace(index, index, insert)) return null; + return content.cut(0, dist).append(insert).append(content.cut(dist)); + } + var inner = insertInto(child.content, dist - offset - 1, insert); + return inner && content.replaceChild(index, child.copy(inner)); +} +function _replace($from, $to, slice) { + if (slice.openStart > $from.depth) throw new ReplaceError("Inserted content deeper than insertion position"); + if ($from.depth - slice.openStart != $to.depth - slice.openEnd) throw new ReplaceError("Inconsistent open depths"); + return replaceOuter($from, $to, slice, 0); +} +function replaceOuter($from, $to, slice, depth) { + var index = $from.index(depth), + node = $from.node(depth); + if (index == $to.index(depth) && depth < $from.depth - slice.openStart) { + var inner = replaceOuter($from, $to, slice, depth + 1); + return node.copy(node.content.replaceChild(index, inner)); + } else if (!slice.content.size) { + return close(node, replaceTwoWay($from, $to, depth)); + } else if (!slice.openStart && !slice.openEnd && $from.depth == depth && $to.depth == depth) { + var parent = $from.parent, + content = parent.content; + return close(parent, content.cut(0, $from.parentOffset).append(slice.content).append(content.cut($to.parentOffset))); + } else { + var _prepareSliceForRepla = prepareSliceForReplace(slice, $from), + start = _prepareSliceForRepla.start, + end = _prepareSliceForRepla.end; + return close(node, replaceThreeWay($from, start, end, $to, depth)); + } +} +function checkJoin(main, sub) { + if (!sub.type.compatibleContent(main.type)) throw new ReplaceError("Cannot join " + sub.type.name + " onto " + main.type.name); +} +function joinable($before, $after, depth) { + var node = $before.node(depth); + checkJoin(node, $after.node(depth)); + return node; +} +function addNode(child, target) { + var last = target.length - 1; + if (last >= 0 && child.isText && child.sameMarkup(target[last])) target[last] = child.withText(target[last].text + child.text);else target.push(child); +} +function addRange($start, $end, depth, target) { + var node = ($end || $start).node(depth); + var startIndex = 0, + endIndex = $end ? $end.index(depth) : node.childCount; + if ($start) { + startIndex = $start.index(depth); + if ($start.depth > depth) { + startIndex++; + } else if ($start.textOffset) { + addNode($start.nodeAfter, target); + startIndex++; + } + } + for (var i = startIndex; i < endIndex; i++) addNode(node.child(i), target); + if ($end && $end.depth == depth && $end.textOffset) addNode($end.nodeBefore, target); +} +function close(node, content) { + node.type.checkContent(content); + return node.copy(content); +} +function replaceThreeWay($from, $start, $end, $to, depth) { + var openStart = $from.depth > depth && joinable($from, $start, depth + 1); + var openEnd = $to.depth > depth && joinable($end, $to, depth + 1); + var content = []; + addRange(null, $from, depth, content); + if (openStart && openEnd && $start.index(depth) == $end.index(depth)) { + checkJoin(openStart, openEnd); + addNode(close(openStart, replaceThreeWay($from, $start, $end, $to, depth + 1)), content); + } else { + if (openStart) addNode(close(openStart, replaceTwoWay($from, $start, depth + 1)), content); + addRange($start, $end, depth, content); + if (openEnd) addNode(close(openEnd, replaceTwoWay($end, $to, depth + 1)), content); + } + addRange($to, null, depth, content); + return new Fragment(content); +} +function replaceTwoWay($from, $to, depth) { + var content = []; + addRange(null, $from, depth, content); + if ($from.depth > depth) { + var type = joinable($from, $to, depth + 1); + addNode(close(type, replaceTwoWay($from, $to, depth + 1)), content); + } + addRange($to, null, depth, content); + return new Fragment(content); +} +function prepareSliceForReplace(slice, $along) { + var extra = $along.depth - slice.openStart, + parent = $along.node(extra); + var node = parent.copy(slice.content); + for (var i = extra - 1; i >= 0; i--) node = $along.node(i).copy(Fragment.from(node)); + return { + start: node.resolveNoCache(slice.openStart + extra), + end: node.resolveNoCache(node.content.size - slice.openEnd - extra) + }; +} +var ResolvedPos = function () { + function ResolvedPos(pos, path, parentOffset) { + _classCallCheck(this, ResolvedPos); + this.pos = pos; + this.path = path; + this.parentOffset = parentOffset; + this.depth = path.length / 3 - 1; + } + _createClass(ResolvedPos, [{ + key: "resolveDepth", + value: function resolveDepth(val) { + if (val == null) return this.depth; + if (val < 0) return this.depth + val; + return val; + } + }, { + key: "parent", + get: function get() { + return this.node(this.depth); + } + }, { + key: "doc", + get: function get() { + return this.node(0); + } + }, { + key: "node", + value: function node(depth) { + return this.path[this.resolveDepth(depth) * 3]; + } + }, { + key: "index", + value: function index(depth) { + return this.path[this.resolveDepth(depth) * 3 + 1]; + } + }, { + key: "indexAfter", + value: function indexAfter(depth) { + depth = this.resolveDepth(depth); + return this.index(depth) + (depth == this.depth && !this.textOffset ? 0 : 1); + } + }, { + key: "start", + value: function start(depth) { + depth = this.resolveDepth(depth); + return depth == 0 ? 0 : this.path[depth * 3 - 1] + 1; + } + }, { + key: "end", + value: function end(depth) { + depth = this.resolveDepth(depth); + return this.start(depth) + this.node(depth).content.size; + } + }, { + key: "before", + value: function before(depth) { + depth = this.resolveDepth(depth); + if (!depth) throw new RangeError("There is no position before the top-level node"); + return depth == this.depth + 1 ? this.pos : this.path[depth * 3 - 1]; + } + }, { + key: "after", + value: function after(depth) { + depth = this.resolveDepth(depth); + if (!depth) throw new RangeError("There is no position after the top-level node"); + return depth == this.depth + 1 ? this.pos : this.path[depth * 3 - 1] + this.path[depth * 3].nodeSize; + } + }, { + key: "textOffset", + get: function get() { + return this.pos - this.path[this.path.length - 1]; + } + }, { + key: "nodeAfter", + get: function get() { + var parent = this.parent, + index = this.index(this.depth); + if (index == parent.childCount) return null; + var dOff = this.pos - this.path[this.path.length - 1], + child = parent.child(index); + return dOff ? parent.child(index).cut(dOff) : child; + } + }, { + key: "nodeBefore", + get: function get() { + var index = this.index(this.depth); + var dOff = this.pos - this.path[this.path.length - 1]; + if (dOff) return this.parent.child(index).cut(0, dOff); + return index == 0 ? null : this.parent.child(index - 1); + } + }, { + key: "posAtIndex", + value: function posAtIndex(index, depth) { + depth = this.resolveDepth(depth); + var node = this.path[depth * 3], + pos = depth == 0 ? 0 : this.path[depth * 3 - 1] + 1; + for (var i = 0; i < index; i++) pos += node.child(i).nodeSize; + return pos; + } + }, { + key: "marks", + value: function marks() { + var parent = this.parent, + index = this.index(); + if (parent.content.size == 0) return Mark.none; + if (this.textOffset) return parent.child(index).marks; + var main = parent.maybeChild(index - 1), + other = parent.maybeChild(index); + if (!main) { + var tmp = main; + main = other; + other = tmp; + } + var marks = main.marks; + for (var i = 0; i < marks.length; i++) if (marks[i].type.spec.inclusive === false && (!other || !marks[i].isInSet(other.marks))) marks = marks[i--].removeFromSet(marks); + return marks; + } + }, { + key: "marksAcross", + value: function marksAcross($end) { + var after = this.parent.maybeChild(this.index()); + if (!after || !after.isInline) return null; + var marks = after.marks, + next = $end.parent.maybeChild($end.index()); + for (var i = 0; i < marks.length; i++) if (marks[i].type.spec.inclusive === false && (!next || !marks[i].isInSet(next.marks))) marks = marks[i--].removeFromSet(marks); + return marks; + } + }, { + key: "sharedDepth", + value: function sharedDepth(pos) { + for (var depth = this.depth; depth > 0; depth--) if (this.start(depth) <= pos && this.end(depth) >= pos) return depth; + return 0; + } + }, { + key: "blockRange", + value: function blockRange() { + var other = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this; + var pred = arguments.length > 1 ? arguments[1] : undefined; + if (other.pos < this.pos) return other.blockRange(this); + for (var d = this.depth - (this.parent.inlineContent || this.pos == other.pos ? 1 : 0); d >= 0; d--) if (other.pos <= this.end(d) && (!pred || pred(this.node(d)))) return new NodeRange(this, other, d); + return null; + } + }, { + key: "sameParent", + value: function sameParent(other) { + return this.pos - this.parentOffset == other.pos - other.parentOffset; + } + }, { + key: "max", + value: function max(other) { + return other.pos > this.pos ? other : this; + } + }, { + key: "min", + value: function min(other) { + return other.pos < this.pos ? other : this; + } + }, { + key: "toString", + value: function toString() { + var str = ""; + for (var i = 1; i <= this.depth; i++) str += (str ? "/" : "") + this.node(i).type.name + "_" + this.index(i - 1); + return str + ":" + this.parentOffset; + } + }], [{ + key: "resolve", + value: function resolve(doc, pos) { + if (!(pos >= 0 && pos <= doc.content.size)) throw new RangeError("Position " + pos + " out of range"); + var path = []; + var start = 0, + parentOffset = pos; + for (var node = doc;;) { + var _node$content$findInd = node.content.findIndex(parentOffset), + index = _node$content$findInd.index, + offset = _node$content$findInd.offset; + var rem = parentOffset - offset; + path.push(node, index, start + offset); + if (!rem) break; + node = node.child(index); + if (node.isText) break; + parentOffset = rem - 1; + start += offset + 1; + } + return new ResolvedPos(pos, path, parentOffset); + } + }, { + key: "resolveCached", + value: function resolveCached(doc, pos) { + var cache = resolveCache.get(doc); + if (cache) { + for (var i = 0; i < cache.elts.length; i++) { + var elt = cache.elts[i]; + if (elt.pos == pos) return elt; + } + } else { + resolveCache.set(doc, cache = new ResolveCache()); + } + var result = cache.elts[cache.i] = ResolvedPos.resolve(doc, pos); + cache.i = (cache.i + 1) % resolveCacheSize; + return result; + } + }]); + return ResolvedPos; +}(); +var ResolveCache = _createClass(function ResolveCache() { + _classCallCheck(this, ResolveCache); + this.elts = []; + this.i = 0; +}); +var resolveCacheSize = 12, + resolveCache = new WeakMap(); +var NodeRange = function () { + function NodeRange($from, $to, depth) { + _classCallCheck(this, NodeRange); + this.$from = $from; + this.$to = $to; + this.depth = depth; + } + _createClass(NodeRange, [{ + key: "start", + get: function get() { + return this.$from.before(this.depth + 1); + } + }, { + key: "end", + get: function get() { + return this.$to.after(this.depth + 1); + } + }, { + key: "parent", + get: function get() { + return this.$from.node(this.depth); + } + }, { + key: "startIndex", + get: function get() { + return this.$from.index(this.depth); + } + }, { + key: "endIndex", + get: function get() { + return this.$to.indexAfter(this.depth); + } + }]); + return NodeRange; +}(); +var emptyAttrs = Object.create(null); +var Node = function () { + function Node(type, attrs, content) { + var marks = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : Mark.none; + _classCallCheck(this, Node); + this.type = type; + this.attrs = attrs; + this.marks = marks; + this.content = content || Fragment.empty; + } + _createClass(Node, [{ + key: "children", + get: function get() { + return this.content.content; + } + }, { + key: "nodeSize", + get: function get() { + return this.isLeaf ? 1 : 2 + this.content.size; + } + }, { + key: "childCount", + get: function get() { + return this.content.childCount; + } + }, { + key: "child", + value: function child(index) { + return this.content.child(index); + } + }, { + key: "maybeChild", + value: function maybeChild(index) { + return this.content.maybeChild(index); + } + }, { + key: "forEach", + value: function forEach(f) { + this.content.forEach(f); + } + }, { + key: "nodesBetween", + value: function nodesBetween(from, to, f) { + var startPos = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; + this.content.nodesBetween(from, to, f, startPos, this); + } + }, { + key: "descendants", + value: function descendants(f) { + this.nodesBetween(0, this.content.size, f); + } + }, { + key: "textContent", + get: function get() { + return this.isLeaf && this.type.spec.leafText ? this.type.spec.leafText(this) : this.textBetween(0, this.content.size, ""); + } + }, { + key: "textBetween", + value: function textBetween(from, to, blockSeparator, leafText) { + return this.content.textBetween(from, to, blockSeparator, leafText); + } + }, { + key: "firstChild", + get: function get() { + return this.content.firstChild; + } + }, { + key: "lastChild", + get: function get() { + return this.content.lastChild; + } + }, { + key: "eq", + value: function eq(other) { + return this == other || this.sameMarkup(other) && this.content.eq(other.content); + } + }, { + key: "sameMarkup", + value: function sameMarkup(other) { + return this.hasMarkup(other.type, other.attrs, other.marks); + } + }, { + key: "hasMarkup", + value: function hasMarkup(type, attrs, marks) { + return this.type == type && compareDeep(this.attrs, attrs || type.defaultAttrs || emptyAttrs) && Mark.sameSet(this.marks, marks || Mark.none); + } + }, { + key: "copy", + value: function copy() { + var content = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + if (content == this.content) return this; + return new Node(this.type, this.attrs, content, this.marks); + } + }, { + key: "mark", + value: function mark(marks) { + return marks == this.marks ? this : new Node(this.type, this.attrs, this.content, marks); + } + }, { + key: "cut", + value: function cut(from) { + var to = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.content.size; + if (from == 0 && to == this.content.size) return this; + return this.copy(this.content.cut(from, to)); + } + }, { + key: "slice", + value: function slice(from) { + var to = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.content.size; + var includeParents = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + if (from == to) return Slice.empty; + var $from = this.resolve(from), + $to = this.resolve(to); + var depth = includeParents ? 0 : $from.sharedDepth(to); + var start = $from.start(depth), + node = $from.node(depth); + var content = node.content.cut($from.pos - start, $to.pos - start); + return new Slice(content, $from.depth - depth, $to.depth - depth); + } + }, { + key: "replace", + value: function replace(from, to, slice) { + return _replace(this.resolve(from), this.resolve(to), slice); + } + }, { + key: "nodeAt", + value: function nodeAt(pos) { + for (var node = this;;) { + var _node$content$findInd2 = node.content.findIndex(pos), + index = _node$content$findInd2.index, + offset = _node$content$findInd2.offset; + node = node.maybeChild(index); + if (!node) return null; + if (offset == pos || node.isText) return node; + pos -= offset + 1; + } + } + }, { + key: "childAfter", + value: function childAfter(pos) { + var _this$content$findInd = this.content.findIndex(pos), + index = _this$content$findInd.index, + offset = _this$content$findInd.offset; + return { + node: this.content.maybeChild(index), + index: index, + offset: offset + }; + } + }, { + key: "childBefore", + value: function childBefore(pos) { + if (pos == 0) return { + node: null, + index: 0, + offset: 0 + }; + var _this$content$findInd2 = this.content.findIndex(pos), + index = _this$content$findInd2.index, + offset = _this$content$findInd2.offset; + if (offset < pos) return { + node: this.content.child(index), + index: index, + offset: offset + }; + var node = this.content.child(index - 1); + return { + node: node, + index: index - 1, + offset: offset - node.nodeSize + }; + } + }, { + key: "resolve", + value: function resolve(pos) { + return ResolvedPos.resolveCached(this, pos); + } + }, { + key: "resolveNoCache", + value: function resolveNoCache(pos) { + return ResolvedPos.resolve(this, pos); + } + }, { + key: "rangeHasMark", + value: function rangeHasMark(from, to, type) { + var found = false; + if (to > from) this.nodesBetween(from, to, function (node) { + if (type.isInSet(node.marks)) found = true; + return !found; + }); + return found; + } + }, { + key: "isBlock", + get: function get() { + return this.type.isBlock; + } + }, { + key: "isTextblock", + get: function get() { + return this.type.isTextblock; + } + }, { + key: "inlineContent", + get: function get() { + return this.type.inlineContent; + } + }, { + key: "isInline", + get: function get() { + return this.type.isInline; + } + }, { + key: "isText", + get: function get() { + return this.type.isText; + } + }, { + key: "isLeaf", + get: function get() { + return this.type.isLeaf; + } + }, { + key: "isAtom", + get: function get() { + return this.type.isAtom; + } + }, { + key: "toString", + value: function toString() { + if (this.type.spec.toDebugString) return this.type.spec.toDebugString(this); + var name = this.type.name; + if (this.content.size) name += "(" + this.content.toStringInner() + ")"; + return wrapMarks(this.marks, name); + } + }, { + key: "contentMatchAt", + value: function contentMatchAt(index) { + var match = this.type.contentMatch.matchFragment(this.content, 0, index); + if (!match) throw new Error("Called contentMatchAt on a node with invalid content"); + return match; + } + }, { + key: "canReplace", + value: function canReplace(from, to) { + var replacement = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Fragment.empty; + var start = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; + var end = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : replacement.childCount; + var one = this.contentMatchAt(from).matchFragment(replacement, start, end); + var two = one && one.matchFragment(this.content, to); + if (!two || !two.validEnd) return false; + for (var i = start; i < end; i++) if (!this.type.allowsMarks(replacement.child(i).marks)) return false; + return true; + } + }, { + key: "canReplaceWith", + value: function canReplaceWith(from, to, type, marks) { + if (marks && !this.type.allowsMarks(marks)) return false; + var start = this.contentMatchAt(from).matchType(type); + var end = start && start.matchFragment(this.content, to); + return end ? end.validEnd : false; + } + }, { + key: "canAppend", + value: function canAppend(other) { + if (other.content.size) return this.canReplace(this.childCount, this.childCount, other.content);else return this.type.compatibleContent(other.type); + } + }, { + key: "check", + value: function check() { + this.type.checkContent(this.content); + this.type.checkAttrs(this.attrs); + var copy = Mark.none; + for (var i = 0; i < this.marks.length; i++) { + var mark = this.marks[i]; + mark.type.checkAttrs(mark.attrs); + copy = mark.addToSet(copy); + } + if (!Mark.sameSet(copy, this.marks)) throw new RangeError("Invalid collection of marks for node ".concat(this.type.name, ": ").concat(this.marks.map(function (m) { + return m.type.name; + }))); + this.content.forEach(function (node) { + return node.check(); + }); + } + }, { + key: "toJSON", + value: function toJSON() { + var obj = { + type: this.type.name + }; + for (var _ in this.attrs) { + obj.attrs = this.attrs; + break; + } + if (this.content.size) obj.content = this.content.toJSON(); + if (this.marks.length) obj.marks = this.marks.map(function (n) { + return n.toJSON(); + }); + return obj; + } + }], [{ + key: "fromJSON", + value: function fromJSON(schema, json) { + if (!json) throw new RangeError("Invalid input for Node.fromJSON"); + var marks = undefined; + if (json.marks) { + if (!Array.isArray(json.marks)) throw new RangeError("Invalid mark data for Node.fromJSON"); + marks = json.marks.map(schema.markFromJSON); + } + if (json.type == "text") { + if (typeof json.text != "string") throw new RangeError("Invalid text node in JSON"); + return schema.text(json.text, marks); + } + var content = Fragment.fromJSON(schema, json.content); + var node = schema.nodeType(json.type).create(json.attrs, content, marks); + node.type.checkAttrs(node.attrs); + return node; + } + }]); + return Node; +}(); +Node.prototype.text = undefined; +var TextNode = function (_Node) { + _inherits(TextNode, _Node); + var _super2 = _createSuper(TextNode); + function TextNode(type, attrs, content, marks) { + var _this; + _classCallCheck(this, TextNode); + _this = _super2.call(this, type, attrs, null, marks); + if (!content) throw new RangeError("Empty text nodes are not allowed"); + _this.text = content; + return _this; + } + _createClass(TextNode, [{ + key: "toString", + value: function toString() { + if (this.type.spec.toDebugString) return this.type.spec.toDebugString(this); + return wrapMarks(this.marks, JSON.stringify(this.text)); + } + }, { + key: "textContent", + get: function get() { + return this.text; + } + }, { + key: "textBetween", + value: function textBetween(from, to) { + return this.text.slice(from, to); + } + }, { + key: "nodeSize", + get: function get() { + return this.text.length; + } + }, { + key: "mark", + value: function mark(marks) { + return marks == this.marks ? this : new TextNode(this.type, this.attrs, this.text, marks); + } + }, { + key: "withText", + value: function withText(text) { + if (text == this.text) return this; + return new TextNode(this.type, this.attrs, text, this.marks); + } + }, { + key: "cut", + value: function cut() { + var from = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var to = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.text.length; + if (from == 0 && to == this.text.length) return this; + return this.withText(this.text.slice(from, to)); + } + }, { + key: "eq", + value: function eq(other) { + return this.sameMarkup(other) && this.text == other.text; + } + }, { + key: "toJSON", + value: function toJSON() { + var base = _get(_getPrototypeOf(TextNode.prototype), "toJSON", this).call(this); + base.text = this.text; + return base; + } + }]); + return TextNode; +}(Node); +function wrapMarks(marks, str) { + for (var i = marks.length - 1; i >= 0; i--) str = marks[i].type.name + "(" + str + ")"; + return str; +} +var ContentMatch = function () { + function ContentMatch(validEnd) { + _classCallCheck(this, ContentMatch); + this.validEnd = validEnd; + this.next = []; + this.wrapCache = []; + } + _createClass(ContentMatch, [{ + key: "matchType", + value: function matchType(type) { + for (var i = 0; i < this.next.length; i++) if (this.next[i].type == type) return this.next[i].next; + return null; + } + }, { + key: "matchFragment", + value: function matchFragment(frag) { + var start = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : frag.childCount; + var cur = this; + for (var i = start; cur && i < end; i++) cur = cur.matchType(frag.child(i).type); + return cur; + } + }, { + key: "inlineContent", + get: function get() { + return this.next.length != 0 && this.next[0].type.isInline; + } + }, { + key: "defaultType", + get: function get() { + for (var i = 0; i < this.next.length; i++) { + var type = this.next[i].type; + if (!(type.isText || type.hasRequiredAttrs())) return type; + } + return null; + } + }, { + key: "compatible", + value: function compatible(other) { + for (var i = 0; i < this.next.length; i++) for (var j = 0; j < other.next.length; j++) if (this.next[i].type == other.next[j].type) return true; + return false; + } + }, { + key: "fillBefore", + value: function fillBefore(after) { + var toEnd = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var startIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var seen = [this]; + function search(match, types) { + var finished = match.matchFragment(after, startIndex); + if (finished && (!toEnd || finished.validEnd)) return Fragment.from(types.map(function (tp) { + return tp.createAndFill(); + })); + for (var i = 0; i < match.next.length; i++) { + var _match$next$i = match.next[i], + type = _match$next$i.type, + next = _match$next$i.next; + if (!(type.isText || type.hasRequiredAttrs()) && seen.indexOf(next) == -1) { + seen.push(next); + var _found = search(next, types.concat(type)); + if (_found) return _found; + } + } + return null; + } + return search(this, []); + } + }, { + key: "findWrapping", + value: function findWrapping(target) { + for (var i = 0; i < this.wrapCache.length; i += 2) if (this.wrapCache[i] == target) return this.wrapCache[i + 1]; + var computed = this.computeWrapping(target); + this.wrapCache.push(target, computed); + return computed; + } + }, { + key: "computeWrapping", + value: function computeWrapping(target) { + var seen = Object.create(null), + active = [{ + match: this, + type: null, + via: null + }]; + while (active.length) { + var current = active.shift(), + match = current.match; + if (match.matchType(target)) { + var result = []; + for (var obj = current; obj.type; obj = obj.via) result.push(obj.type); + return result.reverse(); + } + for (var i = 0; i < match.next.length; i++) { + var _match$next$i2 = match.next[i], + type = _match$next$i2.type, + next = _match$next$i2.next; + if (!type.isLeaf && !type.hasRequiredAttrs() && !(type.name in seen) && (!current.type || next.validEnd)) { + active.push({ + match: type.contentMatch, + type: type, + via: current + }); + seen[type.name] = true; + } + } + } + return null; + } + }, { + key: "edgeCount", + get: function get() { + return this.next.length; + } + }, { + key: "edge", + value: function edge(n) { + if (n >= this.next.length) throw new RangeError("There's no ".concat(n, "th edge in this content match")); + return this.next[n]; + } + }, { + key: "toString", + value: function toString() { + var seen = []; + function scan(m) { + seen.push(m); + for (var i = 0; i < m.next.length; i++) if (seen.indexOf(m.next[i].next) == -1) scan(m.next[i].next); + } + scan(this); + return seen.map(function (m, i) { + var out = i + (m.validEnd ? "*" : " ") + " "; + for (var _i = 0; _i < m.next.length; _i++) out += (_i ? ", " : "") + m.next[_i].type.name + "->" + seen.indexOf(m.next[_i].next); + return out; + }).join("\n"); + } + }], [{ + key: "parse", + value: function parse(string, nodeTypes) { + var stream = new TokenStream(string, nodeTypes); + if (stream.next == null) return ContentMatch.empty; + var expr = parseExpr(stream); + if (stream.next) stream.err("Unexpected trailing text"); + var match = dfa(nfa(expr)); + checkForDeadEnds(match, stream); + return match; + } + }]); + return ContentMatch; +}(); +ContentMatch.empty = new ContentMatch(true); +var TokenStream = function () { + function TokenStream(string, nodeTypes) { + _classCallCheck(this, TokenStream); + this.string = string; + this.nodeTypes = nodeTypes; + this.inline = null; + this.pos = 0; + this.tokens = string.split(/\s*(?=\b|\W|$)/); + if (this.tokens[this.tokens.length - 1] == "") this.tokens.pop(); + if (this.tokens[0] == "") this.tokens.shift(); + } + _createClass(TokenStream, [{ + key: "next", + get: function get() { + return this.tokens[this.pos]; + } + }, { + key: "eat", + value: function eat(tok) { + return this.next == tok && (this.pos++ || true); + } + }, { + key: "err", + value: function err(str) { + throw new SyntaxError(str + " (in content expression '" + this.string + "')"); + } + }]); + return TokenStream; +}(); +function parseExpr(stream) { + var exprs = []; + do { + exprs.push(parseExprSeq(stream)); + } while (stream.eat("|")); + return exprs.length == 1 ? exprs[0] : { + type: "choice", + exprs: exprs + }; +} +function parseExprSeq(stream) { + var exprs = []; + do { + exprs.push(parseExprSubscript(stream)); + } while (stream.next && stream.next != ")" && stream.next != "|"); + return exprs.length == 1 ? exprs[0] : { + type: "seq", + exprs: exprs + }; +} +function parseExprSubscript(stream) { + var expr = parseExprAtom(stream); + for (;;) { + if (stream.eat("+")) expr = { + type: "plus", + expr: expr + };else if (stream.eat("*")) expr = { + type: "star", + expr: expr + };else if (stream.eat("?")) expr = { + type: "opt", + expr: expr + };else if (stream.eat("{")) expr = parseExprRange(stream, expr);else break; + } + return expr; +} +function parseNum(stream) { + if (/\D/.test(stream.next)) stream.err("Expected number, got '" + stream.next + "'"); + var result = Number(stream.next); + stream.pos++; + return result; +} +function parseExprRange(stream, expr) { + var min = parseNum(stream), + max = min; + if (stream.eat(",")) { + if (stream.next != "}") max = parseNum(stream);else max = -1; + } + if (!stream.eat("}")) stream.err("Unclosed braced range"); + return { + type: "range", + min: min, + max: max, + expr: expr + }; +} +function resolveName(stream, name) { + var types = stream.nodeTypes, + type = types[name]; + if (type) return [type]; + var result = []; + for (var typeName in types) { + var _type = types[typeName]; + if (_type.isInGroup(name)) result.push(_type); + } + if (result.length == 0) stream.err("No node type or group '" + name + "' found"); + return result; +} +function parseExprAtom(stream) { + if (stream.eat("(")) { + var expr = parseExpr(stream); + if (!stream.eat(")")) stream.err("Missing closing paren"); + return expr; + } else if (!/\W/.test(stream.next)) { + var exprs = resolveName(stream, stream.next).map(function (type) { + if (stream.inline == null) stream.inline = type.isInline;else if (stream.inline != type.isInline) stream.err("Mixing inline and block content"); + return { + type: "name", + value: type + }; + }); + stream.pos++; + return exprs.length == 1 ? exprs[0] : { + type: "choice", + exprs: exprs + }; + } else { + stream.err("Unexpected token '" + stream.next + "'"); + } +} +function nfa(expr) { + var nfa = [[]]; + connect(compile(expr, 0), node()); + return nfa; + function node() { + return nfa.push([]) - 1; + } + function edge(from, to, term) { + var edge = { + term: term, + to: to + }; + nfa[from].push(edge); + return edge; + } + function connect(edges, to) { + edges.forEach(function (edge) { + return edge.to = to; + }); + } + function compile(expr, from) { + if (expr.type == "choice") { + return expr.exprs.reduce(function (out, expr) { + return out.concat(compile(expr, from)); + }, []); + } else if (expr.type == "seq") { + for (var i = 0;; i++) { + var next = compile(expr.exprs[i], from); + if (i == expr.exprs.length - 1) return next; + connect(next, from = node()); + } + } else if (expr.type == "star") { + var loop = node(); + edge(from, loop); + connect(compile(expr.expr, loop), loop); + return [edge(loop)]; + } else if (expr.type == "plus") { + var _loop = node(); + connect(compile(expr.expr, from), _loop); + connect(compile(expr.expr, _loop), _loop); + return [edge(_loop)]; + } else if (expr.type == "opt") { + return [edge(from)].concat(compile(expr.expr, from)); + } else if (expr.type == "range") { + var cur = from; + for (var _i2 = 0; _i2 < expr.min; _i2++) { + var _next = node(); + connect(compile(expr.expr, cur), _next); + cur = _next; + } + if (expr.max == -1) { + connect(compile(expr.expr, cur), cur); + } else { + for (var _i3 = expr.min; _i3 < expr.max; _i3++) { + var _next2 = node(); + edge(cur, _next2); + connect(compile(expr.expr, cur), _next2); + cur = _next2; + } + } + return [edge(cur)]; + } else if (expr.type == "name") { + return [edge(from, undefined, expr.value)]; + } else { + throw new Error("Unknown expr type"); + } + } +} +function cmp(a, b) { + return b - a; +} +function nullFrom(nfa, node) { + var result = []; + scan(node); + return result.sort(cmp); + function scan(node) { + var edges = nfa[node]; + if (edges.length == 1 && !edges[0].term) return scan(edges[0].to); + result.push(node); + for (var i = 0; i < edges.length; i++) { + var _edges$i = edges[i], + term = _edges$i.term, + to = _edges$i.to; + if (!term && result.indexOf(to) == -1) scan(to); + } + } +} +function dfa(nfa) { + var labeled = Object.create(null); + return explore(nullFrom(nfa, 0)); + function explore(states) { + var out = []; + states.forEach(function (node) { + nfa[node].forEach(function (_ref) { + var term = _ref.term, + to = _ref.to; + if (!term) return; + var set; + for (var i = 0; i < out.length; i++) if (out[i][0] == term) set = out[i][1]; + nullFrom(nfa, to).forEach(function (node) { + if (!set) out.push([term, set = []]); + if (set.indexOf(node) == -1) set.push(node); + }); + }); + }); + var state = labeled[states.join(",")] = new ContentMatch(states.indexOf(nfa.length - 1) > -1); + for (var i = 0; i < out.length; i++) { + var _states = out[i][1].sort(cmp); + state.next.push({ + type: out[i][0], + next: labeled[_states.join(",")] || explore(_states) + }); + } + return state; + } +} +function checkForDeadEnds(match, stream) { + for (var i = 0, work = [match]; i < work.length; i++) { + var state = work[i], + dead = !state.validEnd, + nodes = []; + for (var j = 0; j < state.next.length; j++) { + var _state$next$j = state.next[j], + type = _state$next$j.type, + next = _state$next$j.next; + nodes.push(type.name); + if (dead && !(type.isText || type.hasRequiredAttrs())) dead = false; + if (work.indexOf(next) == -1) work.push(next); + } + if (dead) stream.err("Only non-generatable nodes (" + nodes.join(", ") + ") in a required position (see https://prosemirror.net/docs/guide/#generatable)"); + } +} +function defaultAttrs(attrs) { + var defaults = Object.create(null); + for (var attrName in attrs) { + var attr = attrs[attrName]; + if (!attr.hasDefault) return null; + defaults[attrName] = attr["default"]; + } + return defaults; +} +function _computeAttrs(attrs, value) { + var built = Object.create(null); + for (var name in attrs) { + var given = value && value[name]; + if (given === undefined) { + var attr = attrs[name]; + if (attr.hasDefault) given = attr["default"];else throw new RangeError("No value supplied for attribute " + name); + } + built[name] = given; + } + return built; +} +function _checkAttrs(attrs, values, type, name) { + for (var _name in values) if (!(_name in attrs)) throw new RangeError("Unsupported attribute ".concat(_name, " for ").concat(type, " of type ").concat(_name)); + for (var _name2 in attrs) { + var attr = attrs[_name2]; + if (attr.validate) attr.validate(values[_name2]); + } +} +function initAttrs(typeName, attrs) { + var result = Object.create(null); + if (attrs) for (var name in attrs) result[name] = new Attribute(typeName, name, attrs[name]); + return result; +} +var NodeType = function () { + function NodeType(name, schema, spec) { + _classCallCheck(this, NodeType); + this.name = name; + this.schema = schema; + this.spec = spec; + this.markSet = null; + this.groups = spec.group ? spec.group.split(" ") : []; + this.attrs = initAttrs(name, spec.attrs); + this.defaultAttrs = defaultAttrs(this.attrs); + this.contentMatch = null; + this.inlineContent = null; + this.isBlock = !(spec.inline || name == "text"); + this.isText = name == "text"; + } + _createClass(NodeType, [{ + key: "isInline", + get: function get() { + return !this.isBlock; + } + }, { + key: "isTextblock", + get: function get() { + return this.isBlock && this.inlineContent; + } + }, { + key: "isLeaf", + get: function get() { + return this.contentMatch == ContentMatch.empty; + } + }, { + key: "isAtom", + get: function get() { + return this.isLeaf || !!this.spec.atom; + } + }, { + key: "isInGroup", + value: function isInGroup(group) { + return this.groups.indexOf(group) > -1; + } + }, { + key: "whitespace", + get: function get() { + return this.spec.whitespace || (this.spec.code ? "pre" : "normal"); + } + }, { + key: "hasRequiredAttrs", + value: function hasRequiredAttrs() { + for (var n in this.attrs) if (this.attrs[n].isRequired) return true; + return false; + } + }, { + key: "compatibleContent", + value: function compatibleContent(other) { + return this == other || this.contentMatch.compatible(other.contentMatch); + } + }, { + key: "computeAttrs", + value: function computeAttrs(attrs) { + if (!attrs && this.defaultAttrs) return this.defaultAttrs;else return _computeAttrs(this.attrs, attrs); + } + }, { + key: "create", + value: function create() { + var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var content = arguments.length > 1 ? arguments[1] : undefined; + var marks = arguments.length > 2 ? arguments[2] : undefined; + if (this.isText) throw new Error("NodeType.create can't construct text nodes"); + return new Node(this, this.computeAttrs(attrs), Fragment.from(content), Mark.setFrom(marks)); + } + }, { + key: "createChecked", + value: function createChecked() { + var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var content = arguments.length > 1 ? arguments[1] : undefined; + var marks = arguments.length > 2 ? arguments[2] : undefined; + content = Fragment.from(content); + this.checkContent(content); + return new Node(this, this.computeAttrs(attrs), content, Mark.setFrom(marks)); + } + }, { + key: "createAndFill", + value: function createAndFill() { + var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + var content = arguments.length > 1 ? arguments[1] : undefined; + var marks = arguments.length > 2 ? arguments[2] : undefined; + attrs = this.computeAttrs(attrs); + content = Fragment.from(content); + if (content.size) { + var before = this.contentMatch.fillBefore(content); + if (!before) return null; + content = before.append(content); + } + var matched = this.contentMatch.matchFragment(content); + var after = matched && matched.fillBefore(Fragment.empty, true); + if (!after) return null; + return new Node(this, attrs, content.append(after), Mark.setFrom(marks)); + } + }, { + key: "validContent", + value: function validContent(content) { + var result = this.contentMatch.matchFragment(content); + if (!result || !result.validEnd) return false; + for (var i = 0; i < content.childCount; i++) if (!this.allowsMarks(content.child(i).marks)) return false; + return true; + } + }, { + key: "checkContent", + value: function checkContent(content) { + if (!this.validContent(content)) throw new RangeError("Invalid content for node ".concat(this.name, ": ").concat(content.toString().slice(0, 50))); + } + }, { + key: "checkAttrs", + value: function checkAttrs(attrs) { + _checkAttrs(this.attrs, attrs, "node", this.name); + } + }, { + key: "allowsMarkType", + value: function allowsMarkType(markType) { + return this.markSet == null || this.markSet.indexOf(markType) > -1; + } + }, { + key: "allowsMarks", + value: function allowsMarks(marks) { + if (this.markSet == null) return true; + for (var i = 0; i < marks.length; i++) if (!this.allowsMarkType(marks[i].type)) return false; + return true; + } + }, { + key: "allowedMarks", + value: function allowedMarks(marks) { + if (this.markSet == null) return marks; + var copy; + for (var i = 0; i < marks.length; i++) { + if (!this.allowsMarkType(marks[i].type)) { + if (!copy) copy = marks.slice(0, i); + } else if (copy) { + copy.push(marks[i]); + } + } + return !copy ? marks : copy.length ? copy : Mark.none; + } + }], [{ + key: "compile", + value: function compile(nodes, schema) { + var result = Object.create(null); + nodes.forEach(function (name, spec) { + return result[name] = new NodeType(name, schema, spec); + }); + var topType = schema.spec.topNode || "doc"; + if (!result[topType]) throw new RangeError("Schema is missing its top node type ('" + topType + "')"); + if (!result.text) throw new RangeError("Every schema needs a 'text' type"); + for (var _ in result.text.attrs) throw new RangeError("The text node type should not have attributes"); + return result; + } + }]); + return NodeType; +}(); +function validateType(typeName, attrName, type) { + var types = type.split("|"); + return function (value) { + var name = value === null ? "null" : _typeof(value); + if (types.indexOf(name) < 0) throw new RangeError("Expected value of type ".concat(types, " for attribute ").concat(attrName, " on type ").concat(typeName, ", got ").concat(name)); + }; +} +var Attribute = function () { + function Attribute(typeName, attrName, options) { + _classCallCheck(this, Attribute); + this.hasDefault = Object.prototype.hasOwnProperty.call(options, "default"); + this["default"] = options["default"]; + this.validate = typeof options.validate == "string" ? validateType(typeName, attrName, options.validate) : options.validate; + } + _createClass(Attribute, [{ + key: "isRequired", + get: function get() { + return !this.hasDefault; + } + }]); + return Attribute; +}(); +var MarkType = function () { + function MarkType(name, rank, schema, spec) { + _classCallCheck(this, MarkType); + this.name = name; + this.rank = rank; + this.schema = schema; + this.spec = spec; + this.attrs = initAttrs(name, spec.attrs); + this.excluded = null; + var defaults = defaultAttrs(this.attrs); + this.instance = defaults ? new Mark(this, defaults) : null; + } + _createClass(MarkType, [{ + key: "create", + value: function create() { + var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + if (!attrs && this.instance) return this.instance; + return new Mark(this, _computeAttrs(this.attrs, attrs)); + } + }, { + key: "removeFromSet", + value: function removeFromSet(set) { + for (var i = 0; i < set.length; i++) if (set[i].type == this) { + set = set.slice(0, i).concat(set.slice(i + 1)); + i--; + } + return set; + } + }, { + key: "isInSet", + value: function isInSet(set) { + for (var i = 0; i < set.length; i++) if (set[i].type == this) return set[i]; + } + }, { + key: "checkAttrs", + value: function checkAttrs(attrs) { + _checkAttrs(this.attrs, attrs, "mark", this.name); + } + }, { + key: "excludes", + value: function excludes(other) { + return this.excluded.indexOf(other) > -1; + } + }], [{ + key: "compile", + value: function compile(marks, schema) { + var result = Object.create(null), + rank = 0; + marks.forEach(function (name, spec) { + return result[name] = new MarkType(name, rank++, schema, spec); + }); + return result; + } + }]); + return MarkType; +}(); +var Schema = function () { + function Schema(spec) { + _classCallCheck(this, Schema); + this.linebreakReplacement = null; + this.cached = Object.create(null); + var instanceSpec = this.spec = {}; + for (var prop in spec) instanceSpec[prop] = spec[prop]; + instanceSpec.nodes = OrderedMap.from(spec.nodes), instanceSpec.marks = OrderedMap.from(spec.marks || {}), this.nodes = NodeType.compile(this.spec.nodes, this); + this.marks = MarkType.compile(this.spec.marks, this); + var contentExprCache = Object.create(null); + for (var _prop in this.nodes) { + if (_prop in this.marks) throw new RangeError(_prop + " can not be both a node and a mark"); + var type = this.nodes[_prop], + contentExpr = type.spec.content || "", + markExpr = type.spec.marks; + type.contentMatch = contentExprCache[contentExpr] || (contentExprCache[contentExpr] = ContentMatch.parse(contentExpr, this.nodes)); + type.inlineContent = type.contentMatch.inlineContent; + if (type.spec.linebreakReplacement) { + if (this.linebreakReplacement) throw new RangeError("Multiple linebreak nodes defined"); + if (!type.isInline || !type.isLeaf) throw new RangeError("Linebreak replacement nodes must be inline leaf nodes"); + this.linebreakReplacement = type; + } + type.markSet = markExpr == "_" ? null : markExpr ? gatherMarks(this, markExpr.split(" ")) : markExpr == "" || !type.inlineContent ? [] : null; + } + for (var _prop2 in this.marks) { + var _type2 = this.marks[_prop2], + excl = _type2.spec.excludes; + _type2.excluded = excl == null ? [_type2] : excl == "" ? [] : gatherMarks(this, excl.split(" ")); + } + this.nodeFromJSON = this.nodeFromJSON.bind(this); + this.markFromJSON = this.markFromJSON.bind(this); + this.topNodeType = this.nodes[this.spec.topNode || "doc"]; + this.cached.wrappings = Object.create(null); + } + _createClass(Schema, [{ + key: "node", + value: function node(type) { + var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + var content = arguments.length > 2 ? arguments[2] : undefined; + var marks = arguments.length > 3 ? arguments[3] : undefined; + if (typeof type == "string") type = this.nodeType(type);else if (!(type instanceof NodeType)) throw new RangeError("Invalid node type: " + type);else if (type.schema != this) throw new RangeError("Node type from different schema used (" + type.name + ")"); + return type.createChecked(attrs, content, marks); + } + }, { + key: "text", + value: function text(_text, marks) { + var type = this.nodes.text; + return new TextNode(type, type.defaultAttrs, _text, Mark.setFrom(marks)); + } + }, { + key: "mark", + value: function mark(type, attrs) { + if (typeof type == "string") type = this.marks[type]; + return type.create(attrs); + } + }, { + key: "nodeFromJSON", + value: function nodeFromJSON(json) { + return Node.fromJSON(this, json); + } + }, { + key: "markFromJSON", + value: function markFromJSON(json) { + return Mark.fromJSON(this, json); + } + }, { + key: "nodeType", + value: function nodeType(name) { + var found = this.nodes[name]; + if (!found) throw new RangeError("Unknown node type: " + name); + return found; + } + }]); + return Schema; +}(); +function gatherMarks(schema, marks) { + var found = []; + for (var i = 0; i < marks.length; i++) { + var name = marks[i], + mark = schema.marks[name], + ok = mark; + if (mark) { + found.push(mark); + } else { + for (var prop in schema.marks) { + var _mark = schema.marks[prop]; + if (name == "_" || _mark.spec.group && _mark.spec.group.split(" ").indexOf(name) > -1) found.push(ok = _mark); + } + } + if (!ok) throw new SyntaxError("Unknown mark type: '" + marks[i] + "'"); + } + return found; +} +function isTagRule(rule) { + return rule.tag != null; +} +function isStyleRule(rule) { + return rule.style != null; +} +var DOMParser = function () { + function DOMParser(schema, rules) { + var _this2 = this; + _classCallCheck(this, DOMParser); + this.schema = schema; + this.rules = rules; + this.tags = []; + this.styles = []; + var matchedStyles = this.matchedStyles = []; + rules.forEach(function (rule) { + if (isTagRule(rule)) { + _this2.tags.push(rule); + } else if (isStyleRule(rule)) { + var prop = /[^=]*/.exec(rule.style)[0]; + if (matchedStyles.indexOf(prop) < 0) matchedStyles.push(prop); + _this2.styles.push(rule); + } + }); + this.normalizeLists = !this.tags.some(function (r) { + if (!/^(ul|ol)\b/.test(r.tag) || !r.node) return false; + var node = schema.nodes[r.node]; + return node.contentMatch.matchType(node); + }); + } + _createClass(DOMParser, [{ + key: "parse", + value: function parse(dom) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var context = new ParseContext(this, options, false); + context.addAll(dom, Mark.none, options.from, options.to); + return context.finish(); + } + }, { + key: "parseSlice", + value: function parseSlice(dom) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var context = new ParseContext(this, options, true); + context.addAll(dom, Mark.none, options.from, options.to); + return Slice.maxOpen(context.finish()); + } + }, { + key: "matchTag", + value: function matchTag(dom, context, after) { + for (var i = after ? this.tags.indexOf(after) + 1 : 0; i < this.tags.length; i++) { + var rule = this.tags[i]; + if (matches(dom, rule.tag) && (rule.namespace === undefined || dom.namespaceURI == rule.namespace) && (!rule.context || context.matchesContext(rule.context))) { + if (rule.getAttrs) { + var result = rule.getAttrs(dom); + if (result === false) continue; + rule.attrs = result || undefined; + } + return rule; + } + } + } + }, { + key: "matchStyle", + value: function matchStyle(prop, value, context, after) { + for (var i = after ? this.styles.indexOf(after) + 1 : 0; i < this.styles.length; i++) { + var rule = this.styles[i], + style = rule.style; + if (style.indexOf(prop) != 0 || rule.context && !context.matchesContext(rule.context) || style.length > prop.length && (style.charCodeAt(prop.length) != 61 || style.slice(prop.length + 1) != value)) continue; + if (rule.getAttrs) { + var result = rule.getAttrs(value); + if (result === false) continue; + rule.attrs = result || undefined; + } + return rule; + } + } + }], [{ + key: "schemaRules", + value: function schemaRules(schema) { + var result = []; + function insert(rule) { + var priority = rule.priority == null ? 50 : rule.priority, + i = 0; + for (; i < result.length; i++) { + var next = result[i], + nextPriority = next.priority == null ? 50 : next.priority; + if (nextPriority < priority) break; + } + result.splice(i, 0, rule); + } + var _loop2 = function _loop2(name) { + var rules = schema.marks[name].spec.parseDOM; + if (rules) rules.forEach(function (rule) { + insert(rule = copy(rule)); + if (!(rule.mark || rule.ignore || rule.clearMark)) rule.mark = name; + }); + }; + for (var name in schema.marks) { + _loop2(name); + } + var _loop3 = function _loop3(_name3) { + var rules = schema.nodes[_name3].spec.parseDOM; + if (rules) rules.forEach(function (rule) { + insert(rule = copy(rule)); + if (!(rule.node || rule.ignore || rule.mark)) rule.node = _name3; + }); + }; + for (var _name3 in schema.nodes) { + _loop3(_name3); + } + return result; + } + }, { + key: "fromSchema", + value: function fromSchema(schema) { + return schema.cached.domParser || (schema.cached.domParser = new DOMParser(schema, DOMParser.schemaRules(schema))); + } + }]); + return DOMParser; +}(); +var blockTags = { + address: true, + article: true, + aside: true, + blockquote: true, + canvas: true, + dd: true, + div: true, + dl: true, + fieldset: true, + figcaption: true, + figure: true, + footer: true, + form: true, + h1: true, + h2: true, + h3: true, + h4: true, + h5: true, + h6: true, + header: true, + hgroup: true, + hr: true, + li: true, + noscript: true, + ol: true, + output: true, + p: true, + pre: true, + section: true, + table: true, + tfoot: true, + ul: true +}; +var ignoreTags = { + head: true, + noscript: true, + object: true, + script: true, + style: true, + title: true +}; +var listTags = { + ol: true, + ul: true +}; +var OPT_PRESERVE_WS = 1, + OPT_PRESERVE_WS_FULL = 2, + OPT_OPEN_LEFT = 4; +function wsOptionsFor(type, preserveWhitespace, base) { + if (preserveWhitespace != null) return (preserveWhitespace ? OPT_PRESERVE_WS : 0) | (preserveWhitespace === "full" ? OPT_PRESERVE_WS_FULL : 0); + return type && type.whitespace == "pre" ? OPT_PRESERVE_WS | OPT_PRESERVE_WS_FULL : base & ~OPT_OPEN_LEFT; +} +var NodeContext = function () { + function NodeContext(type, attrs, marks, solid, match, options) { + _classCallCheck(this, NodeContext); + this.type = type; + this.attrs = attrs; + this.marks = marks; + this.solid = solid; + this.options = options; + this.content = []; + this.activeMarks = Mark.none; + this.match = match || (options & OPT_OPEN_LEFT ? null : type.contentMatch); + } + _createClass(NodeContext, [{ + key: "findWrapping", + value: function findWrapping(node) { + if (!this.match) { + if (!this.type) return []; + var fill = this.type.contentMatch.fillBefore(Fragment.from(node)); + if (fill) { + this.match = this.type.contentMatch.matchFragment(fill); + } else { + var start = this.type.contentMatch, + wrap; + if (wrap = start.findWrapping(node.type)) { + this.match = start; + return wrap; + } else { + return null; + } + } + } + return this.match.findWrapping(node.type); + } + }, { + key: "finish", + value: function finish(openEnd) { + if (!(this.options & OPT_PRESERVE_WS)) { + var last = this.content[this.content.length - 1], + m; + if (last && last.isText && (m = /[ \t\r\n\u000c]+$/.exec(last.text))) { + var text = last; + if (last.text.length == m[0].length) this.content.pop();else this.content[this.content.length - 1] = text.withText(text.text.slice(0, text.text.length - m[0].length)); + } + } + var content = Fragment.from(this.content); + if (!openEnd && this.match) content = content.append(this.match.fillBefore(Fragment.empty, true)); + return this.type ? this.type.create(this.attrs, content, this.marks) : content; + } + }, { + key: "inlineContext", + value: function inlineContext(node) { + if (this.type) return this.type.inlineContent; + if (this.content.length) return this.content[0].isInline; + return node.parentNode && !blockTags.hasOwnProperty(node.parentNode.nodeName.toLowerCase()); + } + }]); + return NodeContext; +}(); +var ParseContext = function () { + function ParseContext(parser, options, isOpen) { + _classCallCheck(this, ParseContext); + this.parser = parser; + this.options = options; + this.isOpen = isOpen; + this.open = 0; + this.localPreserveWS = false; + var topNode = options.topNode, + topContext; + var topOptions = wsOptionsFor(null, options.preserveWhitespace, 0) | (isOpen ? OPT_OPEN_LEFT : 0); + if (topNode) topContext = new NodeContext(topNode.type, topNode.attrs, Mark.none, true, options.topMatch || topNode.type.contentMatch, topOptions);else if (isOpen) topContext = new NodeContext(null, null, Mark.none, true, null, topOptions);else topContext = new NodeContext(parser.schema.topNodeType, null, Mark.none, true, null, topOptions); + this.nodes = [topContext]; + this.find = options.findPositions; + this.needsBlock = false; + } + _createClass(ParseContext, [{ + key: "top", + get: function get() { + return this.nodes[this.open]; + } + }, { + key: "addDOM", + value: function addDOM(dom, marks) { + if (dom.nodeType == 3) this.addTextNode(dom, marks);else if (dom.nodeType == 1) this.addElement(dom, marks); + } + }, { + key: "addTextNode", + value: function addTextNode(dom, marks) { + var value = dom.nodeValue; + var top = this.top, + preserveWS = top.options & OPT_PRESERVE_WS_FULL ? "full" : this.localPreserveWS || (top.options & OPT_PRESERVE_WS) > 0; + if (preserveWS === "full" || top.inlineContext(dom) || /[^ \t\r\n\u000c]/.test(value)) { + if (!preserveWS) { + value = value.replace(/[ \t\r\n\u000c]+/g, " "); + if (/^[ \t\r\n\u000c]/.test(value) && this.open == this.nodes.length - 1) { + var nodeBefore = top.content[top.content.length - 1]; + var domNodeBefore = dom.previousSibling; + if (!nodeBefore || domNodeBefore && domNodeBefore.nodeName == 'BR' || nodeBefore.isText && /[ \t\r\n\u000c]$/.test(nodeBefore.text)) value = value.slice(1); + } + } else if (preserveWS !== "full") { + value = value.replace(/\r?\n|\r/g, " "); + } else { + value = value.replace(/\r\n?/g, "\n"); + } + if (value) this.insertNode(this.parser.schema.text(value), marks); + this.findInText(dom); + } else { + this.findInside(dom); + } + } + }, { + key: "addElement", + value: function addElement(dom, marks, matchAfter) { + var outerWS = this.localPreserveWS, + top = this.top; + if (dom.tagName == "PRE" || /pre/.test(dom.style && dom.style.whiteSpace)) this.localPreserveWS = true; + var name = dom.nodeName.toLowerCase(), + ruleID; + if (listTags.hasOwnProperty(name) && this.parser.normalizeLists) normalizeList(dom); + var rule = this.options.ruleFromNode && this.options.ruleFromNode(dom) || (ruleID = this.parser.matchTag(dom, this, matchAfter)); + out: if (rule ? rule.ignore : ignoreTags.hasOwnProperty(name)) { + this.findInside(dom); + this.ignoreFallback(dom, marks); + } else if (!rule || rule.skip || rule.closeParent) { + if (rule && rule.closeParent) this.open = Math.max(0, this.open - 1);else if (rule && rule.skip.nodeType) dom = rule.skip; + var sync, + oldNeedsBlock = this.needsBlock; + if (blockTags.hasOwnProperty(name)) { + if (top.content.length && top.content[0].isInline && this.open) { + this.open--; + top = this.top; + } + sync = true; + if (!top.type) this.needsBlock = true; + } else if (!dom.firstChild) { + this.leafFallback(dom, marks); + break out; + } + var innerMarks = rule && rule.skip ? marks : this.readStyles(dom, marks); + if (innerMarks) this.addAll(dom, innerMarks); + if (sync) this.sync(top); + this.needsBlock = oldNeedsBlock; + } else { + var _innerMarks = this.readStyles(dom, marks); + if (_innerMarks) this.addElementByRule(dom, rule, _innerMarks, rule.consuming === false ? ruleID : undefined); + } + this.localPreserveWS = outerWS; + } + }, { + key: "leafFallback", + value: function leafFallback(dom, marks) { + if (dom.nodeName == "BR" && this.top.type && this.top.type.inlineContent) this.addTextNode(dom.ownerDocument.createTextNode("\n"), marks); + } + }, { + key: "ignoreFallback", + value: function ignoreFallback(dom, marks) { + if (dom.nodeName == "BR" && (!this.top.type || !this.top.type.inlineContent)) this.findPlace(this.parser.schema.text("-"), marks); + } + }, { + key: "readStyles", + value: function readStyles(dom, marks) { + var _this3 = this; + var styles = dom.style; + if (styles && styles.length) for (var i = 0; i < this.parser.matchedStyles.length; i++) { + var name = this.parser.matchedStyles[i], + value = styles.getPropertyValue(name); + if (value) { + var _loop4 = function _loop4(_after) { + var rule = _this3.parser.matchStyle(name, value, _this3, _after); + if (!rule) { + after = _after; + return 0; + } + if (rule.ignore) return { + v: null + }; + if (rule.clearMark) marks = marks.filter(function (m) { + return !rule.clearMark(m); + });else marks = marks.concat(_this3.parser.schema.marks[rule.mark].create(rule.attrs)); + if (rule.consuming === false) _after = rule;else { + after = _after; + return 0; + } + after = _after; + }, + _ret; + for (var after = undefined;;) { + _ret = _loop4(after); + if (_ret === 0) break; + if (_ret) return _ret.v; + } + } + } + return marks; + } + }, { + key: "addElementByRule", + value: function addElementByRule(dom, rule, marks, continueAfter) { + var _this4 = this; + var sync, nodeType; + if (rule.node) { + nodeType = this.parser.schema.nodes[rule.node]; + if (!nodeType.isLeaf) { + var inner = this.enter(nodeType, rule.attrs || null, marks, rule.preserveWhitespace); + if (inner) { + sync = true; + marks = inner; + } + } else if (!this.insertNode(nodeType.create(rule.attrs), marks)) { + this.leafFallback(dom, marks); + } + } else { + var markType = this.parser.schema.marks[rule.mark]; + marks = marks.concat(markType.create(rule.attrs)); + } + var startIn = this.top; + if (nodeType && nodeType.isLeaf) { + this.findInside(dom); + } else if (continueAfter) { + this.addElement(dom, marks, continueAfter); + } else if (rule.getContent) { + this.findInside(dom); + rule.getContent(dom, this.parser.schema).forEach(function (node) { + return _this4.insertNode(node, marks); + }); + } else { + var contentDOM = dom; + if (typeof rule.contentElement == "string") contentDOM = dom.querySelector(rule.contentElement);else if (typeof rule.contentElement == "function") contentDOM = rule.contentElement(dom);else if (rule.contentElement) contentDOM = rule.contentElement; + this.findAround(dom, contentDOM, true); + this.addAll(contentDOM, marks); + this.findAround(dom, contentDOM, false); + } + if (sync && this.sync(startIn)) this.open--; + } + }, { + key: "addAll", + value: function addAll(parent, marks, startIndex, endIndex) { + var index = startIndex || 0; + for (var dom = startIndex ? parent.childNodes[startIndex] : parent.firstChild, end = endIndex == null ? null : parent.childNodes[endIndex]; dom != end; dom = dom.nextSibling, ++index) { + this.findAtPoint(parent, index); + this.addDOM(dom, marks); + } + this.findAtPoint(parent, index); + } + }, { + key: "findPlace", + value: function findPlace(node, marks) { + var route, sync; + for (var depth = this.open; depth >= 0; depth--) { + var cx = this.nodes[depth]; + var _found2 = cx.findWrapping(node); + if (_found2 && (!route || route.length > _found2.length)) { + route = _found2; + sync = cx; + if (!_found2.length) break; + } + if (cx.solid) break; + } + if (!route) return null; + this.sync(sync); + for (var i = 0; i < route.length; i++) marks = this.enterInner(route[i], null, marks, false); + return marks; + } + }, { + key: "insertNode", + value: function insertNode(node, marks) { + if (node.isInline && this.needsBlock && !this.top.type) { + var block = this.textblockFromContext(); + if (block) marks = this.enterInner(block, null, marks); + } + var innerMarks = this.findPlace(node, marks); + if (innerMarks) { + this.closeExtra(); + var top = this.top; + if (top.match) top.match = top.match.matchType(node.type); + var nodeMarks = Mark.none; + var _iterator = _createForOfIteratorHelper(innerMarks.concat(node.marks)), + _step; + try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var m = _step.value; + if (top.type ? top.type.allowsMarkType(m.type) : markMayApply(m.type, node.type)) nodeMarks = m.addToSet(nodeMarks); + } + } catch (err) { + _iterator.e(err); + } finally { + _iterator.f(); + } + top.content.push(node.mark(nodeMarks)); + return true; + } + return false; + } + }, { + key: "enter", + value: function enter(type, attrs, marks, preserveWS) { + var innerMarks = this.findPlace(type.create(attrs), marks); + if (innerMarks) innerMarks = this.enterInner(type, attrs, marks, true, preserveWS); + return innerMarks; + } + }, { + key: "enterInner", + value: function enterInner(type, attrs, marks) { + var solid = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + var preserveWS = arguments.length > 4 ? arguments[4] : undefined; + this.closeExtra(); + var top = this.top; + top.match = top.match && top.match.matchType(type); + var options = wsOptionsFor(type, preserveWS, top.options); + if (top.options & OPT_OPEN_LEFT && top.content.length == 0) options |= OPT_OPEN_LEFT; + var applyMarks = Mark.none; + marks = marks.filter(function (m) { + if (top.type ? top.type.allowsMarkType(m.type) : markMayApply(m.type, type)) { + applyMarks = m.addToSet(applyMarks); + return false; + } + return true; + }); + this.nodes.push(new NodeContext(type, attrs, applyMarks, solid, null, options)); + this.open++; + return marks; + } + }, { + key: "closeExtra", + value: function closeExtra() { + var openEnd = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var i = this.nodes.length - 1; + if (i > this.open) { + for (; i > this.open; i--) this.nodes[i - 1].content.push(this.nodes[i].finish(openEnd)); + this.nodes.length = this.open + 1; + } + } + }, { + key: "finish", + value: function finish() { + this.open = 0; + this.closeExtra(this.isOpen); + return this.nodes[0].finish(!!(this.isOpen || this.options.topOpen)); + } + }, { + key: "sync", + value: function sync(to) { + for (var i = this.open; i >= 0; i--) { + if (this.nodes[i] == to) { + this.open = i; + return true; + } else if (this.localPreserveWS) { + this.nodes[i].options |= OPT_PRESERVE_WS; + } + } + return false; + } + }, { + key: "currentPos", + get: function get() { + this.closeExtra(); + var pos = 0; + for (var i = this.open; i >= 0; i--) { + var content = this.nodes[i].content; + for (var j = content.length - 1; j >= 0; j--) pos += content[j].nodeSize; + if (i) pos++; + } + return pos; + } + }, { + key: "findAtPoint", + value: function findAtPoint(parent, offset) { + if (this.find) for (var i = 0; i < this.find.length; i++) { + if (this.find[i].node == parent && this.find[i].offset == offset) this.find[i].pos = this.currentPos; + } + } + }, { + key: "findInside", + value: function findInside(parent) { + if (this.find) for (var i = 0; i < this.find.length; i++) { + if (this.find[i].pos == null && parent.nodeType == 1 && parent.contains(this.find[i].node)) this.find[i].pos = this.currentPos; + } + } + }, { + key: "findAround", + value: function findAround(parent, content, before) { + if (parent != content && this.find) for (var i = 0; i < this.find.length; i++) { + if (this.find[i].pos == null && parent.nodeType == 1 && parent.contains(this.find[i].node)) { + var pos = content.compareDocumentPosition(this.find[i].node); + if (pos & (before ? 2 : 4)) this.find[i].pos = this.currentPos; + } + } + } + }, { + key: "findInText", + value: function findInText(textNode) { + if (this.find) for (var i = 0; i < this.find.length; i++) { + if (this.find[i].node == textNode) this.find[i].pos = this.currentPos - (textNode.nodeValue.length - this.find[i].offset); + } + } + }, { + key: "matchesContext", + value: function matchesContext(context) { + var _this5 = this; + if (context.indexOf("|") > -1) return context.split(/\s*\|\s*/).some(this.matchesContext, this); + var parts = context.split("/"); + var option = this.options.context; + var useRoot = !this.isOpen && (!option || option.parent.type == this.nodes[0].type); + var minDepth = -(option ? option.depth + 1 : 0) + (useRoot ? 0 : 1); + var match = function match(i, depth) { + for (; i >= 0; i--) { + var part = parts[i]; + if (part == "") { + if (i == parts.length - 1 || i == 0) continue; + for (; depth >= minDepth; depth--) if (match(i - 1, depth)) return true; + return false; + } else { + var next = depth > 0 || depth == 0 && useRoot ? _this5.nodes[depth].type : option && depth >= minDepth ? option.node(depth - minDepth).type : null; + if (!next || next.name != part && !next.isInGroup(part)) return false; + depth--; + } + } + return true; + }; + return match(parts.length - 1, this.open); + } + }, { + key: "textblockFromContext", + value: function textblockFromContext() { + var $context = this.options.context; + if ($context) for (var d = $context.depth; d >= 0; d--) { + var deflt = $context.node(d).contentMatchAt($context.indexAfter(d)).defaultType; + if (deflt && deflt.isTextblock && deflt.defaultAttrs) return deflt; + } + for (var name in this.parser.schema.nodes) { + var type = this.parser.schema.nodes[name]; + if (type.isTextblock && type.defaultAttrs) return type; + } + } + }]); + return ParseContext; +}(); +function normalizeList(dom) { + for (var child = dom.firstChild, prevItem = null; child; child = child.nextSibling) { + var name = child.nodeType == 1 ? child.nodeName.toLowerCase() : null; + if (name && listTags.hasOwnProperty(name) && prevItem) { + prevItem.appendChild(child); + child = prevItem; + } else if (name == "li") { + prevItem = child; + } else if (name) { + prevItem = null; + } + } +} +function matches(dom, selector) { + return (dom.matches || dom.msMatchesSelector || dom.webkitMatchesSelector || dom.mozMatchesSelector).call(dom, selector); +} +function copy(obj) { + var copy = {}; + for (var prop in obj) copy[prop] = obj[prop]; + return copy; +} +function markMayApply(markType, nodeType) { + var nodes = nodeType.schema.nodes; + var _loop5 = function _loop5() { + var parent = nodes[name]; + if (!parent.allowsMarkType(markType)) return 0; + var seen = [], + scan = function scan(match) { + seen.push(match); + for (var i = 0; i < match.edgeCount; i++) { + var _match$edge = match.edge(i), + type = _match$edge.type, + next = _match$edge.next; + if (type == nodeType) return true; + if (seen.indexOf(next) < 0 && scan(next)) return true; + } + }; + if (scan(parent.contentMatch)) return { + v: true + }; + }, + _ret2; + for (var name in nodes) { + _ret2 = _loop5(); + if (_ret2 === 0) continue; + if (_ret2) return _ret2.v; + } +} +var DOMSerializer = function () { + function DOMSerializer(nodes, marks) { + _classCallCheck(this, DOMSerializer); + this.nodes = nodes; + this.marks = marks; + } + _createClass(DOMSerializer, [{ + key: "serializeFragment", + value: function serializeFragment(fragment) { + var _this6 = this; + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var target = arguments.length > 2 ? arguments[2] : undefined; + if (!target) target = doc(options).createDocumentFragment(); + var top = target, + active = []; + fragment.forEach(function (node) { + if (active.length || node.marks.length) { + var keep = 0, + rendered = 0; + while (keep < active.length && rendered < node.marks.length) { + var next = node.marks[rendered]; + if (!_this6.marks[next.type.name]) { + rendered++; + continue; + } + if (!next.eq(active[keep][0]) || next.type.spec.spanning === false) break; + keep++; + rendered++; + } + while (keep < active.length) top = active.pop()[1]; + while (rendered < node.marks.length) { + var add = node.marks[rendered++]; + var markDOM = _this6.serializeMark(add, node.isInline, options); + if (markDOM) { + active.push([add, top]); + top.appendChild(markDOM.dom); + top = markDOM.contentDOM || markDOM.dom; + } + } + } + top.appendChild(_this6.serializeNodeInner(node, options)); + }); + return target; + } + }, { + key: "serializeNodeInner", + value: function serializeNodeInner(node, options) { + var _renderSpec2 = _renderSpec(doc(options), this.nodes[node.type.name](node), null, node.attrs), + dom = _renderSpec2.dom, + contentDOM = _renderSpec2.contentDOM; + if (contentDOM) { + if (node.isLeaf) throw new RangeError("Content hole not allowed in a leaf node spec"); + this.serializeFragment(node.content, options, contentDOM); + } + return dom; + } + }, { + key: "serializeNode", + value: function serializeNode(node) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var dom = this.serializeNodeInner(node, options); + for (var i = node.marks.length - 1; i >= 0; i--) { + var wrap = this.serializeMark(node.marks[i], node.isInline, options); + if (wrap) { + (wrap.contentDOM || wrap.dom).appendChild(dom); + dom = wrap.dom; + } + } + return dom; + } + }, { + key: "serializeMark", + value: function serializeMark(mark, inline) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var toDOM = this.marks[mark.type.name]; + return toDOM && _renderSpec(doc(options), toDOM(mark, inline), null, mark.attrs); + } + }], [{ + key: "renderSpec", + value: function renderSpec(doc, structure) { + var xmlNS = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + var blockArraysIn = arguments.length > 3 ? arguments[3] : undefined; + return _renderSpec(doc, structure, xmlNS, blockArraysIn); + } + }, { + key: "fromSchema", + value: function fromSchema(schema) { + return schema.cached.domSerializer || (schema.cached.domSerializer = new DOMSerializer(this.nodesFromSchema(schema), this.marksFromSchema(schema))); + } + }, { + key: "nodesFromSchema", + value: function nodesFromSchema(schema) { + var result = gatherToDOM(schema.nodes); + if (!result.text) result.text = function (node) { + return node.text; + }; + return result; + } + }, { + key: "marksFromSchema", + value: function marksFromSchema(schema) { + return gatherToDOM(schema.marks); + } + }]); + return DOMSerializer; +}(); +function gatherToDOM(obj) { + var result = {}; + for (var name in obj) { + var toDOM = obj[name].spec.toDOM; + if (toDOM) result[name] = toDOM; + } + return result; +} +function doc(options) { + return options.document || window.document; +} +var suspiciousAttributeCache = new WeakMap(); +function suspiciousAttributes(attrs) { + var value = suspiciousAttributeCache.get(attrs); + if (value === undefined) suspiciousAttributeCache.set(attrs, value = suspiciousAttributesInner(attrs)); + return value; +} +function suspiciousAttributesInner(attrs) { + var result = null; + function scan(value) { + if (value && _typeof(value) == "object") { + if (Array.isArray(value)) { + if (typeof value[0] == "string") { + if (!result) result = []; + result.push(value); + } else { + for (var i = 0; i < value.length; i++) scan(value[i]); + } + } else { + for (var prop in value) scan(value[prop]); + } + } + } + scan(attrs); + return result; +} +function _renderSpec(doc, structure, xmlNS, blockArraysIn) { + if (typeof structure == "string") return { + dom: doc.createTextNode(structure) + }; + if (structure.nodeType != null) return { + dom: structure + }; + if (structure.dom && structure.dom.nodeType != null) return structure; + var tagName = structure[0], + suspicious; + if (typeof tagName != "string") throw new RangeError("Invalid array passed to renderSpec"); + if (blockArraysIn && (suspicious = suspiciousAttributes(blockArraysIn)) && suspicious.indexOf(structure) > -1) throw new RangeError("Using an array from an attribute object as a DOM spec. This may be an attempted cross site scripting attack."); + var space = tagName.indexOf(" "); + if (space > 0) { + xmlNS = tagName.slice(0, space); + tagName = tagName.slice(space + 1); + } + var contentDOM; + var dom = xmlNS ? doc.createElementNS(xmlNS, tagName) : doc.createElement(tagName); + var attrs = structure[1], + start = 1; + if (attrs && _typeof(attrs) == "object" && attrs.nodeType == null && !Array.isArray(attrs)) { + start = 2; + for (var name in attrs) if (attrs[name] != null) { + var _space = name.indexOf(" "); + if (_space > 0) dom.setAttributeNS(name.slice(0, _space), name.slice(_space + 1), attrs[name]);else dom.setAttribute(name, attrs[name]); + } + } + for (var i = start; i < structure.length; i++) { + var child = structure[i]; + if (child === 0) { + if (i < structure.length - 1 || i > start) throw new RangeError("Content hole must be the only child of its parent node"); + return { + dom: dom, + contentDOM: dom + }; + } else { + var _renderSpec3 = _renderSpec(doc, child, xmlNS, blockArraysIn), + inner = _renderSpec3.dom, + innerContent = _renderSpec3.contentDOM; + dom.appendChild(inner); + if (innerContent) { + if (contentDOM) throw new RangeError("Multiple content holes"); + contentDOM = innerContent; + } + } + } + return { + dom: dom, + contentDOM: contentDOM + }; +} +exports.ContentMatch = ContentMatch; +exports.DOMParser = DOMParser; +exports.DOMSerializer = DOMSerializer; +exports.Fragment = Fragment; +exports.Mark = Mark; +exports.MarkType = MarkType; +exports.Node = Node; +exports.NodeRange = NodeRange; +exports.NodeType = NodeType; +exports.ReplaceError = ReplaceError; +exports.ResolvedPos = ResolvedPos; +exports.Schema = Schema; +exports.Slice = Slice; diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-schema-basic.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-schema-basic.cjs new file mode 100644 index 000000000..4c3bee244 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-schema-basic.cjs @@ -0,0 +1,246 @@ +'use strict'; + +var prosemirrorModel = require('prosemirror-model'); +var pDOM = ["p", 0], + blockquoteDOM = ["blockquote", 0], + hrDOM = ["hr"], + preDOM = ["pre", ["code", 0]], + brDOM = ["br"]; +var nodes = { + doc: { + content: "block+" + }, + paragraph: { + content: "inline*", + group: "block", + parseDOM: [{ + tag: "p" + }], + toDOM: function toDOM() { + return pDOM; + } + }, + blockquote: { + content: "block+", + group: "block", + defining: true, + parseDOM: [{ + tag: "blockquote" + }], + toDOM: function toDOM() { + return blockquoteDOM; + } + }, + horizontal_rule: { + group: "block", + parseDOM: [{ + tag: "hr" + }], + toDOM: function toDOM() { + return hrDOM; + } + }, + heading: { + attrs: { + level: { + "default": 1, + validate: "number" + } + }, + content: "inline*", + group: "block", + defining: true, + parseDOM: [{ + tag: "h1", + attrs: { + level: 1 + } + }, { + tag: "h2", + attrs: { + level: 2 + } + }, { + tag: "h3", + attrs: { + level: 3 + } + }, { + tag: "h4", + attrs: { + level: 4 + } + }, { + tag: "h5", + attrs: { + level: 5 + } + }, { + tag: "h6", + attrs: { + level: 6 + } + }], + toDOM: function toDOM(node) { + return ["h" + node.attrs.level, 0]; + } + }, + code_block: { + content: "text*", + marks: "", + group: "block", + code: true, + defining: true, + parseDOM: [{ + tag: "pre", + preserveWhitespace: "full" + }], + toDOM: function toDOM() { + return preDOM; + } + }, + text: { + group: "inline" + }, + image: { + inline: true, + attrs: { + src: { + validate: "string" + }, + alt: { + "default": null, + validate: "string|null" + }, + title: { + "default": null, + validate: "string|null" + } + }, + group: "inline", + draggable: true, + parseDOM: [{ + tag: "img[src]", + getAttrs: function getAttrs(dom) { + return { + src: dom.getAttribute("src"), + title: dom.getAttribute("title"), + alt: dom.getAttribute("alt") + }; + } + }], + toDOM: function toDOM(node) { + var _node$attrs = node.attrs, + src = _node$attrs.src, + alt = _node$attrs.alt, + title = _node$attrs.title; + return ["img", { + src: src, + alt: alt, + title: title + }]; + } + }, + hard_break: { + inline: true, + group: "inline", + selectable: false, + parseDOM: [{ + tag: "br" + }], + toDOM: function toDOM() { + return brDOM; + } + } +}; +var emDOM = ["em", 0], + strongDOM = ["strong", 0], + codeDOM = ["code", 0]; +var marks = { + link: { + attrs: { + href: { + validate: "string" + }, + title: { + "default": null, + validate: "string|null" + } + }, + inclusive: false, + parseDOM: [{ + tag: "a[href]", + getAttrs: function getAttrs(dom) { + return { + href: dom.getAttribute("href"), + title: dom.getAttribute("title") + }; + } + }], + toDOM: function toDOM(node) { + var _node$attrs2 = node.attrs, + href = _node$attrs2.href, + title = _node$attrs2.title; + return ["a", { + href: href, + title: title + }, 0]; + } + }, + em: { + parseDOM: [{ + tag: "i" + }, { + tag: "em" + }, { + style: "font-style=italic" + }, { + style: "font-style=normal", + clearMark: function clearMark(m) { + return m.type.name == "em"; + } + }], + toDOM: function toDOM() { + return emDOM; + } + }, + strong: { + parseDOM: [{ + tag: "strong" + }, { + tag: "b", + getAttrs: function getAttrs(node) { + return node.style.fontWeight != "normal" && null; + } + }, { + style: "font-weight=400", + clearMark: function clearMark(m) { + return m.type.name == "strong"; + } + }, { + style: "font-weight", + getAttrs: function getAttrs(value) { + return /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null; + } + }], + toDOM: function toDOM() { + return strongDOM; + } + }, + code: { + code: true, + parseDOM: [{ + tag: "code" + }], + toDOM: function toDOM() { + return codeDOM; + } + } +}; +var schema = new prosemirrorModel.Schema({ + nodes: nodes, + marks: marks +}); +exports.marks = marks; +exports.nodes = nodes; +exports.schema = schema; diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-schema-list.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-schema-list.cjs new file mode 100644 index 000000000..006f7077c --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-schema-list.cjs @@ -0,0 +1,253 @@ +'use strict'; + +var prosemirrorTransform = require('prosemirror-transform'); +var prosemirrorModel = require('prosemirror-model'); +var prosemirrorState = require('prosemirror-state'); +var olDOM = ["ol", 0], + ulDOM = ["ul", 0], + liDOM = ["li", 0]; +var orderedList = { + attrs: { + order: { + "default": 1, + validate: "number" + } + }, + parseDOM: [{ + tag: "ol", + getAttrs: function getAttrs(dom) { + return { + order: dom.hasAttribute("start") ? +dom.getAttribute("start") : 1 + }; + } + }], + toDOM: function toDOM(node) { + return node.attrs.order == 1 ? olDOM : ["ol", { + start: node.attrs.order + }, 0]; + } +}; +var bulletList = { + parseDOM: [{ + tag: "ul" + }], + toDOM: function toDOM() { + return ulDOM; + } +}; +var listItem = { + parseDOM: [{ + tag: "li" + }], + toDOM: function toDOM() { + return liDOM; + }, + defining: true +}; +function add(obj, props) { + var copy = {}; + for (var prop in obj) copy[prop] = obj[prop]; + for (var _prop in props) copy[_prop] = props[_prop]; + return copy; +} +function addListNodes(nodes, itemContent, listGroup) { + return nodes.append({ + ordered_list: add(orderedList, { + content: "list_item+", + group: listGroup + }), + bullet_list: add(bulletList, { + content: "list_item+", + group: listGroup + }), + list_item: add(listItem, { + content: itemContent + }) + }); +} +function wrapInList(listType) { + var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + return function (state, dispatch) { + var _state$selection = state.selection, + $from = _state$selection.$from, + $to = _state$selection.$to; + var range = $from.blockRange($to); + if (!range) return false; + var tr = dispatch ? state.tr : null; + if (!wrapRangeInList(tr, range, listType, attrs)) return false; + if (dispatch) dispatch(tr.scrollIntoView()); + return true; + }; +} +function wrapRangeInList(tr, range, listType) { + var attrs = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + var doJoin = false, + outerRange = range, + doc = range.$from.doc; + if (range.depth >= 2 && range.$from.node(range.depth - 1).type.compatibleContent(listType) && range.startIndex == 0) { + if (range.$from.index(range.depth - 1) == 0) return false; + var $insert = doc.resolve(range.start - 2); + outerRange = new prosemirrorModel.NodeRange($insert, $insert, range.depth); + if (range.endIndex < range.parent.childCount) range = new prosemirrorModel.NodeRange(range.$from, doc.resolve(range.$to.end(range.depth)), range.depth); + doJoin = true; + } + var wrap = prosemirrorTransform.findWrapping(outerRange, listType, attrs, range); + if (!wrap) return false; + if (tr) doWrapInList(tr, range, wrap, doJoin, listType); + return true; +} +function doWrapInList(tr, range, wrappers, joinBefore, listType) { + var content = prosemirrorModel.Fragment.empty; + for (var i = wrappers.length - 1; i >= 0; i--) content = prosemirrorModel.Fragment.from(wrappers[i].type.create(wrappers[i].attrs, content)); + tr.step(new prosemirrorTransform.ReplaceAroundStep(range.start - (joinBefore ? 2 : 0), range.end, range.start, range.end, new prosemirrorModel.Slice(content, 0, 0), wrappers.length, true)); + var found = 0; + for (var _i = 0; _i < wrappers.length; _i++) if (wrappers[_i].type == listType) found = _i + 1; + var splitDepth = wrappers.length - found; + var splitPos = range.start + wrappers.length - (joinBefore ? 2 : 0), + parent = range.parent; + for (var _i2 = range.startIndex, e = range.endIndex, first = true; _i2 < e; _i2++, first = false) { + if (!first && prosemirrorTransform.canSplit(tr.doc, splitPos, splitDepth)) { + tr.split(splitPos, splitDepth); + splitPos += 2 * splitDepth; + } + splitPos += parent.child(_i2).nodeSize; + } + return tr; +} +function splitListItem(itemType, itemAttrs) { + return function (state, dispatch) { + var _state$selection2 = state.selection, + $from = _state$selection2.$from, + $to = _state$selection2.$to, + node = _state$selection2.node; + if (node && node.isBlock || $from.depth < 2 || !$from.sameParent($to)) return false; + var grandParent = $from.node(-1); + if (grandParent.type != itemType) return false; + if ($from.parent.content.size == 0 && $from.node(-1).childCount == $from.indexAfter(-1)) { + if ($from.depth == 3 || $from.node(-3).type != itemType || $from.index(-2) != $from.node(-2).childCount - 1) return false; + if (dispatch) { + var wrap = prosemirrorModel.Fragment.empty; + var depthBefore = $from.index(-1) ? 1 : $from.index(-2) ? 2 : 3; + for (var d = $from.depth - depthBefore; d >= $from.depth - 3; d--) wrap = prosemirrorModel.Fragment.from($from.node(d).copy(wrap)); + var depthAfter = $from.indexAfter(-1) < $from.node(-2).childCount ? 1 : $from.indexAfter(-2) < $from.node(-3).childCount ? 2 : 3; + wrap = wrap.append(prosemirrorModel.Fragment.from(itemType.createAndFill())); + var start = $from.before($from.depth - (depthBefore - 1)); + var _tr = state.tr.replace(start, $from.after(-depthAfter), new prosemirrorModel.Slice(wrap, 4 - depthBefore, 0)); + var sel = -1; + _tr.doc.nodesBetween(start, _tr.doc.content.size, function (node, pos) { + if (sel > -1) return false; + if (node.isTextblock && node.content.size == 0) sel = pos + 1; + }); + if (sel > -1) _tr.setSelection(prosemirrorState.Selection.near(_tr.doc.resolve(sel))); + dispatch(_tr.scrollIntoView()); + } + return true; + } + var nextType = $to.pos == $from.end() ? grandParent.contentMatchAt(0).defaultType : null; + var tr = state.tr["delete"]($from.pos, $to.pos); + var types = nextType ? [itemAttrs ? { + type: itemType, + attrs: itemAttrs + } : null, { + type: nextType + }] : undefined; + if (!prosemirrorTransform.canSplit(tr.doc, $from.pos, 2, types)) return false; + if (dispatch) dispatch(tr.split($from.pos, 2, types).scrollIntoView()); + return true; + }; +} +function splitListItemKeepMarks(itemType, itemAttrs) { + var split = splitListItem(itemType, itemAttrs); + return function (state, dispatch) { + return split(state, dispatch && function (tr) { + var marks = state.storedMarks || state.selection.$to.parentOffset && state.selection.$from.marks(); + if (marks) tr.ensureMarks(marks); + dispatch(tr); + }); + }; +} +function liftListItem(itemType) { + return function (state, dispatch) { + var _state$selection3 = state.selection, + $from = _state$selection3.$from, + $to = _state$selection3.$to; + var range = $from.blockRange($to, function (node) { + return node.childCount > 0 && node.firstChild.type == itemType; + }); + if (!range) return false; + if (!dispatch) return true; + if ($from.node(range.depth - 1).type == itemType) return liftToOuterList(state, dispatch, itemType, range);else return liftOutOfList(state, dispatch, range); + }; +} +function liftToOuterList(state, dispatch, itemType, range) { + var tr = state.tr, + end = range.end, + endOfList = range.$to.end(range.depth); + if (end < endOfList) { + tr.step(new prosemirrorTransform.ReplaceAroundStep(end - 1, endOfList, end, endOfList, new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(itemType.create(null, range.parent.copy())), 1, 0), 1, true)); + range = new prosemirrorModel.NodeRange(tr.doc.resolve(range.$from.pos), tr.doc.resolve(endOfList), range.depth); + } + var target = prosemirrorTransform.liftTarget(range); + if (target == null) return false; + tr.lift(range, target); + var $after = tr.doc.resolve(tr.mapping.map(end, -1) - 1); + if (prosemirrorTransform.canJoin(tr.doc, $after.pos) && $after.nodeBefore.type == $after.nodeAfter.type) tr.join($after.pos); + dispatch(tr.scrollIntoView()); + return true; +} +function liftOutOfList(state, dispatch, range) { + var tr = state.tr, + list = range.parent; + for (var pos = range.end, i = range.endIndex - 1, e = range.startIndex; i > e; i--) { + pos -= list.child(i).nodeSize; + tr["delete"](pos - 1, pos + 1); + } + var $start = tr.doc.resolve(range.start), + item = $start.nodeAfter; + if (tr.mapping.map(range.end) != range.start + $start.nodeAfter.nodeSize) return false; + var atStart = range.startIndex == 0, + atEnd = range.endIndex == list.childCount; + var parent = $start.node(-1), + indexBefore = $start.index(-1); + if (!parent.canReplace(indexBefore + (atStart ? 0 : 1), indexBefore + 1, item.content.append(atEnd ? prosemirrorModel.Fragment.empty : prosemirrorModel.Fragment.from(list)))) return false; + var start = $start.pos, + end = start + item.nodeSize; + tr.step(new prosemirrorTransform.ReplaceAroundStep(start - (atStart ? 1 : 0), end + (atEnd ? 1 : 0), start + 1, end - 1, new prosemirrorModel.Slice((atStart ? prosemirrorModel.Fragment.empty : prosemirrorModel.Fragment.from(list.copy(prosemirrorModel.Fragment.empty))).append(atEnd ? prosemirrorModel.Fragment.empty : prosemirrorModel.Fragment.from(list.copy(prosemirrorModel.Fragment.empty))), atStart ? 0 : 1, atEnd ? 0 : 1), atStart ? 0 : 1)); + dispatch(tr.scrollIntoView()); + return true; +} +function sinkListItem(itemType) { + return function (state, dispatch) { + var _state$selection4 = state.selection, + $from = _state$selection4.$from, + $to = _state$selection4.$to; + var range = $from.blockRange($to, function (node) { + return node.childCount > 0 && node.firstChild.type == itemType; + }); + if (!range) return false; + var startIndex = range.startIndex; + if (startIndex == 0) return false; + var parent = range.parent, + nodeBefore = parent.child(startIndex - 1); + if (nodeBefore.type != itemType) return false; + if (dispatch) { + var nestedBefore = nodeBefore.lastChild && nodeBefore.lastChild.type == parent.type; + var inner = prosemirrorModel.Fragment.from(nestedBefore ? itemType.create() : null); + var slice = new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(itemType.create(null, prosemirrorModel.Fragment.from(parent.type.create(null, inner)))), nestedBefore ? 3 : 1, 0); + var before = range.start, + after = range.end; + dispatch(state.tr.step(new prosemirrorTransform.ReplaceAroundStep(before - (nestedBefore ? 3 : 1), after, before, after, slice, 1, true)).scrollIntoView()); + } + return true; + }; +} +exports.addListNodes = addListNodes; +exports.bulletList = bulletList; +exports.liftListItem = liftListItem; +exports.listItem = listItem; +exports.orderedList = orderedList; +exports.sinkListItem = sinkListItem; +exports.splitListItem = splitListItem; +exports.splitListItemKeepMarks = splitListItemKeepMarks; +exports.wrapInList = wrapInList; +exports.wrapRangeInList = wrapRangeInList; diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-state.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-state.cjs new file mode 100644 index 000000000..475bbd864 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-state.cjs @@ -0,0 +1,1034 @@ +'use strict'; + +function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } + +function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); } + +function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } + +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } + +Object.defineProperty(exports, '__esModule', { + value: true +}); + +var prosemirrorModel = require('prosemirror-model'); + +var prosemirrorTransform = require('prosemirror-transform'); + +var classesById = Object.create(null); + +var Selection = function () { + function Selection($anchor, $head, ranges) { + _classCallCheck(this, Selection); + + this.$anchor = $anchor; + this.$head = $head; + this.ranges = ranges || [new SelectionRange($anchor.min($head), $anchor.max($head))]; + } + + _createClass(Selection, [{ + key: "anchor", + get: function get() { + return this.$anchor.pos; + } + }, { + key: "head", + get: function get() { + return this.$head.pos; + } + }, { + key: "from", + get: function get() { + return this.$from.pos; + } + }, { + key: "to", + get: function get() { + return this.$to.pos; + } + }, { + key: "$from", + get: function get() { + return this.ranges[0].$from; + } + }, { + key: "$to", + get: function get() { + return this.ranges[0].$to; + } + }, { + key: "empty", + get: function get() { + var ranges = this.ranges; + + for (var i = 0; i < ranges.length; i++) { + if (ranges[i].$from.pos != ranges[i].$to.pos) return false; + } + + return true; + } + }, { + key: "content", + value: function content() { + return this.$from.doc.slice(this.from, this.to, true); + } + }, { + key: "replace", + value: function replace(tr) { + var content = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : prosemirrorModel.Slice.empty; + var lastNode = content.content.lastChild, + lastParent = null; + + for (var i = 0; i < content.openEnd; i++) { + lastParent = lastNode; + lastNode = lastNode.lastChild; + } + + var mapFrom = tr.steps.length, + ranges = this.ranges; + + for (var _i = 0; _i < ranges.length; _i++) { + var _ranges$_i = ranges[_i], + $from = _ranges$_i.$from, + $to = _ranges$_i.$to, + mapping = tr.mapping.slice(mapFrom); + tr.replaceRange(mapping.map($from.pos), mapping.map($to.pos), _i ? prosemirrorModel.Slice.empty : content); + if (_i == 0) selectionToInsertionEnd(tr, mapFrom, (lastNode ? lastNode.isInline : lastParent && lastParent.isTextblock) ? -1 : 1); + } + } + }, { + key: "replaceWith", + value: function replaceWith(tr, node) { + var mapFrom = tr.steps.length, + ranges = this.ranges; + + for (var i = 0; i < ranges.length; i++) { + var _ranges$i = ranges[i], + $from = _ranges$i.$from, + $to = _ranges$i.$to, + mapping = tr.mapping.slice(mapFrom); + var from = mapping.map($from.pos), + to = mapping.map($to.pos); + + if (i) { + tr.deleteRange(from, to); + } else { + tr.replaceRangeWith(from, to, node); + selectionToInsertionEnd(tr, mapFrom, node.isInline ? -1 : 1); + } + } + } + }, { + key: "getBookmark", + value: function getBookmark() { + return TextSelection.between(this.$anchor, this.$head).getBookmark(); + } + }], [{ + key: "findFrom", + value: function findFrom($pos, dir) { + var textOnly = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + var inner = $pos.parent.inlineContent ? new TextSelection($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly); + if (inner) return inner; + + for (var depth = $pos.depth - 1; depth >= 0; depth--) { + var found = dir < 0 ? findSelectionIn($pos.node(0), $pos.node(depth), $pos.before(depth + 1), $pos.index(depth), dir, textOnly) : findSelectionIn($pos.node(0), $pos.node(depth), $pos.after(depth + 1), $pos.index(depth) + 1, dir, textOnly); + if (found) return found; + } + + return null; + } + }, { + key: "near", + value: function near($pos) { + var bias = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + return this.findFrom($pos, bias) || this.findFrom($pos, -bias) || new AllSelection($pos.node(0)); + } + }, { + key: "atStart", + value: function atStart(doc) { + return findSelectionIn(doc, doc, 0, 0, 1) || new AllSelection(doc); + } + }, { + key: "atEnd", + value: function atEnd(doc) { + return findSelectionIn(doc, doc, doc.content.size, doc.childCount, -1) || new AllSelection(doc); + } + }, { + key: "fromJSON", + value: function fromJSON(doc, json) { + if (!json || !json.type) throw new RangeError("Invalid input for Selection.fromJSON"); + var cls = classesById[json.type]; + if (!cls) throw new RangeError("No selection type ".concat(json.type, " defined")); + return cls.fromJSON(doc, json); + } + }, { + key: "jsonID", + value: function jsonID(id, selectionClass) { + if (id in classesById) throw new RangeError("Duplicate use of selection JSON ID " + id); + classesById[id] = selectionClass; + selectionClass.prototype.jsonID = id; + return selectionClass; + } + }]); + + return Selection; +}(); + +Selection.prototype.visible = true; + +var SelectionRange = _createClass(function SelectionRange($from, $to) { + _classCallCheck(this, SelectionRange); + + this.$from = $from; + this.$to = $to; +}); + +var warnedAboutTextSelection = false; + +function checkTextSelection($pos) { + if (!warnedAboutTextSelection && !$pos.parent.inlineContent) { + warnedAboutTextSelection = true; + console["warn"]("TextSelection endpoint not pointing into a node with inline content (" + $pos.parent.type.name + ")"); + } +} + +var TextSelection = function (_Selection) { + _inherits(TextSelection, _Selection); + + var _super = _createSuper(TextSelection); + + function TextSelection($anchor) { + var $head = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : $anchor; + + _classCallCheck(this, TextSelection); + + checkTextSelection($anchor); + checkTextSelection($head); + return _super.call(this, $anchor, $head); + } + + _createClass(TextSelection, [{ + key: "$cursor", + get: function get() { + return this.$anchor.pos == this.$head.pos ? this.$head : null; + } + }, { + key: "map", + value: function map(doc, mapping) { + var $head = doc.resolve(mapping.map(this.head)); + if (!$head.parent.inlineContent) return Selection.near($head); + var $anchor = doc.resolve(mapping.map(this.anchor)); + return new TextSelection($anchor.parent.inlineContent ? $anchor : $head, $head); + } + }, { + key: "replace", + value: function replace(tr) { + var content = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : prosemirrorModel.Slice.empty; + + _get(_getPrototypeOf(TextSelection.prototype), "replace", this).call(this, tr, content); + + if (content == prosemirrorModel.Slice.empty) { + var marks = this.$from.marksAcross(this.$to); + if (marks) tr.ensureMarks(marks); + } + } + }, { + key: "eq", + value: function eq(other) { + return other instanceof TextSelection && other.anchor == this.anchor && other.head == this.head; + } + }, { + key: "getBookmark", + value: function getBookmark() { + return new TextBookmark(this.anchor, this.head); + } + }, { + key: "toJSON", + value: function toJSON() { + return { + type: "text", + anchor: this.anchor, + head: this.head + }; + } + }], [{ + key: "fromJSON", + value: function fromJSON(doc, json) { + if (typeof json.anchor != "number" || typeof json.head != "number") throw new RangeError("Invalid input for TextSelection.fromJSON"); + return new TextSelection(doc.resolve(json.anchor), doc.resolve(json.head)); + } + }, { + key: "create", + value: function create(doc, anchor) { + var head = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : anchor; + var $anchor = doc.resolve(anchor); + return new this($anchor, head == anchor ? $anchor : doc.resolve(head)); + } + }, { + key: "between", + value: function between($anchor, $head, bias) { + var dPos = $anchor.pos - $head.pos; + if (!bias || dPos) bias = dPos >= 0 ? 1 : -1; + + if (!$head.parent.inlineContent) { + var found = Selection.findFrom($head, bias, true) || Selection.findFrom($head, -bias, true); + if (found) $head = found.$head;else return Selection.near($head, bias); + } + + if (!$anchor.parent.inlineContent) { + if (dPos == 0) { + $anchor = $head; + } else { + $anchor = (Selection.findFrom($anchor, -bias, true) || Selection.findFrom($anchor, bias, true)).$anchor; + if ($anchor.pos < $head.pos != dPos < 0) $anchor = $head; + } + } + + return new TextSelection($anchor, $head); + } + }]); + + return TextSelection; +}(Selection); + +Selection.jsonID("text", TextSelection); + +var TextBookmark = function () { + function TextBookmark(anchor, head) { + _classCallCheck(this, TextBookmark); + + this.anchor = anchor; + this.head = head; + } + + _createClass(TextBookmark, [{ + key: "map", + value: function map(mapping) { + return new TextBookmark(mapping.map(this.anchor), mapping.map(this.head)); + } + }, { + key: "resolve", + value: function resolve(doc) { + return TextSelection.between(doc.resolve(this.anchor), doc.resolve(this.head)); + } + }]); + + return TextBookmark; +}(); + +var NodeSelection = function (_Selection2) { + _inherits(NodeSelection, _Selection2); + + var _super2 = _createSuper(NodeSelection); + + function NodeSelection($pos) { + var _this; + + _classCallCheck(this, NodeSelection); + + var node = $pos.nodeAfter; + var $end = $pos.node(0).resolve($pos.pos + node.nodeSize); + _this = _super2.call(this, $pos, $end); + _this.node = node; + return _this; + } + + _createClass(NodeSelection, [{ + key: "map", + value: function map(doc, mapping) { + var _mapping$mapResult = mapping.mapResult(this.anchor), + deleted = _mapping$mapResult.deleted, + pos = _mapping$mapResult.pos; + + var $pos = doc.resolve(pos); + if (deleted) return Selection.near($pos); + return new NodeSelection($pos); + } + }, { + key: "content", + value: function content() { + return new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(this.node), 0, 0); + } + }, { + key: "eq", + value: function eq(other) { + return other instanceof NodeSelection && other.anchor == this.anchor; + } + }, { + key: "toJSON", + value: function toJSON() { + return { + type: "node", + anchor: this.anchor + }; + } + }, { + key: "getBookmark", + value: function getBookmark() { + return new NodeBookmark(this.anchor); + } + }], [{ + key: "fromJSON", + value: function fromJSON(doc, json) { + if (typeof json.anchor != "number") throw new RangeError("Invalid input for NodeSelection.fromJSON"); + return new NodeSelection(doc.resolve(json.anchor)); + } + }, { + key: "create", + value: function create(doc, from) { + return new NodeSelection(doc.resolve(from)); + } + }, { + key: "isSelectable", + value: function isSelectable(node) { + return !node.isText && node.type.spec.selectable !== false; + } + }]); + + return NodeSelection; +}(Selection); + +NodeSelection.prototype.visible = false; +Selection.jsonID("node", NodeSelection); + +var NodeBookmark = function () { + function NodeBookmark(anchor) { + _classCallCheck(this, NodeBookmark); + + this.anchor = anchor; + } + + _createClass(NodeBookmark, [{ + key: "map", + value: function map(mapping) { + var _mapping$mapResult2 = mapping.mapResult(this.anchor), + deleted = _mapping$mapResult2.deleted, + pos = _mapping$mapResult2.pos; + + return deleted ? new TextBookmark(pos, pos) : new NodeBookmark(pos); + } + }, { + key: "resolve", + value: function resolve(doc) { + var $pos = doc.resolve(this.anchor), + node = $pos.nodeAfter; + if (node && NodeSelection.isSelectable(node)) return new NodeSelection($pos); + return Selection.near($pos); + } + }]); + + return NodeBookmark; +}(); + +var AllSelection = function (_Selection3) { + _inherits(AllSelection, _Selection3); + + var _super3 = _createSuper(AllSelection); + + function AllSelection(doc) { + _classCallCheck(this, AllSelection); + + return _super3.call(this, doc.resolve(0), doc.resolve(doc.content.size)); + } + + _createClass(AllSelection, [{ + key: "replace", + value: function replace(tr) { + var content = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : prosemirrorModel.Slice.empty; + + if (content == prosemirrorModel.Slice.empty) { + tr["delete"](0, tr.doc.content.size); + var sel = Selection.atStart(tr.doc); + if (!sel.eq(tr.selection)) tr.setSelection(sel); + } else { + _get(_getPrototypeOf(AllSelection.prototype), "replace", this).call(this, tr, content); + } + } + }, { + key: "toJSON", + value: function toJSON() { + return { + type: "all" + }; + } + }, { + key: "map", + value: function map(doc) { + return new AllSelection(doc); + } + }, { + key: "eq", + value: function eq(other) { + return other instanceof AllSelection; + } + }, { + key: "getBookmark", + value: function getBookmark() { + return AllBookmark; + } + }], [{ + key: "fromJSON", + value: function fromJSON(doc) { + return new AllSelection(doc); + } + }]); + + return AllSelection; +}(Selection); + +Selection.jsonID("all", AllSelection); +var AllBookmark = { + map: function map() { + return this; + }, + resolve: function resolve(doc) { + return new AllSelection(doc); + } +}; + +function findSelectionIn(doc, node, pos, index, dir) { + var text = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; + if (node.inlineContent) return TextSelection.create(doc, pos); + + for (var i = index - (dir > 0 ? 0 : 1); dir > 0 ? i < node.childCount : i >= 0; i += dir) { + var child = node.child(i); + + if (!child.isAtom) { + var inner = findSelectionIn(doc, child, pos + dir, dir < 0 ? child.childCount : 0, dir, text); + if (inner) return inner; + } else if (!text && NodeSelection.isSelectable(child)) { + return NodeSelection.create(doc, pos - (dir < 0 ? child.nodeSize : 0)); + } + + pos += child.nodeSize * dir; + } + + return null; +} + +function selectionToInsertionEnd(tr, startLen, bias) { + var last = tr.steps.length - 1; + if (last < startLen) return; + var step = tr.steps[last]; + if (!(step instanceof prosemirrorTransform.ReplaceStep || step instanceof prosemirrorTransform.ReplaceAroundStep)) return; + var map = tr.mapping.maps[last], + end; + map.forEach(function (_from, _to, _newFrom, newTo) { + if (end == null) end = newTo; + }); + tr.setSelection(Selection.near(tr.doc.resolve(end), bias)); +} + +var UPDATED_SEL = 1, + UPDATED_MARKS = 2, + UPDATED_SCROLL = 4; + +var Transaction = function (_prosemirrorTransform) { + _inherits(Transaction, _prosemirrorTransform); + + var _super4 = _createSuper(Transaction); + + function Transaction(state) { + var _this2; + + _classCallCheck(this, Transaction); + + _this2 = _super4.call(this, state.doc); + _this2.curSelectionFor = 0; + _this2.updated = 0; + _this2.meta = Object.create(null); + _this2.time = Date.now(); + _this2.curSelection = state.selection; + _this2.storedMarks = state.storedMarks; + return _this2; + } + + _createClass(Transaction, [{ + key: "selection", + get: function get() { + if (this.curSelectionFor < this.steps.length) { + this.curSelection = this.curSelection.map(this.doc, this.mapping.slice(this.curSelectionFor)); + this.curSelectionFor = this.steps.length; + } + + return this.curSelection; + } + }, { + key: "setSelection", + value: function setSelection(selection) { + if (selection.$from.doc != this.doc) throw new RangeError("Selection passed to setSelection must point at the current document"); + this.curSelection = selection; + this.curSelectionFor = this.steps.length; + this.updated = (this.updated | UPDATED_SEL) & ~UPDATED_MARKS; + this.storedMarks = null; + return this; + } + }, { + key: "selectionSet", + get: function get() { + return (this.updated & UPDATED_SEL) > 0; + } + }, { + key: "setStoredMarks", + value: function setStoredMarks(marks) { + this.storedMarks = marks; + this.updated |= UPDATED_MARKS; + return this; + } + }, { + key: "ensureMarks", + value: function ensureMarks(marks) { + if (!prosemirrorModel.Mark.sameSet(this.storedMarks || this.selection.$from.marks(), marks)) this.setStoredMarks(marks); + return this; + } + }, { + key: "addStoredMark", + value: function addStoredMark(mark) { + return this.ensureMarks(mark.addToSet(this.storedMarks || this.selection.$head.marks())); + } + }, { + key: "removeStoredMark", + value: function removeStoredMark(mark) { + return this.ensureMarks(mark.removeFromSet(this.storedMarks || this.selection.$head.marks())); + } + }, { + key: "storedMarksSet", + get: function get() { + return (this.updated & UPDATED_MARKS) > 0; + } + }, { + key: "addStep", + value: function addStep(step, doc) { + _get(_getPrototypeOf(Transaction.prototype), "addStep", this).call(this, step, doc); + + this.updated = this.updated & ~UPDATED_MARKS; + this.storedMarks = null; + } + }, { + key: "setTime", + value: function setTime(time) { + this.time = time; + return this; + } + }, { + key: "replaceSelection", + value: function replaceSelection(slice) { + this.selection.replace(this, slice); + return this; + } + }, { + key: "replaceSelectionWith", + value: function replaceSelectionWith(node) { + var inheritMarks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var selection = this.selection; + if (inheritMarks) node = node.mark(this.storedMarks || (selection.empty ? selection.$from.marks() : selection.$from.marksAcross(selection.$to) || prosemirrorModel.Mark.none)); + selection.replaceWith(this, node); + return this; + } + }, { + key: "deleteSelection", + value: function deleteSelection() { + this.selection.replace(this); + return this; + } + }, { + key: "insertText", + value: function insertText(text, from, to) { + var schema = this.doc.type.schema; + + if (from == null) { + if (!text) return this.deleteSelection(); + return this.replaceSelectionWith(schema.text(text), true); + } else { + if (to == null) to = from; + to = to == null ? from : to; + if (!text) return this.deleteRange(from, to); + var marks = this.storedMarks; + + if (!marks) { + var $from = this.doc.resolve(from); + marks = to == from ? $from.marks() : $from.marksAcross(this.doc.resolve(to)); + } + + this.replaceRangeWith(from, to, schema.text(text, marks)); + if (!this.selection.empty) this.setSelection(Selection.near(this.selection.$to)); + return this; + } + } + }, { + key: "setMeta", + value: function setMeta(key, value) { + this.meta[typeof key == "string" ? key : key.key] = value; + return this; + } + }, { + key: "getMeta", + value: function getMeta(key) { + return this.meta[typeof key == "string" ? key : key.key]; + } + }, { + key: "isGeneric", + get: function get() { + for (var _ in this.meta) { + return false; + } + + return true; + } + }, { + key: "scrollIntoView", + value: function scrollIntoView() { + this.updated |= UPDATED_SCROLL; + return this; + } + }, { + key: "scrolledIntoView", + get: function get() { + return (this.updated & UPDATED_SCROLL) > 0; + } + }]); + + return Transaction; +}(prosemirrorTransform.Transform); + +function bind(f, self) { + return !self || !f ? f : f.bind(self); +} + +var FieldDesc = _createClass(function FieldDesc(name, desc, self) { + _classCallCheck(this, FieldDesc); + + this.name = name; + this.init = bind(desc.init, self); + this.apply = bind(desc.apply, self); +}); + +var baseFields = [new FieldDesc("doc", { + init: function init(config) { + return config.doc || config.schema.topNodeType.createAndFill(); + }, + apply: function apply(tr) { + return tr.doc; + } +}), new FieldDesc("selection", { + init: function init(config, instance) { + return config.selection || Selection.atStart(instance.doc); + }, + apply: function apply(tr) { + return tr.selection; + } +}), new FieldDesc("storedMarks", { + init: function init(config) { + return config.storedMarks || null; + }, + apply: function apply(tr, _marks, _old, state) { + return state.selection.$cursor ? tr.storedMarks : null; + } +}), new FieldDesc("scrollToSelection", { + init: function init() { + return 0; + }, + apply: function apply(tr, prev) { + return tr.scrolledIntoView ? prev + 1 : prev; + } +})]; + +var Configuration = _createClass(function Configuration(schema, plugins) { + var _this3 = this; + + _classCallCheck(this, Configuration); + + this.schema = schema; + this.plugins = []; + this.pluginsByKey = Object.create(null); + this.fields = baseFields.slice(); + if (plugins) plugins.forEach(function (plugin) { + if (_this3.pluginsByKey[plugin.key]) throw new RangeError("Adding different instances of a keyed plugin (" + plugin.key + ")"); + + _this3.plugins.push(plugin); + + _this3.pluginsByKey[plugin.key] = plugin; + if (plugin.spec.state) _this3.fields.push(new FieldDesc(plugin.key, plugin.spec.state, plugin)); + }); +}); + +var EditorState = function () { + function EditorState(config) { + _classCallCheck(this, EditorState); + + this.config = config; + } + + _createClass(EditorState, [{ + key: "schema", + get: function get() { + return this.config.schema; + } + }, { + key: "plugins", + get: function get() { + return this.config.plugins; + } + }, { + key: "apply", + value: function apply(tr) { + return this.applyTransaction(tr).state; + } + }, { + key: "filterTransaction", + value: function filterTransaction(tr) { + var ignore = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; + + for (var i = 0; i < this.config.plugins.length; i++) { + if (i != ignore) { + var plugin = this.config.plugins[i]; + if (plugin.spec.filterTransaction && !plugin.spec.filterTransaction.call(plugin, tr, this)) return false; + } + } + + return true; + } + }, { + key: "applyTransaction", + value: function applyTransaction(rootTr) { + if (!this.filterTransaction(rootTr)) return { + state: this, + transactions: [] + }; + var trs = [rootTr], + newState = this.applyInner(rootTr), + seen = null; + + for (;;) { + var haveNew = false; + + for (var i = 0; i < this.config.plugins.length; i++) { + var plugin = this.config.plugins[i]; + + if (plugin.spec.appendTransaction) { + var n = seen ? seen[i].n : 0, + oldState = seen ? seen[i].state : this; + var tr = n < trs.length && plugin.spec.appendTransaction.call(plugin, n ? trs.slice(n) : trs, oldState, newState); + + if (tr && newState.filterTransaction(tr, i)) { + tr.setMeta("appendedTransaction", rootTr); + + if (!seen) { + seen = []; + + for (var j = 0; j < this.config.plugins.length; j++) { + seen.push(j < i ? { + state: newState, + n: trs.length + } : { + state: this, + n: 0 + }); + } + } + + trs.push(tr); + newState = newState.applyInner(tr); + haveNew = true; + } + + if (seen) seen[i] = { + state: newState, + n: trs.length + }; + } + } + + if (!haveNew) return { + state: newState, + transactions: trs + }; + } + } + }, { + key: "applyInner", + value: function applyInner(tr) { + if (!tr.before.eq(this.doc)) throw new RangeError("Applying a mismatched transaction"); + var newInstance = new EditorState(this.config), + fields = this.config.fields; + + for (var i = 0; i < fields.length; i++) { + var field = fields[i]; + newInstance[field.name] = field.apply(tr, this[field.name], this, newInstance); + } + + return newInstance; + } + }, { + key: "tr", + get: function get() { + return new Transaction(this); + } + }, { + key: "reconfigure", + value: function reconfigure(config) { + var $config = new Configuration(this.schema, config.plugins); + var fields = $config.fields, + instance = new EditorState($config); + + for (var i = 0; i < fields.length; i++) { + var name = fields[i].name; + instance[name] = this.hasOwnProperty(name) ? this[name] : fields[i].init(config, instance); + } + + return instance; + } + }, { + key: "toJSON", + value: function toJSON(pluginFields) { + var result = { + doc: this.doc.toJSON(), + selection: this.selection.toJSON() + }; + if (this.storedMarks) result.storedMarks = this.storedMarks.map(function (m) { + return m.toJSON(); + }); + if (pluginFields && _typeof(pluginFields) == 'object') for (var prop in pluginFields) { + if (prop == "doc" || prop == "selection") throw new RangeError("The JSON fields `doc` and `selection` are reserved"); + var plugin = pluginFields[prop], + state = plugin.spec.state; + if (state && state.toJSON) result[prop] = state.toJSON.call(plugin, this[plugin.key]); + } + return result; + } + }], [{ + key: "create", + value: function create(config) { + var $config = new Configuration(config.doc ? config.doc.type.schema : config.schema, config.plugins); + var instance = new EditorState($config); + + for (var i = 0; i < $config.fields.length; i++) { + instance[$config.fields[i].name] = $config.fields[i].init(config, instance); + } + + return instance; + } + }, { + key: "fromJSON", + value: function fromJSON(config, json, pluginFields) { + if (!json) throw new RangeError("Invalid input for EditorState.fromJSON"); + if (!config.schema) throw new RangeError("Required config field 'schema' missing"); + var $config = new Configuration(config.schema, config.plugins); + var instance = new EditorState($config); + $config.fields.forEach(function (field) { + if (field.name == "doc") { + instance.doc = prosemirrorModel.Node.fromJSON(config.schema, json.doc); + } else if (field.name == "selection") { + instance.selection = Selection.fromJSON(instance.doc, json.selection); + } else if (field.name == "storedMarks") { + if (json.storedMarks) instance.storedMarks = json.storedMarks.map(config.schema.markFromJSON); + } else { + if (pluginFields) for (var prop in pluginFields) { + var plugin = pluginFields[prop], + state = plugin.spec.state; + + if (plugin.key == field.name && state && state.fromJSON && Object.prototype.hasOwnProperty.call(json, prop)) { + instance[field.name] = state.fromJSON.call(plugin, config, json[prop], instance); + return; + } + } + instance[field.name] = field.init(config, instance); + } + }); + return instance; + } + }]); + + return EditorState; +}(); + +function bindProps(obj, self, target) { + for (var prop in obj) { + var val = obj[prop]; + if (val instanceof Function) val = val.bind(self);else if (prop == "handleDOMEvents") val = bindProps(val, self, {}); + target[prop] = val; + } + + return target; +} + +var Plugin = function () { + function Plugin(spec) { + _classCallCheck(this, Plugin); + + this.spec = spec; + this.props = {}; + if (spec.props) bindProps(spec.props, this, this.props); + this.key = spec.key ? spec.key.key : createKey("plugin"); + } + + _createClass(Plugin, [{ + key: "getState", + value: function getState(state) { + return state[this.key]; + } + }]); + + return Plugin; +}(); + +var keys = Object.create(null); + +function createKey(name) { + if (name in keys) return name + "$" + ++keys[name]; + keys[name] = 0; + return name + "$"; +} + +var PluginKey = function () { + function PluginKey() { + var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "key"; + + _classCallCheck(this, PluginKey); + + this.key = createKey(name); + } + + _createClass(PluginKey, [{ + key: "get", + value: function get(state) { + return state.config.pluginsByKey[this.key]; + } + }, { + key: "getState", + value: function getState(state) { + return state[this.key]; + } + }]); + + return PluginKey; +}(); + +exports.AllSelection = AllSelection; +exports.EditorState = EditorState; +exports.NodeSelection = NodeSelection; +exports.Plugin = Plugin; +exports.PluginKey = PluginKey; +exports.Selection = Selection; +exports.SelectionRange = SelectionRange; +exports.TextSelection = TextSelection; +exports.Transaction = Transaction; diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-view.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-view.cjs new file mode 100644 index 000000000..7432b57e4 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-view.cjs @@ -0,0 +1,5253 @@ +'use strict'; + +function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } +function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } +function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } +function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } +function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } +function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } +function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } +function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get.bind(); } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); } +function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } +function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } +function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var prosemirrorState = require('prosemirror-state'); +var prosemirrorModel = require('prosemirror-model'); +var prosemirrorTransform = require('prosemirror-transform'); +var domIndex = function domIndex(node) { + for (var index = 0;; index++) { + node = node.previousSibling; + if (!node) return index; + } +}; +var parentNode = function parentNode(node) { + var parent = node.assignedSlot || node.parentNode; + return parent && parent.nodeType == 11 ? parent.host : parent; +}; +var reusedRange = null; +var textRange = function textRange(node, from, to) { + var range = reusedRange || (reusedRange = document.createRange()); + range.setEnd(node, to == null ? node.nodeValue.length : to); + range.setStart(node, from || 0); + return range; +}; +var clearReusedRange = function clearReusedRange() { + reusedRange = null; +}; +var isEquivalentPosition = function isEquivalentPosition(node, off, targetNode, targetOff) { + return targetNode && (scanFor(node, off, targetNode, targetOff, -1) || scanFor(node, off, targetNode, targetOff, 1)); +}; +var atomElements = /^(img|br|input|textarea|hr)$/i; +function scanFor(node, off, targetNode, targetOff, dir) { + for (;;) { + if (node == targetNode && off == targetOff) return true; + if (off == (dir < 0 ? 0 : nodeSize(node))) { + var parent = node.parentNode; + if (!parent || parent.nodeType != 1 || hasBlockDesc(node) || atomElements.test(node.nodeName) || node.contentEditable == "false") return false; + off = domIndex(node) + (dir < 0 ? 0 : 1); + node = parent; + } else if (node.nodeType == 1) { + node = node.childNodes[off + (dir < 0 ? -1 : 0)]; + if (node.contentEditable == "false") return false; + off = dir < 0 ? nodeSize(node) : 0; + } else { + return false; + } + } +} +function nodeSize(node) { + return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length; +} +function textNodeBefore$1(node, offset) { + for (;;) { + if (node.nodeType == 3 && offset) return node; + if (node.nodeType == 1 && offset > 0) { + if (node.contentEditable == "false") return null; + node = node.childNodes[offset - 1]; + offset = nodeSize(node); + } else if (node.parentNode && !hasBlockDesc(node)) { + offset = domIndex(node); + node = node.parentNode; + } else { + return null; + } + } +} +function textNodeAfter$1(node, offset) { + for (;;) { + if (node.nodeType == 3 && offset < node.nodeValue.length) return node; + if (node.nodeType == 1 && offset < node.childNodes.length) { + if (node.contentEditable == "false") return null; + node = node.childNodes[offset]; + offset = 0; + } else if (node.parentNode && !hasBlockDesc(node)) { + offset = domIndex(node) + 1; + node = node.parentNode; + } else { + return null; + } + } +} +function isOnEdge(node, offset, parent) { + for (var atStart = offset == 0, atEnd = offset == nodeSize(node); atStart || atEnd;) { + if (node == parent) return true; + var index = domIndex(node); + node = node.parentNode; + if (!node) return false; + atStart = atStart && index == 0; + atEnd = atEnd && index == nodeSize(node); + } +} +function hasBlockDesc(dom) { + var desc; + for (var cur = dom; cur; cur = cur.parentNode) if (desc = cur.pmViewDesc) break; + return desc && desc.node && desc.node.isBlock && (desc.dom == dom || desc.contentDOM == dom); +} +var selectionCollapsed = function selectionCollapsed(domSel) { + return domSel.focusNode && isEquivalentPosition(domSel.focusNode, domSel.focusOffset, domSel.anchorNode, domSel.anchorOffset); +}; +function keyEvent(keyCode, key) { + var event = document.createEvent("Event"); + event.initEvent("keydown", true, true); + event.keyCode = keyCode; + event.key = event.code = key; + return event; +} +function deepActiveElement(doc) { + var elt = doc.activeElement; + while (elt && elt.shadowRoot) elt = elt.shadowRoot.activeElement; + return elt; +} +function caretFromPoint(doc, x, y) { + if (doc.caretPositionFromPoint) { + try { + var pos = doc.caretPositionFromPoint(x, y); + if (pos) return { + node: pos.offsetNode, + offset: Math.min(nodeSize(pos.offsetNode), pos.offset) + }; + } catch (_) {} + } + if (doc.caretRangeFromPoint) { + var range = doc.caretRangeFromPoint(x, y); + if (range) return { + node: range.startContainer, + offset: Math.min(nodeSize(range.startContainer), range.startOffset) + }; + } +} +var nav = typeof navigator != "undefined" ? navigator : null; +var doc = typeof document != "undefined" ? document : null; +var agent = nav && nav.userAgent || ""; +var ie_edge = /Edge\/(\d+)/.exec(agent); +var ie_upto10 = /MSIE \d/.exec(agent); +var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(agent); +var ie = !!(ie_upto10 || ie_11up || ie_edge); +var ie_version = ie_upto10 ? document.documentMode : ie_11up ? +ie_11up[1] : ie_edge ? +ie_edge[1] : 0; +var gecko = !ie && /gecko\/(\d+)/i.test(agent); +gecko && +(/Firefox\/(\d+)/.exec(agent) || [0, 0])[1]; +var _chrome = !ie && /Chrome\/(\d+)/.exec(agent); +var chrome = !!_chrome; +var chrome_version = _chrome ? +_chrome[1] : 0; +var safari = !ie && !!nav && /Apple Computer/.test(nav.vendor); +var ios = safari && (/Mobile\/\w+/.test(agent) || !!nav && nav.maxTouchPoints > 2); +var mac = ios || (nav ? /Mac/.test(nav.platform) : false); +var windows = nav ? /Win/.test(nav.platform) : false; +var android = /Android \d/.test(agent); +var webkit = !!doc && "webkitFontSmoothing" in doc.documentElement.style; +var webkit_version = webkit ? +(/\bAppleWebKit\/(\d+)/.exec(navigator.userAgent) || [0, 0])[1] : 0; +function windowRect(doc) { + var vp = doc.defaultView && doc.defaultView.visualViewport; + if (vp) return { + left: 0, + right: vp.width, + top: 0, + bottom: vp.height + }; + return { + left: 0, + right: doc.documentElement.clientWidth, + top: 0, + bottom: doc.documentElement.clientHeight + }; +} +function getSide(value, side) { + return typeof value == "number" ? value : value[side]; +} +function clientRect(node) { + var rect = node.getBoundingClientRect(); + var scaleX = rect.width / node.offsetWidth || 1; + var scaleY = rect.height / node.offsetHeight || 1; + return { + left: rect.left, + right: rect.left + node.clientWidth * scaleX, + top: rect.top, + bottom: rect.top + node.clientHeight * scaleY + }; +} +function scrollRectIntoView(view, rect, startDOM) { + var scrollThreshold = view.someProp("scrollThreshold") || 0, + scrollMargin = view.someProp("scrollMargin") || 5; + var doc = view.dom.ownerDocument; + for (var parent = startDOM || view.dom;;) { + if (!parent) break; + if (parent.nodeType != 1) { + parent = parentNode(parent); + continue; + } + var elt = parent; + var atTop = elt == doc.body; + var bounding = atTop ? windowRect(doc) : clientRect(elt); + var moveX = 0, + moveY = 0; + if (rect.top < bounding.top + getSide(scrollThreshold, "top")) moveY = -(bounding.top - rect.top + getSide(scrollMargin, "top"));else if (rect.bottom > bounding.bottom - getSide(scrollThreshold, "bottom")) moveY = rect.bottom - rect.top > bounding.bottom - bounding.top ? rect.top + getSide(scrollMargin, "top") - bounding.top : rect.bottom - bounding.bottom + getSide(scrollMargin, "bottom"); + if (rect.left < bounding.left + getSide(scrollThreshold, "left")) moveX = -(bounding.left - rect.left + getSide(scrollMargin, "left"));else if (rect.right > bounding.right - getSide(scrollThreshold, "right")) moveX = rect.right - bounding.right + getSide(scrollMargin, "right"); + if (moveX || moveY) { + if (atTop) { + doc.defaultView.scrollBy(moveX, moveY); + } else { + var startX = elt.scrollLeft, + startY = elt.scrollTop; + if (moveY) elt.scrollTop += moveY; + if (moveX) elt.scrollLeft += moveX; + var dX = elt.scrollLeft - startX, + dY = elt.scrollTop - startY; + rect = { + left: rect.left - dX, + top: rect.top - dY, + right: rect.right - dX, + bottom: rect.bottom - dY + }; + } + } + var pos = atTop ? "fixed" : getComputedStyle(parent).position; + if (/^(fixed|sticky)$/.test(pos)) break; + parent = pos == "absolute" ? parent.offsetParent : parentNode(parent); + } +} +function storeScrollPos(view) { + var rect = view.dom.getBoundingClientRect(), + startY = Math.max(0, rect.top); + var refDOM, refTop; + for (var x = (rect.left + rect.right) / 2, y = startY + 1; y < Math.min(innerHeight, rect.bottom); y += 5) { + var dom = view.root.elementFromPoint(x, y); + if (!dom || dom == view.dom || !view.dom.contains(dom)) continue; + var localRect = dom.getBoundingClientRect(); + if (localRect.top >= startY - 20) { + refDOM = dom; + refTop = localRect.top; + break; + } + } + return { + refDOM: refDOM, + refTop: refTop, + stack: scrollStack(view.dom) + }; +} +function scrollStack(dom) { + var stack = [], + doc = dom.ownerDocument; + for (var cur = dom; cur; cur = parentNode(cur)) { + stack.push({ + dom: cur, + top: cur.scrollTop, + left: cur.scrollLeft + }); + if (dom == doc) break; + } + return stack; +} +function resetScrollPos(_ref) { + var refDOM = _ref.refDOM, + refTop = _ref.refTop, + stack = _ref.stack; + var newRefTop = refDOM ? refDOM.getBoundingClientRect().top : 0; + restoreScrollStack(stack, newRefTop == 0 ? 0 : newRefTop - refTop); +} +function restoreScrollStack(stack, dTop) { + for (var i = 0; i < stack.length; i++) { + var _stack$i = stack[i], + dom = _stack$i.dom, + top = _stack$i.top, + left = _stack$i.left; + if (dom.scrollTop != top + dTop) dom.scrollTop = top + dTop; + if (dom.scrollLeft != left) dom.scrollLeft = left; + } +} +var preventScrollSupported = null; +function focusPreventScroll(dom) { + if (dom.setActive) return dom.setActive(); + if (preventScrollSupported) return dom.focus(preventScrollSupported); + var stored = scrollStack(dom); + dom.focus(preventScrollSupported == null ? { + get preventScroll() { + preventScrollSupported = { + preventScroll: true + }; + return true; + } + } : undefined); + if (!preventScrollSupported) { + preventScrollSupported = false; + restoreScrollStack(stored, 0); + } +} +function findOffsetInNode(node, coords) { + var closest, + dxClosest = 2e8, + coordsClosest, + offset = 0; + var rowBot = coords.top, + rowTop = coords.top; + var firstBelow, coordsBelow; + for (var child = node.firstChild, childIndex = 0; child; child = child.nextSibling, childIndex++) { + var rects = void 0; + if (child.nodeType == 1) rects = child.getClientRects();else if (child.nodeType == 3) rects = textRange(child).getClientRects();else continue; + for (var i = 0; i < rects.length; i++) { + var rect = rects[i]; + if (rect.top <= rowBot && rect.bottom >= rowTop) { + rowBot = Math.max(rect.bottom, rowBot); + rowTop = Math.min(rect.top, rowTop); + var dx = rect.left > coords.left ? rect.left - coords.left : rect.right < coords.left ? coords.left - rect.right : 0; + if (dx < dxClosest) { + closest = child; + dxClosest = dx; + coordsClosest = dx && closest.nodeType == 3 ? { + left: rect.right < coords.left ? rect.right : rect.left, + top: coords.top + } : coords; + if (child.nodeType == 1 && dx) offset = childIndex + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0); + continue; + } + } else if (rect.top > coords.top && !firstBelow && rect.left <= coords.left && rect.right >= coords.left) { + firstBelow = child; + coordsBelow = { + left: Math.max(rect.left, Math.min(rect.right, coords.left)), + top: rect.top + }; + } + if (!closest && (coords.left >= rect.right && coords.top >= rect.top || coords.left >= rect.left && coords.top >= rect.bottom)) offset = childIndex + 1; + } + } + if (!closest && firstBelow) { + closest = firstBelow; + coordsClosest = coordsBelow; + dxClosest = 0; + } + if (closest && closest.nodeType == 3) return findOffsetInText(closest, coordsClosest); + if (!closest || dxClosest && closest.nodeType == 1) return { + node: node, + offset: offset + }; + return findOffsetInNode(closest, coordsClosest); +} +function findOffsetInText(node, coords) { + var len = node.nodeValue.length; + var range = document.createRange(); + for (var i = 0; i < len; i++) { + range.setEnd(node, i + 1); + range.setStart(node, i); + var rect = singleRect(range, 1); + if (rect.top == rect.bottom) continue; + if (inRect(coords, rect)) return { + node: node, + offset: i + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0) + }; + } + return { + node: node, + offset: 0 + }; +} +function inRect(coords, rect) { + return coords.left >= rect.left - 1 && coords.left <= rect.right + 1 && coords.top >= rect.top - 1 && coords.top <= rect.bottom + 1; +} +function targetKludge(dom, coords) { + var parent = dom.parentNode; + if (parent && /^li$/i.test(parent.nodeName) && coords.left < dom.getBoundingClientRect().left) return parent; + return dom; +} +function posFromElement(view, elt, coords) { + var _findOffsetInNode = findOffsetInNode(elt, coords), + node = _findOffsetInNode.node, + offset = _findOffsetInNode.offset, + bias = -1; + if (node.nodeType == 1 && !node.firstChild) { + var rect = node.getBoundingClientRect(); + bias = rect.left != rect.right && coords.left > (rect.left + rect.right) / 2 ? 1 : -1; + } + return view.docView.posFromDOM(node, offset, bias); +} +function posFromCaret(view, node, offset, coords) { + var outsideBlock = -1; + for (var cur = node, sawBlock = false;;) { + if (cur == view.dom) break; + var desc = view.docView.nearestDesc(cur, true), + rect = void 0; + if (!desc) return null; + if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent || !desc.contentDOM) && ((rect = desc.dom.getBoundingClientRect()).width || rect.height)) { + if (desc.node.isBlock && desc.parent) { + if (!sawBlock && rect.left > coords.left || rect.top > coords.top) outsideBlock = desc.posBefore;else if (!sawBlock && rect.right < coords.left || rect.bottom < coords.top) outsideBlock = desc.posAfter; + sawBlock = true; + } + if (!desc.contentDOM && outsideBlock < 0 && !desc.node.isText) { + var before = desc.node.isBlock ? coords.top < (rect.top + rect.bottom) / 2 : coords.left < (rect.left + rect.right) / 2; + return before ? desc.posBefore : desc.posAfter; + } + } + cur = desc.dom.parentNode; + } + return outsideBlock > -1 ? outsideBlock : view.docView.posFromDOM(node, offset, -1); +} +function elementFromPoint(element, coords, box) { + var len = element.childNodes.length; + if (len && box.top < box.bottom) { + for (var startI = Math.max(0, Math.min(len - 1, Math.floor(len * (coords.top - box.top) / (box.bottom - box.top)) - 2)), i = startI;;) { + var child = element.childNodes[i]; + if (child.nodeType == 1) { + var rects = child.getClientRects(); + for (var j = 0; j < rects.length; j++) { + var rect = rects[j]; + if (inRect(coords, rect)) return elementFromPoint(child, coords, rect); + } + } + if ((i = (i + 1) % len) == startI) break; + } + } + return element; +} +function _posAtCoords(view, coords) { + var doc = view.dom.ownerDocument, + node, + offset = 0; + var caret = caretFromPoint(doc, coords.left, coords.top); + if (caret) { + node = caret.node; + offset = caret.offset; + } + var elt = (view.root.elementFromPoint ? view.root : doc).elementFromPoint(coords.left, coords.top); + var pos; + if (!elt || !view.dom.contains(elt.nodeType != 1 ? elt.parentNode : elt)) { + var box = view.dom.getBoundingClientRect(); + if (!inRect(coords, box)) return null; + elt = elementFromPoint(view.dom, coords, box); + if (!elt) return null; + } + if (safari) { + for (var p = elt; node && p; p = parentNode(p)) if (p.draggable) node = undefined; + } + elt = targetKludge(elt, coords); + if (node) { + if (gecko && node.nodeType == 1) { + offset = Math.min(offset, node.childNodes.length); + if (offset < node.childNodes.length) { + var next = node.childNodes[offset], + _box; + if (next.nodeName == "IMG" && (_box = next.getBoundingClientRect()).right <= coords.left && _box.bottom > coords.top) offset++; + } + } + var prev; + if (webkit && offset && node.nodeType == 1 && (prev = node.childNodes[offset - 1]).nodeType == 1 && prev.contentEditable == "false" && prev.getBoundingClientRect().top >= coords.top) offset--; + if (node == view.dom && offset == node.childNodes.length - 1 && node.lastChild.nodeType == 1 && coords.top > node.lastChild.getBoundingClientRect().bottom) pos = view.state.doc.content.size;else if (offset == 0 || node.nodeType != 1 || node.childNodes[offset - 1].nodeName != "BR") pos = posFromCaret(view, node, offset, coords); + } + if (pos == null) pos = posFromElement(view, elt, coords); + var desc = view.docView.nearestDesc(elt, true); + return { + pos: pos, + inside: desc ? desc.posAtStart - desc.border : -1 + }; +} +function nonZero(rect) { + return rect.top < rect.bottom || rect.left < rect.right; +} +function singleRect(target, bias) { + var rects = target.getClientRects(); + if (rects.length) { + var first = rects[bias < 0 ? 0 : rects.length - 1]; + if (nonZero(first)) return first; + } + return Array.prototype.find.call(rects, nonZero) || target.getBoundingClientRect(); +} +var BIDI = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; +function _coordsAtPos(view, pos, side) { + var _view$docView$domFrom = view.docView.domFromPos(pos, side < 0 ? -1 : 1), + node = _view$docView$domFrom.node, + offset = _view$docView$domFrom.offset, + atom = _view$docView$domFrom.atom; + var supportEmptyRange = webkit || gecko; + if (node.nodeType == 3) { + if (supportEmptyRange && (BIDI.test(node.nodeValue) || (side < 0 ? !offset : offset == node.nodeValue.length))) { + var rect = singleRect(textRange(node, offset, offset), side); + if (gecko && offset && /\s/.test(node.nodeValue[offset - 1]) && offset < node.nodeValue.length) { + var rectBefore = singleRect(textRange(node, offset - 1, offset - 1), -1); + if (rectBefore.top == rect.top) { + var rectAfter = singleRect(textRange(node, offset, offset + 1), -1); + if (rectAfter.top != rect.top) return flattenV(rectAfter, rectAfter.left < rectBefore.left); + } + } + return rect; + } else { + var from = offset, + to = offset, + takeSide = side < 0 ? 1 : -1; + if (side < 0 && !offset) { + to++; + takeSide = -1; + } else if (side >= 0 && offset == node.nodeValue.length) { + from--; + takeSide = 1; + } else if (side < 0) { + from--; + } else { + to++; + } + return flattenV(singleRect(textRange(node, from, to), takeSide), takeSide < 0); + } + } + var $dom = view.state.doc.resolve(pos - (atom || 0)); + if (!$dom.parent.inlineContent) { + if (atom == null && offset && (side < 0 || offset == nodeSize(node))) { + var before = node.childNodes[offset - 1]; + if (before.nodeType == 1) return flattenH(before.getBoundingClientRect(), false); + } + if (atom == null && offset < nodeSize(node)) { + var after = node.childNodes[offset]; + if (after.nodeType == 1) return flattenH(after.getBoundingClientRect(), true); + } + return flattenH(node.getBoundingClientRect(), side >= 0); + } + if (atom == null && offset && (side < 0 || offset == nodeSize(node))) { + var _before = node.childNodes[offset - 1]; + var target = _before.nodeType == 3 ? textRange(_before, nodeSize(_before) - (supportEmptyRange ? 0 : 1)) : _before.nodeType == 1 && (_before.nodeName != "BR" || !_before.nextSibling) ? _before : null; + if (target) return flattenV(singleRect(target, 1), false); + } + if (atom == null && offset < nodeSize(node)) { + var _after = node.childNodes[offset]; + while (_after.pmViewDesc && _after.pmViewDesc.ignoreForCoords) _after = _after.nextSibling; + var _target = !_after ? null : _after.nodeType == 3 ? textRange(_after, 0, supportEmptyRange ? 0 : 1) : _after.nodeType == 1 ? _after : null; + if (_target) return flattenV(singleRect(_target, -1), true); + } + return flattenV(singleRect(node.nodeType == 3 ? textRange(node) : node, -side), side >= 0); +} +function flattenV(rect, left) { + if (rect.width == 0) return rect; + var x = left ? rect.left : rect.right; + return { + top: rect.top, + bottom: rect.bottom, + left: x, + right: x + }; +} +function flattenH(rect, top) { + if (rect.height == 0) return rect; + var y = top ? rect.top : rect.bottom; + return { + top: y, + bottom: y, + left: rect.left, + right: rect.right + }; +} +function withFlushedState(view, state, f) { + var viewState = view.state, + active = view.root.activeElement; + if (viewState != state) view.updateState(state); + if (active != view.dom) view.focus(); + try { + return f(); + } finally { + if (viewState != state) view.updateState(viewState); + if (active != view.dom && active) active.focus(); + } +} +function endOfTextblockVertical(view, state, dir) { + var sel = state.selection; + var $pos = dir == "up" ? sel.$from : sel.$to; + return withFlushedState(view, state, function () { + var _view$docView$domFrom2 = view.docView.domFromPos($pos.pos, dir == "up" ? -1 : 1), + dom = _view$docView$domFrom2.node; + for (;;) { + var nearest = view.docView.nearestDesc(dom, true); + if (!nearest) break; + if (nearest.node.isBlock) { + dom = nearest.contentDOM || nearest.dom; + break; + } + dom = nearest.dom.parentNode; + } + var coords = _coordsAtPos(view, $pos.pos, 1); + for (var child = dom.firstChild; child; child = child.nextSibling) { + var boxes = void 0; + if (child.nodeType == 1) boxes = child.getClientRects();else if (child.nodeType == 3) boxes = textRange(child, 0, child.nodeValue.length).getClientRects();else continue; + for (var i = 0; i < boxes.length; i++) { + var box = boxes[i]; + if (box.bottom > box.top + 1 && (dir == "up" ? coords.top - box.top > (box.bottom - coords.top) * 2 : box.bottom - coords.bottom > (coords.bottom - box.top) * 2)) return false; + } + } + return true; + }); +} +var maybeRTL = /[\u0590-\u08ac]/; +function endOfTextblockHorizontal(view, state, dir) { + var $head = state.selection.$head; + if (!$head.parent.isTextblock) return false; + var offset = $head.parentOffset, + atStart = !offset, + atEnd = offset == $head.parent.content.size; + var sel = view.domSelection(); + if (!sel) return $head.pos == $head.start() || $head.pos == $head.end(); + if (!maybeRTL.test($head.parent.textContent) || !sel.modify) return dir == "left" || dir == "backward" ? atStart : atEnd; + return withFlushedState(view, state, function () { + var _view$domSelectionRan = view.domSelectionRange(), + oldNode = _view$domSelectionRan.focusNode, + oldOff = _view$domSelectionRan.focusOffset, + anchorNode = _view$domSelectionRan.anchorNode, + anchorOffset = _view$domSelectionRan.anchorOffset; + var oldBidiLevel = sel.caretBidiLevel; + sel.modify("move", dir, "character"); + var parentDOM = $head.depth ? view.docView.domAfterPos($head.before()) : view.dom; + var _view$domSelectionRan2 = view.domSelectionRange(), + newNode = _view$domSelectionRan2.focusNode, + newOff = _view$domSelectionRan2.focusOffset; + var result = newNode && !parentDOM.contains(newNode.nodeType == 1 ? newNode : newNode.parentNode) || oldNode == newNode && oldOff == newOff; + try { + sel.collapse(anchorNode, anchorOffset); + if (oldNode && (oldNode != anchorNode || oldOff != anchorOffset) && sel.extend) sel.extend(oldNode, oldOff); + } catch (_) {} + if (oldBidiLevel != null) sel.caretBidiLevel = oldBidiLevel; + return result; + }); +} +var cachedState = null; +var cachedDir = null; +var cachedResult = false; +function _endOfTextblock(view, state, dir) { + if (cachedState == state && cachedDir == dir) return cachedResult; + cachedState = state; + cachedDir = dir; + return cachedResult = dir == "up" || dir == "down" ? endOfTextblockVertical(view, state, dir) : endOfTextblockHorizontal(view, state, dir); +} +var NOT_DIRTY = 0, + CHILD_DIRTY = 1, + CONTENT_DIRTY = 2, + NODE_DIRTY = 3; +var ViewDesc = function () { + function ViewDesc(parent, children, dom, contentDOM) { + _classCallCheck(this, ViewDesc); + this.parent = parent; + this.children = children; + this.dom = dom; + this.contentDOM = contentDOM; + this.dirty = NOT_DIRTY; + dom.pmViewDesc = this; + } + _createClass(ViewDesc, [{ + key: "matchesWidget", + value: function matchesWidget(widget) { + return false; + } + }, { + key: "matchesMark", + value: function matchesMark(mark) { + return false; + } + }, { + key: "matchesNode", + value: function matchesNode(node, outerDeco, innerDeco) { + return false; + } + }, { + key: "matchesHack", + value: function matchesHack(nodeName) { + return false; + } + }, { + key: "parseRule", + value: function parseRule() { + return null; + } + }, { + key: "stopEvent", + value: function stopEvent(event) { + return false; + } + }, { + key: "size", + get: function get() { + var size = 0; + for (var i = 0; i < this.children.length; i++) size += this.children[i].size; + return size; + } + }, { + key: "border", + get: function get() { + return 0; + } + }, { + key: "destroy", + value: function destroy() { + this.parent = undefined; + if (this.dom.pmViewDesc == this) this.dom.pmViewDesc = undefined; + for (var i = 0; i < this.children.length; i++) this.children[i].destroy(); + } + }, { + key: "posBeforeChild", + value: function posBeforeChild(child) { + for (var i = 0, pos = this.posAtStart;; i++) { + var cur = this.children[i]; + if (cur == child) return pos; + pos += cur.size; + } + } + }, { + key: "posBefore", + get: function get() { + return this.parent.posBeforeChild(this); + } + }, { + key: "posAtStart", + get: function get() { + return this.parent ? this.parent.posBeforeChild(this) + this.border : 0; + } + }, { + key: "posAfter", + get: function get() { + return this.posBefore + this.size; + } + }, { + key: "posAtEnd", + get: function get() { + return this.posAtStart + this.size - 2 * this.border; + } + }, { + key: "localPosFromDOM", + value: function localPosFromDOM(dom, offset, bias) { + if (this.contentDOM && this.contentDOM.contains(dom.nodeType == 1 ? dom : dom.parentNode)) { + if (bias < 0) { + var domBefore, desc; + if (dom == this.contentDOM) { + domBefore = dom.childNodes[offset - 1]; + } else { + while (dom.parentNode != this.contentDOM) dom = dom.parentNode; + domBefore = dom.previousSibling; + } + while (domBefore && !((desc = domBefore.pmViewDesc) && desc.parent == this)) domBefore = domBefore.previousSibling; + return domBefore ? this.posBeforeChild(desc) + desc.size : this.posAtStart; + } else { + var domAfter, _desc; + if (dom == this.contentDOM) { + domAfter = dom.childNodes[offset]; + } else { + while (dom.parentNode != this.contentDOM) dom = dom.parentNode; + domAfter = dom.nextSibling; + } + while (domAfter && !((_desc = domAfter.pmViewDesc) && _desc.parent == this)) domAfter = domAfter.nextSibling; + return domAfter ? this.posBeforeChild(_desc) : this.posAtEnd; + } + } + var atEnd; + if (dom == this.dom && this.contentDOM) { + atEnd = offset > domIndex(this.contentDOM); + } else if (this.contentDOM && this.contentDOM != this.dom && this.dom.contains(this.contentDOM)) { + atEnd = dom.compareDocumentPosition(this.contentDOM) & 2; + } else if (this.dom.firstChild) { + if (offset == 0) for (var search = dom;; search = search.parentNode) { + if (search == this.dom) { + atEnd = false; + break; + } + if (search.previousSibling) break; + } + if (atEnd == null && offset == dom.childNodes.length) for (var _search = dom;; _search = _search.parentNode) { + if (_search == this.dom) { + atEnd = true; + break; + } + if (_search.nextSibling) break; + } + } + return (atEnd == null ? bias > 0 : atEnd) ? this.posAtEnd : this.posAtStart; + } + }, { + key: "nearestDesc", + value: function nearestDesc(dom) { + var onlyNodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + for (var first = true, cur = dom; cur; cur = cur.parentNode) { + var desc = this.getDesc(cur), + nodeDOM = void 0; + if (desc && (!onlyNodes || desc.node)) { + if (first && (nodeDOM = desc.nodeDOM) && !(nodeDOM.nodeType == 1 ? nodeDOM.contains(dom.nodeType == 1 ? dom : dom.parentNode) : nodeDOM == dom)) first = false;else return desc; + } + } + } + }, { + key: "getDesc", + value: function getDesc(dom) { + var desc = dom.pmViewDesc; + for (var cur = desc; cur; cur = cur.parent) if (cur == this) return desc; + } + }, { + key: "posFromDOM", + value: function posFromDOM(dom, offset, bias) { + for (var scan = dom; scan; scan = scan.parentNode) { + var desc = this.getDesc(scan); + if (desc) return desc.localPosFromDOM(dom, offset, bias); + } + return -1; + } + }, { + key: "descAt", + value: function descAt(pos) { + for (var i = 0, offset = 0; i < this.children.length; i++) { + var child = this.children[i], + end = offset + child.size; + if (offset == pos && end != offset) { + while (!child.border && child.children.length) { + for (var _i = 0; _i < child.children.length; _i++) { + var inner = child.children[_i]; + if (inner.size) { + child = inner; + break; + } + } + } + return child; + } + if (pos < end) return child.descAt(pos - offset - child.border); + offset = end; + } + } + }, { + key: "domFromPos", + value: function domFromPos(pos, side) { + if (!this.contentDOM) return { + node: this.dom, + offset: 0, + atom: pos + 1 + }; + var i = 0, + offset = 0; + for (var curPos = 0; i < this.children.length; i++) { + var child = this.children[i], + end = curPos + child.size; + if (end > pos || child instanceof TrailingHackViewDesc) { + offset = pos - curPos; + break; + } + curPos = end; + } + if (offset) return this.children[i].domFromPos(offset - this.children[i].border, side); + for (var prev; i && !(prev = this.children[i - 1]).size && prev instanceof WidgetViewDesc && prev.side >= 0; i--) {} + if (side <= 0) { + var _prev, + enter = true; + for (;; i--, enter = false) { + _prev = i ? this.children[i - 1] : null; + if (!_prev || _prev.dom.parentNode == this.contentDOM) break; + } + if (_prev && side && enter && !_prev.border && !_prev.domAtom) return _prev.domFromPos(_prev.size, side); + return { + node: this.contentDOM, + offset: _prev ? domIndex(_prev.dom) + 1 : 0 + }; + } else { + var next, + _enter = true; + for (;; i++, _enter = false) { + next = i < this.children.length ? this.children[i] : null; + if (!next || next.dom.parentNode == this.contentDOM) break; + } + if (next && _enter && !next.border && !next.domAtom) return next.domFromPos(0, side); + return { + node: this.contentDOM, + offset: next ? domIndex(next.dom) : this.contentDOM.childNodes.length + }; + } + } + }, { + key: "parseRange", + value: function parseRange(from, to) { + var base = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + if (this.children.length == 0) return { + node: this.contentDOM, + from: from, + to: to, + fromOffset: 0, + toOffset: this.contentDOM.childNodes.length + }; + var fromOffset = -1, + toOffset = -1; + for (var offset = base, i = 0;; i++) { + var child = this.children[i], + end = offset + child.size; + if (fromOffset == -1 && from <= end) { + var childBase = offset + child.border; + if (from >= childBase && to <= end - child.border && child.node && child.contentDOM && this.contentDOM.contains(child.contentDOM)) return child.parseRange(from, to, childBase); + from = offset; + for (var j = i; j > 0; j--) { + var prev = this.children[j - 1]; + if (prev.size && prev.dom.parentNode == this.contentDOM && !prev.emptyChildAt(1)) { + fromOffset = domIndex(prev.dom) + 1; + break; + } + from -= prev.size; + } + if (fromOffset == -1) fromOffset = 0; + } + if (fromOffset > -1 && (end > to || i == this.children.length - 1)) { + to = end; + for (var _j = i + 1; _j < this.children.length; _j++) { + var next = this.children[_j]; + if (next.size && next.dom.parentNode == this.contentDOM && !next.emptyChildAt(-1)) { + toOffset = domIndex(next.dom); + break; + } + to += next.size; + } + if (toOffset == -1) toOffset = this.contentDOM.childNodes.length; + break; + } + offset = end; + } + return { + node: this.contentDOM, + from: from, + to: to, + fromOffset: fromOffset, + toOffset: toOffset + }; + } + }, { + key: "emptyChildAt", + value: function emptyChildAt(side) { + if (this.border || !this.contentDOM || !this.children.length) return false; + var child = this.children[side < 0 ? 0 : this.children.length - 1]; + return child.size == 0 || child.emptyChildAt(side); + } + }, { + key: "domAfterPos", + value: function domAfterPos(pos) { + var _this$domFromPos = this.domFromPos(pos, 0), + node = _this$domFromPos.node, + offset = _this$domFromPos.offset; + if (node.nodeType != 1 || offset == node.childNodes.length) throw new RangeError("No node after pos " + pos); + return node.childNodes[offset]; + } + }, { + key: "setSelection", + value: function setSelection(anchor, head, view) { + var force = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + var from = Math.min(anchor, head), + to = Math.max(anchor, head); + for (var i = 0, offset = 0; i < this.children.length; i++) { + var child = this.children[i], + end = offset + child.size; + if (from > offset && to < end) return child.setSelection(anchor - offset - child.border, head - offset - child.border, view, force); + offset = end; + } + var anchorDOM = this.domFromPos(anchor, anchor ? -1 : 1); + var headDOM = head == anchor ? anchorDOM : this.domFromPos(head, head ? -1 : 1); + var domSel = view.root.getSelection(); + var selRange = view.domSelectionRange(); + var brKludge = false; + if ((gecko || safari) && anchor == head) { + var _anchorDOM = anchorDOM, + node = _anchorDOM.node, + _offset = _anchorDOM.offset; + if (node.nodeType == 3) { + brKludge = !!(_offset && node.nodeValue[_offset - 1] == "\n"); + if (brKludge && _offset == node.nodeValue.length) { + for (var scan = node, after; scan; scan = scan.parentNode) { + if (after = scan.nextSibling) { + if (after.nodeName == "BR") anchorDOM = headDOM = { + node: after.parentNode, + offset: domIndex(after) + 1 + }; + break; + } + var desc = scan.pmViewDesc; + if (desc && desc.node && desc.node.isBlock) break; + } + } + } else { + var prev = node.childNodes[_offset - 1]; + brKludge = prev && (prev.nodeName == "BR" || prev.contentEditable == "false"); + } + } + if (gecko && selRange.focusNode && selRange.focusNode != headDOM.node && selRange.focusNode.nodeType == 1) { + var _after2 = selRange.focusNode.childNodes[selRange.focusOffset]; + if (_after2 && _after2.contentEditable == "false") force = true; + } + if (!(force || brKludge && safari) && isEquivalentPosition(anchorDOM.node, anchorDOM.offset, selRange.anchorNode, selRange.anchorOffset) && isEquivalentPosition(headDOM.node, headDOM.offset, selRange.focusNode, selRange.focusOffset)) return; + var domSelExtended = false; + if ((domSel.extend || anchor == head) && !brKludge) { + domSel.collapse(anchorDOM.node, anchorDOM.offset); + try { + if (anchor != head) domSel.extend(headDOM.node, headDOM.offset); + domSelExtended = true; + } catch (_) {} + } + if (!domSelExtended) { + if (anchor > head) { + var tmp = anchorDOM; + anchorDOM = headDOM; + headDOM = tmp; + } + var range = document.createRange(); + range.setEnd(headDOM.node, headDOM.offset); + range.setStart(anchorDOM.node, anchorDOM.offset); + domSel.removeAllRanges(); + domSel.addRange(range); + } + } + }, { + key: "ignoreMutation", + value: function ignoreMutation(mutation) { + return !this.contentDOM && mutation.type != "selection"; + } + }, { + key: "contentLost", + get: function get() { + return this.contentDOM && this.contentDOM != this.dom && !this.dom.contains(this.contentDOM); + } + }, { + key: "markDirty", + value: function markDirty(from, to) { + for (var offset = 0, i = 0; i < this.children.length; i++) { + var child = this.children[i], + end = offset + child.size; + if (offset == end ? from <= end && to >= offset : from < end && to > offset) { + var startInside = offset + child.border, + endInside = end - child.border; + if (from >= startInside && to <= endInside) { + this.dirty = from == offset || to == end ? CONTENT_DIRTY : CHILD_DIRTY; + if (from == startInside && to == endInside && (child.contentLost || child.dom.parentNode != this.contentDOM)) child.dirty = NODE_DIRTY;else child.markDirty(from - startInside, to - startInside); + return; + } else { + child.dirty = child.dom == child.contentDOM && child.dom.parentNode == this.contentDOM && !child.children.length ? CONTENT_DIRTY : NODE_DIRTY; + } + } + offset = end; + } + this.dirty = CONTENT_DIRTY; + } + }, { + key: "markParentsDirty", + value: function markParentsDirty() { + var level = 1; + for (var node = this.parent; node; node = node.parent, level++) { + var dirty = level == 1 ? CONTENT_DIRTY : CHILD_DIRTY; + if (node.dirty < dirty) node.dirty = dirty; + } + } + }, { + key: "domAtom", + get: function get() { + return false; + } + }, { + key: "ignoreForCoords", + get: function get() { + return false; + } + }, { + key: "isText", + value: function isText(text) { + return false; + } + }]); + return ViewDesc; +}(); +var WidgetViewDesc = function (_ViewDesc) { + _inherits(WidgetViewDesc, _ViewDesc); + var _super = _createSuper(WidgetViewDesc); + function WidgetViewDesc(parent, widget, view, pos) { + var _this; + _classCallCheck(this, WidgetViewDesc); + var self, + dom = widget.type.toDOM; + if (typeof dom == "function") dom = dom(view, function () { + if (!self) return pos; + if (self.parent) return self.parent.posBeforeChild(self); + }); + if (!widget.type.spec.raw) { + if (dom.nodeType != 1) { + var wrap = document.createElement("span"); + wrap.appendChild(dom); + dom = wrap; + } + dom.contentEditable = "false"; + dom.classList.add("ProseMirror-widget"); + } + _this = _super.call(this, parent, [], dom, null); + _this.widget = widget; + _this.widget = widget; + self = _assertThisInitialized(_this); + return _this; + } + _createClass(WidgetViewDesc, [{ + key: "matchesWidget", + value: function matchesWidget(widget) { + return this.dirty == NOT_DIRTY && widget.type.eq(this.widget.type); + } + }, { + key: "parseRule", + value: function parseRule() { + return { + ignore: true + }; + } + }, { + key: "stopEvent", + value: function stopEvent(event) { + var stop = this.widget.spec.stopEvent; + return stop ? stop(event) : false; + } + }, { + key: "ignoreMutation", + value: function ignoreMutation(mutation) { + return mutation.type != "selection" || this.widget.spec.ignoreSelection; + } + }, { + key: "destroy", + value: function destroy() { + this.widget.type.destroy(this.dom); + _get(_getPrototypeOf(WidgetViewDesc.prototype), "destroy", this).call(this); + } + }, { + key: "domAtom", + get: function get() { + return true; + } + }, { + key: "side", + get: function get() { + return this.widget.type.side; + } + }]); + return WidgetViewDesc; +}(ViewDesc); +var CompositionViewDesc = function (_ViewDesc2) { + _inherits(CompositionViewDesc, _ViewDesc2); + var _super2 = _createSuper(CompositionViewDesc); + function CompositionViewDesc(parent, dom, textDOM, text) { + var _this2; + _classCallCheck(this, CompositionViewDesc); + _this2 = _super2.call(this, parent, [], dom, null); + _this2.textDOM = textDOM; + _this2.text = text; + return _this2; + } + _createClass(CompositionViewDesc, [{ + key: "size", + get: function get() { + return this.text.length; + } + }, { + key: "localPosFromDOM", + value: function localPosFromDOM(dom, offset) { + if (dom != this.textDOM) return this.posAtStart + (offset ? this.size : 0); + return this.posAtStart + offset; + } + }, { + key: "domFromPos", + value: function domFromPos(pos) { + return { + node: this.textDOM, + offset: pos + }; + } + }, { + key: "ignoreMutation", + value: function ignoreMutation(mut) { + return mut.type === 'characterData' && mut.target.nodeValue == mut.oldValue; + } + }]); + return CompositionViewDesc; +}(ViewDesc); +var MarkViewDesc = function (_ViewDesc3) { + _inherits(MarkViewDesc, _ViewDesc3); + var _super3 = _createSuper(MarkViewDesc); + function MarkViewDesc(parent, mark, dom, contentDOM, spec) { + var _this3; + _classCallCheck(this, MarkViewDesc); + _this3 = _super3.call(this, parent, [], dom, contentDOM); + _this3.mark = mark; + _this3.spec = spec; + return _this3; + } + _createClass(MarkViewDesc, [{ + key: "parseRule", + value: function parseRule() { + if (this.dirty & NODE_DIRTY || this.mark.type.spec.reparseInView) return null; + return { + mark: this.mark.type.name, + attrs: this.mark.attrs, + contentElement: this.contentDOM + }; + } + }, { + key: "matchesMark", + value: function matchesMark(mark) { + return this.dirty != NODE_DIRTY && this.mark.eq(mark); + } + }, { + key: "markDirty", + value: function markDirty(from, to) { + _get(_getPrototypeOf(MarkViewDesc.prototype), "markDirty", this).call(this, from, to); + if (this.dirty != NOT_DIRTY) { + var parent = this.parent; + while (!parent.node) parent = parent.parent; + if (parent.dirty < this.dirty) parent.dirty = this.dirty; + this.dirty = NOT_DIRTY; + } + } + }, { + key: "slice", + value: function slice(from, to, view) { + var copy = MarkViewDesc.create(this.parent, this.mark, true, view); + var nodes = this.children, + size = this.size; + if (to < size) nodes = replaceNodes(nodes, to, size, view); + if (from > 0) nodes = replaceNodes(nodes, 0, from, view); + for (var i = 0; i < nodes.length; i++) nodes[i].parent = copy; + copy.children = nodes; + return copy; + } + }, { + key: "ignoreMutation", + value: function ignoreMutation(mutation) { + return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : _get(_getPrototypeOf(MarkViewDesc.prototype), "ignoreMutation", this).call(this, mutation); + } + }, { + key: "destroy", + value: function destroy() { + if (this.spec.destroy) this.spec.destroy(); + _get(_getPrototypeOf(MarkViewDesc.prototype), "destroy", this).call(this); + } + }], [{ + key: "create", + value: function create(parent, mark, inline, view) { + var custom = view.nodeViews[mark.type.name]; + var spec = custom && custom(mark, view, inline); + if (!spec || !spec.dom) spec = prosemirrorModel.DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline), null, mark.attrs); + return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom, spec); + } + }]); + return MarkViewDesc; +}(ViewDesc); +var NodeViewDesc = function (_ViewDesc4) { + _inherits(NodeViewDesc, _ViewDesc4); + var _super4 = _createSuper(NodeViewDesc); + function NodeViewDesc(parent, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, view, pos) { + var _this4; + _classCallCheck(this, NodeViewDesc); + _this4 = _super4.call(this, parent, [], dom, contentDOM); + _this4.node = node; + _this4.outerDeco = outerDeco; + _this4.innerDeco = innerDeco; + _this4.nodeDOM = nodeDOM; + return _this4; + } + _createClass(NodeViewDesc, [{ + key: "parseRule", + value: function parseRule() { + var _this5 = this; + if (this.node.type.spec.reparseInView) return null; + var rule = { + node: this.node.type.name, + attrs: this.node.attrs + }; + if (this.node.type.whitespace == "pre") rule.preserveWhitespace = "full"; + if (!this.contentDOM) { + rule.getContent = function () { + return _this5.node.content; + }; + } else if (!this.contentLost) { + rule.contentElement = this.contentDOM; + } else { + for (var i = this.children.length - 1; i >= 0; i--) { + var child = this.children[i]; + if (this.dom.contains(child.dom.parentNode)) { + rule.contentElement = child.dom.parentNode; + break; + } + } + if (!rule.contentElement) rule.getContent = function () { + return prosemirrorModel.Fragment.empty; + }; + } + return rule; + } + }, { + key: "matchesNode", + value: function matchesNode(node, outerDeco, innerDeco) { + return this.dirty == NOT_DIRTY && node.eq(this.node) && sameOuterDeco(outerDeco, this.outerDeco) && innerDeco.eq(this.innerDeco); + } + }, { + key: "size", + get: function get() { + return this.node.nodeSize; + } + }, { + key: "border", + get: function get() { + return this.node.isLeaf ? 0 : 1; + } + }, { + key: "updateChildren", + value: function updateChildren(view, pos) { + var _this6 = this; + var inline = this.node.inlineContent, + off = pos; + var composition = view.composing ? this.localCompositionInfo(view, pos) : null; + var localComposition = composition && composition.pos > -1 ? composition : null; + var compositionInChild = composition && composition.pos < 0; + var updater = new ViewTreeUpdater(this, localComposition && localComposition.node, view); + iterDeco(this.node, this.innerDeco, function (widget, i, insideNode) { + if (widget.spec.marks) updater.syncToMarks(widget.spec.marks, inline, view);else if (widget.type.side >= 0 && !insideNode) updater.syncToMarks(i == _this6.node.childCount ? prosemirrorModel.Mark.none : _this6.node.child(i).marks, inline, view); + updater.placeWidget(widget, view, off); + }, function (child, outerDeco, innerDeco, i) { + updater.syncToMarks(child.marks, inline, view); + var compIndex; + if (updater.findNodeMatch(child, outerDeco, innerDeco, i)) ;else if (compositionInChild && view.state.selection.from > off && view.state.selection.to < off + child.nodeSize && (compIndex = updater.findIndexWithChild(composition.node)) > -1 && updater.updateNodeAt(child, outerDeco, innerDeco, compIndex, view)) ;else if (updater.updateNextNode(child, outerDeco, innerDeco, view, i, off)) ;else { + updater.addNode(child, outerDeco, innerDeco, view, off); + } + off += child.nodeSize; + }); + updater.syncToMarks([], inline, view); + if (this.node.isTextblock) updater.addTextblockHacks(); + updater.destroyRest(); + if (updater.changed || this.dirty == CONTENT_DIRTY) { + if (localComposition) this.protectLocalComposition(view, localComposition); + renderDescs(this.contentDOM, this.children, view); + if (ios) iosHacks(this.dom); + } + } + }, { + key: "localCompositionInfo", + value: function localCompositionInfo(view, pos) { + var _view$state$selection = view.state.selection, + from = _view$state$selection.from, + to = _view$state$selection.to; + if (!(view.state.selection instanceof prosemirrorState.TextSelection) || from < pos || to > pos + this.node.content.size) return null; + var textNode = view.input.compositionNode; + if (!textNode || !this.dom.contains(textNode.parentNode)) return null; + if (this.node.inlineContent) { + var text = textNode.nodeValue; + var textPos = findTextInFragment(this.node.content, text, from - pos, to - pos); + return textPos < 0 ? null : { + node: textNode, + pos: textPos, + text: text + }; + } else { + return { + node: textNode, + pos: -1, + text: "" + }; + } + } + }, { + key: "protectLocalComposition", + value: function protectLocalComposition(view, _ref2) { + var node = _ref2.node, + pos = _ref2.pos, + text = _ref2.text; + if (this.getDesc(node)) return; + var topNode = node; + for (;; topNode = topNode.parentNode) { + if (topNode.parentNode == this.contentDOM) break; + while (topNode.previousSibling) topNode.parentNode.removeChild(topNode.previousSibling); + while (topNode.nextSibling) topNode.parentNode.removeChild(topNode.nextSibling); + if (topNode.pmViewDesc) topNode.pmViewDesc = undefined; + } + var desc = new CompositionViewDesc(this, topNode, node, text); + view.input.compositionNodes.push(desc); + this.children = replaceNodes(this.children, pos, pos + text.length, view, desc); + } + }, { + key: "update", + value: function update(node, outerDeco, innerDeco, view) { + if (this.dirty == NODE_DIRTY || !node.sameMarkup(this.node)) return false; + this.updateInner(node, outerDeco, innerDeco, view); + return true; + } + }, { + key: "updateInner", + value: function updateInner(node, outerDeco, innerDeco, view) { + this.updateOuterDeco(outerDeco); + this.node = node; + this.innerDeco = innerDeco; + if (this.contentDOM) this.updateChildren(view, this.posAtStart); + this.dirty = NOT_DIRTY; + } + }, { + key: "updateOuterDeco", + value: function updateOuterDeco(outerDeco) { + if (sameOuterDeco(outerDeco, this.outerDeco)) return; + var needsWrap = this.nodeDOM.nodeType != 1; + var oldDOM = this.dom; + this.dom = patchOuterDeco(this.dom, this.nodeDOM, computeOuterDeco(this.outerDeco, this.node, needsWrap), computeOuterDeco(outerDeco, this.node, needsWrap)); + if (this.dom != oldDOM) { + oldDOM.pmViewDesc = undefined; + this.dom.pmViewDesc = this; + } + this.outerDeco = outerDeco; + } + }, { + key: "selectNode", + value: function selectNode() { + if (this.nodeDOM.nodeType == 1) this.nodeDOM.classList.add("ProseMirror-selectednode"); + if (this.contentDOM || !this.node.type.spec.draggable) this.dom.draggable = true; + } + }, { + key: "deselectNode", + value: function deselectNode() { + if (this.nodeDOM.nodeType == 1) { + this.nodeDOM.classList.remove("ProseMirror-selectednode"); + if (this.contentDOM || !this.node.type.spec.draggable) this.dom.removeAttribute("draggable"); + } + } + }, { + key: "domAtom", + get: function get() { + return this.node.isAtom; + } + }], [{ + key: "create", + value: function create(parent, node, outerDeco, innerDeco, view, pos) { + var custom = view.nodeViews[node.type.name], + descObj; + var spec = custom && custom(node, view, function () { + if (!descObj) return pos; + if (descObj.parent) return descObj.parent.posBeforeChild(descObj); + }, outerDeco, innerDeco); + var dom = spec && spec.dom, + contentDOM = spec && spec.contentDOM; + if (node.isText) { + if (!dom) dom = document.createTextNode(node.text);else if (dom.nodeType != 3) throw new RangeError("Text must be rendered as a DOM text node"); + } else if (!dom) { + var _spec = prosemirrorModel.DOMSerializer.renderSpec(document, node.type.spec.toDOM(node), null, node.attrs); + dom = _spec.dom; + contentDOM = _spec.contentDOM; + } + if (!contentDOM && !node.isText && dom.nodeName != "BR") { + if (!dom.hasAttribute("contenteditable")) dom.contentEditable = "false"; + if (node.type.spec.draggable) dom.draggable = true; + } + var nodeDOM = dom; + dom = applyOuterDeco(dom, outerDeco, node); + if (spec) return descObj = new CustomNodeViewDesc(parent, node, outerDeco, innerDeco, dom, contentDOM || null, nodeDOM, spec, view, pos + 1);else if (node.isText) return new TextViewDesc(parent, node, outerDeco, innerDeco, dom, nodeDOM, view);else return new NodeViewDesc(parent, node, outerDeco, innerDeco, dom, contentDOM || null, nodeDOM, view, pos + 1); + } + }]); + return NodeViewDesc; +}(ViewDesc); +function docViewDesc(doc, outerDeco, innerDeco, dom, view) { + applyOuterDeco(dom, outerDeco, doc); + var docView = new NodeViewDesc(undefined, doc, outerDeco, innerDeco, dom, dom, dom, view, 0); + if (docView.contentDOM) docView.updateChildren(view, 0); + return docView; +} +var TextViewDesc = function (_NodeViewDesc) { + _inherits(TextViewDesc, _NodeViewDesc); + var _super5 = _createSuper(TextViewDesc); + function TextViewDesc(parent, node, outerDeco, innerDeco, dom, nodeDOM, view) { + _classCallCheck(this, TextViewDesc); + return _super5.call(this, parent, node, outerDeco, innerDeco, dom, null, nodeDOM, view, 0); + } + _createClass(TextViewDesc, [{ + key: "parseRule", + value: function parseRule() { + var skip = this.nodeDOM.parentNode; + while (skip && skip != this.dom && !skip.pmIsDeco) skip = skip.parentNode; + return { + skip: skip || true + }; + } + }, { + key: "update", + value: function update(node, outerDeco, innerDeco, view) { + if (this.dirty == NODE_DIRTY || this.dirty != NOT_DIRTY && !this.inParent() || !node.sameMarkup(this.node)) return false; + this.updateOuterDeco(outerDeco); + if ((this.dirty != NOT_DIRTY || node.text != this.node.text) && node.text != this.nodeDOM.nodeValue) { + this.nodeDOM.nodeValue = node.text; + if (view.trackWrites == this.nodeDOM) view.trackWrites = null; + } + this.node = node; + this.dirty = NOT_DIRTY; + return true; + } + }, { + key: "inParent", + value: function inParent() { + var parentDOM = this.parent.contentDOM; + for (var n = this.nodeDOM; n; n = n.parentNode) if (n == parentDOM) return true; + return false; + } + }, { + key: "domFromPos", + value: function domFromPos(pos) { + return { + node: this.nodeDOM, + offset: pos + }; + } + }, { + key: "localPosFromDOM", + value: function localPosFromDOM(dom, offset, bias) { + if (dom == this.nodeDOM) return this.posAtStart + Math.min(offset, this.node.text.length); + return _get(_getPrototypeOf(TextViewDesc.prototype), "localPosFromDOM", this).call(this, dom, offset, bias); + } + }, { + key: "ignoreMutation", + value: function ignoreMutation(mutation) { + return mutation.type != "characterData" && mutation.type != "selection"; + } + }, { + key: "slice", + value: function slice(from, to, view) { + var node = this.node.cut(from, to), + dom = document.createTextNode(node.text); + return new TextViewDesc(this.parent, node, this.outerDeco, this.innerDeco, dom, dom, view); + } + }, { + key: "markDirty", + value: function markDirty(from, to) { + _get(_getPrototypeOf(TextViewDesc.prototype), "markDirty", this).call(this, from, to); + if (this.dom != this.nodeDOM && (from == 0 || to == this.nodeDOM.nodeValue.length)) this.dirty = NODE_DIRTY; + } + }, { + key: "domAtom", + get: function get() { + return false; + } + }, { + key: "isText", + value: function isText(text) { + return this.node.text == text; + } + }]); + return TextViewDesc; +}(NodeViewDesc); +var TrailingHackViewDesc = function (_ViewDesc5) { + _inherits(TrailingHackViewDesc, _ViewDesc5); + var _super6 = _createSuper(TrailingHackViewDesc); + function TrailingHackViewDesc() { + _classCallCheck(this, TrailingHackViewDesc); + return _super6.apply(this, arguments); + } + _createClass(TrailingHackViewDesc, [{ + key: "parseRule", + value: function parseRule() { + return { + ignore: true + }; + } + }, { + key: "matchesHack", + value: function matchesHack(nodeName) { + return this.dirty == NOT_DIRTY && this.dom.nodeName == nodeName; + } + }, { + key: "domAtom", + get: function get() { + return true; + } + }, { + key: "ignoreForCoords", + get: function get() { + return this.dom.nodeName == "IMG"; + } + }]); + return TrailingHackViewDesc; +}(ViewDesc); +var CustomNodeViewDesc = function (_NodeViewDesc2) { + _inherits(CustomNodeViewDesc, _NodeViewDesc2); + var _super7 = _createSuper(CustomNodeViewDesc); + function CustomNodeViewDesc(parent, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, spec, view, pos) { + var _this7; + _classCallCheck(this, CustomNodeViewDesc); + _this7 = _super7.call(this, parent, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, view, pos); + _this7.spec = spec; + return _this7; + } + _createClass(CustomNodeViewDesc, [{ + key: "update", + value: function update(node, outerDeco, innerDeco, view) { + if (this.dirty == NODE_DIRTY) return false; + if (this.spec.update && (this.node.type == node.type || this.spec.multiType)) { + var result = this.spec.update(node, outerDeco, innerDeco); + if (result) this.updateInner(node, outerDeco, innerDeco, view); + return result; + } else if (!this.contentDOM && !node.isLeaf) { + return false; + } else { + return _get(_getPrototypeOf(CustomNodeViewDesc.prototype), "update", this).call(this, node, outerDeco, innerDeco, view); + } + } + }, { + key: "selectNode", + value: function selectNode() { + this.spec.selectNode ? this.spec.selectNode() : _get(_getPrototypeOf(CustomNodeViewDesc.prototype), "selectNode", this).call(this); + } + }, { + key: "deselectNode", + value: function deselectNode() { + this.spec.deselectNode ? this.spec.deselectNode() : _get(_getPrototypeOf(CustomNodeViewDesc.prototype), "deselectNode", this).call(this); + } + }, { + key: "setSelection", + value: function setSelection(anchor, head, view, force) { + this.spec.setSelection ? this.spec.setSelection(anchor, head, view.root) : _get(_getPrototypeOf(CustomNodeViewDesc.prototype), "setSelection", this).call(this, anchor, head, view, force); + } + }, { + key: "destroy", + value: function destroy() { + if (this.spec.destroy) this.spec.destroy(); + _get(_getPrototypeOf(CustomNodeViewDesc.prototype), "destroy", this).call(this); + } + }, { + key: "stopEvent", + value: function stopEvent(event) { + return this.spec.stopEvent ? this.spec.stopEvent(event) : false; + } + }, { + key: "ignoreMutation", + value: function ignoreMutation(mutation) { + return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : _get(_getPrototypeOf(CustomNodeViewDesc.prototype), "ignoreMutation", this).call(this, mutation); + } + }]); + return CustomNodeViewDesc; +}(NodeViewDesc); +function renderDescs(parentDOM, descs, view) { + var dom = parentDOM.firstChild, + written = false; + for (var i = 0; i < descs.length; i++) { + var desc = descs[i], + childDOM = desc.dom; + if (childDOM.parentNode == parentDOM) { + while (childDOM != dom) { + dom = rm(dom); + written = true; + } + dom = dom.nextSibling; + } else { + written = true; + parentDOM.insertBefore(childDOM, dom); + } + if (desc instanceof MarkViewDesc) { + var pos = dom ? dom.previousSibling : parentDOM.lastChild; + renderDescs(desc.contentDOM, desc.children, view); + dom = pos ? pos.nextSibling : parentDOM.firstChild; + } + } + while (dom) { + dom = rm(dom); + written = true; + } + if (written && view.trackWrites == parentDOM) view.trackWrites = null; +} +var OuterDecoLevel = function OuterDecoLevel(nodeName) { + if (nodeName) this.nodeName = nodeName; +}; +OuterDecoLevel.prototype = Object.create(null); +var noDeco = [new OuterDecoLevel()]; +function computeOuterDeco(outerDeco, node, needsWrap) { + if (outerDeco.length == 0) return noDeco; + var top = needsWrap ? noDeco[0] : new OuterDecoLevel(), + result = [top]; + for (var i = 0; i < outerDeco.length; i++) { + var attrs = outerDeco[i].type.attrs; + if (!attrs) continue; + if (attrs.nodeName) result.push(top = new OuterDecoLevel(attrs.nodeName)); + for (var name in attrs) { + var val = attrs[name]; + if (val == null) continue; + if (needsWrap && result.length == 1) result.push(top = new OuterDecoLevel(node.isInline ? "span" : "div")); + if (name == "class") top["class"] = (top["class"] ? top["class"] + " " : "") + val;else if (name == "style") top.style = (top.style ? top.style + ";" : "") + val;else if (name != "nodeName") top[name] = val; + } + } + return result; +} +function patchOuterDeco(outerDOM, nodeDOM, prevComputed, curComputed) { + if (prevComputed == noDeco && curComputed == noDeco) return nodeDOM; + var curDOM = nodeDOM; + for (var i = 0; i < curComputed.length; i++) { + var deco = curComputed[i], + prev = prevComputed[i]; + if (i) { + var parent = void 0; + if (prev && prev.nodeName == deco.nodeName && curDOM != outerDOM && (parent = curDOM.parentNode) && parent.nodeName.toLowerCase() == deco.nodeName) { + curDOM = parent; + } else { + parent = document.createElement(deco.nodeName); + parent.pmIsDeco = true; + parent.appendChild(curDOM); + prev = noDeco[0]; + curDOM = parent; + } + } + patchAttributes(curDOM, prev || noDeco[0], deco); + } + return curDOM; +} +function patchAttributes(dom, prev, cur) { + for (var name in prev) if (name != "class" && name != "style" && name != "nodeName" && !(name in cur)) dom.removeAttribute(name); + for (var _name in cur) if (_name != "class" && _name != "style" && _name != "nodeName" && cur[_name] != prev[_name]) dom.setAttribute(_name, cur[_name]); + if (prev["class"] != cur["class"]) { + var prevList = prev["class"] ? prev["class"].split(" ").filter(Boolean) : []; + var curList = cur["class"] ? cur["class"].split(" ").filter(Boolean) : []; + for (var i = 0; i < prevList.length; i++) if (curList.indexOf(prevList[i]) == -1) dom.classList.remove(prevList[i]); + for (var _i2 = 0; _i2 < curList.length; _i2++) if (prevList.indexOf(curList[_i2]) == -1) dom.classList.add(curList[_i2]); + if (dom.classList.length == 0) dom.removeAttribute("class"); + } + if (prev.style != cur.style) { + if (prev.style) { + var prop = /\s*([\w\-\xa1-\uffff]+)\s*:(?:"(?:\\.|[^"])*"|'(?:\\.|[^'])*'|\(.*?\)|[^;])*/g, + m; + while (m = prop.exec(prev.style)) dom.style.removeProperty(m[1]); + } + if (cur.style) dom.style.cssText += cur.style; + } +} +function applyOuterDeco(dom, deco, node) { + return patchOuterDeco(dom, dom, noDeco, computeOuterDeco(deco, node, dom.nodeType != 1)); +} +function sameOuterDeco(a, b) { + if (a.length != b.length) return false; + for (var i = 0; i < a.length; i++) if (!a[i].type.eq(b[i].type)) return false; + return true; +} +function rm(dom) { + var next = dom.nextSibling; + dom.parentNode.removeChild(dom); + return next; +} +var ViewTreeUpdater = function () { + function ViewTreeUpdater(top, lock, view) { + _classCallCheck(this, ViewTreeUpdater); + this.lock = lock; + this.view = view; + this.index = 0; + this.stack = []; + this.changed = false; + this.top = top; + this.preMatch = preMatch(top.node.content, top); + } + _createClass(ViewTreeUpdater, [{ + key: "destroyBetween", + value: function destroyBetween(start, end) { + if (start == end) return; + for (var i = start; i < end; i++) this.top.children[i].destroy(); + this.top.children.splice(start, end - start); + this.changed = true; + } + }, { + key: "destroyRest", + value: function destroyRest() { + this.destroyBetween(this.index, this.top.children.length); + } + }, { + key: "syncToMarks", + value: function syncToMarks(marks, inline, view) { + var keep = 0, + depth = this.stack.length >> 1; + var maxKeep = Math.min(depth, marks.length); + while (keep < maxKeep && (keep == depth - 1 ? this.top : this.stack[keep + 1 << 1]).matchesMark(marks[keep]) && marks[keep].type.spec.spanning !== false) keep++; + while (keep < depth) { + this.destroyRest(); + this.top.dirty = NOT_DIRTY; + this.index = this.stack.pop(); + this.top = this.stack.pop(); + depth--; + } + while (depth < marks.length) { + this.stack.push(this.top, this.index + 1); + var found = -1; + for (var i = this.index; i < Math.min(this.index + 3, this.top.children.length); i++) { + var next = this.top.children[i]; + if (next.matchesMark(marks[depth]) && !this.isLocked(next.dom)) { + found = i; + break; + } + } + if (found > -1) { + if (found > this.index) { + this.changed = true; + this.destroyBetween(this.index, found); + } + this.top = this.top.children[this.index]; + } else { + var markDesc = MarkViewDesc.create(this.top, marks[depth], inline, view); + this.top.children.splice(this.index, 0, markDesc); + this.top = markDesc; + this.changed = true; + } + this.index = 0; + depth++; + } + } + }, { + key: "findNodeMatch", + value: function findNodeMatch(node, outerDeco, innerDeco, index) { + var found = -1, + targetDesc; + if (index >= this.preMatch.index && (targetDesc = this.preMatch.matches[index - this.preMatch.index]).parent == this.top && targetDesc.matchesNode(node, outerDeco, innerDeco)) { + found = this.top.children.indexOf(targetDesc, this.index); + } else { + for (var i = this.index, e = Math.min(this.top.children.length, i + 5); i < e; i++) { + var child = this.top.children[i]; + if (child.matchesNode(node, outerDeco, innerDeco) && !this.preMatch.matched.has(child)) { + found = i; + break; + } + } + } + if (found < 0) return false; + this.destroyBetween(this.index, found); + this.index++; + return true; + } + }, { + key: "updateNodeAt", + value: function updateNodeAt(node, outerDeco, innerDeco, index, view) { + var child = this.top.children[index]; + if (child.dirty == NODE_DIRTY && child.dom == child.contentDOM) child.dirty = CONTENT_DIRTY; + if (!child.update(node, outerDeco, innerDeco, view)) return false; + this.destroyBetween(this.index, index); + this.index++; + return true; + } + }, { + key: "findIndexWithChild", + value: function findIndexWithChild(domNode) { + for (;;) { + var parent = domNode.parentNode; + if (!parent) return -1; + if (parent == this.top.contentDOM) { + var desc = domNode.pmViewDesc; + if (desc) for (var i = this.index; i < this.top.children.length; i++) { + if (this.top.children[i] == desc) return i; + } + return -1; + } + domNode = parent; + } + } + }, { + key: "updateNextNode", + value: function updateNextNode(node, outerDeco, innerDeco, view, index, pos) { + for (var i = this.index; i < this.top.children.length; i++) { + var next = this.top.children[i]; + if (next instanceof NodeViewDesc) { + var _preMatch = this.preMatch.matched.get(next); + if (_preMatch != null && _preMatch != index) return false; + var nextDOM = next.dom, + updated = void 0; + var locked = this.isLocked(nextDOM) && !(node.isText && next.node && next.node.isText && next.nodeDOM.nodeValue == node.text && next.dirty != NODE_DIRTY && sameOuterDeco(outerDeco, next.outerDeco)); + if (!locked && next.update(node, outerDeco, innerDeco, view)) { + this.destroyBetween(this.index, i); + if (next.dom != nextDOM) this.changed = true; + this.index++; + return true; + } else if (!locked && (updated = this.recreateWrapper(next, node, outerDeco, innerDeco, view, pos))) { + this.destroyBetween(this.index, i); + this.top.children[this.index] = updated; + if (updated.contentDOM) { + updated.dirty = CONTENT_DIRTY; + updated.updateChildren(view, pos + 1); + updated.dirty = NOT_DIRTY; + } + this.changed = true; + this.index++; + return true; + } + break; + } + } + return false; + } + }, { + key: "recreateWrapper", + value: function recreateWrapper(next, node, outerDeco, innerDeco, view, pos) { + if (next.dirty || node.isAtom || !next.children.length || !next.node.content.eq(node.content) || !sameOuterDeco(outerDeco, next.outerDeco) || !innerDeco.eq(next.innerDeco)) return null; + var wrapper = NodeViewDesc.create(this.top, node, outerDeco, innerDeco, view, pos); + if (wrapper.contentDOM) { + wrapper.children = next.children; + next.children = []; + var _iterator = _createForOfIteratorHelper(wrapper.children), + _step; + try { + for (_iterator.s(); !(_step = _iterator.n()).done;) { + var ch = _step.value; + ch.parent = wrapper; + } + } catch (err) { + _iterator.e(err); + } finally { + _iterator.f(); + } + } + next.destroy(); + return wrapper; + } + }, { + key: "addNode", + value: function addNode(node, outerDeco, innerDeco, view, pos) { + var desc = NodeViewDesc.create(this.top, node, outerDeco, innerDeco, view, pos); + if (desc.contentDOM) desc.updateChildren(view, pos + 1); + this.top.children.splice(this.index++, 0, desc); + this.changed = true; + } + }, { + key: "placeWidget", + value: function placeWidget(widget, view, pos) { + var next = this.index < this.top.children.length ? this.top.children[this.index] : null; + if (next && next.matchesWidget(widget) && (widget == next.widget || !next.widget.type.toDOM.parentNode)) { + this.index++; + } else { + var desc = new WidgetViewDesc(this.top, widget, view, pos); + this.top.children.splice(this.index++, 0, desc); + this.changed = true; + } + } + }, { + key: "addTextblockHacks", + value: function addTextblockHacks() { + var lastChild = this.top.children[this.index - 1], + parent = this.top; + while (lastChild instanceof MarkViewDesc) { + parent = lastChild; + lastChild = parent.children[parent.children.length - 1]; + } + if (!lastChild || !(lastChild instanceof TextViewDesc) || /\n$/.test(lastChild.node.text) || this.view.requiresGeckoHackNode && /\s$/.test(lastChild.node.text)) { + if ((safari || chrome) && lastChild && lastChild.dom.contentEditable == "false") this.addHackNode("IMG", parent); + this.addHackNode("BR", this.top); + } + } + }, { + key: "addHackNode", + value: function addHackNode(nodeName, parent) { + if (parent == this.top && this.index < parent.children.length && parent.children[this.index].matchesHack(nodeName)) { + this.index++; + } else { + var dom = document.createElement(nodeName); + if (nodeName == "IMG") { + dom.className = "ProseMirror-separator"; + dom.alt = ""; + } + if (nodeName == "BR") dom.className = "ProseMirror-trailingBreak"; + var hack = new TrailingHackViewDesc(this.top, [], dom, null); + if (parent != this.top) parent.children.push(hack);else parent.children.splice(this.index++, 0, hack); + this.changed = true; + } + } + }, { + key: "isLocked", + value: function isLocked(node) { + return this.lock && (node == this.lock || node.nodeType == 1 && node.contains(this.lock.parentNode)); + } + }]); + return ViewTreeUpdater; +}(); +function preMatch(frag, parentDesc) { + var curDesc = parentDesc, + descI = curDesc.children.length; + var fI = frag.childCount, + matched = new Map(), + matches = []; + outer: while (fI > 0) { + var desc = void 0; + for (;;) { + if (descI) { + var next = curDesc.children[descI - 1]; + if (next instanceof MarkViewDesc) { + curDesc = next; + descI = next.children.length; + } else { + desc = next; + descI--; + break; + } + } else if (curDesc == parentDesc) { + break outer; + } else { + descI = curDesc.parent.children.indexOf(curDesc); + curDesc = curDesc.parent; + } + } + var node = desc.node; + if (!node) continue; + if (node != frag.child(fI - 1)) break; + --fI; + matched.set(desc, fI); + matches.push(desc); + } + return { + index: fI, + matched: matched, + matches: matches.reverse() + }; +} +function compareSide(a, b) { + return a.type.side - b.type.side; +} +function iterDeco(parent, deco, onWidget, onNode) { + var locals = deco.locals(parent), + offset = 0; + if (locals.length == 0) { + for (var i = 0; i < parent.childCount; i++) { + var child = parent.child(i); + onNode(child, locals, deco.forChild(offset, child), i); + offset += child.nodeSize; + } + return; + } + var decoIndex = 0, + active = [], + restNode = null; + for (var parentIndex = 0;;) { + var widget = void 0, + widgets = void 0; + while (decoIndex < locals.length && locals[decoIndex].to == offset) { + var next = locals[decoIndex++]; + if (next.widget) { + if (!widget) widget = next;else (widgets || (widgets = [widget])).push(next); + } + } + if (widget) { + if (widgets) { + widgets.sort(compareSide); + for (var _i3 = 0; _i3 < widgets.length; _i3++) onWidget(widgets[_i3], parentIndex, !!restNode); + } else { + onWidget(widget, parentIndex, !!restNode); + } + } + var _child = void 0, + index = void 0; + if (restNode) { + index = -1; + _child = restNode; + restNode = null; + } else if (parentIndex < parent.childCount) { + index = parentIndex; + _child = parent.child(parentIndex++); + } else { + break; + } + for (var _i4 = 0; _i4 < active.length; _i4++) if (active[_i4].to <= offset) active.splice(_i4--, 1); + while (decoIndex < locals.length && locals[decoIndex].from <= offset && locals[decoIndex].to > offset) active.push(locals[decoIndex++]); + var end = offset + _child.nodeSize; + if (_child.isText) { + var cutAt = end; + if (decoIndex < locals.length && locals[decoIndex].from < cutAt) cutAt = locals[decoIndex].from; + for (var _i5 = 0; _i5 < active.length; _i5++) if (active[_i5].to < cutAt) cutAt = active[_i5].to; + if (cutAt < end) { + restNode = _child.cut(cutAt - offset); + _child = _child.cut(0, cutAt - offset); + end = cutAt; + index = -1; + } + } else { + while (decoIndex < locals.length && locals[decoIndex].to < end) decoIndex++; + } + var outerDeco = _child.isInline && !_child.isLeaf ? active.filter(function (d) { + return !d.inline; + }) : active.slice(); + onNode(_child, outerDeco, deco.forChild(offset, _child), index); + offset = end; + } +} +function iosHacks(dom) { + if (dom.nodeName == "UL" || dom.nodeName == "OL") { + var oldCSS = dom.style.cssText; + dom.style.cssText = oldCSS + "; list-style: square !important"; + window.getComputedStyle(dom).listStyle; + dom.style.cssText = oldCSS; + } +} +function findTextInFragment(frag, text, from, to) { + for (var i = 0, pos = 0; i < frag.childCount && pos <= to;) { + var child = frag.child(i++), + childStart = pos; + pos += child.nodeSize; + if (!child.isText) continue; + var str = child.text; + while (i < frag.childCount) { + var next = frag.child(i++); + pos += next.nodeSize; + if (!next.isText) break; + str += next.text; + } + if (pos >= from) { + if (pos >= to && str.slice(to - text.length - childStart, to - childStart) == text) return to - text.length; + var found = childStart < to ? str.lastIndexOf(text, to - childStart - 1) : -1; + if (found >= 0 && found + text.length + childStart >= from) return childStart + found; + if (from == to && str.length >= to + text.length - childStart && str.slice(to - childStart, to - childStart + text.length) == text) return to; + } + } + return -1; +} +function replaceNodes(nodes, from, to, view, replacement) { + var result = []; + for (var i = 0, off = 0; i < nodes.length; i++) { + var child = nodes[i], + start = off, + end = off += child.size; + if (start >= to || end <= from) { + result.push(child); + } else { + if (start < from) result.push(child.slice(0, from - start, view)); + if (replacement) { + result.push(replacement); + replacement = undefined; + } + if (end > to) result.push(child.slice(to - start, child.size, view)); + } + } + return result; +} +function selectionFromDOM(view) { + var origin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + var domSel = view.domSelectionRange(), + doc = view.state.doc; + if (!domSel.focusNode) return null; + var nearestDesc = view.docView.nearestDesc(domSel.focusNode), + inWidget = nearestDesc && nearestDesc.size == 0; + var head = view.docView.posFromDOM(domSel.focusNode, domSel.focusOffset, 1); + if (head < 0) return null; + var $head = doc.resolve(head), + anchor, + selection; + if (selectionCollapsed(domSel)) { + anchor = head; + while (nearestDesc && !nearestDesc.node) nearestDesc = nearestDesc.parent; + var nearestDescNode = nearestDesc.node; + if (nearestDesc && nearestDescNode.isAtom && prosemirrorState.NodeSelection.isSelectable(nearestDescNode) && nearestDesc.parent && !(nearestDescNode.isInline && isOnEdge(domSel.focusNode, domSel.focusOffset, nearestDesc.dom))) { + var pos = nearestDesc.posBefore; + selection = new prosemirrorState.NodeSelection(head == pos ? $head : doc.resolve(pos)); + } + } else { + if (domSel instanceof view.dom.ownerDocument.defaultView.Selection && domSel.rangeCount > 1) { + var min = head, + max = head; + for (var i = 0; i < domSel.rangeCount; i++) { + var range = domSel.getRangeAt(i); + min = Math.min(min, view.docView.posFromDOM(range.startContainer, range.startOffset, 1)); + max = Math.max(max, view.docView.posFromDOM(range.endContainer, range.endOffset, -1)); + } + if (min < 0) return null; + var _ref3 = max == view.state.selection.anchor ? [max, min] : [min, max]; + var _ref4 = _slicedToArray(_ref3, 2); + anchor = _ref4[0]; + head = _ref4[1]; + $head = doc.resolve(head); + } else { + anchor = view.docView.posFromDOM(domSel.anchorNode, domSel.anchorOffset, 1); + } + if (anchor < 0) return null; + } + var $anchor = doc.resolve(anchor); + if (!selection) { + var bias = origin == "pointer" || view.state.selection.head < $head.pos && !inWidget ? 1 : -1; + selection = selectionBetween(view, $anchor, $head, bias); + } + return selection; +} +function editorOwnsSelection(view) { + return view.editable ? view.hasFocus() : hasSelection(view) && document.activeElement && document.activeElement.contains(view.dom); +} +function selectionToDOM(view) { + var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + var sel = view.state.selection; + syncNodeSelection(view, sel); + if (!editorOwnsSelection(view)) return; + if (!force && view.input.mouseDown && view.input.mouseDown.allowDefault && chrome) { + var domSel = view.domSelectionRange(), + curSel = view.domObserver.currentSelection; + if (domSel.anchorNode && curSel.anchorNode && isEquivalentPosition(domSel.anchorNode, domSel.anchorOffset, curSel.anchorNode, curSel.anchorOffset)) { + view.input.mouseDown.delayedSelectionSync = true; + view.domObserver.setCurSelection(); + return; + } + } + view.domObserver.disconnectSelection(); + if (view.cursorWrapper) { + selectCursorWrapper(view); + } else { + var anchor = sel.anchor, + head = sel.head, + resetEditableFrom, + resetEditableTo; + if (brokenSelectBetweenUneditable && !(sel instanceof prosemirrorState.TextSelection)) { + if (!sel.$from.parent.inlineContent) resetEditableFrom = temporarilyEditableNear(view, sel.from); + if (!sel.empty && !sel.$from.parent.inlineContent) resetEditableTo = temporarilyEditableNear(view, sel.to); + } + view.docView.setSelection(anchor, head, view, force); + if (brokenSelectBetweenUneditable) { + if (resetEditableFrom) resetEditable(resetEditableFrom); + if (resetEditableTo) resetEditable(resetEditableTo); + } + if (sel.visible) { + view.dom.classList.remove("ProseMirror-hideselection"); + } else { + view.dom.classList.add("ProseMirror-hideselection"); + if ("onselectionchange" in document) removeClassOnSelectionChange(view); + } + } + view.domObserver.setCurSelection(); + view.domObserver.connectSelection(); +} +var brokenSelectBetweenUneditable = safari || chrome && chrome_version < 63; +function temporarilyEditableNear(view, pos) { + var _view$docView$domFrom3 = view.docView.domFromPos(pos, 0), + node = _view$docView$domFrom3.node, + offset = _view$docView$domFrom3.offset; + var after = offset < node.childNodes.length ? node.childNodes[offset] : null; + var before = offset ? node.childNodes[offset - 1] : null; + if (safari && after && after.contentEditable == "false") return setEditable(after); + if ((!after || after.contentEditable == "false") && (!before || before.contentEditable == "false")) { + if (after) return setEditable(after);else if (before) return setEditable(before); + } +} +function setEditable(element) { + element.contentEditable = "true"; + if (safari && element.draggable) { + element.draggable = false; + element.wasDraggable = true; + } + return element; +} +function resetEditable(element) { + element.contentEditable = "false"; + if (element.wasDraggable) { + element.draggable = true; + element.wasDraggable = null; + } +} +function removeClassOnSelectionChange(view) { + var doc = view.dom.ownerDocument; + doc.removeEventListener("selectionchange", view.input.hideSelectionGuard); + var domSel = view.domSelectionRange(); + var node = domSel.anchorNode, + offset = domSel.anchorOffset; + doc.addEventListener("selectionchange", view.input.hideSelectionGuard = function () { + if (domSel.anchorNode != node || domSel.anchorOffset != offset) { + doc.removeEventListener("selectionchange", view.input.hideSelectionGuard); + setTimeout(function () { + if (!editorOwnsSelection(view) || view.state.selection.visible) view.dom.classList.remove("ProseMirror-hideselection"); + }, 20); + } + }); +} +function selectCursorWrapper(view) { + var domSel = view.domSelection(), + range = document.createRange(); + if (!domSel) return; + var node = view.cursorWrapper.dom, + img = node.nodeName == "IMG"; + if (img) range.setStart(node.parentNode, domIndex(node) + 1);else range.setStart(node, 0); + range.collapse(true); + domSel.removeAllRanges(); + domSel.addRange(range); + if (!img && !view.state.selection.visible && ie && ie_version <= 11) { + node.disabled = true; + node.disabled = false; + } +} +function syncNodeSelection(view, sel) { + if (sel instanceof prosemirrorState.NodeSelection) { + var desc = view.docView.descAt(sel.from); + if (desc != view.lastSelectedViewDesc) { + clearNodeSelection(view); + if (desc) desc.selectNode(); + view.lastSelectedViewDesc = desc; + } + } else { + clearNodeSelection(view); + } +} +function clearNodeSelection(view) { + if (view.lastSelectedViewDesc) { + if (view.lastSelectedViewDesc.parent) view.lastSelectedViewDesc.deselectNode(); + view.lastSelectedViewDesc = undefined; + } +} +function selectionBetween(view, $anchor, $head, bias) { + return view.someProp("createSelectionBetween", function (f) { + return f(view, $anchor, $head); + }) || prosemirrorState.TextSelection.between($anchor, $head, bias); +} +function hasFocusAndSelection(view) { + if (view.editable && !view.hasFocus()) return false; + return hasSelection(view); +} +function hasSelection(view) { + var sel = view.domSelectionRange(); + if (!sel.anchorNode) return false; + try { + return view.dom.contains(sel.anchorNode.nodeType == 3 ? sel.anchorNode.parentNode : sel.anchorNode) && (view.editable || view.dom.contains(sel.focusNode.nodeType == 3 ? sel.focusNode.parentNode : sel.focusNode)); + } catch (_) { + return false; + } +} +function anchorInRightPlace(view) { + var anchorDOM = view.docView.domFromPos(view.state.selection.anchor, 0); + var domSel = view.domSelectionRange(); + return isEquivalentPosition(anchorDOM.node, anchorDOM.offset, domSel.anchorNode, domSel.anchorOffset); +} +function moveSelectionBlock(state, dir) { + var _state$selection = state.selection, + $anchor = _state$selection.$anchor, + $head = _state$selection.$head; + var $side = dir > 0 ? $anchor.max($head) : $anchor.min($head); + var $start = !$side.parent.inlineContent ? $side : $side.depth ? state.doc.resolve(dir > 0 ? $side.after() : $side.before()) : null; + return $start && prosemirrorState.Selection.findFrom($start, dir); +} +function apply(view, sel) { + view.dispatch(view.state.tr.setSelection(sel).scrollIntoView()); + return true; +} +function selectHorizontally(view, dir, mods) { + var sel = view.state.selection; + if (sel instanceof prosemirrorState.TextSelection) { + if (mods.indexOf("s") > -1) { + var $head = sel.$head, + node = $head.textOffset ? null : dir < 0 ? $head.nodeBefore : $head.nodeAfter; + if (!node || node.isText || !node.isLeaf) return false; + var $newHead = view.state.doc.resolve($head.pos + node.nodeSize * (dir < 0 ? -1 : 1)); + return apply(view, new prosemirrorState.TextSelection(sel.$anchor, $newHead)); + } else if (!sel.empty) { + return false; + } else if (view.endOfTextblock(dir > 0 ? "forward" : "backward")) { + var next = moveSelectionBlock(view.state, dir); + if (next && next instanceof prosemirrorState.NodeSelection) return apply(view, next); + return false; + } else if (!(mac && mods.indexOf("m") > -1)) { + var _$head = sel.$head, + _node = _$head.textOffset ? null : dir < 0 ? _$head.nodeBefore : _$head.nodeAfter, + desc; + if (!_node || _node.isText) return false; + var nodePos = dir < 0 ? _$head.pos - _node.nodeSize : _$head.pos; + if (!(_node.isAtom || (desc = view.docView.descAt(nodePos)) && !desc.contentDOM)) return false; + if (prosemirrorState.NodeSelection.isSelectable(_node)) { + return apply(view, new prosemirrorState.NodeSelection(dir < 0 ? view.state.doc.resolve(_$head.pos - _node.nodeSize) : _$head)); + } else if (webkit) { + return apply(view, new prosemirrorState.TextSelection(view.state.doc.resolve(dir < 0 ? nodePos : nodePos + _node.nodeSize))); + } else { + return false; + } + } + } else if (sel instanceof prosemirrorState.NodeSelection && sel.node.isInline) { + return apply(view, new prosemirrorState.TextSelection(dir > 0 ? sel.$to : sel.$from)); + } else { + var _next = moveSelectionBlock(view.state, dir); + if (_next) return apply(view, _next); + return false; + } +} +function nodeLen(node) { + return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length; +} +function isIgnorable(dom, dir) { + var desc = dom.pmViewDesc; + return desc && desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR"); +} +function skipIgnoredNodes(view, dir) { + return dir < 0 ? skipIgnoredNodesBefore(view) : skipIgnoredNodesAfter(view); +} +function skipIgnoredNodesBefore(view) { + var sel = view.domSelectionRange(); + var node = sel.focusNode, + offset = sel.focusOffset; + if (!node) return; + var moveNode, + moveOffset, + force = false; + if (gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset], -1)) force = true; + for (;;) { + if (offset > 0) { + if (node.nodeType != 1) { + break; + } else { + var before = node.childNodes[offset - 1]; + if (isIgnorable(before, -1)) { + moveNode = node; + moveOffset = --offset; + } else if (before.nodeType == 3) { + node = before; + offset = node.nodeValue.length; + } else break; + } + } else if (isBlockNode(node)) { + break; + } else { + var prev = node.previousSibling; + while (prev && isIgnorable(prev, -1)) { + moveNode = node.parentNode; + moveOffset = domIndex(prev); + prev = prev.previousSibling; + } + if (!prev) { + node = node.parentNode; + if (node == view.dom) break; + offset = 0; + } else { + node = prev; + offset = nodeLen(node); + } + } + } + if (force) setSelFocus(view, node, offset);else if (moveNode) setSelFocus(view, moveNode, moveOffset); +} +function skipIgnoredNodesAfter(view) { + var sel = view.domSelectionRange(); + var node = sel.focusNode, + offset = sel.focusOffset; + if (!node) return; + var len = nodeLen(node); + var moveNode, moveOffset; + for (;;) { + if (offset < len) { + if (node.nodeType != 1) break; + var after = node.childNodes[offset]; + if (isIgnorable(after, 1)) { + moveNode = node; + moveOffset = ++offset; + } else break; + } else if (isBlockNode(node)) { + break; + } else { + var next = node.nextSibling; + while (next && isIgnorable(next, 1)) { + moveNode = next.parentNode; + moveOffset = domIndex(next) + 1; + next = next.nextSibling; + } + if (!next) { + node = node.parentNode; + if (node == view.dom) break; + offset = len = 0; + } else { + node = next; + offset = 0; + len = nodeLen(node); + } + } + } + if (moveNode) setSelFocus(view, moveNode, moveOffset); +} +function isBlockNode(dom) { + var desc = dom.pmViewDesc; + return desc && desc.node && desc.node.isBlock; +} +function textNodeAfter(node, offset) { + while (node && offset == node.childNodes.length && !hasBlockDesc(node)) { + offset = domIndex(node) + 1; + node = node.parentNode; + } + while (node && offset < node.childNodes.length) { + var next = node.childNodes[offset]; + if (next.nodeType == 3) return next; + if (next.nodeType == 1 && next.contentEditable == "false") break; + node = next; + offset = 0; + } +} +function textNodeBefore(node, offset) { + while (node && !offset && !hasBlockDesc(node)) { + offset = domIndex(node); + node = node.parentNode; + } + while (node && offset) { + var next = node.childNodes[offset - 1]; + if (next.nodeType == 3) return next; + if (next.nodeType == 1 && next.contentEditable == "false") break; + node = next; + offset = node.childNodes.length; + } +} +function setSelFocus(view, node, offset) { + if (node.nodeType != 3) { + var before, after; + if (after = textNodeAfter(node, offset)) { + node = after; + offset = 0; + } else if (before = textNodeBefore(node, offset)) { + node = before; + offset = before.nodeValue.length; + } + } + var sel = view.domSelection(); + if (!sel) return; + if (selectionCollapsed(sel)) { + var range = document.createRange(); + range.setEnd(node, offset); + range.setStart(node, offset); + sel.removeAllRanges(); + sel.addRange(range); + } else if (sel.extend) { + sel.extend(node, offset); + } + view.domObserver.setCurSelection(); + var state = view.state; + setTimeout(function () { + if (view.state == state) selectionToDOM(view); + }, 50); +} +function findDirection(view, pos) { + var $pos = view.state.doc.resolve(pos); + if (!(chrome || windows) && $pos.parent.inlineContent) { + var coords = view.coordsAtPos(pos); + if (pos > $pos.start()) { + var before = view.coordsAtPos(pos - 1); + var mid = (before.top + before.bottom) / 2; + if (mid > coords.top && mid < coords.bottom && Math.abs(before.left - coords.left) > 1) return before.left < coords.left ? "ltr" : "rtl"; + } + if (pos < $pos.end()) { + var after = view.coordsAtPos(pos + 1); + var _mid = (after.top + after.bottom) / 2; + if (_mid > coords.top && _mid < coords.bottom && Math.abs(after.left - coords.left) > 1) return after.left > coords.left ? "ltr" : "rtl"; + } + } + var computed = getComputedStyle(view.dom).direction; + return computed == "rtl" ? "rtl" : "ltr"; +} +function selectVertically(view, dir, mods) { + var sel = view.state.selection; + if (sel instanceof prosemirrorState.TextSelection && !sel.empty || mods.indexOf("s") > -1) return false; + if (mac && mods.indexOf("m") > -1) return false; + var $from = sel.$from, + $to = sel.$to; + if (!$from.parent.inlineContent || view.endOfTextblock(dir < 0 ? "up" : "down")) { + var next = moveSelectionBlock(view.state, dir); + if (next && next instanceof prosemirrorState.NodeSelection) return apply(view, next); + } + if (!$from.parent.inlineContent) { + var side = dir < 0 ? $from : $to; + var beyond = sel instanceof prosemirrorState.AllSelection ? prosemirrorState.Selection.near(side, dir) : prosemirrorState.Selection.findFrom(side, dir); + return beyond ? apply(view, beyond) : false; + } + return false; +} +function stopNativeHorizontalDelete(view, dir) { + if (!(view.state.selection instanceof prosemirrorState.TextSelection)) return true; + var _view$state$selection2 = view.state.selection, + $head = _view$state$selection2.$head, + $anchor = _view$state$selection2.$anchor, + empty = _view$state$selection2.empty; + if (!$head.sameParent($anchor)) return true; + if (!empty) return false; + if (view.endOfTextblock(dir > 0 ? "forward" : "backward")) return true; + var nextNode = !$head.textOffset && (dir < 0 ? $head.nodeBefore : $head.nodeAfter); + if (nextNode && !nextNode.isText) { + var tr = view.state.tr; + if (dir < 0) tr["delete"]($head.pos - nextNode.nodeSize, $head.pos);else tr["delete"]($head.pos, $head.pos + nextNode.nodeSize); + view.dispatch(tr); + return true; + } + return false; +} +function switchEditable(view, node, state) { + view.domObserver.stop(); + node.contentEditable = state; + view.domObserver.start(); +} +function safariDownArrowBug(view) { + if (!safari || view.state.selection.$head.parentOffset > 0) return false; + var _view$domSelectionRan3 = view.domSelectionRange(), + focusNode = _view$domSelectionRan3.focusNode, + focusOffset = _view$domSelectionRan3.focusOffset; + if (focusNode && focusNode.nodeType == 1 && focusOffset == 0 && focusNode.firstChild && focusNode.firstChild.contentEditable == "false") { + var child = focusNode.firstChild; + switchEditable(view, child, "true"); + setTimeout(function () { + return switchEditable(view, child, "false"); + }, 20); + } + return false; +} +function getMods(event) { + var result = ""; + if (event.ctrlKey) result += "c"; + if (event.metaKey) result += "m"; + if (event.altKey) result += "a"; + if (event.shiftKey) result += "s"; + return result; +} +function captureKeyDown(view, event) { + var code = event.keyCode, + mods = getMods(event); + if (code == 8 || mac && code == 72 && mods == "c") { + return stopNativeHorizontalDelete(view, -1) || skipIgnoredNodes(view, -1); + } else if (code == 46 && !event.shiftKey || mac && code == 68 && mods == "c") { + return stopNativeHorizontalDelete(view, 1) || skipIgnoredNodes(view, 1); + } else if (code == 13 || code == 27) { + return true; + } else if (code == 37 || mac && code == 66 && mods == "c") { + var dir = code == 37 ? findDirection(view, view.state.selection.from) == "ltr" ? -1 : 1 : -1; + return selectHorizontally(view, dir, mods) || skipIgnoredNodes(view, dir); + } else if (code == 39 || mac && code == 70 && mods == "c") { + var _dir = code == 39 ? findDirection(view, view.state.selection.from) == "ltr" ? 1 : -1 : 1; + return selectHorizontally(view, _dir, mods) || skipIgnoredNodes(view, _dir); + } else if (code == 38 || mac && code == 80 && mods == "c") { + return selectVertically(view, -1, mods) || skipIgnoredNodes(view, -1); + } else if (code == 40 || mac && code == 78 && mods == "c") { + return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodes(view, 1); + } else if (mods == (mac ? "m" : "c") && (code == 66 || code == 73 || code == 89 || code == 90)) { + return true; + } + return false; +} +function _serializeForClipboard(view, slice) { + view.someProp("transformCopied", function (f) { + slice = f(slice, view); + }); + var context = [], + _slice = slice, + content = _slice.content, + openStart = _slice.openStart, + openEnd = _slice.openEnd; + while (openStart > 1 && openEnd > 1 && content.childCount == 1 && content.firstChild.childCount == 1) { + openStart--; + openEnd--; + var node = content.firstChild; + context.push(node.type.name, node.attrs != node.type.defaultAttrs ? node.attrs : null); + content = node.content; + } + var serializer = view.someProp("clipboardSerializer") || prosemirrorModel.DOMSerializer.fromSchema(view.state.schema); + var doc = detachedDoc(), + wrap = doc.createElement("div"); + wrap.appendChild(serializer.serializeFragment(content, { + document: doc + })); + var firstChild = wrap.firstChild, + needsWrap, + wrappers = 0; + while (firstChild && firstChild.nodeType == 1 && (needsWrap = wrapMap[firstChild.nodeName.toLowerCase()])) { + for (var i = needsWrap.length - 1; i >= 0; i--) { + var wrapper = doc.createElement(needsWrap[i]); + while (wrap.firstChild) wrapper.appendChild(wrap.firstChild); + wrap.appendChild(wrapper); + wrappers++; + } + firstChild = wrap.firstChild; + } + if (firstChild && firstChild.nodeType == 1) firstChild.setAttribute("data-pm-slice", "".concat(openStart, " ").concat(openEnd).concat(wrappers ? " -".concat(wrappers) : "", " ").concat(JSON.stringify(context))); + var text = view.someProp("clipboardTextSerializer", function (f) { + return f(slice, view); + }) || slice.content.textBetween(0, slice.content.size, "\n\n"); + return { + dom: wrap, + text: text, + slice: slice + }; +} +function parseFromClipboard(view, text, html, plainText, $context) { + var inCode = $context.parent.type.spec.code; + var dom, slice; + if (!html && !text) return null; + var asText = text && (plainText || inCode || !html); + if (asText) { + view.someProp("transformPastedText", function (f) { + text = f(text, inCode || plainText, view); + }); + if (inCode) return text ? new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(view.state.schema.text(text.replace(/\r\n?/g, "\n"))), 0, 0) : prosemirrorModel.Slice.empty; + var parsed = view.someProp("clipboardTextParser", function (f) { + return f(text, $context, plainText, view); + }); + if (parsed) { + slice = parsed; + } else { + var marks = $context.marks(); + var schema = view.state.schema, + serializer = prosemirrorModel.DOMSerializer.fromSchema(schema); + dom = document.createElement("div"); + text.split(/(?:\r\n?|\n)+/).forEach(function (block) { + var p = dom.appendChild(document.createElement("p")); + if (block) p.appendChild(serializer.serializeNode(schema.text(block, marks))); + }); + } + } else { + view.someProp("transformPastedHTML", function (f) { + html = f(html, view); + }); + dom = readHTML(html); + if (webkit) restoreReplacedSpaces(dom); + } + var contextNode = dom && dom.querySelector("[data-pm-slice]"); + var sliceData = contextNode && /^(\d+) (\d+)(?: -(\d+))? (.*)/.exec(contextNode.getAttribute("data-pm-slice") || ""); + if (sliceData && sliceData[3]) for (var i = +sliceData[3]; i > 0; i--) { + var child = dom.firstChild; + while (child && child.nodeType != 1) child = child.nextSibling; + if (!child) break; + dom = child; + } + if (!slice) { + var parser = view.someProp("clipboardParser") || view.someProp("domParser") || prosemirrorModel.DOMParser.fromSchema(view.state.schema); + slice = parser.parseSlice(dom, { + preserveWhitespace: !!(asText || sliceData), + context: $context, + ruleFromNode: function ruleFromNode(dom) { + if (dom.nodeName == "BR" && !dom.nextSibling && dom.parentNode && !inlineParents.test(dom.parentNode.nodeName)) return { + ignore: true + }; + return null; + } + }); + } + if (sliceData) { + slice = addContext(closeSlice(slice, +sliceData[1], +sliceData[2]), sliceData[4]); + } else { + slice = prosemirrorModel.Slice.maxOpen(normalizeSiblings(slice.content, $context), true); + if (slice.openStart || slice.openEnd) { + var openStart = 0, + openEnd = 0; + for (var node = slice.content.firstChild; openStart < slice.openStart && !node.type.spec.isolating; openStart++, node = node.firstChild) {} + for (var _node2 = slice.content.lastChild; openEnd < slice.openEnd && !_node2.type.spec.isolating; openEnd++, _node2 = _node2.lastChild) {} + slice = closeSlice(slice, openStart, openEnd); + } + } + view.someProp("transformPasted", function (f) { + slice = f(slice, view); + }); + return slice; +} +var inlineParents = /^(a|abbr|acronym|b|cite|code|del|em|i|ins|kbd|label|output|q|ruby|s|samp|span|strong|sub|sup|time|u|tt|var)$/i; +function normalizeSiblings(fragment, $context) { + if (fragment.childCount < 2) return fragment; + var _loop = function _loop() { + var parent = $context.node(d); + var match = parent.contentMatchAt($context.index(d)); + var lastWrap, + result = []; + fragment.forEach(function (node) { + if (!result) return; + var wrap = match.findWrapping(node.type), + inLast; + if (!wrap) return result = null; + if (inLast = result.length && lastWrap.length && addToSibling(wrap, lastWrap, node, result[result.length - 1], 0)) { + result[result.length - 1] = inLast; + } else { + if (result.length) result[result.length - 1] = closeRight(result[result.length - 1], lastWrap.length); + var wrapped = withWrappers(node, wrap); + result.push(wrapped); + match = match.matchType(wrapped.type); + lastWrap = wrap; + } + }); + if (result) return { + v: prosemirrorModel.Fragment.from(result) + }; + }, + _ret; + for (var d = $context.depth; d >= 0; d--) { + _ret = _loop(); + if (_ret) return _ret.v; + } + return fragment; +} +function withWrappers(node, wrap) { + var from = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + for (var i = wrap.length - 1; i >= from; i--) node = wrap[i].create(null, prosemirrorModel.Fragment.from(node)); + return node; +} +function addToSibling(wrap, lastWrap, node, sibling, depth) { + if (depth < wrap.length && depth < lastWrap.length && wrap[depth] == lastWrap[depth]) { + var inner = addToSibling(wrap, lastWrap, node, sibling.lastChild, depth + 1); + if (inner) return sibling.copy(sibling.content.replaceChild(sibling.childCount - 1, inner)); + var match = sibling.contentMatchAt(sibling.childCount); + if (match.matchType(depth == wrap.length - 1 ? node.type : wrap[depth + 1])) return sibling.copy(sibling.content.append(prosemirrorModel.Fragment.from(withWrappers(node, wrap, depth + 1)))); + } +} +function closeRight(node, depth) { + if (depth == 0) return node; + var fragment = node.content.replaceChild(node.childCount - 1, closeRight(node.lastChild, depth - 1)); + var fill = node.contentMatchAt(node.childCount).fillBefore(prosemirrorModel.Fragment.empty, true); + return node.copy(fragment.append(fill)); +} +function closeRange(fragment, side, from, to, depth, openEnd) { + var node = side < 0 ? fragment.firstChild : fragment.lastChild, + inner = node.content; + if (fragment.childCount > 1) openEnd = 0; + if (depth < to - 1) inner = closeRange(inner, side, from, to, depth + 1, openEnd); + if (depth >= from) inner = side < 0 ? node.contentMatchAt(0).fillBefore(inner, openEnd <= depth).append(inner) : inner.append(node.contentMatchAt(node.childCount).fillBefore(prosemirrorModel.Fragment.empty, true)); + return fragment.replaceChild(side < 0 ? 0 : fragment.childCount - 1, node.copy(inner)); +} +function closeSlice(slice, openStart, openEnd) { + if (openStart < slice.openStart) slice = new prosemirrorModel.Slice(closeRange(slice.content, -1, openStart, slice.openStart, 0, slice.openEnd), openStart, slice.openEnd); + if (openEnd < slice.openEnd) slice = new prosemirrorModel.Slice(closeRange(slice.content, 1, openEnd, slice.openEnd, 0, 0), slice.openStart, openEnd); + return slice; +} +var wrapMap = { + thead: ["table"], + tbody: ["table"], + tfoot: ["table"], + caption: ["table"], + colgroup: ["table"], + col: ["table", "colgroup"], + tr: ["table", "tbody"], + td: ["table", "tbody", "tr"], + th: ["table", "tbody", "tr"] +}; +var _detachedDoc = null; +function detachedDoc() { + return _detachedDoc || (_detachedDoc = document.implementation.createHTMLDocument("title")); +} +var _policy = null; +function maybeWrapTrusted(html) { + var trustedTypes = window.trustedTypes; + if (!trustedTypes) return html; + if (!_policy) _policy = trustedTypes.createPolicy("ProseMirrorClipboard", { + createHTML: function createHTML(s) { + return s; + } + }); + return _policy.createHTML(html); +} +function readHTML(html) { + var metas = /^(\s*]*>)*/.exec(html); + if (metas) html = html.slice(metas[0].length); + var elt = detachedDoc().createElement("div"); + var firstTag = /<([a-z][^>\s]+)/i.exec(html), + wrap; + if (wrap = firstTag && wrapMap[firstTag[1].toLowerCase()]) html = wrap.map(function (n) { + return "<" + n + ">"; + }).join("") + html + wrap.map(function (n) { + return ""; + }).reverse().join(""); + elt.innerHTML = maybeWrapTrusted(html); + if (wrap) for (var i = 0; i < wrap.length; i++) elt = elt.querySelector(wrap[i]) || elt; + return elt; +} +function restoreReplacedSpaces(dom) { + var nodes = dom.querySelectorAll(chrome ? "span:not([class]):not([style])" : "span.Apple-converted-space"); + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + if (node.childNodes.length == 1 && node.textContent == "\xA0" && node.parentNode) node.parentNode.replaceChild(dom.ownerDocument.createTextNode(" "), node); + } +} +function addContext(slice, context) { + if (!slice.size) return slice; + var schema = slice.content.firstChild.type.schema, + array; + try { + array = JSON.parse(context); + } catch (e) { + return slice; + } + var content = slice.content, + openStart = slice.openStart, + openEnd = slice.openEnd; + for (var i = array.length - 2; i >= 0; i -= 2) { + var type = schema.nodes[array[i]]; + if (!type || type.hasRequiredAttrs()) break; + content = prosemirrorModel.Fragment.from(type.create(array[i + 1], content)); + openStart++; + openEnd++; + } + return new prosemirrorModel.Slice(content, openStart, openEnd); +} +var handlers = {}; +var editHandlers = {}; +var passiveHandlers = { + touchstart: true, + touchmove: true +}; +var InputState = _createClass(function InputState() { + _classCallCheck(this, InputState); + this.shiftKey = false; + this.mouseDown = null; + this.lastKeyCode = null; + this.lastKeyCodeTime = 0; + this.lastClick = { + time: 0, + x: 0, + y: 0, + type: "" + }; + this.lastSelectionOrigin = null; + this.lastSelectionTime = 0; + this.lastIOSEnter = 0; + this.lastIOSEnterFallbackTimeout = -1; + this.lastFocus = 0; + this.lastTouch = 0; + this.lastChromeDelete = 0; + this.composing = false; + this.compositionNode = null; + this.composingTimeout = -1; + this.compositionNodes = []; + this.compositionEndedAt = -2e8; + this.compositionID = 1; + this.compositionPendingChanges = 0; + this.domChangeCount = 0; + this.eventHandlers = Object.create(null); + this.hideSelectionGuard = null; +}); +function initInput(view) { + var _loop2 = function _loop2() { + var handler = handlers[event]; + view.dom.addEventListener(event, view.input.eventHandlers[event] = function (event) { + if (eventBelongsToView(view, event) && !runCustomHandler(view, event) && (view.editable || !(event.type in editHandlers))) handler(view, event); + }, passiveHandlers[event] ? { + passive: true + } : undefined); + }; + for (var event in handlers) { + _loop2(); + } + if (safari) view.dom.addEventListener("input", function () { + return null; + }); + ensureListeners(view); +} +function setSelectionOrigin(view, origin) { + view.input.lastSelectionOrigin = origin; + view.input.lastSelectionTime = Date.now(); +} +function destroyInput(view) { + view.domObserver.stop(); + for (var type in view.input.eventHandlers) view.dom.removeEventListener(type, view.input.eventHandlers[type]); + clearTimeout(view.input.composingTimeout); + clearTimeout(view.input.lastIOSEnterFallbackTimeout); +} +function ensureListeners(view) { + view.someProp("handleDOMEvents", function (currentHandlers) { + for (var type in currentHandlers) if (!view.input.eventHandlers[type]) view.dom.addEventListener(type, view.input.eventHandlers[type] = function (event) { + return runCustomHandler(view, event); + }); + }); +} +function runCustomHandler(view, event) { + return view.someProp("handleDOMEvents", function (handlers) { + var handler = handlers[event.type]; + return handler ? handler(view, event) || event.defaultPrevented : false; + }); +} +function eventBelongsToView(view, event) { + if (!event.bubbles) return true; + if (event.defaultPrevented) return false; + for (var node = event.target; node != view.dom; node = node.parentNode) if (!node || node.nodeType == 11 || node.pmViewDesc && node.pmViewDesc.stopEvent(event)) return false; + return true; +} +function _dispatchEvent(view, event) { + if (!runCustomHandler(view, event) && handlers[event.type] && (view.editable || !(event.type in editHandlers))) handlers[event.type](view, event); +} +editHandlers.keydown = function (view, _event) { + var event = _event; + view.input.shiftKey = event.keyCode == 16 || event.shiftKey; + if (inOrNearComposition(view, event)) return; + view.input.lastKeyCode = event.keyCode; + view.input.lastKeyCodeTime = Date.now(); + if (android && chrome && event.keyCode == 13) return; + if (event.keyCode != 229) view.domObserver.forceFlush(); + if (ios && event.keyCode == 13 && !event.ctrlKey && !event.altKey && !event.metaKey) { + var now = Date.now(); + view.input.lastIOSEnter = now; + view.input.lastIOSEnterFallbackTimeout = setTimeout(function () { + if (view.input.lastIOSEnter == now) { + view.someProp("handleKeyDown", function (f) { + return f(view, keyEvent(13, "Enter")); + }); + view.input.lastIOSEnter = 0; + } + }, 200); + } else if (view.someProp("handleKeyDown", function (f) { + return f(view, event); + }) || captureKeyDown(view, event)) { + event.preventDefault(); + } else { + setSelectionOrigin(view, "key"); + } +}; +editHandlers.keyup = function (view, event) { + if (event.keyCode == 16) view.input.shiftKey = false; +}; +editHandlers.keypress = function (view, _event) { + var event = _event; + if (inOrNearComposition(view, event) || !event.charCode || event.ctrlKey && !event.altKey || mac && event.metaKey) return; + if (view.someProp("handleKeyPress", function (f) { + return f(view, event); + })) { + event.preventDefault(); + return; + } + var sel = view.state.selection; + if (!(sel instanceof prosemirrorState.TextSelection) || !sel.$from.sameParent(sel.$to)) { + var text = String.fromCharCode(event.charCode); + if (!/[\r\n]/.test(text) && !view.someProp("handleTextInput", function (f) { + return f(view, sel.$from.pos, sel.$to.pos, text); + })) view.dispatch(view.state.tr.insertText(text).scrollIntoView()); + event.preventDefault(); + } +}; +function eventCoords(event) { + return { + left: event.clientX, + top: event.clientY + }; +} +function isNear(event, click) { + var dx = click.x - event.clientX, + dy = click.y - event.clientY; + return dx * dx + dy * dy < 100; +} +function runHandlerOnContext(view, propName, pos, inside, event) { + if (inside == -1) return false; + var $pos = view.state.doc.resolve(inside); + var _loop3 = function _loop3(i) { + if (view.someProp(propName, function (f) { + return i > $pos.depth ? f(view, pos, $pos.nodeAfter, $pos.before(i), event, true) : f(view, pos, $pos.node(i), $pos.before(i), event, false); + })) return { + v: true + }; + }, + _ret2; + for (var i = $pos.depth + 1; i > 0; i--) { + _ret2 = _loop3(i); + if (_ret2) return _ret2.v; + } + return false; +} +function updateSelection(view, selection, origin) { + if (!view.focused) view.focus(); + if (view.state.selection.eq(selection)) return; + var tr = view.state.tr.setSelection(selection); + if (origin == "pointer") tr.setMeta("pointer", true); + view.dispatch(tr); +} +function selectClickedLeaf(view, inside) { + if (inside == -1) return false; + var $pos = view.state.doc.resolve(inside), + node = $pos.nodeAfter; + if (node && node.isAtom && prosemirrorState.NodeSelection.isSelectable(node)) { + updateSelection(view, new prosemirrorState.NodeSelection($pos), "pointer"); + return true; + } + return false; +} +function selectClickedNode(view, inside) { + if (inside == -1) return false; + var sel = view.state.selection, + selectedNode, + selectAt; + if (sel instanceof prosemirrorState.NodeSelection) selectedNode = sel.node; + var $pos = view.state.doc.resolve(inside); + for (var i = $pos.depth + 1; i > 0; i--) { + var node = i > $pos.depth ? $pos.nodeAfter : $pos.node(i); + if (prosemirrorState.NodeSelection.isSelectable(node)) { + if (selectedNode && sel.$from.depth > 0 && i >= sel.$from.depth && $pos.before(sel.$from.depth + 1) == sel.$from.pos) selectAt = $pos.before(sel.$from.depth);else selectAt = $pos.before(i); + break; + } + } + if (selectAt != null) { + updateSelection(view, prosemirrorState.NodeSelection.create(view.state.doc, selectAt), "pointer"); + return true; + } else { + return false; + } +} +function handleSingleClick(view, pos, inside, event, selectNode) { + return runHandlerOnContext(view, "handleClickOn", pos, inside, event) || view.someProp("handleClick", function (f) { + return f(view, pos, event); + }) || (selectNode ? selectClickedNode(view, inside) : selectClickedLeaf(view, inside)); +} +function handleDoubleClick(view, pos, inside, event) { + return runHandlerOnContext(view, "handleDoubleClickOn", pos, inside, event) || view.someProp("handleDoubleClick", function (f) { + return f(view, pos, event); + }); +} +function handleTripleClick(view, pos, inside, event) { + return runHandlerOnContext(view, "handleTripleClickOn", pos, inside, event) || view.someProp("handleTripleClick", function (f) { + return f(view, pos, event); + }) || defaultTripleClick(view, inside, event); +} +function defaultTripleClick(view, inside, event) { + if (event.button != 0) return false; + var doc = view.state.doc; + if (inside == -1) { + if (doc.inlineContent) { + updateSelection(view, prosemirrorState.TextSelection.create(doc, 0, doc.content.size), "pointer"); + return true; + } + return false; + } + var $pos = doc.resolve(inside); + for (var i = $pos.depth + 1; i > 0; i--) { + var node = i > $pos.depth ? $pos.nodeAfter : $pos.node(i); + var nodePos = $pos.before(i); + if (node.inlineContent) updateSelection(view, prosemirrorState.TextSelection.create(doc, nodePos + 1, nodePos + 1 + node.content.size), "pointer");else if (prosemirrorState.NodeSelection.isSelectable(node)) updateSelection(view, prosemirrorState.NodeSelection.create(doc, nodePos), "pointer");else continue; + return true; + } +} +function forceDOMFlush(view) { + return endComposition(view); +} +var selectNodeModifier = mac ? "metaKey" : "ctrlKey"; +handlers.mousedown = function (view, _event) { + var event = _event; + view.input.shiftKey = event.shiftKey; + var flushed = forceDOMFlush(view); + var now = Date.now(), + type = "singleClick"; + if (now - view.input.lastClick.time < 500 && isNear(event, view.input.lastClick) && !event[selectNodeModifier]) { + if (view.input.lastClick.type == "singleClick") type = "doubleClick";else if (view.input.lastClick.type == "doubleClick") type = "tripleClick"; + } + view.input.lastClick = { + time: now, + x: event.clientX, + y: event.clientY, + type: type + }; + var pos = view.posAtCoords(eventCoords(event)); + if (!pos) return; + if (type == "singleClick") { + if (view.input.mouseDown) view.input.mouseDown.done(); + view.input.mouseDown = new MouseDown(view, pos, event, !!flushed); + } else if ((type == "doubleClick" ? handleDoubleClick : handleTripleClick)(view, pos.pos, pos.inside, event)) { + event.preventDefault(); + } else { + setSelectionOrigin(view, "pointer"); + } +}; +var MouseDown = function () { + function MouseDown(view, pos, event, flushed) { + var _this8 = this; + _classCallCheck(this, MouseDown); + this.view = view; + this.pos = pos; + this.event = event; + this.flushed = flushed; + this.delayedSelectionSync = false; + this.mightDrag = null; + this.startDoc = view.state.doc; + this.selectNode = !!event[selectNodeModifier]; + this.allowDefault = event.shiftKey; + var targetNode, targetPos; + if (pos.inside > -1) { + targetNode = view.state.doc.nodeAt(pos.inside); + targetPos = pos.inside; + } else { + var $pos = view.state.doc.resolve(pos.pos); + targetNode = $pos.parent; + targetPos = $pos.depth ? $pos.before() : 0; + } + var target = flushed ? null : event.target; + var targetDesc = target ? view.docView.nearestDesc(target, true) : null; + this.target = targetDesc && targetDesc.dom.nodeType == 1 ? targetDesc.dom : null; + var selection = view.state.selection; + if (event.button == 0 && targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false || selection instanceof prosemirrorState.NodeSelection && selection.from <= targetPos && selection.to > targetPos) this.mightDrag = { + node: targetNode, + pos: targetPos, + addAttr: !!(this.target && !this.target.draggable), + setUneditable: !!(this.target && gecko && !this.target.hasAttribute("contentEditable")) + }; + if (this.target && this.mightDrag && (this.mightDrag.addAttr || this.mightDrag.setUneditable)) { + this.view.domObserver.stop(); + if (this.mightDrag.addAttr) this.target.draggable = true; + if (this.mightDrag.setUneditable) setTimeout(function () { + if (_this8.view.input.mouseDown == _this8) _this8.target.setAttribute("contentEditable", "false"); + }, 20); + this.view.domObserver.start(); + } + view.root.addEventListener("mouseup", this.up = this.up.bind(this)); + view.root.addEventListener("mousemove", this.move = this.move.bind(this)); + setSelectionOrigin(view, "pointer"); + } + _createClass(MouseDown, [{ + key: "done", + value: function done() { + var _this9 = this; + this.view.root.removeEventListener("mouseup", this.up); + this.view.root.removeEventListener("mousemove", this.move); + if (this.mightDrag && this.target) { + this.view.domObserver.stop(); + if (this.mightDrag.addAttr) this.target.removeAttribute("draggable"); + if (this.mightDrag.setUneditable) this.target.removeAttribute("contentEditable"); + this.view.domObserver.start(); + } + if (this.delayedSelectionSync) setTimeout(function () { + return selectionToDOM(_this9.view); + }); + this.view.input.mouseDown = null; + } + }, { + key: "up", + value: function up(event) { + this.done(); + if (!this.view.dom.contains(event.target)) return; + var pos = this.pos; + if (this.view.state.doc != this.startDoc) pos = this.view.posAtCoords(eventCoords(event)); + this.updateAllowDefault(event); + if (this.allowDefault || !pos) { + setSelectionOrigin(this.view, "pointer"); + } else if (handleSingleClick(this.view, pos.pos, pos.inside, event, this.selectNode)) { + event.preventDefault(); + } else if (event.button == 0 && (this.flushed || safari && this.mightDrag && !this.mightDrag.node.isAtom || chrome && !this.view.state.selection.visible && Math.min(Math.abs(pos.pos - this.view.state.selection.from), Math.abs(pos.pos - this.view.state.selection.to)) <= 2)) { + updateSelection(this.view, prosemirrorState.Selection.near(this.view.state.doc.resolve(pos.pos)), "pointer"); + event.preventDefault(); + } else { + setSelectionOrigin(this.view, "pointer"); + } + } + }, { + key: "move", + value: function move(event) { + this.updateAllowDefault(event); + setSelectionOrigin(this.view, "pointer"); + if (event.buttons == 0) this.done(); + } + }, { + key: "updateAllowDefault", + value: function updateAllowDefault(event) { + if (!this.allowDefault && (Math.abs(this.event.x - event.clientX) > 4 || Math.abs(this.event.y - event.clientY) > 4)) this.allowDefault = true; + } + }]); + return MouseDown; +}(); +handlers.touchstart = function (view) { + view.input.lastTouch = Date.now(); + forceDOMFlush(view); + setSelectionOrigin(view, "pointer"); +}; +handlers.touchmove = function (view) { + view.input.lastTouch = Date.now(); + setSelectionOrigin(view, "pointer"); +}; +handlers.contextmenu = function (view) { + return forceDOMFlush(view); +}; +function inOrNearComposition(view, event) { + if (view.composing) return true; + if (safari && Math.abs(event.timeStamp - view.input.compositionEndedAt) < 500) { + view.input.compositionEndedAt = -2e8; + return true; + } + return false; +} +var timeoutComposition = android ? 5000 : -1; +editHandlers.compositionstart = editHandlers.compositionupdate = function (view) { + if (!view.composing) { + view.domObserver.flush(); + var state = view.state, + $pos = state.selection.$to; + if (state.selection instanceof prosemirrorState.TextSelection && (state.storedMarks || !$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some(function (m) { + return m.type.spec.inclusive === false; + }))) { + view.markCursor = view.state.storedMarks || $pos.marks(); + endComposition(view, true); + view.markCursor = null; + } else { + endComposition(view, !state.selection.empty); + if (gecko && state.selection.empty && $pos.parentOffset && !$pos.textOffset && $pos.nodeBefore.marks.length) { + var sel = view.domSelectionRange(); + for (var node = sel.focusNode, offset = sel.focusOffset; node && node.nodeType == 1 && offset != 0;) { + var before = offset < 0 ? node.lastChild : node.childNodes[offset - 1]; + if (!before) break; + if (before.nodeType == 3) { + var _sel = view.domSelection(); + if (_sel) _sel.collapse(before, before.nodeValue.length); + break; + } else { + node = before; + offset = -1; + } + } + } + } + view.input.composing = true; + } + scheduleComposeEnd(view, timeoutComposition); +}; +editHandlers.compositionend = function (view, event) { + if (view.composing) { + view.input.composing = false; + view.input.compositionEndedAt = event.timeStamp; + view.input.compositionPendingChanges = view.domObserver.pendingRecords().length ? view.input.compositionID : 0; + view.input.compositionNode = null; + if (view.input.compositionPendingChanges) Promise.resolve().then(function () { + return view.domObserver.flush(); + }); + view.input.compositionID++; + scheduleComposeEnd(view, 20); + } +}; +function scheduleComposeEnd(view, delay) { + clearTimeout(view.input.composingTimeout); + if (delay > -1) view.input.composingTimeout = setTimeout(function () { + return endComposition(view); + }, delay); +} +function clearComposition(view) { + if (view.composing) { + view.input.composing = false; + view.input.compositionEndedAt = timestampFromCustomEvent(); + } + while (view.input.compositionNodes.length > 0) view.input.compositionNodes.pop().markParentsDirty(); +} +function findCompositionNode(view) { + var sel = view.domSelectionRange(); + if (!sel.focusNode) return null; + var textBefore = textNodeBefore$1(sel.focusNode, sel.focusOffset); + var textAfter = textNodeAfter$1(sel.focusNode, sel.focusOffset); + if (textBefore && textAfter && textBefore != textAfter) { + var descAfter = textAfter.pmViewDesc, + lastChanged = view.domObserver.lastChangedTextNode; + if (textBefore == lastChanged || textAfter == lastChanged) return lastChanged; + if (!descAfter || !descAfter.isText(textAfter.nodeValue)) { + return textAfter; + } else if (view.input.compositionNode == textAfter) { + var descBefore = textBefore.pmViewDesc; + if (!(!descBefore || !descBefore.isText(textBefore.nodeValue))) return textAfter; + } + } + return textBefore || textAfter; +} +function timestampFromCustomEvent() { + var event = document.createEvent("Event"); + event.initEvent("event", true, true); + return event.timeStamp; +} +function endComposition(view) { + var restarting = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + if (android && view.domObserver.flushingSoon >= 0) return; + view.domObserver.forceFlush(); + clearComposition(view); + if (restarting || view.docView && view.docView.dirty) { + var sel = selectionFromDOM(view); + if (sel && !sel.eq(view.state.selection)) view.dispatch(view.state.tr.setSelection(sel));else if ((view.markCursor || restarting) && !view.state.selection.empty) view.dispatch(view.state.tr.deleteSelection());else view.updateState(view.state); + return true; + } + return false; +} +function captureCopy(view, dom) { + if (!view.dom.parentNode) return; + var wrap = view.dom.parentNode.appendChild(document.createElement("div")); + wrap.appendChild(dom); + wrap.style.cssText = "position: fixed; left: -10000px; top: 10px"; + var sel = getSelection(), + range = document.createRange(); + range.selectNodeContents(dom); + view.dom.blur(); + sel.removeAllRanges(); + sel.addRange(range); + setTimeout(function () { + if (wrap.parentNode) wrap.parentNode.removeChild(wrap); + view.focus(); + }, 50); +} +var brokenClipboardAPI = ie && ie_version < 15 || ios && webkit_version < 604; +handlers.copy = editHandlers.cut = function (view, _event) { + var event = _event; + var sel = view.state.selection, + cut = event.type == "cut"; + if (sel.empty) return; + var data = brokenClipboardAPI ? null : event.clipboardData; + var slice = sel.content(), + _serializeForClipboar = _serializeForClipboard(view, slice), + dom = _serializeForClipboar.dom, + text = _serializeForClipboar.text; + if (data) { + event.preventDefault(); + data.clearData(); + data.setData("text/html", dom.innerHTML); + data.setData("text/plain", text); + } else { + captureCopy(view, dom); + } + if (cut) view.dispatch(view.state.tr.deleteSelection().scrollIntoView().setMeta("uiEvent", "cut")); +}; +function sliceSingleNode(slice) { + return slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1 ? slice.content.firstChild : null; +} +function capturePaste(view, event) { + if (!view.dom.parentNode) return; + var plainText = view.input.shiftKey || view.state.selection.$from.parent.type.spec.code; + var target = view.dom.parentNode.appendChild(document.createElement(plainText ? "textarea" : "div")); + if (!plainText) target.contentEditable = "true"; + target.style.cssText = "position: fixed; left: -10000px; top: 10px"; + target.focus(); + var plain = view.input.shiftKey && view.input.lastKeyCode != 45; + setTimeout(function () { + view.focus(); + if (target.parentNode) target.parentNode.removeChild(target); + if (plainText) doPaste(view, target.value, null, plain, event);else doPaste(view, target.textContent, target.innerHTML, plain, event); + }, 50); +} +function doPaste(view, text, html, preferPlain, event) { + var slice = parseFromClipboard(view, text, html, preferPlain, view.state.selection.$from); + if (view.someProp("handlePaste", function (f) { + return f(view, event, slice || prosemirrorModel.Slice.empty); + })) return true; + if (!slice) return false; + var singleNode = sliceSingleNode(slice); + var tr = singleNode ? view.state.tr.replaceSelectionWith(singleNode, preferPlain) : view.state.tr.replaceSelection(slice); + view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste")); + return true; +} +function getText(clipboardData) { + var text = clipboardData.getData("text/plain") || clipboardData.getData("Text"); + if (text) return text; + var uris = clipboardData.getData("text/uri-list"); + return uris ? uris.replace(/\r?\n/g, " ") : ""; +} +editHandlers.paste = function (view, _event) { + var event = _event; + if (view.composing && !android) return; + var data = brokenClipboardAPI ? null : event.clipboardData; + var plain = view.input.shiftKey && view.input.lastKeyCode != 45; + if (data && doPaste(view, getText(data), data.getData("text/html"), plain, event)) event.preventDefault();else capturePaste(view, event); +}; +var Dragging = _createClass(function Dragging(slice, move, node) { + _classCallCheck(this, Dragging); + this.slice = slice; + this.move = move; + this.node = node; +}); +var dragCopyModifier = mac ? "altKey" : "ctrlKey"; +handlers.dragstart = function (view, _event) { + var event = _event; + var mouseDown = view.input.mouseDown; + if (mouseDown) mouseDown.done(); + if (!event.dataTransfer) return; + var sel = view.state.selection; + var pos = sel.empty ? null : view.posAtCoords(eventCoords(event)); + var node; + if (pos && pos.pos >= sel.from && pos.pos <= (sel instanceof prosemirrorState.NodeSelection ? sel.to - 1 : sel.to)) ;else if (mouseDown && mouseDown.mightDrag) { + node = prosemirrorState.NodeSelection.create(view.state.doc, mouseDown.mightDrag.pos); + } else if (event.target && event.target.nodeType == 1) { + var desc = view.docView.nearestDesc(event.target, true); + if (desc && desc.node.type.spec.draggable && desc != view.docView) node = prosemirrorState.NodeSelection.create(view.state.doc, desc.posBefore); + } + var draggedSlice = (node || view.state.selection).content(); + var _serializeForClipboar2 = _serializeForClipboard(view, draggedSlice), + dom = _serializeForClipboar2.dom, + text = _serializeForClipboar2.text, + slice = _serializeForClipboar2.slice; + if (!event.dataTransfer.files.length || !chrome || chrome_version > 120) event.dataTransfer.clearData(); + event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML); + event.dataTransfer.effectAllowed = "copyMove"; + if (!brokenClipboardAPI) event.dataTransfer.setData("text/plain", text); + view.dragging = new Dragging(slice, !event[dragCopyModifier], node); +}; +handlers.dragend = function (view) { + var dragging = view.dragging; + window.setTimeout(function () { + if (view.dragging == dragging) view.dragging = null; + }, 50); +}; +editHandlers.dragover = editHandlers.dragenter = function (_, e) { + return e.preventDefault(); +}; +editHandlers.drop = function (view, _event) { + var event = _event; + var dragging = view.dragging; + view.dragging = null; + if (!event.dataTransfer) return; + var eventPos = view.posAtCoords(eventCoords(event)); + if (!eventPos) return; + var $mouse = view.state.doc.resolve(eventPos.pos); + var slice = dragging && dragging.slice; + if (slice) { + view.someProp("transformPasted", function (f) { + slice = f(slice, view); + }); + } else { + slice = parseFromClipboard(view, getText(event.dataTransfer), brokenClipboardAPI ? null : event.dataTransfer.getData("text/html"), false, $mouse); + } + var move = !!(dragging && !event[dragCopyModifier]); + if (view.someProp("handleDrop", function (f) { + return f(view, event, slice || prosemirrorModel.Slice.empty, move); + })) { + event.preventDefault(); + return; + } + if (!slice) return; + event.preventDefault(); + var insertPos = slice ? prosemirrorTransform.dropPoint(view.state.doc, $mouse.pos, slice) : $mouse.pos; + if (insertPos == null) insertPos = $mouse.pos; + var tr = view.state.tr; + if (move) { + var node = dragging.node; + if (node) node.replace(tr);else tr.deleteSelection(); + } + var pos = tr.mapping.map(insertPos); + var isNode = slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1; + var beforeInsert = tr.doc; + if (isNode) tr.replaceRangeWith(pos, pos, slice.content.firstChild);else tr.replaceRange(pos, pos, slice); + if (tr.doc.eq(beforeInsert)) return; + var $pos = tr.doc.resolve(pos); + if (isNode && prosemirrorState.NodeSelection.isSelectable(slice.content.firstChild) && $pos.nodeAfter && $pos.nodeAfter.sameMarkup(slice.content.firstChild)) { + tr.setSelection(new prosemirrorState.NodeSelection($pos)); + } else { + var end = tr.mapping.map(insertPos); + tr.mapping.maps[tr.mapping.maps.length - 1].forEach(function (_from, _to, _newFrom, newTo) { + return end = newTo; + }); + tr.setSelection(selectionBetween(view, $pos, tr.doc.resolve(end))); + } + view.focus(); + view.dispatch(tr.setMeta("uiEvent", "drop")); +}; +handlers.focus = function (view) { + view.input.lastFocus = Date.now(); + if (!view.focused) { + view.domObserver.stop(); + view.dom.classList.add("ProseMirror-focused"); + view.domObserver.start(); + view.focused = true; + setTimeout(function () { + if (view.docView && view.hasFocus() && !view.domObserver.currentSelection.eq(view.domSelectionRange())) selectionToDOM(view); + }, 20); + } +}; +handlers.blur = function (view, _event) { + var event = _event; + if (view.focused) { + view.domObserver.stop(); + view.dom.classList.remove("ProseMirror-focused"); + view.domObserver.start(); + if (event.relatedTarget && view.dom.contains(event.relatedTarget)) view.domObserver.currentSelection.clear(); + view.focused = false; + } +}; +handlers.beforeinput = function (view, _event) { + var event = _event; + if (chrome && android && event.inputType == "deleteContentBackward") { + view.domObserver.flushSoon(); + var domChangeCount = view.input.domChangeCount; + setTimeout(function () { + if (view.input.domChangeCount != domChangeCount) return; + view.dom.blur(); + view.focus(); + if (view.someProp("handleKeyDown", function (f) { + return f(view, keyEvent(8, "Backspace")); + })) return; + var $cursor = view.state.selection.$cursor; + if ($cursor && $cursor.pos > 0) view.dispatch(view.state.tr["delete"]($cursor.pos - 1, $cursor.pos).scrollIntoView()); + }, 50); + } +}; +for (var prop in editHandlers) handlers[prop] = editHandlers[prop]; +function compareObjs(a, b) { + if (a == b) return true; + for (var p in a) if (a[p] !== b[p]) return false; + for (var _p in b) if (!(_p in a)) return false; + return true; +} +var WidgetType = function () { + function WidgetType(toDOM, spec) { + _classCallCheck(this, WidgetType); + this.toDOM = toDOM; + this.spec = spec || noSpec; + this.side = this.spec.side || 0; + } + _createClass(WidgetType, [{ + key: "map", + value: function map(mapping, span, offset, oldOffset) { + var _mapping$mapResult = mapping.mapResult(span.from + oldOffset, this.side < 0 ? -1 : 1), + pos = _mapping$mapResult.pos, + deleted = _mapping$mapResult.deleted; + return deleted ? null : new Decoration(pos - offset, pos - offset, this); + } + }, { + key: "valid", + value: function valid() { + return true; + } + }, { + key: "eq", + value: function eq(other) { + return this == other || other instanceof WidgetType && (this.spec.key && this.spec.key == other.spec.key || this.toDOM == other.toDOM && compareObjs(this.spec, other.spec)); + } + }, { + key: "destroy", + value: function destroy(node) { + if (this.spec.destroy) this.spec.destroy(node); + } + }]); + return WidgetType; +}(); +var InlineType = function () { + function InlineType(attrs, spec) { + _classCallCheck(this, InlineType); + this.attrs = attrs; + this.spec = spec || noSpec; + } + _createClass(InlineType, [{ + key: "map", + value: function map(mapping, span, offset, oldOffset) { + var from = mapping.map(span.from + oldOffset, this.spec.inclusiveStart ? -1 : 1) - offset; + var to = mapping.map(span.to + oldOffset, this.spec.inclusiveEnd ? 1 : -1) - offset; + return from >= to ? null : new Decoration(from, to, this); + } + }, { + key: "valid", + value: function valid(_, span) { + return span.from < span.to; + } + }, { + key: "eq", + value: function eq(other) { + return this == other || other instanceof InlineType && compareObjs(this.attrs, other.attrs) && compareObjs(this.spec, other.spec); + } + }, { + key: "destroy", + value: function destroy() {} + }], [{ + key: "is", + value: function is(span) { + return span.type instanceof InlineType; + } + }]); + return InlineType; +}(); +var NodeType = function () { + function NodeType(attrs, spec) { + _classCallCheck(this, NodeType); + this.attrs = attrs; + this.spec = spec || noSpec; + } + _createClass(NodeType, [{ + key: "map", + value: function map(mapping, span, offset, oldOffset) { + var from = mapping.mapResult(span.from + oldOffset, 1); + if (from.deleted) return null; + var to = mapping.mapResult(span.to + oldOffset, -1); + if (to.deleted || to.pos <= from.pos) return null; + return new Decoration(from.pos - offset, to.pos - offset, this); + } + }, { + key: "valid", + value: function valid(node, span) { + var _node$content$findInd = node.content.findIndex(span.from), + index = _node$content$findInd.index, + offset = _node$content$findInd.offset, + child; + return offset == span.from && !(child = node.child(index)).isText && offset + child.nodeSize == span.to; + } + }, { + key: "eq", + value: function eq(other) { + return this == other || other instanceof NodeType && compareObjs(this.attrs, other.attrs) && compareObjs(this.spec, other.spec); + } + }, { + key: "destroy", + value: function destroy() {} + }]); + return NodeType; +}(); +var Decoration = function () { + function Decoration(from, to, type) { + _classCallCheck(this, Decoration); + this.from = from; + this.to = to; + this.type = type; + } + _createClass(Decoration, [{ + key: "copy", + value: function copy(from, to) { + return new Decoration(from, to, this.type); + } + }, { + key: "eq", + value: function eq(other) { + var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + return this.type.eq(other.type) && this.from + offset == other.from && this.to + offset == other.to; + } + }, { + key: "map", + value: function map(mapping, offset, oldOffset) { + return this.type.map(mapping, this, offset, oldOffset); + } + }, { + key: "spec", + get: function get() { + return this.type.spec; + } + }, { + key: "inline", + get: function get() { + return this.type instanceof InlineType; + } + }, { + key: "widget", + get: function get() { + return this.type instanceof WidgetType; + } + }], [{ + key: "widget", + value: function widget(pos, toDOM, spec) { + return new Decoration(pos, pos, new WidgetType(toDOM, spec)); + } + }, { + key: "inline", + value: function inline(from, to, attrs, spec) { + return new Decoration(from, to, new InlineType(attrs, spec)); + } + }, { + key: "node", + value: function node(from, to, attrs, spec) { + return new Decoration(from, to, new NodeType(attrs, spec)); + } + }]); + return Decoration; +}(); +var none = [], + noSpec = {}; +var DecorationSet = function () { + function DecorationSet(local, children) { + _classCallCheck(this, DecorationSet); + this.local = local.length ? local : none; + this.children = children.length ? children : none; + } + _createClass(DecorationSet, [{ + key: "find", + value: function find(start, end, predicate) { + var result = []; + this.findInner(start == null ? 0 : start, end == null ? 1e9 : end, result, 0, predicate); + return result; + } + }, { + key: "findInner", + value: function findInner(start, end, result, offset, predicate) { + for (var i = 0; i < this.local.length; i++) { + var span = this.local[i]; + if (span.from <= end && span.to >= start && (!predicate || predicate(span.spec))) result.push(span.copy(span.from + offset, span.to + offset)); + } + for (var _i6 = 0; _i6 < this.children.length; _i6 += 3) { + if (this.children[_i6] < end && this.children[_i6 + 1] > start) { + var childOff = this.children[_i6] + 1; + this.children[_i6 + 2].findInner(start - childOff, end - childOff, result, offset + childOff, predicate); + } + } + } + }, { + key: "map", + value: function map(mapping, doc, options) { + if (this == empty || mapping.maps.length == 0) return this; + return this.mapInner(mapping, doc, 0, 0, options || noSpec); + } + }, { + key: "mapInner", + value: function mapInner(mapping, node, offset, oldOffset, options) { + var newLocal; + for (var i = 0; i < this.local.length; i++) { + var mapped = this.local[i].map(mapping, offset, oldOffset); + if (mapped && mapped.type.valid(node, mapped)) (newLocal || (newLocal = [])).push(mapped);else if (options.onRemove) options.onRemove(this.local[i].spec); + } + if (this.children.length) return mapChildren(this.children, newLocal || [], mapping, node, offset, oldOffset, options);else return newLocal ? new DecorationSet(newLocal.sort(byPos), none) : empty; + } + }, { + key: "add", + value: function add(doc, decorations) { + if (!decorations.length) return this; + if (this == empty) return DecorationSet.create(doc, decorations); + return this.addInner(doc, decorations, 0); + } + }, { + key: "addInner", + value: function addInner(doc, decorations, offset) { + var _this10 = this; + var children, + childIndex = 0; + doc.forEach(function (childNode, childOffset) { + var baseOffset = childOffset + offset, + found; + if (!(found = takeSpansForNode(decorations, childNode, baseOffset))) return; + if (!children) children = _this10.children.slice(); + while (childIndex < children.length && children[childIndex] < childOffset) childIndex += 3; + if (children[childIndex] == childOffset) children[childIndex + 2] = children[childIndex + 2].addInner(childNode, found, baseOffset + 1);else children.splice(childIndex, 0, childOffset, childOffset + childNode.nodeSize, buildTree(found, childNode, baseOffset + 1, noSpec)); + childIndex += 3; + }); + var local = moveSpans(childIndex ? withoutNulls(decorations) : decorations, -offset); + for (var i = 0; i < local.length; i++) if (!local[i].type.valid(doc, local[i])) local.splice(i--, 1); + return new DecorationSet(local.length ? this.local.concat(local).sort(byPos) : this.local, children || this.children); + } + }, { + key: "remove", + value: function remove(decorations) { + if (decorations.length == 0 || this == empty) return this; + return this.removeInner(decorations, 0); + } + }, { + key: "removeInner", + value: function removeInner(decorations, offset) { + var children = this.children, + local = this.local; + for (var i = 0; i < children.length; i += 3) { + var found = void 0; + var from = children[i] + offset, + to = children[i + 1] + offset; + for (var j = 0, span; j < decorations.length; j++) if (span = decorations[j]) { + if (span.from > from && span.to < to) { + decorations[j] = null; + (found || (found = [])).push(span); + } + } + if (!found) continue; + if (children == this.children) children = this.children.slice(); + var removed = children[i + 2].removeInner(found, from + 1); + if (removed != empty) { + children[i + 2] = removed; + } else { + children.splice(i, 3); + i -= 3; + } + } + if (local.length) for (var _i7 = 0, _span; _i7 < decorations.length; _i7++) if (_span = decorations[_i7]) { + for (var _j2 = 0; _j2 < local.length; _j2++) if (local[_j2].eq(_span, offset)) { + if (local == this.local) local = this.local.slice(); + local.splice(_j2--, 1); + } + } + if (children == this.children && local == this.local) return this; + return local.length || children.length ? new DecorationSet(local, children) : empty; + } + }, { + key: "forChild", + value: function forChild(offset, node) { + if (this == empty) return this; + if (node.isLeaf) return DecorationSet.empty; + var child, local; + for (var i = 0; i < this.children.length; i += 3) if (this.children[i] >= offset) { + if (this.children[i] == offset) child = this.children[i + 2]; + break; + } + var start = offset + 1, + end = start + node.content.size; + for (var _i8 = 0; _i8 < this.local.length; _i8++) { + var dec = this.local[_i8]; + if (dec.from < end && dec.to > start && dec.type instanceof InlineType) { + var from = Math.max(start, dec.from) - start, + to = Math.min(end, dec.to) - start; + if (from < to) (local || (local = [])).push(dec.copy(from, to)); + } + } + if (local) { + var localSet = new DecorationSet(local.sort(byPos), none); + return child ? new DecorationGroup([localSet, child]) : localSet; + } + return child || empty; + } + }, { + key: "eq", + value: function eq(other) { + if (this == other) return true; + if (!(other instanceof DecorationSet) || this.local.length != other.local.length || this.children.length != other.children.length) return false; + for (var i = 0; i < this.local.length; i++) if (!this.local[i].eq(other.local[i])) return false; + for (var _i9 = 0; _i9 < this.children.length; _i9 += 3) if (this.children[_i9] != other.children[_i9] || this.children[_i9 + 1] != other.children[_i9 + 1] || !this.children[_i9 + 2].eq(other.children[_i9 + 2])) return false; + return true; + } + }, { + key: "locals", + value: function locals(node) { + return removeOverlap(this.localsInner(node)); + } + }, { + key: "localsInner", + value: function localsInner(node) { + if (this == empty) return none; + if (node.inlineContent || !this.local.some(InlineType.is)) return this.local; + var result = []; + for (var i = 0; i < this.local.length; i++) { + if (!(this.local[i].type instanceof InlineType)) result.push(this.local[i]); + } + return result; + } + }, { + key: "forEachSet", + value: function forEachSet(f) { + f(this); + } + }], [{ + key: "create", + value: function create(doc, decorations) { + return decorations.length ? buildTree(decorations, doc, 0, noSpec) : empty; + } + }]); + return DecorationSet; +}(); +DecorationSet.empty = new DecorationSet([], []); +DecorationSet.removeOverlap = removeOverlap; +var empty = DecorationSet.empty; +var DecorationGroup = function () { + function DecorationGroup(members) { + _classCallCheck(this, DecorationGroup); + this.members = members; + } + _createClass(DecorationGroup, [{ + key: "map", + value: function map(mapping, doc) { + var mappedDecos = this.members.map(function (member) { + return member.map(mapping, doc, noSpec); + }); + return DecorationGroup.from(mappedDecos); + } + }, { + key: "forChild", + value: function forChild(offset, child) { + if (child.isLeaf) return DecorationSet.empty; + var found = []; + for (var i = 0; i < this.members.length; i++) { + var result = this.members[i].forChild(offset, child); + if (result == empty) continue; + if (result instanceof DecorationGroup) found = found.concat(result.members);else found.push(result); + } + return DecorationGroup.from(found); + } + }, { + key: "eq", + value: function eq(other) { + if (!(other instanceof DecorationGroup) || other.members.length != this.members.length) return false; + for (var i = 0; i < this.members.length; i++) if (!this.members[i].eq(other.members[i])) return false; + return true; + } + }, { + key: "locals", + value: function locals(node) { + var result, + sorted = true; + for (var i = 0; i < this.members.length; i++) { + var locals = this.members[i].localsInner(node); + if (!locals.length) continue; + if (!result) { + result = locals; + } else { + if (sorted) { + result = result.slice(); + sorted = false; + } + for (var j = 0; j < locals.length; j++) result.push(locals[j]); + } + } + return result ? removeOverlap(sorted ? result : result.sort(byPos)) : none; + } + }, { + key: "forEachSet", + value: function forEachSet(f) { + for (var i = 0; i < this.members.length; i++) this.members[i].forEachSet(f); + } + }], [{ + key: "from", + value: function from(members) { + switch (members.length) { + case 0: + return empty; + case 1: + return members[0]; + default: + return new DecorationGroup(members.every(function (m) { + return m instanceof DecorationSet; + }) ? members : members.reduce(function (r, m) { + return r.concat(m instanceof DecorationSet ? m : m.members); + }, [])); + } + } + }]); + return DecorationGroup; +}(); +function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, options) { + var children = oldChildren.slice(); + var _loop4 = function _loop4(_baseOffset) { + var moved = 0; + mapping.maps[i].forEach(function (oldStart, oldEnd, newStart, newEnd) { + var dSize = newEnd - newStart - (oldEnd - oldStart); + for (var _i13 = 0; _i13 < children.length; _i13 += 3) { + var end = children[_i13 + 1]; + if (end < 0 || oldStart > end + _baseOffset - moved) continue; + var start = children[_i13] + _baseOffset - moved; + if (oldEnd >= start) { + children[_i13 + 1] = oldStart <= start ? -2 : -1; + } else if (oldStart >= _baseOffset && dSize) { + children[_i13] += dSize; + children[_i13 + 1] += dSize; + } + } + moved += dSize; + }); + _baseOffset = mapping.maps[i].map(_baseOffset, -1); + baseOffset = _baseOffset; + }; + for (var i = 0, baseOffset = oldOffset; i < mapping.maps.length; i++) { + _loop4(baseOffset); + } + var mustRebuild = false; + for (var _i10 = 0; _i10 < children.length; _i10 += 3) if (children[_i10 + 1] < 0) { + if (children[_i10 + 1] == -2) { + mustRebuild = true; + children[_i10 + 1] = -1; + continue; + } + var from = mapping.map(oldChildren[_i10] + oldOffset), + fromLocal = from - offset; + if (fromLocal < 0 || fromLocal >= node.content.size) { + mustRebuild = true; + continue; + } + var to = mapping.map(oldChildren[_i10 + 1] + oldOffset, -1), + toLocal = to - offset; + var _node$content$findInd2 = node.content.findIndex(fromLocal), + index = _node$content$findInd2.index, + childOffset = _node$content$findInd2.offset; + var childNode = node.maybeChild(index); + if (childNode && childOffset == fromLocal && childOffset + childNode.nodeSize == toLocal) { + var mapped = children[_i10 + 2].mapInner(mapping, childNode, from + 1, oldChildren[_i10] + oldOffset + 1, options); + if (mapped != empty) { + children[_i10] = fromLocal; + children[_i10 + 1] = toLocal; + children[_i10 + 2] = mapped; + } else { + children[_i10 + 1] = -2; + mustRebuild = true; + } + } else { + mustRebuild = true; + } + } + if (mustRebuild) { + var decorations = mapAndGatherRemainingDecorations(children, oldChildren, newLocal, mapping, offset, oldOffset, options); + var built = buildTree(decorations, node, 0, options); + newLocal = built.local; + for (var _i11 = 0; _i11 < children.length; _i11 += 3) if (children[_i11 + 1] < 0) { + children.splice(_i11, 3); + _i11 -= 3; + } + for (var _i12 = 0, j = 0; _i12 < built.children.length; _i12 += 3) { + var _from2 = built.children[_i12]; + while (j < children.length && children[j] < _from2) j += 3; + children.splice(j, 0, built.children[_i12], built.children[_i12 + 1], built.children[_i12 + 2]); + } + } + return new DecorationSet(newLocal.sort(byPos), children); +} +function moveSpans(spans, offset) { + if (!offset || !spans.length) return spans; + var result = []; + for (var i = 0; i < spans.length; i++) { + var span = spans[i]; + result.push(new Decoration(span.from + offset, span.to + offset, span.type)); + } + return result; +} +function mapAndGatherRemainingDecorations(children, oldChildren, decorations, mapping, offset, oldOffset, options) { + function gather(set, oldOffset) { + for (var i = 0; i < set.local.length; i++) { + var mapped = set.local[i].map(mapping, offset, oldOffset); + if (mapped) decorations.push(mapped);else if (options.onRemove) options.onRemove(set.local[i].spec); + } + for (var _i14 = 0; _i14 < set.children.length; _i14 += 3) gather(set.children[_i14 + 2], set.children[_i14] + oldOffset + 1); + } + for (var i = 0; i < children.length; i += 3) if (children[i + 1] == -1) gather(children[i + 2], oldChildren[i] + oldOffset + 1); + return decorations; +} +function takeSpansForNode(spans, node, offset) { + if (node.isLeaf) return null; + var end = offset + node.nodeSize, + found = null; + for (var i = 0, span; i < spans.length; i++) { + if ((span = spans[i]) && span.from > offset && span.to < end) { + (found || (found = [])).push(span); + spans[i] = null; + } + } + return found; +} +function withoutNulls(array) { + var result = []; + for (var i = 0; i < array.length; i++) if (array[i] != null) result.push(array[i]); + return result; +} +function buildTree(spans, node, offset, options) { + var children = [], + hasNulls = false; + node.forEach(function (childNode, localStart) { + var found = takeSpansForNode(spans, childNode, localStart + offset); + if (found) { + hasNulls = true; + var subtree = buildTree(found, childNode, offset + localStart + 1, options); + if (subtree != empty) children.push(localStart, localStart + childNode.nodeSize, subtree); + } + }); + var locals = moveSpans(hasNulls ? withoutNulls(spans) : spans, -offset).sort(byPos); + for (var i = 0; i < locals.length; i++) if (!locals[i].type.valid(node, locals[i])) { + if (options.onRemove) options.onRemove(locals[i].spec); + locals.splice(i--, 1); + } + return locals.length || children.length ? new DecorationSet(locals, children) : empty; +} +function byPos(a, b) { + return a.from - b.from || a.to - b.to; +} +function removeOverlap(spans) { + var working = spans; + for (var i = 0; i < working.length - 1; i++) { + var span = working[i]; + if (span.from != span.to) for (var j = i + 1; j < working.length; j++) { + var next = working[j]; + if (next.from == span.from) { + if (next.to != span.to) { + if (working == spans) working = spans.slice(); + working[j] = next.copy(next.from, span.to); + insertAhead(working, j + 1, next.copy(span.to, next.to)); + } + continue; + } else { + if (next.from < span.to) { + if (working == spans) working = spans.slice(); + working[i] = span.copy(span.from, next.from); + insertAhead(working, j, span.copy(next.from, span.to)); + } + break; + } + } + } + return working; +} +function insertAhead(array, i, deco) { + while (i < array.length && byPos(deco, array[i]) > 0) i++; + array.splice(i, 0, deco); +} +function viewDecorations(view) { + var found = []; + view.someProp("decorations", function (f) { + var result = f(view.state); + if (result && result != empty) found.push(result); + }); + if (view.cursorWrapper) found.push(DecorationSet.create(view.state.doc, [view.cursorWrapper.deco])); + return DecorationGroup.from(found); +} +var observeOptions = { + childList: true, + characterData: true, + characterDataOldValue: true, + attributes: true, + attributeOldValue: true, + subtree: true +}; +var useCharData = ie && ie_version <= 11; +var SelectionState = function () { + function SelectionState() { + _classCallCheck(this, SelectionState); + this.anchorNode = null; + this.anchorOffset = 0; + this.focusNode = null; + this.focusOffset = 0; + } + _createClass(SelectionState, [{ + key: "set", + value: function set(sel) { + this.anchorNode = sel.anchorNode; + this.anchorOffset = sel.anchorOffset; + this.focusNode = sel.focusNode; + this.focusOffset = sel.focusOffset; + } + }, { + key: "clear", + value: function clear() { + this.anchorNode = this.focusNode = null; + } + }, { + key: "eq", + value: function eq(sel) { + return sel.anchorNode == this.anchorNode && sel.anchorOffset == this.anchorOffset && sel.focusNode == this.focusNode && sel.focusOffset == this.focusOffset; + } + }]); + return SelectionState; +}(); +var DOMObserver = function () { + function DOMObserver(view, handleDOMChange) { + var _this11 = this; + _classCallCheck(this, DOMObserver); + this.view = view; + this.handleDOMChange = handleDOMChange; + this.queue = []; + this.flushingSoon = -1; + this.observer = null; + this.currentSelection = new SelectionState(); + this.onCharData = null; + this.suppressingSelectionUpdates = false; + this.lastChangedTextNode = null; + this.observer = window.MutationObserver && new window.MutationObserver(function (mutations) { + for (var i = 0; i < mutations.length; i++) _this11.queue.push(mutations[i]); + if (ie && ie_version <= 11 && mutations.some(function (m) { + return m.type == "childList" && m.removedNodes.length || m.type == "characterData" && m.oldValue.length > m.target.nodeValue.length; + })) _this11.flushSoon();else _this11.flush(); + }); + if (useCharData) { + this.onCharData = function (e) { + _this11.queue.push({ + target: e.target, + type: "characterData", + oldValue: e.prevValue + }); + _this11.flushSoon(); + }; + } + this.onSelectionChange = this.onSelectionChange.bind(this); + } + _createClass(DOMObserver, [{ + key: "flushSoon", + value: function flushSoon() { + var _this12 = this; + if (this.flushingSoon < 0) this.flushingSoon = window.setTimeout(function () { + _this12.flushingSoon = -1; + _this12.flush(); + }, 20); + } + }, { + key: "forceFlush", + value: function forceFlush() { + if (this.flushingSoon > -1) { + window.clearTimeout(this.flushingSoon); + this.flushingSoon = -1; + this.flush(); + } + } + }, { + key: "start", + value: function start() { + if (this.observer) { + this.observer.takeRecords(); + this.observer.observe(this.view.dom, observeOptions); + } + if (this.onCharData) this.view.dom.addEventListener("DOMCharacterDataModified", this.onCharData); + this.connectSelection(); + } + }, { + key: "stop", + value: function stop() { + var _this13 = this; + if (this.observer) { + var take = this.observer.takeRecords(); + if (take.length) { + for (var i = 0; i < take.length; i++) this.queue.push(take[i]); + window.setTimeout(function () { + return _this13.flush(); + }, 20); + } + this.observer.disconnect(); + } + if (this.onCharData) this.view.dom.removeEventListener("DOMCharacterDataModified", this.onCharData); + this.disconnectSelection(); + } + }, { + key: "connectSelection", + value: function connectSelection() { + this.view.dom.ownerDocument.addEventListener("selectionchange", this.onSelectionChange); + } + }, { + key: "disconnectSelection", + value: function disconnectSelection() { + this.view.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange); + } + }, { + key: "suppressSelectionUpdates", + value: function suppressSelectionUpdates() { + var _this14 = this; + this.suppressingSelectionUpdates = true; + setTimeout(function () { + return _this14.suppressingSelectionUpdates = false; + }, 50); + } + }, { + key: "onSelectionChange", + value: function onSelectionChange() { + if (!hasFocusAndSelection(this.view)) return; + if (this.suppressingSelectionUpdates) return selectionToDOM(this.view); + if (ie && ie_version <= 11 && !this.view.state.selection.empty) { + var sel = this.view.domSelectionRange(); + if (sel.focusNode && isEquivalentPosition(sel.focusNode, sel.focusOffset, sel.anchorNode, sel.anchorOffset)) return this.flushSoon(); + } + this.flush(); + } + }, { + key: "setCurSelection", + value: function setCurSelection() { + this.currentSelection.set(this.view.domSelectionRange()); + } + }, { + key: "ignoreSelectionChange", + value: function ignoreSelectionChange(sel) { + if (!sel.focusNode) return true; + var ancestors = new Set(), + container; + for (var scan = sel.focusNode; scan; scan = parentNode(scan)) ancestors.add(scan); + for (var _scan = sel.anchorNode; _scan; _scan = parentNode(_scan)) if (ancestors.has(_scan)) { + container = _scan; + break; + } + var desc = container && this.view.docView.nearestDesc(container); + if (desc && desc.ignoreMutation({ + type: "selection", + target: container.nodeType == 3 ? container.parentNode : container + })) { + this.setCurSelection(); + return true; + } + } + }, { + key: "pendingRecords", + value: function pendingRecords() { + if (this.observer) { + var _iterator2 = _createForOfIteratorHelper(this.observer.takeRecords()), + _step2; + try { + for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { + var mut = _step2.value; + this.queue.push(mut); + } + } catch (err) { + _iterator2.e(err); + } finally { + _iterator2.f(); + } + } + return this.queue; + } + }, { + key: "flush", + value: function flush() { + var view = this.view; + if (!view.docView || this.flushingSoon > -1) return; + var mutations = this.pendingRecords(); + if (mutations.length) this.queue = []; + var sel = view.domSelectionRange(); + var newSel = !this.suppressingSelectionUpdates && !this.currentSelection.eq(sel) && hasFocusAndSelection(view) && !this.ignoreSelectionChange(sel); + var from = -1, + to = -1, + typeOver = false, + added = []; + if (view.editable) { + for (var i = 0; i < mutations.length; i++) { + var result = this.registerMutation(mutations[i], added); + if (result) { + from = from < 0 ? result.from : Math.min(result.from, from); + to = to < 0 ? result.to : Math.max(result.to, to); + if (result.typeOver) typeOver = true; + } + } + } + if (gecko && added.length) { + var brs = added.filter(function (n) { + return n.nodeName == "BR"; + }); + if (brs.length == 2) { + var _brs = _slicedToArray(brs, 2), + a = _brs[0], + b = _brs[1]; + if (a.parentNode && a.parentNode.parentNode == b.parentNode) b.remove();else a.remove(); + } else { + var focusNode = this.currentSelection.focusNode; + var _iterator3 = _createForOfIteratorHelper(brs), + _step3; + try { + for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) { + var br = _step3.value; + var parent = br.parentNode; + if (parent && parent.nodeName == "LI" && (!focusNode || blockParent(view, focusNode) != parent)) br.remove(); + } + } catch (err) { + _iterator3.e(err); + } finally { + _iterator3.f(); + } + } + } + var readSel = null; + if (from < 0 && newSel && view.input.lastFocus > Date.now() - 200 && Math.max(view.input.lastTouch, view.input.lastClick.time) < Date.now() - 300 && selectionCollapsed(sel) && (readSel = selectionFromDOM(view)) && readSel.eq(prosemirrorState.Selection.near(view.state.doc.resolve(0), 1))) { + view.input.lastFocus = 0; + selectionToDOM(view); + this.currentSelection.set(sel); + view.scrollToSelection(); + } else if (from > -1 || newSel) { + if (from > -1) { + view.docView.markDirty(from, to); + checkCSS(view); + } + this.handleDOMChange(from, to, typeOver, added); + if (view.docView && view.docView.dirty) view.updateState(view.state);else if (!this.currentSelection.eq(sel)) selectionToDOM(view); + this.currentSelection.set(sel); + } + } + }, { + key: "registerMutation", + value: function registerMutation(mut, added) { + if (added.indexOf(mut.target) > -1) return null; + var desc = this.view.docView.nearestDesc(mut.target); + if (mut.type == "attributes" && (desc == this.view.docView || mut.attributeName == "contenteditable" || mut.attributeName == "style" && !mut.oldValue && !mut.target.getAttribute("style"))) return null; + if (!desc || desc.ignoreMutation(mut)) return null; + if (mut.type == "childList") { + for (var i = 0; i < mut.addedNodes.length; i++) { + var node = mut.addedNodes[i]; + added.push(node); + if (node.nodeType == 3) this.lastChangedTextNode = node; + } + if (desc.contentDOM && desc.contentDOM != desc.dom && !desc.contentDOM.contains(mut.target)) return { + from: desc.posBefore, + to: desc.posAfter + }; + var prev = mut.previousSibling, + next = mut.nextSibling; + if (ie && ie_version <= 11 && mut.addedNodes.length) { + for (var _i15 = 0; _i15 < mut.addedNodes.length; _i15++) { + var _mut$addedNodes$_i = mut.addedNodes[_i15], + previousSibling = _mut$addedNodes$_i.previousSibling, + nextSibling = _mut$addedNodes$_i.nextSibling; + if (!previousSibling || Array.prototype.indexOf.call(mut.addedNodes, previousSibling) < 0) prev = previousSibling; + if (!nextSibling || Array.prototype.indexOf.call(mut.addedNodes, nextSibling) < 0) next = nextSibling; + } + } + var fromOffset = prev && prev.parentNode == mut.target ? domIndex(prev) + 1 : 0; + var from = desc.localPosFromDOM(mut.target, fromOffset, -1); + var toOffset = next && next.parentNode == mut.target ? domIndex(next) : mut.target.childNodes.length; + var to = desc.localPosFromDOM(mut.target, toOffset, 1); + return { + from: from, + to: to + }; + } else if (mut.type == "attributes") { + return { + from: desc.posAtStart - desc.border, + to: desc.posAtEnd + desc.border + }; + } else { + this.lastChangedTextNode = mut.target; + return { + from: desc.posAtStart, + to: desc.posAtEnd, + typeOver: mut.target.nodeValue == mut.oldValue + }; + } + } + }]); + return DOMObserver; +}(); +var cssChecked = new WeakMap(); +var cssCheckWarned = false; +function checkCSS(view) { + if (cssChecked.has(view)) return; + cssChecked.set(view, null); + if (['normal', 'nowrap', 'pre-line'].indexOf(getComputedStyle(view.dom).whiteSpace) !== -1) { + view.requiresGeckoHackNode = gecko; + if (cssCheckWarned) return; + console["warn"]("ProseMirror expects the CSS white-space property to be set, preferably to 'pre-wrap'. It is recommended to load style/prosemirror.css from the prosemirror-view package."); + cssCheckWarned = true; + } +} +function rangeToSelectionRange(view, range) { + var anchorNode = range.startContainer, + anchorOffset = range.startOffset; + var focusNode = range.endContainer, + focusOffset = range.endOffset; + var currentAnchor = view.domAtPos(view.state.selection.anchor); + if (isEquivalentPosition(currentAnchor.node, currentAnchor.offset, focusNode, focusOffset)) { + var _ref5 = [focusNode, focusOffset, anchorNode, anchorOffset]; + anchorNode = _ref5[0]; + anchorOffset = _ref5[1]; + focusNode = _ref5[2]; + focusOffset = _ref5[3]; + } + return { + anchorNode: anchorNode, + anchorOffset: anchorOffset, + focusNode: focusNode, + focusOffset: focusOffset + }; +} +function safariShadowSelectionRange(view, selection) { + if (selection.getComposedRanges) { + var range = selection.getComposedRanges(view.root)[0]; + if (range) return rangeToSelectionRange(view, range); + } + var found; + function read(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + found = event.getTargetRanges()[0]; + } + view.dom.addEventListener("beforeinput", read, true); + document.execCommand("indent"); + view.dom.removeEventListener("beforeinput", read, true); + return found ? rangeToSelectionRange(view, found) : null; +} +function blockParent(view, node) { + for (var p = node.parentNode; p && p != view.dom; p = p.parentNode) { + var desc = view.docView.nearestDesc(p, true); + if (desc && desc.node.isBlock) return p; + } + return null; +} +function parseBetween(view, from_, to_) { + var _view$docView$parseRa = view.docView.parseRange(from_, to_), + parent = _view$docView$parseRa.node, + fromOffset = _view$docView$parseRa.fromOffset, + toOffset = _view$docView$parseRa.toOffset, + from = _view$docView$parseRa.from, + to = _view$docView$parseRa.to; + var domSel = view.domSelectionRange(); + var find; + var anchor = domSel.anchorNode; + if (anchor && view.dom.contains(anchor.nodeType == 1 ? anchor : anchor.parentNode)) { + find = [{ + node: anchor, + offset: domSel.anchorOffset + }]; + if (!selectionCollapsed(domSel)) find.push({ + node: domSel.focusNode, + offset: domSel.focusOffset + }); + } + if (chrome && view.input.lastKeyCode === 8) { + for (var off = toOffset; off > fromOffset; off--) { + var node = parent.childNodes[off - 1], + desc = node.pmViewDesc; + if (node.nodeName == "BR" && !desc) { + toOffset = off; + break; + } + if (!desc || desc.size) break; + } + } + var startDoc = view.state.doc; + var parser = view.someProp("domParser") || prosemirrorModel.DOMParser.fromSchema(view.state.schema); + var $from = startDoc.resolve(from); + var sel = null, + doc = parser.parse(parent, { + topNode: $from.parent, + topMatch: $from.parent.contentMatchAt($from.index()), + topOpen: true, + from: fromOffset, + to: toOffset, + preserveWhitespace: $from.parent.type.whitespace == "pre" ? "full" : true, + findPositions: find, + ruleFromNode: ruleFromNode, + context: $from + }); + if (find && find[0].pos != null) { + var _anchor = find[0].pos, + head = find[1] && find[1].pos; + if (head == null) head = _anchor; + sel = { + anchor: _anchor + from, + head: head + from + }; + } + return { + doc: doc, + sel: sel, + from: from, + to: to + }; +} +function ruleFromNode(dom) { + var desc = dom.pmViewDesc; + if (desc) { + return desc.parseRule(); + } else if (dom.nodeName == "BR" && dom.parentNode) { + if (safari && /^(ul|ol)$/i.test(dom.parentNode.nodeName)) { + var skip = document.createElement("div"); + skip.appendChild(document.createElement("li")); + return { + skip: skip + }; + } else if (dom.parentNode.lastChild == dom || safari && /^(tr|table)$/i.test(dom.parentNode.nodeName)) { + return { + ignore: true + }; + } + } else if (dom.nodeName == "IMG" && dom.getAttribute("mark-placeholder")) { + return { + ignore: true + }; + } + return null; +} +var isInline = /^(a|abbr|acronym|b|bd[io]|big|br|button|cite|code|data(list)?|del|dfn|em|i|ins|kbd|label|map|mark|meter|output|q|ruby|s|samp|small|span|strong|su[bp]|time|u|tt|var)$/i; +function readDOMChange(view, from, to, typeOver, addedNodes) { + var compositionID = view.input.compositionPendingChanges || (view.composing ? view.input.compositionID : 0); + view.input.compositionPendingChanges = 0; + if (from < 0) { + var origin = view.input.lastSelectionTime > Date.now() - 50 ? view.input.lastSelectionOrigin : null; + var newSel = selectionFromDOM(view, origin); + if (newSel && !view.state.selection.eq(newSel)) { + if (chrome && android && view.input.lastKeyCode === 13 && Date.now() - 100 < view.input.lastKeyCodeTime && view.someProp("handleKeyDown", function (f) { + return f(view, keyEvent(13, "Enter")); + })) return; + var _tr = view.state.tr.setSelection(newSel); + if (origin == "pointer") _tr.setMeta("pointer", true);else if (origin == "key") _tr.scrollIntoView(); + if (compositionID) _tr.setMeta("composition", compositionID); + view.dispatch(_tr); + } + return; + } + var $before = view.state.doc.resolve(from); + var shared = $before.sharedDepth(to); + from = $before.before(shared + 1); + to = view.state.doc.resolve(to).after(shared + 1); + var sel = view.state.selection; + var parse = parseBetween(view, from, to); + var doc = view.state.doc, + compare = doc.slice(parse.from, parse.to); + var preferredPos, preferredSide; + if (view.input.lastKeyCode === 8 && Date.now() - 100 < view.input.lastKeyCodeTime) { + preferredPos = view.state.selection.to; + preferredSide = "end"; + } else { + preferredPos = view.state.selection.from; + preferredSide = "start"; + } + view.input.lastKeyCode = null; + var change = findDiff(compare.content, parse.doc.content, parse.from, preferredPos, preferredSide); + if (change) view.input.domChangeCount++; + if ((ios && view.input.lastIOSEnter > Date.now() - 225 || android) && addedNodes.some(function (n) { + return n.nodeType == 1 && !isInline.test(n.nodeName); + }) && (!change || change.endA >= change.endB) && view.someProp("handleKeyDown", function (f) { + return f(view, keyEvent(13, "Enter")); + })) { + view.input.lastIOSEnter = 0; + return; + } + if (!change) { + if (typeOver && sel instanceof prosemirrorState.TextSelection && !sel.empty && sel.$head.sameParent(sel.$anchor) && !view.composing && !(parse.sel && parse.sel.anchor != parse.sel.head)) { + change = { + start: sel.from, + endA: sel.to, + endB: sel.to + }; + } else { + if (parse.sel) { + var _sel2 = resolveSelection(view, view.state.doc, parse.sel); + if (_sel2 && !_sel2.eq(view.state.selection)) { + var _tr2 = view.state.tr.setSelection(_sel2); + if (compositionID) _tr2.setMeta("composition", compositionID); + view.dispatch(_tr2); + } + } + return; + } + } + if (view.state.selection.from < view.state.selection.to && change.start == change.endB && view.state.selection instanceof prosemirrorState.TextSelection) { + if (change.start > view.state.selection.from && change.start <= view.state.selection.from + 2 && view.state.selection.from >= parse.from) { + change.start = view.state.selection.from; + } else if (change.endA < view.state.selection.to && change.endA >= view.state.selection.to - 2 && view.state.selection.to <= parse.to) { + change.endB += view.state.selection.to - change.endA; + change.endA = view.state.selection.to; + } + } + if (ie && ie_version <= 11 && change.endB == change.start + 1 && change.endA == change.start && change.start > parse.from && parse.doc.textBetween(change.start - parse.from - 1, change.start - parse.from + 1) == " \xA0") { + change.start--; + change.endA--; + change.endB--; + } + var $from = parse.doc.resolveNoCache(change.start - parse.from); + var $to = parse.doc.resolveNoCache(change.endB - parse.from); + var $fromA = doc.resolve(change.start); + var inlineChange = $from.sameParent($to) && $from.parent.inlineContent && $fromA.end() >= change.endA; + var nextSel; + if ((ios && view.input.lastIOSEnter > Date.now() - 225 && (!inlineChange || addedNodes.some(function (n) { + return n.nodeName == "DIV" || n.nodeName == "P"; + })) || !inlineChange && $from.pos < parse.doc.content.size && !$from.sameParent($to) && (nextSel = prosemirrorState.Selection.findFrom(parse.doc.resolve($from.pos + 1), 1, true)) && nextSel.head == $to.pos) && view.someProp("handleKeyDown", function (f) { + return f(view, keyEvent(13, "Enter")); + })) { + view.input.lastIOSEnter = 0; + return; + } + if (view.state.selection.anchor > change.start && looksLikeBackspace(doc, change.start, change.endA, $from, $to) && view.someProp("handleKeyDown", function (f) { + return f(view, keyEvent(8, "Backspace")); + })) { + if (android && chrome) view.domObserver.suppressSelectionUpdates(); + return; + } + if (chrome && change.endB == change.start) view.input.lastChromeDelete = Date.now(); + if (android && !inlineChange && $from.start() != $to.start() && $to.parentOffset == 0 && $from.depth == $to.depth && parse.sel && parse.sel.anchor == parse.sel.head && parse.sel.head == change.endA) { + change.endB -= 2; + $to = parse.doc.resolveNoCache(change.endB - parse.from); + setTimeout(function () { + view.someProp("handleKeyDown", function (f) { + return f(view, keyEvent(13, "Enter")); + }); + }, 20); + } + var chFrom = change.start, + chTo = change.endA; + var tr, storedMarks, markChange; + if (inlineChange) { + if ($from.pos == $to.pos) { + if (ie && ie_version <= 11 && $from.parentOffset == 0) { + view.domObserver.suppressSelectionUpdates(); + setTimeout(function () { + return selectionToDOM(view); + }, 20); + } + tr = view.state.tr["delete"](chFrom, chTo); + storedMarks = doc.resolve(change.start).marksAcross(doc.resolve(change.endA)); + } else if (change.endA == change.endB && (markChange = isMarkChange($from.parent.content.cut($from.parentOffset, $to.parentOffset), $fromA.parent.content.cut($fromA.parentOffset, change.endA - $fromA.start())))) { + tr = view.state.tr; + if (markChange.type == "add") tr.addMark(chFrom, chTo, markChange.mark);else tr.removeMark(chFrom, chTo, markChange.mark); + } else if ($from.parent.child($from.index()).isText && $from.index() == $to.index() - ($to.textOffset ? 0 : 1)) { + var text = $from.parent.textBetween($from.parentOffset, $to.parentOffset); + if (view.someProp("handleTextInput", function (f) { + return f(view, chFrom, chTo, text); + })) return; + tr = view.state.tr.insertText(text, chFrom, chTo); + } + } + if (!tr) tr = view.state.tr.replace(chFrom, chTo, parse.doc.slice(change.start - parse.from, change.endB - parse.from)); + if (parse.sel) { + var _sel3 = resolveSelection(view, tr.doc, parse.sel); + if (_sel3 && !(chrome && view.composing && _sel3.empty && (change.start != change.endB || view.input.lastChromeDelete < Date.now() - 100) && (_sel3.head == chFrom || _sel3.head == tr.mapping.map(chTo) - 1) || ie && _sel3.empty && _sel3.head == chFrom)) tr.setSelection(_sel3); + } + if (storedMarks) tr.ensureMarks(storedMarks); + if (compositionID) tr.setMeta("composition", compositionID); + view.dispatch(tr.scrollIntoView()); +} +function resolveSelection(view, doc, parsedSel) { + if (Math.max(parsedSel.anchor, parsedSel.head) > doc.content.size) return null; + return selectionBetween(view, doc.resolve(parsedSel.anchor), doc.resolve(parsedSel.head)); +} +function isMarkChange(cur, prev) { + var curMarks = cur.firstChild.marks, + prevMarks = prev.firstChild.marks; + var added = curMarks, + removed = prevMarks, + type, + mark, + update; + for (var i = 0; i < prevMarks.length; i++) added = prevMarks[i].removeFromSet(added); + for (var _i16 = 0; _i16 < curMarks.length; _i16++) removed = curMarks[_i16].removeFromSet(removed); + if (added.length == 1 && removed.length == 0) { + mark = added[0]; + type = "add"; + update = function update(node) { + return node.mark(mark.addToSet(node.marks)); + }; + } else if (added.length == 0 && removed.length == 1) { + mark = removed[0]; + type = "remove"; + update = function update(node) { + return node.mark(mark.removeFromSet(node.marks)); + }; + } else { + return null; + } + var updated = []; + for (var _i17 = 0; _i17 < prev.childCount; _i17++) updated.push(update(prev.child(_i17))); + if (prosemirrorModel.Fragment.from(updated).eq(cur)) return { + mark: mark, + type: type + }; +} +function looksLikeBackspace(old, start, end, $newStart, $newEnd) { + if (end - start <= $newEnd.pos - $newStart.pos || skipClosingAndOpening($newStart, true, false) < $newEnd.pos) return false; + var $start = old.resolve(start); + if (!$newStart.parent.isTextblock) { + var after = $start.nodeAfter; + return after != null && end == start + after.nodeSize; + } + if ($start.parentOffset < $start.parent.content.size || !$start.parent.isTextblock) return false; + var $next = old.resolve(skipClosingAndOpening($start, true, true)); + if (!$next.parent.isTextblock || $next.pos > end || skipClosingAndOpening($next, true, false) < end) return false; + return $newStart.parent.content.cut($newStart.parentOffset).eq($next.parent.content); +} +function skipClosingAndOpening($pos, fromEnd, mayOpen) { + var depth = $pos.depth, + end = fromEnd ? $pos.end() : $pos.pos; + while (depth > 0 && (fromEnd || $pos.indexAfter(depth) == $pos.node(depth).childCount)) { + depth--; + end++; + fromEnd = false; + } + if (mayOpen) { + var next = $pos.node(depth).maybeChild($pos.indexAfter(depth)); + while (next && !next.isLeaf) { + next = next.firstChild; + end++; + } + } + return end; +} +function findDiff(a, b, pos, preferredPos, preferredSide) { + var start = a.findDiffStart(b, pos); + if (start == null) return null; + var _a$findDiffEnd = a.findDiffEnd(b, pos + a.size, pos + b.size), + endA = _a$findDiffEnd.a, + endB = _a$findDiffEnd.b; + if (preferredSide == "end") { + var adjust = Math.max(0, start - Math.min(endA, endB)); + preferredPos -= endA + adjust - start; + } + if (endA < start && a.size < b.size) { + var move = preferredPos <= start && preferredPos >= endA ? start - preferredPos : 0; + start -= move; + if (start && start < b.size && isSurrogatePair(b.textBetween(start - 1, start + 1))) start += move ? 1 : -1; + endB = start + (endB - endA); + endA = start; + } else if (endB < start) { + var _move = preferredPos <= start && preferredPos >= endB ? start - preferredPos : 0; + start -= _move; + if (start && start < a.size && isSurrogatePair(a.textBetween(start - 1, start + 1))) start += _move ? 1 : -1; + endA = start + (endA - endB); + endB = start; + } + return { + start: start, + endA: endA, + endB: endB + }; +} +function isSurrogatePair(str) { + if (str.length != 2) return false; + var a = str.charCodeAt(0), + b = str.charCodeAt(1); + return a >= 0xDC00 && a <= 0xDFFF && b >= 0xD800 && b <= 0xDBFF; +} +var __parseFromClipboard = parseFromClipboard; +var __endComposition = endComposition; +var EditorView = function () { + function EditorView(place, props) { + var _this15 = this; + _classCallCheck(this, EditorView); + this._root = null; + this.focused = false; + this.trackWrites = null; + this.mounted = false; + this.markCursor = null; + this.cursorWrapper = null; + this.lastSelectedViewDesc = undefined; + this.input = new InputState(); + this.prevDirectPlugins = []; + this.pluginViews = []; + this.requiresGeckoHackNode = false; + this.dragging = null; + this._props = props; + this.state = props.state; + this.directPlugins = props.plugins || []; + this.directPlugins.forEach(checkStateComponent); + this.dispatch = this.dispatch.bind(this); + this.dom = place && place.mount || document.createElement("div"); + if (place) { + if (place.appendChild) place.appendChild(this.dom);else if (typeof place == "function") place(this.dom);else if (place.mount) this.mounted = true; + } + this.editable = getEditable(this); + updateCursorWrapper(this); + this.nodeViews = buildNodeViews(this); + this.docView = docViewDesc(this.state.doc, computeDocDeco(this), viewDecorations(this), this.dom, this); + this.domObserver = new DOMObserver(this, function (from, to, typeOver, added) { + return readDOMChange(_this15, from, to, typeOver, added); + }); + this.domObserver.start(); + initInput(this); + this.updatePluginViews(); + } + _createClass(EditorView, [{ + key: "composing", + get: function get() { + return this.input.composing; + } + }, { + key: "props", + get: function get() { + if (this._props.state != this.state) { + var prev = this._props; + this._props = {}; + for (var name in prev) this._props[name] = prev[name]; + this._props.state = this.state; + } + return this._props; + } + }, { + key: "update", + value: function update(props) { + if (props.handleDOMEvents != this._props.handleDOMEvents) ensureListeners(this); + var prevProps = this._props; + this._props = props; + if (props.plugins) { + props.plugins.forEach(checkStateComponent); + this.directPlugins = props.plugins; + } + this.updateStateInner(props.state, prevProps); + } + }, { + key: "setProps", + value: function setProps(props) { + var updated = {}; + for (var name in this._props) updated[name] = this._props[name]; + updated.state = this.state; + for (var _name2 in props) updated[_name2] = props[_name2]; + this.update(updated); + } + }, { + key: "updateState", + value: function updateState(state) { + this.updateStateInner(state, this._props); + } + }, { + key: "updateStateInner", + value: function updateStateInner(state, prevProps) { + var _a; + var prev = this.state, + redraw = false, + updateSel = false; + if (state.storedMarks && this.composing) { + clearComposition(this); + updateSel = true; + } + this.state = state; + var pluginsChanged = prev.plugins != state.plugins || this._props.plugins != prevProps.plugins; + if (pluginsChanged || this._props.plugins != prevProps.plugins || this._props.nodeViews != prevProps.nodeViews) { + var nodeViews = buildNodeViews(this); + if (changedNodeViews(nodeViews, this.nodeViews)) { + this.nodeViews = nodeViews; + redraw = true; + } + } + if (pluginsChanged || prevProps.handleDOMEvents != this._props.handleDOMEvents) { + ensureListeners(this); + } + this.editable = getEditable(this); + updateCursorWrapper(this); + var innerDeco = viewDecorations(this), + outerDeco = computeDocDeco(this); + var scroll = prev.plugins != state.plugins && !prev.doc.eq(state.doc) ? "reset" : state.scrollToSelection > prev.scrollToSelection ? "to selection" : "preserve"; + var updateDoc = redraw || !this.docView.matchesNode(state.doc, outerDeco, innerDeco); + if (updateDoc || !state.selection.eq(prev.selection)) updateSel = true; + var oldScrollPos = scroll == "preserve" && updateSel && this.dom.style.overflowAnchor == null && storeScrollPos(this); + if (updateSel) { + this.domObserver.stop(); + var forceSelUpdate = updateDoc && (ie || chrome) && !this.composing && !prev.selection.empty && !state.selection.empty && selectionContextChanged(prev.selection, state.selection); + if (updateDoc) { + var chromeKludge = chrome ? this.trackWrites = this.domSelectionRange().focusNode : null; + if (this.composing) this.input.compositionNode = findCompositionNode(this); + if (redraw || !this.docView.update(state.doc, outerDeco, innerDeco, this)) { + this.docView.updateOuterDeco(outerDeco); + this.docView.destroy(); + this.docView = docViewDesc(state.doc, outerDeco, innerDeco, this.dom, this); + } + if (chromeKludge && !this.trackWrites) forceSelUpdate = true; + } + if (forceSelUpdate || !(this.input.mouseDown && this.domObserver.currentSelection.eq(this.domSelectionRange()) && anchorInRightPlace(this))) { + selectionToDOM(this, forceSelUpdate); + } else { + syncNodeSelection(this, state.selection); + this.domObserver.setCurSelection(); + } + this.domObserver.start(); + } + this.updatePluginViews(prev); + if (((_a = this.dragging) === null || _a === void 0 ? void 0 : _a.node) && !prev.doc.eq(state.doc)) this.updateDraggedNode(this.dragging, prev); + if (scroll == "reset") { + this.dom.scrollTop = 0; + } else if (scroll == "to selection") { + this.scrollToSelection(); + } else if (oldScrollPos) { + resetScrollPos(oldScrollPos); + } + } + }, { + key: "scrollToSelection", + value: function scrollToSelection() { + var _this16 = this; + var startDOM = this.domSelectionRange().focusNode; + if (!startDOM || !this.dom.contains(startDOM.nodeType == 1 ? startDOM : startDOM.parentNode)) ;else if (this.someProp("handleScrollToSelection", function (f) { + return f(_this16); + })) ;else if (this.state.selection instanceof prosemirrorState.NodeSelection) { + var target = this.docView.domAfterPos(this.state.selection.from); + if (target.nodeType == 1) scrollRectIntoView(this, target.getBoundingClientRect(), startDOM); + } else { + scrollRectIntoView(this, this.coordsAtPos(this.state.selection.head, 1), startDOM); + } + } + }, { + key: "destroyPluginViews", + value: function destroyPluginViews() { + var view; + while (view = this.pluginViews.pop()) if (view.destroy) view.destroy(); + } + }, { + key: "updatePluginViews", + value: function updatePluginViews(prevState) { + if (!prevState || prevState.plugins != this.state.plugins || this.directPlugins != this.prevDirectPlugins) { + this.prevDirectPlugins = this.directPlugins; + this.destroyPluginViews(); + for (var i = 0; i < this.directPlugins.length; i++) { + var plugin = this.directPlugins[i]; + if (plugin.spec.view) this.pluginViews.push(plugin.spec.view(this)); + } + for (var _i18 = 0; _i18 < this.state.plugins.length; _i18++) { + var _plugin = this.state.plugins[_i18]; + if (_plugin.spec.view) this.pluginViews.push(_plugin.spec.view(this)); + } + } else { + for (var _i19 = 0; _i19 < this.pluginViews.length; _i19++) { + var pluginView = this.pluginViews[_i19]; + if (pluginView.update) pluginView.update(this, prevState); + } + } + } + }, { + key: "updateDraggedNode", + value: function updateDraggedNode(dragging, prev) { + var sel = dragging.node, + found = -1; + if (this.state.doc.nodeAt(sel.from) == sel.node) { + found = sel.from; + } else { + var movedPos = sel.from + (this.state.doc.content.size - prev.doc.content.size); + var moved = movedPos > 0 && this.state.doc.nodeAt(movedPos); + if (moved == sel.node) found = movedPos; + } + this.dragging = new Dragging(dragging.slice, dragging.move, found < 0 ? undefined : prosemirrorState.NodeSelection.create(this.state.doc, found)); + } + }, { + key: "someProp", + value: function someProp(propName, f) { + var prop = this._props && this._props[propName], + value; + if (prop != null && (value = f ? f(prop) : prop)) return value; + for (var i = 0; i < this.directPlugins.length; i++) { + var _prop = this.directPlugins[i].props[propName]; + if (_prop != null && (value = f ? f(_prop) : _prop)) return value; + } + var plugins = this.state.plugins; + if (plugins) for (var _i20 = 0; _i20 < plugins.length; _i20++) { + var _prop2 = plugins[_i20].props[propName]; + if (_prop2 != null && (value = f ? f(_prop2) : _prop2)) return value; + } + } + }, { + key: "hasFocus", + value: function hasFocus() { + if (ie) { + var node = this.root.activeElement; + if (node == this.dom) return true; + if (!node || !this.dom.contains(node)) return false; + while (node && this.dom != node && this.dom.contains(node)) { + if (node.contentEditable == 'false') return false; + node = node.parentElement; + } + return true; + } + return this.root.activeElement == this.dom; + } + }, { + key: "focus", + value: function focus() { + this.domObserver.stop(); + if (this.editable) focusPreventScroll(this.dom); + selectionToDOM(this); + this.domObserver.start(); + } + }, { + key: "root", + get: function get() { + var _this17 = this; + var cached = this._root; + if (cached == null) { + var _loop5 = function _loop5(search) { + if (search.nodeType == 9 || search.nodeType == 11 && search.host) { + if (!search.getSelection) Object.getPrototypeOf(search).getSelection = function () { + return search.ownerDocument.getSelection(); + }; + return { + v: _this17._root = search + }; + } + }, + _ret3; + for (var search = this.dom.parentNode; search; search = search.parentNode) { + _ret3 = _loop5(search); + if (_ret3) return _ret3.v; + } + } + return cached || document; + } + }, { + key: "updateRoot", + value: function updateRoot() { + this._root = null; + } + }, { + key: "posAtCoords", + value: function posAtCoords(coords) { + return _posAtCoords(this, coords); + } + }, { + key: "coordsAtPos", + value: function coordsAtPos(pos) { + var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + return _coordsAtPos(this, pos, side); + } + }, { + key: "domAtPos", + value: function domAtPos(pos) { + var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + return this.docView.domFromPos(pos, side); + } + }, { + key: "nodeDOM", + value: function nodeDOM(pos) { + var desc = this.docView.descAt(pos); + return desc ? desc.nodeDOM : null; + } + }, { + key: "posAtDOM", + value: function posAtDOM(node, offset) { + var bias = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -1; + var pos = this.docView.posFromDOM(node, offset, bias); + if (pos == null) throw new RangeError("DOM position not inside the editor"); + return pos; + } + }, { + key: "endOfTextblock", + value: function endOfTextblock(dir, state) { + return _endOfTextblock(this, state || this.state, dir); + } + }, { + key: "pasteHTML", + value: function pasteHTML(html, event) { + return doPaste(this, "", html, false, event || new ClipboardEvent("paste")); + } + }, { + key: "pasteText", + value: function pasteText(text, event) { + return doPaste(this, text, null, true, event || new ClipboardEvent("paste")); + } + }, { + key: "serializeForClipboard", + value: function serializeForClipboard(slice) { + return _serializeForClipboard(this, slice); + } + }, { + key: "destroy", + value: function destroy() { + if (!this.docView) return; + destroyInput(this); + this.destroyPluginViews(); + if (this.mounted) { + this.docView.update(this.state.doc, [], viewDecorations(this), this); + this.dom.textContent = ""; + } else if (this.dom.parentNode) { + this.dom.parentNode.removeChild(this.dom); + } + this.docView.destroy(); + this.docView = null; + clearReusedRange(); + } + }, { + key: "isDestroyed", + get: function get() { + return this.docView == null; + } + }, { + key: "dispatchEvent", + value: function dispatchEvent(event) { + return _dispatchEvent(this, event); + } + }, { + key: "dispatch", + value: function dispatch(tr) { + var dispatchTransaction = this._props.dispatchTransaction; + if (dispatchTransaction) dispatchTransaction.call(this, tr);else this.updateState(this.state.apply(tr)); + } + }, { + key: "domSelectionRange", + value: function domSelectionRange() { + var sel = this.domSelection(); + if (!sel) return { + focusNode: null, + focusOffset: 0, + anchorNode: null, + anchorOffset: 0 + }; + return safari && this.root.nodeType === 11 && deepActiveElement(this.dom.ownerDocument) == this.dom && safariShadowSelectionRange(this, sel) || sel; + } + }, { + key: "domSelection", + value: function domSelection() { + return this.root.getSelection(); + } + }]); + return EditorView; +}(); +function computeDocDeco(view) { + var attrs = Object.create(null); + attrs["class"] = "ProseMirror"; + attrs.contenteditable = String(view.editable); + view.someProp("attributes", function (value) { + if (typeof value == "function") value = value(view.state); + if (value) for (var attr in value) { + if (attr == "class") attrs["class"] += " " + value[attr];else if (attr == "style") attrs.style = (attrs.style ? attrs.style + ";" : "") + value[attr];else if (!attrs[attr] && attr != "contenteditable" && attr != "nodeName") attrs[attr] = String(value[attr]); + } + }); + if (!attrs.translate) attrs.translate = "no"; + return [Decoration.node(0, view.state.doc.content.size, attrs)]; +} +function updateCursorWrapper(view) { + if (view.markCursor) { + var dom = document.createElement("img"); + dom.className = "ProseMirror-separator"; + dom.setAttribute("mark-placeholder", "true"); + dom.setAttribute("alt", ""); + view.cursorWrapper = { + dom: dom, + deco: Decoration.widget(view.state.selection.from, dom, { + raw: true, + marks: view.markCursor + }) + }; + } else { + view.cursorWrapper = null; + } +} +function getEditable(view) { + return !view.someProp("editable", function (value) { + return value(view.state) === false; + }); +} +function selectionContextChanged(sel1, sel2) { + var depth = Math.min(sel1.$anchor.sharedDepth(sel1.head), sel2.$anchor.sharedDepth(sel2.head)); + return sel1.$anchor.start(depth) != sel2.$anchor.start(depth); +} +function buildNodeViews(view) { + var result = Object.create(null); + function add(obj) { + for (var _prop3 in obj) if (!Object.prototype.hasOwnProperty.call(result, _prop3)) result[_prop3] = obj[_prop3]; + } + view.someProp("nodeViews", add); + view.someProp("markViews", add); + return result; +} +function changedNodeViews(a, b) { + var nA = 0, + nB = 0; + for (var _prop4 in a) { + if (a[_prop4] != b[_prop4]) return true; + nA++; + } + for (var _ in b) nB++; + return nA != nB; +} +function checkStateComponent(plugin) { + if (plugin.spec.state || plugin.spec.filterTransaction || plugin.spec.appendTransaction) throw new RangeError("Plugins passed directly to the view must not have a state component"); +} +exports.Decoration = Decoration; +exports.DecorationSet = DecorationSet; +exports.EditorView = EditorView; +exports.__endComposition = __endComposition; +exports.__parseFromClipboard = __parseFromClipboard; diff --git a/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files b/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files new file mode 100755 index 000000000..1913e1b7f --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files @@ -0,0 +1,47 @@ +{ + "tiddlers": [ + { + "file": "prosemirror-model.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-model", + "module-type": "library" + } + },{ + "file": "prosemirror-state.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-state", + "module-type": "library" + } + },{ + "file": "prosemirror-view.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-view", + "module-type": "library" + } + },{ + "file": "prosemirror-schema-list.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-schema-list", + "module-type": "library" + } + },{ + "file": "prosemirror-example-setup.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-example-setup", + "module-type": "library" + } + },{ + "file": "prosemirror-schema-basic.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-schema-basic", + "module-type": "library" + } + } + ] +} diff --git a/plugins/tiddlywiki/editorjs/plugin.info b/plugins/tiddlywiki/prosemirror/plugin.info similarity index 62% rename from plugins/tiddlywiki/editorjs/plugin.info rename to plugins/tiddlywiki/prosemirror/plugin.info index adb17be56..6476cc369 100755 --- a/plugins/tiddlywiki/editorjs/plugin.info +++ b/plugins/tiddlywiki/prosemirror/plugin.info @@ -1,6 +1,6 @@ { - "title": "$:/plugins/tiddlywiki/editorjs", - "name": "EditorJS Visual Editor", + "title": "$:/plugins/tiddlywiki/prosemirror", + "name": "Prosemirror Visual Editor", "description": "WYSIWYG editor (What You See Is What You Get) for TiddlyWiki", "list": "readme", "stability": "STABILITY_1_EXPERIMENTAL" diff --git a/plugins/tiddlywiki/prosemirror/readme.tid b/plugins/tiddlywiki/prosemirror/readme.tid new file mode 100755 index 000000000..b77ad6a8a --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/readme.tid @@ -0,0 +1,23 @@ +title: $:/plugins/tiddlywiki/prosemirror/readme + +Test Test + +<$prosemirror /> + +Downloaded from JsDelivr CDN (like `https://cdn.jsdelivr.net/npm/prosemirror-state@latest/dist/index.cjs` and store as `prosemirror-state.js`): + +* [ext[prosemirror-state|https://cdn.jsdelivr.net/npm/prosemirror-state@latest/dist/index.cjs]]: 1.4.3 +* [ext[prosemirror-view|https://cdn.jsdelivr.net/npm/prosemirror-view@latest/dist/index.cjs]]: 1.38.1 +* [ext[prosemirror-model|https://cdn.jsdelivr.net/npm/prosemirror-model@latest/dist/index.cjs]]: 1.25.0 +* [ext[prosemirror-schema-basic|https://cdn.jsdelivr.net/npm/prosemirror-schema-basic@latest/dist/index.cjs]]: 1.2.4 +* [ext[prosemirror-schema-list|https://cdn.jsdelivr.net/npm/prosemirror-schema-list@latest/dist/index.cjs]]: 1.5.1 +* [ext[prosemirror-example-setup|https://cdn.jsdelivr.net/npm/prosemirror-example-setup@latest/dist/index.cjs]]: 1.2.3 +* [ext[orderedmap|https://cdn.jsdelivr.net/npm/orderedmap@latest/dist/index.cjs]]: latest +* [ext[prosemirror-transform|https://cdn.jsdelivr.net/npm/prosemirror-transform@latest/dist/index.cjs]]: latest +* [ext[prosemirror-keymap|https://cdn.jsdelivr.net/npm/prosemirror-keymap@latest/dist/index.cjs]]: latest +* [ext[prosemirror-history|https://cdn.jsdelivr.net/npm/prosemirror-history@latest/dist/index.cjs]]: latest +* [ext[prosemirror-commands|https://cdn.jsdelivr.net/npm/prosemirror-commands@latest/dist/index.cjs]]: latest +* [ext[prosemirror-dropcursor|https://cdn.jsdelivr.net/npm/prosemirror-dropcursor@latest/dist/index.cjs]]: latest +* [ext[prosemirror-gapcursor|https://cdn.jsdelivr.net/npm/prosemirror-gapcursor@latest/dist/index.cjs]]: latest +* [ext[prosemirror-menu|https://cdn.jsdelivr.net/npm/prosemirror-menu@latest/dist/index.cjs]]: latest +* [ext[prosemirror-inputrules|https://cdn.jsdelivr.net/npm/prosemirror-inputrules@latest/dist/index.cjs]]: latest diff --git a/plugins/tiddlywiki/prosemirror/widget.js b/plugins/tiddlywiki/prosemirror/widget.js new file mode 100644 index 000000000..1be2c7a65 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/widget.js @@ -0,0 +1,97 @@ +/*\ +title: $:/plugins/tiddlywiki/prosemirror/widget.js +type: application/javascript +module-type: widget + +Text node widget + +\*/ + +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget; +var debounce = require("$:/core/modules/utils/debounce.js").debounce; + +var { EditorState } = require("prosemirror-state"); +var { EditorView } = require("prosemirror-view"); +var { Schema, DOMParser } = require("prosemirror-model"); +var { schema } = require("prosemirror-schema-basic"); +var { addListNodes } = require("prosemirror-schema-list"); +var { exampleSetup } = require("prosemirror-example-setup"); + +var ProsemirrorWidget = function(parseTreeNode,options) { + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +ProsemirrorWidget.prototype = new Widget(); + +/* +Render this widget into the DOM +*/ +ProsemirrorWidget.prototype.render = function(parent,nextSibling) { + this.parentDomNode = parent; + this.computeAttributes(); + this.execute(); + var container = $tw.utils.domMaker('div', { + class: 'tc-prosemirror-container', + }); + + // Mix the nodes from prosemirror-schema-list into the basic schema to + // create a schema with list support. + const mySchema = new Schema({ + nodes: addListNodes(schema.spec.nodes, "paragraph block*", "block"), + marks: schema.spec.marks + }) + + var self = this; + this.view = new EditorView(container, { + state: EditorState.create({ + doc: DOMParser.fromSchema(mySchema).parse(document.querySelector("#content")), + plugins: exampleSetup({schema: mySchema}) + }), + dispatchTransaction: function(transaction) { + var newState = self.view.state.apply(transaction); + self.view.updateState(newState); + self.debouncedSaveEditorContent(); + } + }) + + parent.insertBefore(container,nextSibling); + this.domNodes.push(container); +}; + +ProsemirrorWidget.prototype.saveEditorContent = function() { + this.editor.save().then((outputData) => { + console.log('Article data: ', outputData) + }).catch((error) => { + console.log('Saving failed: ', error) + }); +} + +// Debounced save function for performance +ProsemirrorWidget.prototype.debouncedSaveEditorContent = debounce(ProsemirrorWidget.prototype.saveEditorContent, 300); + +/* +Compute the internal state of the widget +*/ +ProsemirrorWidget.prototype.execute = function() { + // Nothing to do for a text node +}; + +/* +Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering +*/ +ProsemirrorWidget.prototype.refresh = function(changedTiddlers) { + var changedAttributes = this.computeAttributes(); + if(changedAttributes.text) { + this.refreshSelf(); + return true; + } else { + return false; + } +}; + +exports.prosemirror = ProsemirrorWidget; From 685520aa88a9ec7dcc15a5057fe3ace4469066a5 Mon Sep 17 00:00:00 2001 From: linonetwo Date: Sun, 23 Mar 2025 21:54:57 +0800 Subject: [PATCH 81/98] chore: add dependencies --- .../tiddlywiki/prosemirror/files/crelt.cjs | 31 + .../prosemirror/files/orderedmap.cjs | 139 ++ .../files/prosemirror-commands.cjs | 686 ++++++ .../files/prosemirror-dropcursor.cjs | 208 ++ .../files/prosemirror-gapcursor.cjs | 295 +++ .../prosemirror/files/prosemirror-history.cjs | 378 ++++ .../files/prosemirror-inputrules.cjs | 175 ++ .../prosemirror/files/prosemirror-keymap.cjs | 85 + .../prosemirror/files/prosemirror-menu.cjs | 726 +++++++ .../files/prosemirror-transform.cjs | 1858 +++++++++++++++++ .../prosemirror/files/rope-sequence.cjs | 209 ++ .../prosemirror/files/tiddlywiki.files | 96 + .../prosemirror/files/w3c-keyname.cjs | 127 ++ plugins/tiddlywiki/prosemirror/readme.tid | 33 +- 14 files changed, 5031 insertions(+), 15 deletions(-) create mode 100644 plugins/tiddlywiki/prosemirror/files/crelt.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/orderedmap.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-commands.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-dropcursor.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-gapcursor.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-history.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-inputrules.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-keymap.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-menu.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-transform.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/rope-sequence.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/w3c-keyname.cjs diff --git a/plugins/tiddlywiki/prosemirror/files/crelt.cjs b/plugins/tiddlywiki/prosemirror/files/crelt.cjs new file mode 100644 index 000000000..633313f08 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/crelt.cjs @@ -0,0 +1,31 @@ +'use strict'; + +function crelt() { + var elt = arguments[0]; + if (typeof elt == "string") elt = document.createElement(elt); + var i = 1, next = arguments[1]; + if (next && typeof next == "object" && next.nodeType == null && !Array.isArray(next)) { + for (var name in next) if (Object.prototype.hasOwnProperty.call(next, name)) { + var value = next[name]; + if (typeof value == "string") elt.setAttribute(name, value); + else if (value != null) elt[name] = value; + } + i++; + } + for (; i < arguments.length; i++) add(elt, arguments[i]); + return elt +} + +function add(elt, child) { + if (typeof child == "string") { + elt.appendChild(document.createTextNode(child)); + } else if (child == null) ; else if (child.nodeType != null) { + elt.appendChild(child); + } else if (Array.isArray(child)) { + for (var i = 0; i < child.length; i++) add(elt, child[i]); + } else { + throw new RangeError("Unsupported child node: " + child) + } +} + +module.exports = crelt; diff --git a/plugins/tiddlywiki/prosemirror/files/orderedmap.cjs b/plugins/tiddlywiki/prosemirror/files/orderedmap.cjs new file mode 100644 index 000000000..32e85854f --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/orderedmap.cjs @@ -0,0 +1,139 @@ +'use strict'; + +// ::- Persistent data structure representing an ordered mapping from +// strings to values, with some convenient update methods. +function OrderedMap(content) { + this.content = content; +} + +OrderedMap.prototype = { + constructor: OrderedMap, + + find: function(key) { + for (var i = 0; i < this.content.length; i += 2) + if (this.content[i] === key) return i + return -1 + }, + + // :: (string) → ?any + // Retrieve the value stored under `key`, or return undefined when + // no such key exists. + get: function(key) { + var found = this.find(key); + return found == -1 ? undefined : this.content[found + 1] + }, + + // :: (string, any, ?string) → OrderedMap + // Create a new map by replacing the value of `key` with a new + // value, or adding a binding to the end of the map. If `newKey` is + // given, the key of the binding will be replaced with that key. + update: function(key, value, newKey) { + var self = newKey && newKey != key ? this.remove(newKey) : this; + var found = self.find(key), content = self.content.slice(); + if (found == -1) { + content.push(newKey || key, value); + } else { + content[found + 1] = value; + if (newKey) content[found] = newKey; + } + return new OrderedMap(content) + }, + + // :: (string) → OrderedMap + // Return a map with the given key removed, if it existed. + remove: function(key) { + var found = this.find(key); + if (found == -1) return this + var content = this.content.slice(); + content.splice(found, 2); + return new OrderedMap(content) + }, + + // :: (string, any) → OrderedMap + // Add a new key to the start of the map. + addToStart: function(key, value) { + return new OrderedMap([key, value].concat(this.remove(key).content)) + }, + + // :: (string, any) → OrderedMap + // Add a new key to the end of the map. + addToEnd: function(key, value) { + var content = this.remove(key).content.slice(); + content.push(key, value); + return new OrderedMap(content) + }, + + // :: (string, string, any) → OrderedMap + // Add a key after the given key. If `place` is not found, the new + // key is added to the end. + addBefore: function(place, key, value) { + var without = this.remove(key), content = without.content.slice(); + var found = without.find(place); + content.splice(found == -1 ? content.length : found, 0, key, value); + return new OrderedMap(content) + }, + + // :: ((key: string, value: any)) + // Call the given function for each key/value pair in the map, in + // order. + forEach: function(f) { + for (var i = 0; i < this.content.length; i += 2) + f(this.content[i], this.content[i + 1]); + }, + + // :: (union) → OrderedMap + // Create a new map by prepending the keys in this map that don't + // appear in `map` before the keys in `map`. + prepend: function(map) { + map = OrderedMap.from(map); + if (!map.size) return this + return new OrderedMap(map.content.concat(this.subtract(map).content)) + }, + + // :: (union) → OrderedMap + // Create a new map by appending the keys in this map that don't + // appear in `map` after the keys in `map`. + append: function(map) { + map = OrderedMap.from(map); + if (!map.size) return this + return new OrderedMap(this.subtract(map).content.concat(map.content)) + }, + + // :: (union) → OrderedMap + // Create a map containing all the keys in this map that don't + // appear in `map`. + subtract: function(map) { + var result = this; + map = OrderedMap.from(map); + for (var i = 0; i < map.content.length; i += 2) + result = result.remove(map.content[i]); + return result + }, + + // :: () → Object + // Turn ordered map into a plain object. + toObject: function() { + var result = {}; + this.forEach(function(key, value) { result[key] = value; }); + return result + }, + + // :: number + // The amount of keys in this map. + get size() { + return this.content.length >> 1 + } +}; + +// :: (?union) → OrderedMap +// Return a map with the given content. If null, create an empty +// map. If given an ordered map, return that map itself. If given an +// object, create a map from the object's properties. +OrderedMap.from = function(value) { + if (value instanceof OrderedMap) return value + var content = []; + if (value) for (var prop in value) content.push(prop, value[prop]); + return new OrderedMap(content) +}; + +module.exports = OrderedMap; diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-commands.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-commands.cjs new file mode 100644 index 000000000..ec07bdc64 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-commands.cjs @@ -0,0 +1,686 @@ +'use strict'; + +var prosemirrorTransform = require('prosemirror-transform'); +var prosemirrorModel = require('prosemirror-model'); +var prosemirrorState = require('prosemirror-state'); +var deleteSelection = function deleteSelection(state, dispatch) { + if (state.selection.empty) return false; + if (dispatch) dispatch(state.tr.deleteSelection().scrollIntoView()); + return true; +}; +function atBlockStart(state, view) { + var $cursor = state.selection.$cursor; + if (!$cursor || (view ? !view.endOfTextblock("backward", state) : $cursor.parentOffset > 0)) return null; + return $cursor; +} +var joinBackward = function joinBackward(state, dispatch, view) { + var $cursor = atBlockStart(state, view); + if (!$cursor) return false; + var $cut = findCutBefore($cursor); + if (!$cut) { + var range = $cursor.blockRange(), + target = range && prosemirrorTransform.liftTarget(range); + if (target == null) return false; + if (dispatch) dispatch(state.tr.lift(range, target).scrollIntoView()); + return true; + } + var before = $cut.nodeBefore; + if (deleteBarrier(state, $cut, dispatch, -1)) return true; + if ($cursor.parent.content.size == 0 && (textblockAt(before, "end") || prosemirrorState.NodeSelection.isSelectable(before))) { + for (var depth = $cursor.depth;; depth--) { + var delStep = prosemirrorTransform.replaceStep(state.doc, $cursor.before(depth), $cursor.after(depth), prosemirrorModel.Slice.empty); + if (delStep && delStep.slice.size < delStep.to - delStep.from) { + if (dispatch) { + var tr = state.tr.step(delStep); + tr.setSelection(textblockAt(before, "end") ? prosemirrorState.Selection.findFrom(tr.doc.resolve(tr.mapping.map($cut.pos, -1)), -1) : prosemirrorState.NodeSelection.create(tr.doc, $cut.pos - before.nodeSize)); + dispatch(tr.scrollIntoView()); + } + return true; + } + if (depth == 1 || $cursor.node(depth - 1).childCount > 1) break; + } + } + if (before.isAtom && $cut.depth == $cursor.depth - 1) { + if (dispatch) dispatch(state.tr["delete"]($cut.pos - before.nodeSize, $cut.pos).scrollIntoView()); + return true; + } + return false; +}; +var joinTextblockBackward = function joinTextblockBackward(state, dispatch, view) { + var $cursor = atBlockStart(state, view); + if (!$cursor) return false; + var $cut = findCutBefore($cursor); + return $cut ? joinTextblocksAround(state, $cut, dispatch) : false; +}; +var joinTextblockForward = function joinTextblockForward(state, dispatch, view) { + var $cursor = atBlockEnd(state, view); + if (!$cursor) return false; + var $cut = findCutAfter($cursor); + return $cut ? joinTextblocksAround(state, $cut, dispatch) : false; +}; +function joinTextblocksAround(state, $cut, dispatch) { + var before = $cut.nodeBefore, + beforeText = before, + beforePos = $cut.pos - 1; + for (; !beforeText.isTextblock; beforePos--) { + if (beforeText.type.spec.isolating) return false; + var child = beforeText.lastChild; + if (!child) return false; + beforeText = child; + } + var after = $cut.nodeAfter, + afterText = after, + afterPos = $cut.pos + 1; + for (; !afterText.isTextblock; afterPos++) { + if (afterText.type.spec.isolating) return false; + var _child = afterText.firstChild; + if (!_child) return false; + afterText = _child; + } + var step = prosemirrorTransform.replaceStep(state.doc, beforePos, afterPos, prosemirrorModel.Slice.empty); + if (!step || step.from != beforePos || step instanceof prosemirrorTransform.ReplaceStep && step.slice.size >= afterPos - beforePos) return false; + if (dispatch) { + var tr = state.tr.step(step); + tr.setSelection(prosemirrorState.TextSelection.create(tr.doc, beforePos)); + dispatch(tr.scrollIntoView()); + } + return true; +} +function textblockAt(node, side) { + var only = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + for (var scan = node; scan; scan = side == "start" ? scan.firstChild : scan.lastChild) { + if (scan.isTextblock) return true; + if (only && scan.childCount != 1) return false; + } + return false; +} +var selectNodeBackward = function selectNodeBackward(state, dispatch, view) { + var _state$selection = state.selection, + $head = _state$selection.$head, + empty = _state$selection.empty, + $cut = $head; + if (!empty) return false; + if ($head.parent.isTextblock) { + if (view ? !view.endOfTextblock("backward", state) : $head.parentOffset > 0) return false; + $cut = findCutBefore($head); + } + var node = $cut && $cut.nodeBefore; + if (!node || !prosemirrorState.NodeSelection.isSelectable(node)) return false; + if (dispatch) dispatch(state.tr.setSelection(prosemirrorState.NodeSelection.create(state.doc, $cut.pos - node.nodeSize)).scrollIntoView()); + return true; +}; +function findCutBefore($pos) { + if (!$pos.parent.type.spec.isolating) for (var i = $pos.depth - 1; i >= 0; i--) { + if ($pos.index(i) > 0) return $pos.doc.resolve($pos.before(i + 1)); + if ($pos.node(i).type.spec.isolating) break; + } + return null; +} +function atBlockEnd(state, view) { + var $cursor = state.selection.$cursor; + if (!$cursor || (view ? !view.endOfTextblock("forward", state) : $cursor.parentOffset < $cursor.parent.content.size)) return null; + return $cursor; +} +var joinForward = function joinForward(state, dispatch, view) { + var $cursor = atBlockEnd(state, view); + if (!$cursor) return false; + var $cut = findCutAfter($cursor); + if (!$cut) return false; + var after = $cut.nodeAfter; + if (deleteBarrier(state, $cut, dispatch, 1)) return true; + if ($cursor.parent.content.size == 0 && (textblockAt(after, "start") || prosemirrorState.NodeSelection.isSelectable(after))) { + var delStep = prosemirrorTransform.replaceStep(state.doc, $cursor.before(), $cursor.after(), prosemirrorModel.Slice.empty); + if (delStep && delStep.slice.size < delStep.to - delStep.from) { + if (dispatch) { + var tr = state.tr.step(delStep); + tr.setSelection(textblockAt(after, "start") ? prosemirrorState.Selection.findFrom(tr.doc.resolve(tr.mapping.map($cut.pos)), 1) : prosemirrorState.NodeSelection.create(tr.doc, tr.mapping.map($cut.pos))); + dispatch(tr.scrollIntoView()); + } + return true; + } + } + if (after.isAtom && $cut.depth == $cursor.depth - 1) { + if (dispatch) dispatch(state.tr["delete"]($cut.pos, $cut.pos + after.nodeSize).scrollIntoView()); + return true; + } + return false; +}; +var selectNodeForward = function selectNodeForward(state, dispatch, view) { + var _state$selection2 = state.selection, + $head = _state$selection2.$head, + empty = _state$selection2.empty, + $cut = $head; + if (!empty) return false; + if ($head.parent.isTextblock) { + if (view ? !view.endOfTextblock("forward", state) : $head.parentOffset < $head.parent.content.size) return false; + $cut = findCutAfter($head); + } + var node = $cut && $cut.nodeAfter; + if (!node || !prosemirrorState.NodeSelection.isSelectable(node)) return false; + if (dispatch) dispatch(state.tr.setSelection(prosemirrorState.NodeSelection.create(state.doc, $cut.pos)).scrollIntoView()); + return true; +}; +function findCutAfter($pos) { + if (!$pos.parent.type.spec.isolating) for (var i = $pos.depth - 1; i >= 0; i--) { + var parent = $pos.node(i); + if ($pos.index(i) + 1 < parent.childCount) return $pos.doc.resolve($pos.after(i + 1)); + if (parent.type.spec.isolating) break; + } + return null; +} +var joinUp = function joinUp(state, dispatch) { + var sel = state.selection, + nodeSel = sel instanceof prosemirrorState.NodeSelection, + point; + if (nodeSel) { + if (sel.node.isTextblock || !prosemirrorTransform.canJoin(state.doc, sel.from)) return false; + point = sel.from; + } else { + point = prosemirrorTransform.joinPoint(state.doc, sel.from, -1); + if (point == null) return false; + } + if (dispatch) { + var tr = state.tr.join(point); + if (nodeSel) tr.setSelection(prosemirrorState.NodeSelection.create(tr.doc, point - state.doc.resolve(point).nodeBefore.nodeSize)); + dispatch(tr.scrollIntoView()); + } + return true; +}; +var joinDown = function joinDown(state, dispatch) { + var sel = state.selection, + point; + if (sel instanceof prosemirrorState.NodeSelection) { + if (sel.node.isTextblock || !prosemirrorTransform.canJoin(state.doc, sel.to)) return false; + point = sel.to; + } else { + point = prosemirrorTransform.joinPoint(state.doc, sel.to, 1); + if (point == null) return false; + } + if (dispatch) dispatch(state.tr.join(point).scrollIntoView()); + return true; +}; +var lift = function lift(state, dispatch) { + var _state$selection3 = state.selection, + $from = _state$selection3.$from, + $to = _state$selection3.$to; + var range = $from.blockRange($to), + target = range && prosemirrorTransform.liftTarget(range); + if (target == null) return false; + if (dispatch) dispatch(state.tr.lift(range, target).scrollIntoView()); + return true; +}; +var newlineInCode = function newlineInCode(state, dispatch) { + var _state$selection4 = state.selection, + $head = _state$selection4.$head, + $anchor = _state$selection4.$anchor; + if (!$head.parent.type.spec.code || !$head.sameParent($anchor)) return false; + if (dispatch) dispatch(state.tr.insertText("\n").scrollIntoView()); + return true; +}; +function defaultBlockAt(match) { + for (var i = 0; i < match.edgeCount; i++) { + var _match$edge = match.edge(i), + type = _match$edge.type; + if (type.isTextblock && !type.hasRequiredAttrs()) return type; + } + return null; +} +var exitCode = function exitCode(state, dispatch) { + var _state$selection5 = state.selection, + $head = _state$selection5.$head, + $anchor = _state$selection5.$anchor; + if (!$head.parent.type.spec.code || !$head.sameParent($anchor)) return false; + var above = $head.node(-1), + after = $head.indexAfter(-1), + type = defaultBlockAt(above.contentMatchAt(after)); + if (!type || !above.canReplaceWith(after, after, type)) return false; + if (dispatch) { + var pos = $head.after(), + tr = state.tr.replaceWith(pos, pos, type.createAndFill()); + tr.setSelection(prosemirrorState.Selection.near(tr.doc.resolve(pos), 1)); + dispatch(tr.scrollIntoView()); + } + return true; +}; +var createParagraphNear = function createParagraphNear(state, dispatch) { + var sel = state.selection, + $from = sel.$from, + $to = sel.$to; + if (sel instanceof prosemirrorState.AllSelection || $from.parent.inlineContent || $to.parent.inlineContent) return false; + var type = defaultBlockAt($to.parent.contentMatchAt($to.indexAfter())); + if (!type || !type.isTextblock) return false; + if (dispatch) { + var side = (!$from.parentOffset && $to.index() < $to.parent.childCount ? $from : $to).pos; + var tr = state.tr.insert(side, type.createAndFill()); + tr.setSelection(prosemirrorState.TextSelection.create(tr.doc, side + 1)); + dispatch(tr.scrollIntoView()); + } + return true; +}; +var liftEmptyBlock = function liftEmptyBlock(state, dispatch) { + var $cursor = state.selection.$cursor; + if (!$cursor || $cursor.parent.content.size) return false; + if ($cursor.depth > 1 && $cursor.after() != $cursor.end(-1)) { + var before = $cursor.before(); + if (prosemirrorTransform.canSplit(state.doc, before)) { + if (dispatch) dispatch(state.tr.split(before).scrollIntoView()); + return true; + } + } + var range = $cursor.blockRange(), + target = range && prosemirrorTransform.liftTarget(range); + if (target == null) return false; + if (dispatch) dispatch(state.tr.lift(range, target).scrollIntoView()); + return true; +}; +function splitBlockAs(splitNode) { + return function (state, dispatch) { + var _state$selection6 = state.selection, + $from = _state$selection6.$from, + $to = _state$selection6.$to; + if (state.selection instanceof prosemirrorState.NodeSelection && state.selection.node.isBlock) { + if (!$from.parentOffset || !prosemirrorTransform.canSplit(state.doc, $from.pos)) return false; + if (dispatch) dispatch(state.tr.split($from.pos).scrollIntoView()); + return true; + } + if (!$from.depth) return false; + var types = []; + var splitDepth, + deflt, + atEnd = false, + atStart = false; + for (var d = $from.depth;; d--) { + var node = $from.node(d); + if (node.isBlock) { + atEnd = $from.end(d) == $from.pos + ($from.depth - d); + atStart = $from.start(d) == $from.pos - ($from.depth - d); + deflt = defaultBlockAt($from.node(d - 1).contentMatchAt($from.indexAfter(d - 1))); + var splitType = splitNode && splitNode($to.parent, atEnd, $from); + types.unshift(splitType || (atEnd && deflt ? { + type: deflt + } : null)); + splitDepth = d; + break; + } else { + if (d == 1) return false; + types.unshift(null); + } + } + var tr = state.tr; + if (state.selection instanceof prosemirrorState.TextSelection || state.selection instanceof prosemirrorState.AllSelection) tr.deleteSelection(); + var splitPos = tr.mapping.map($from.pos); + var can = prosemirrorTransform.canSplit(tr.doc, splitPos, types.length, types); + if (!can) { + types[0] = deflt ? { + type: deflt + } : null; + can = prosemirrorTransform.canSplit(tr.doc, splitPos, types.length, types); + } + tr.split(splitPos, types.length, types); + if (!atEnd && atStart && $from.node(splitDepth).type != deflt) { + var first = tr.mapping.map($from.before(splitDepth)), + $first = tr.doc.resolve(first); + if (deflt && $from.node(splitDepth - 1).canReplaceWith($first.index(), $first.index() + 1, deflt)) tr.setNodeMarkup(tr.mapping.map($from.before(splitDepth)), deflt); + } + if (dispatch) dispatch(tr.scrollIntoView()); + return true; + }; +} +var splitBlock = splitBlockAs(); +var splitBlockKeepMarks = function splitBlockKeepMarks(state, dispatch) { + return splitBlock(state, dispatch && function (tr) { + var marks = state.storedMarks || state.selection.$to.parentOffset && state.selection.$from.marks(); + if (marks) tr.ensureMarks(marks); + dispatch(tr); + }); +}; +var selectParentNode = function selectParentNode(state, dispatch) { + var _state$selection7 = state.selection, + $from = _state$selection7.$from, + to = _state$selection7.to, + pos; + var same = $from.sharedDepth(to); + if (same == 0) return false; + pos = $from.before(same); + if (dispatch) dispatch(state.tr.setSelection(prosemirrorState.NodeSelection.create(state.doc, pos))); + return true; +}; +var selectAll = function selectAll(state, dispatch) { + if (dispatch) dispatch(state.tr.setSelection(new prosemirrorState.AllSelection(state.doc))); + return true; +}; +function joinMaybeClear(state, $pos, dispatch) { + var before = $pos.nodeBefore, + after = $pos.nodeAfter, + index = $pos.index(); + if (!before || !after || !before.type.compatibleContent(after.type)) return false; + if (!before.content.size && $pos.parent.canReplace(index - 1, index)) { + if (dispatch) dispatch(state.tr["delete"]($pos.pos - before.nodeSize, $pos.pos).scrollIntoView()); + return true; + } + if (!$pos.parent.canReplace(index, index + 1) || !(after.isTextblock || prosemirrorTransform.canJoin(state.doc, $pos.pos))) return false; + if (dispatch) dispatch(state.tr.join($pos.pos).scrollIntoView()); + return true; +} +function deleteBarrier(state, $cut, dispatch, dir) { + var before = $cut.nodeBefore, + after = $cut.nodeAfter, + conn, + match; + var isolated = before.type.spec.isolating || after.type.spec.isolating; + if (!isolated && joinMaybeClear(state, $cut, dispatch)) return true; + var canDelAfter = !isolated && $cut.parent.canReplace($cut.index(), $cut.index() + 1); + if (canDelAfter && (conn = (match = before.contentMatchAt(before.childCount)).findWrapping(after.type)) && match.matchType(conn[0] || after.type).validEnd) { + if (dispatch) { + var end = $cut.pos + after.nodeSize, + wrap = prosemirrorModel.Fragment.empty; + for (var i = conn.length - 1; i >= 0; i--) wrap = prosemirrorModel.Fragment.from(conn[i].create(null, wrap)); + wrap = prosemirrorModel.Fragment.from(before.copy(wrap)); + var tr = state.tr.step(new prosemirrorTransform.ReplaceAroundStep($cut.pos - 1, end, $cut.pos, end, new prosemirrorModel.Slice(wrap, 1, 0), conn.length, true)); + var $joinAt = tr.doc.resolve(end + 2 * conn.length); + if ($joinAt.nodeAfter && $joinAt.nodeAfter.type == before.type && prosemirrorTransform.canJoin(tr.doc, $joinAt.pos)) tr.join($joinAt.pos); + dispatch(tr.scrollIntoView()); + } + return true; + } + var selAfter = after.type.spec.isolating || dir > 0 && isolated ? null : prosemirrorState.Selection.findFrom($cut, 1); + var range = selAfter && selAfter.$from.blockRange(selAfter.$to), + target = range && prosemirrorTransform.liftTarget(range); + if (target != null && target >= $cut.depth) { + if (dispatch) dispatch(state.tr.lift(range, target).scrollIntoView()); + return true; + } + if (canDelAfter && textblockAt(after, "start", true) && textblockAt(before, "end")) { + var at = before, + _wrap = []; + for (;;) { + _wrap.push(at); + if (at.isTextblock) break; + at = at.lastChild; + } + var afterText = after, + afterDepth = 1; + for (; !afterText.isTextblock; afterText = afterText.firstChild) afterDepth++; + if (at.canReplace(at.childCount, at.childCount, afterText.content)) { + if (dispatch) { + var _end = prosemirrorModel.Fragment.empty; + for (var _i = _wrap.length - 1; _i >= 0; _i--) _end = prosemirrorModel.Fragment.from(_wrap[_i].copy(_end)); + var _tr = state.tr.step(new prosemirrorTransform.ReplaceAroundStep($cut.pos - _wrap.length, $cut.pos + after.nodeSize, $cut.pos + afterDepth, $cut.pos + after.nodeSize - afterDepth, new prosemirrorModel.Slice(_end, _wrap.length, 0), 0, true)); + dispatch(_tr.scrollIntoView()); + } + return true; + } + } + return false; +} +function selectTextblockSide(side) { + return function (state, dispatch) { + var sel = state.selection, + $pos = side < 0 ? sel.$from : sel.$to; + var depth = $pos.depth; + while ($pos.node(depth).isInline) { + if (!depth) return false; + depth--; + } + if (!$pos.node(depth).isTextblock) return false; + if (dispatch) dispatch(state.tr.setSelection(prosemirrorState.TextSelection.create(state.doc, side < 0 ? $pos.start(depth) : $pos.end(depth)))); + return true; + }; +} +var selectTextblockStart = selectTextblockSide(-1); +var selectTextblockEnd = selectTextblockSide(1); +function wrapIn(nodeType) { + var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + return function (state, dispatch) { + var _state$selection8 = state.selection, + $from = _state$selection8.$from, + $to = _state$selection8.$to; + var range = $from.blockRange($to), + wrapping = range && prosemirrorTransform.findWrapping(range, nodeType, attrs); + if (!wrapping) return false; + if (dispatch) dispatch(state.tr.wrap(range, wrapping).scrollIntoView()); + return true; + }; +} +function setBlockType(nodeType) { + var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + return function (state, dispatch) { + var applicable = false; + for (var i = 0; i < state.selection.ranges.length && !applicable; i++) { + var _state$selection$rang = state.selection.ranges[i], + from = _state$selection$rang.$from.pos, + to = _state$selection$rang.$to.pos; + state.doc.nodesBetween(from, to, function (node, pos) { + if (applicable) return false; + if (!node.isTextblock || node.hasMarkup(nodeType, attrs)) return; + if (node.type == nodeType) { + applicable = true; + } else { + var $pos = state.doc.resolve(pos), + index = $pos.index(); + applicable = $pos.parent.canReplaceWith(index, index + 1, nodeType); + } + }); + } + if (!applicable) return false; + if (dispatch) { + var tr = state.tr; + for (var _i2 = 0; _i2 < state.selection.ranges.length; _i2++) { + var _state$selection$rang2 = state.selection.ranges[_i2], + _from = _state$selection$rang2.$from.pos, + _to = _state$selection$rang2.$to.pos; + tr.setBlockType(_from, _to, nodeType, attrs); + } + dispatch(tr.scrollIntoView()); + } + return true; + }; +} +function markApplies(doc, ranges, type, enterAtoms) { + var _loop = function _loop() { + var _ranges$i = ranges[i], + $from = _ranges$i.$from, + $to = _ranges$i.$to; + var can = $from.depth == 0 ? doc.inlineContent && doc.type.allowsMarkType(type) : false; + doc.nodesBetween($from.pos, $to.pos, function (node, pos) { + if (can || !enterAtoms && node.isAtom && node.isInline && pos >= $from.pos && pos + node.nodeSize <= $to.pos) return false; + can = node.inlineContent && node.type.allowsMarkType(type); + }); + if (can) return { + v: true + }; + }, + _ret; + for (var i = 0; i < ranges.length; i++) { + _ret = _loop(); + if (_ret) return _ret.v; + } + return false; +} +function removeInlineAtoms(ranges) { + var result = []; + var _loop2 = function _loop2() { + var _ranges$i2 = ranges[i], + $from = _ranges$i2.$from, + $to = _ranges$i2.$to; + $from.doc.nodesBetween($from.pos, $to.pos, function (node, pos) { + if (node.isAtom && node.content.size && node.isInline && pos >= $from.pos && pos + node.nodeSize <= $to.pos) { + if (pos + 1 > $from.pos) result.push(new prosemirrorState.SelectionRange($from, $from.doc.resolve(pos + 1))); + $from = $from.doc.resolve(pos + 1 + node.content.size); + return false; + } + }); + if ($from.pos < $to.pos) result.push(new prosemirrorState.SelectionRange($from, $to)); + }; + for (var i = 0; i < ranges.length; i++) { + _loop2(); + } + return result; +} +function toggleMark(markType) { + var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + var options = arguments.length > 2 ? arguments[2] : undefined; + var removeWhenPresent = (options && options.removeWhenPresent) !== false; + var enterAtoms = (options && options.enterInlineAtoms) !== false; + var dropSpace = !(options && options.includeWhitespace); + return function (state, dispatch) { + var _state$selection9 = state.selection, + empty = _state$selection9.empty, + $cursor = _state$selection9.$cursor, + ranges = _state$selection9.ranges; + if (empty && !$cursor || !markApplies(state.doc, ranges, markType, enterAtoms)) return false; + if (dispatch) { + if ($cursor) { + if (markType.isInSet(state.storedMarks || $cursor.marks())) dispatch(state.tr.removeStoredMark(markType));else dispatch(state.tr.addStoredMark(markType.create(attrs))); + } else { + var add, + tr = state.tr; + if (!enterAtoms) ranges = removeInlineAtoms(ranges); + if (removeWhenPresent) { + add = !ranges.some(function (r) { + return state.doc.rangeHasMark(r.$from.pos, r.$to.pos, markType); + }); + } else { + add = !ranges.every(function (r) { + var missing = false; + tr.doc.nodesBetween(r.$from.pos, r.$to.pos, function (node, pos, parent) { + if (missing) return false; + missing = !markType.isInSet(node.marks) && !!parent && parent.type.allowsMarkType(markType) && !(node.isText && /^\s*$/.test(node.textBetween(Math.max(0, r.$from.pos - pos), Math.min(node.nodeSize, r.$to.pos - pos)))); + }); + return !missing; + }); + } + for (var i = 0; i < ranges.length; i++) { + var _ranges$i3 = ranges[i], + $from = _ranges$i3.$from, + $to = _ranges$i3.$to; + if (!add) { + tr.removeMark($from.pos, $to.pos, markType); + } else { + var from = $from.pos, + to = $to.pos, + start = $from.nodeAfter, + end = $to.nodeBefore; + var spaceStart = dropSpace && start && start.isText ? /^\s*/.exec(start.text)[0].length : 0; + var spaceEnd = dropSpace && end && end.isText ? /\s*$/.exec(end.text)[0].length : 0; + if (from + spaceStart < to) { + from += spaceStart; + to -= spaceEnd; + } + tr.addMark(from, to, markType.create(attrs)); + } + } + dispatch(tr.scrollIntoView()); + } + } + return true; + }; +} +function wrapDispatchForJoin(dispatch, isJoinable) { + return function (tr) { + if (!tr.isGeneric) return dispatch(tr); + var ranges = []; + for (var i = 0; i < tr.mapping.maps.length; i++) { + var map = tr.mapping.maps[i]; + for (var j = 0; j < ranges.length; j++) ranges[j] = map.map(ranges[j]); + map.forEach(function (_s, _e, from, to) { + return ranges.push(from, to); + }); + } + var joinable = []; + for (var _i3 = 0; _i3 < ranges.length; _i3 += 2) { + var from = ranges[_i3], + to = ranges[_i3 + 1]; + var $from = tr.doc.resolve(from), + depth = $from.sharedDepth(to), + parent = $from.node(depth); + for (var index = $from.indexAfter(depth), pos = $from.after(depth + 1); pos <= to; ++index) { + var after = parent.maybeChild(index); + if (!after) break; + if (index && joinable.indexOf(pos) == -1) { + var before = parent.child(index - 1); + if (before.type == after.type && isJoinable(before, after)) joinable.push(pos); + } + pos += after.nodeSize; + } + } + joinable.sort(function (a, b) { + return a - b; + }); + for (var _i4 = joinable.length - 1; _i4 >= 0; _i4--) { + if (prosemirrorTransform.canJoin(tr.doc, joinable[_i4])) tr.join(joinable[_i4]); + } + dispatch(tr); + }; +} +function autoJoin(command, isJoinable) { + var canJoin = Array.isArray(isJoinable) ? function (node) { + return isJoinable.indexOf(node.type.name) > -1; + } : isJoinable; + return function (state, dispatch, view) { + return command(state, dispatch && wrapDispatchForJoin(dispatch, canJoin), view); + }; +} +function chainCommands() { + for (var _len = arguments.length, commands = new Array(_len), _key = 0; _key < _len; _key++) { + commands[_key] = arguments[_key]; + } + return function (state, dispatch, view) { + for (var i = 0; i < commands.length; i++) if (commands[i](state, dispatch, view)) return true; + return false; + }; +} +var backspace = chainCommands(deleteSelection, joinBackward, selectNodeBackward); +var del = chainCommands(deleteSelection, joinForward, selectNodeForward); +var pcBaseKeymap = { + "Enter": chainCommands(newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock), + "Mod-Enter": exitCode, + "Backspace": backspace, + "Mod-Backspace": backspace, + "Shift-Backspace": backspace, + "Delete": del, + "Mod-Delete": del, + "Mod-a": selectAll +}; +var macBaseKeymap = { + "Ctrl-h": pcBaseKeymap["Backspace"], + "Alt-Backspace": pcBaseKeymap["Mod-Backspace"], + "Ctrl-d": pcBaseKeymap["Delete"], + "Ctrl-Alt-Backspace": pcBaseKeymap["Mod-Delete"], + "Alt-Delete": pcBaseKeymap["Mod-Delete"], + "Alt-d": pcBaseKeymap["Mod-Delete"], + "Ctrl-a": selectTextblockStart, + "Ctrl-e": selectTextblockEnd +}; +for (var key in pcBaseKeymap) macBaseKeymap[key] = pcBaseKeymap[key]; +var mac = typeof navigator != "undefined" ? /Mac|iP(hone|[oa]d)/.test(navigator.platform) : typeof os != "undefined" && os.platform ? os.platform() == "darwin" : false; +var baseKeymap = mac ? macBaseKeymap : pcBaseKeymap; +exports.autoJoin = autoJoin; +exports.baseKeymap = baseKeymap; +exports.chainCommands = chainCommands; +exports.createParagraphNear = createParagraphNear; +exports.deleteSelection = deleteSelection; +exports.exitCode = exitCode; +exports.joinBackward = joinBackward; +exports.joinDown = joinDown; +exports.joinForward = joinForward; +exports.joinTextblockBackward = joinTextblockBackward; +exports.joinTextblockForward = joinTextblockForward; +exports.joinUp = joinUp; +exports.lift = lift; +exports.liftEmptyBlock = liftEmptyBlock; +exports.macBaseKeymap = macBaseKeymap; +exports.newlineInCode = newlineInCode; +exports.pcBaseKeymap = pcBaseKeymap; +exports.selectAll = selectAll; +exports.selectNodeBackward = selectNodeBackward; +exports.selectNodeForward = selectNodeForward; +exports.selectParentNode = selectParentNode; +exports.selectTextblockEnd = selectTextblockEnd; +exports.selectTextblockStart = selectTextblockStart; +exports.setBlockType = setBlockType; +exports.splitBlock = splitBlock; +exports.splitBlockAs = splitBlockAs; +exports.splitBlockKeepMarks = splitBlockKeepMarks; +exports.toggleMark = toggleMark; +exports.wrapIn = wrapIn; diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-dropcursor.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-dropcursor.cjs new file mode 100644 index 000000000..9c76bd187 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-dropcursor.cjs @@ -0,0 +1,208 @@ +'use strict'; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } + +Object.defineProperty(exports, '__esModule', { + value: true +}); + +var prosemirrorState = require('prosemirror-state'); + +var prosemirrorTransform = require('prosemirror-transform'); + +function dropCursor() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + return new prosemirrorState.Plugin({ + view: function view(editorView) { + return new DropCursorView(editorView, options); + } + }); +} + +var DropCursorView = function () { + function DropCursorView(editorView, options) { + var _this = this; + + _classCallCheck(this, DropCursorView); + + var _a; + + this.editorView = editorView; + this.cursorPos = null; + this.element = null; + this.timeout = -1; + this.width = (_a = options.width) !== null && _a !== void 0 ? _a : 1; + this.color = options.color === false ? undefined : options.color || "black"; + this["class"] = options["class"]; + this.handlers = ["dragover", "dragend", "drop", "dragleave"].map(function (name) { + var handler = function handler(e) { + _this[name](e); + }; + + editorView.dom.addEventListener(name, handler); + return { + name: name, + handler: handler + }; + }); + } + + _createClass(DropCursorView, [{ + key: "destroy", + value: function destroy() { + var _this2 = this; + + this.handlers.forEach(function (_ref) { + var name = _ref.name, + handler = _ref.handler; + return _this2.editorView.dom.removeEventListener(name, handler); + }); + } + }, { + key: "update", + value: function update(editorView, prevState) { + if (this.cursorPos != null && prevState.doc != editorView.state.doc) { + if (this.cursorPos > editorView.state.doc.content.size) this.setCursor(null);else this.updateOverlay(); + } + } + }, { + key: "setCursor", + value: function setCursor(pos) { + if (pos == this.cursorPos) return; + this.cursorPos = pos; + + if (pos == null) { + this.element.parentNode.removeChild(this.element); + this.element = null; + } else { + this.updateOverlay(); + } + } + }, { + key: "updateOverlay", + value: function updateOverlay() { + var $pos = this.editorView.state.doc.resolve(this.cursorPos); + var isBlock = !$pos.parent.inlineContent, + rect; + + if (isBlock) { + var before = $pos.nodeBefore, + after = $pos.nodeAfter; + + if (before || after) { + var node = this.editorView.nodeDOM(this.cursorPos - (before ? before.nodeSize : 0)); + + if (node) { + var nodeRect = node.getBoundingClientRect(); + var top = before ? nodeRect.bottom : nodeRect.top; + if (before && after) top = (top + this.editorView.nodeDOM(this.cursorPos).getBoundingClientRect().top) / 2; + rect = { + left: nodeRect.left, + right: nodeRect.right, + top: top - this.width / 2, + bottom: top + this.width / 2 + }; + } + } + } + + if (!rect) { + var coords = this.editorView.coordsAtPos(this.cursorPos); + rect = { + left: coords.left - this.width / 2, + right: coords.left + this.width / 2, + top: coords.top, + bottom: coords.bottom + }; + } + + var parent = this.editorView.dom.offsetParent; + + if (!this.element) { + this.element = parent.appendChild(document.createElement("div")); + if (this["class"]) this.element.className = this["class"]; + this.element.style.cssText = "position: absolute; z-index: 50; pointer-events: none;"; + + if (this.color) { + this.element.style.backgroundColor = this.color; + } + } + + this.element.classList.toggle("prosemirror-dropcursor-block", isBlock); + this.element.classList.toggle("prosemirror-dropcursor-inline", !isBlock); + var parentLeft, parentTop; + + if (!parent || parent == document.body && getComputedStyle(parent).position == "static") { + parentLeft = -pageXOffset; + parentTop = -pageYOffset; + } else { + var _rect = parent.getBoundingClientRect(); + + parentLeft = _rect.left - parent.scrollLeft; + parentTop = _rect.top - parent.scrollTop; + } + + this.element.style.left = rect.left - parentLeft + "px"; + this.element.style.top = rect.top - parentTop + "px"; + this.element.style.width = rect.right - rect.left + "px"; + this.element.style.height = rect.bottom - rect.top + "px"; + } + }, { + key: "scheduleRemoval", + value: function scheduleRemoval(timeout) { + var _this3 = this; + + clearTimeout(this.timeout); + this.timeout = setTimeout(function () { + return _this3.setCursor(null); + }, timeout); + } + }, { + key: "dragover", + value: function dragover(event) { + if (!this.editorView.editable) return; + var pos = this.editorView.posAtCoords({ + left: event.clientX, + top: event.clientY + }); + var node = pos && pos.inside >= 0 && this.editorView.state.doc.nodeAt(pos.inside); + var disableDropCursor = node && node.type.spec.disableDropCursor; + var disabled = typeof disableDropCursor == "function" ? disableDropCursor(this.editorView, pos, event) : disableDropCursor; + + if (pos && !disabled) { + var target = pos.pos; + + if (this.editorView.dragging && this.editorView.dragging.slice) { + var point = prosemirrorTransform.dropPoint(this.editorView.state.doc, target, this.editorView.dragging.slice); + if (point != null) target = point; + } + + this.setCursor(target); + this.scheduleRemoval(5000); + } + } + }, { + key: "dragend", + value: function dragend() { + this.scheduleRemoval(20); + } + }, { + key: "drop", + value: function drop() { + this.scheduleRemoval(20); + } + }, { + key: "dragleave", + value: function dragleave(event) { + if (event.target == this.editorView.dom || !this.editorView.dom.contains(event.relatedTarget)) this.setCursor(null); + } + }]); + + return DropCursorView; +}(); + +exports.dropCursor = dropCursor; diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-gapcursor.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-gapcursor.cjs new file mode 100644 index 000000000..7dfb0eeb8 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-gapcursor.cjs @@ -0,0 +1,295 @@ +'use strict'; + +function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } + +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + +Object.defineProperty(exports, '__esModule', { + value: true +}); + +var prosemirrorKeymap = require('prosemirror-keymap'); + +var prosemirrorState = require('prosemirror-state'); + +var prosemirrorModel = require('prosemirror-model'); + +var prosemirrorView = require('prosemirror-view'); + +var GapCursor = function (_prosemirrorState$Sel) { + _inherits(GapCursor, _prosemirrorState$Sel); + + var _super = _createSuper(GapCursor); + + function GapCursor($pos) { + _classCallCheck(this, GapCursor); + + return _super.call(this, $pos, $pos); + } + + _createClass(GapCursor, [{ + key: "map", + value: function map(doc, mapping) { + var $pos = doc.resolve(mapping.map(this.head)); + return GapCursor.valid($pos) ? new GapCursor($pos) : prosemirrorState.Selection.near($pos); + } + }, { + key: "content", + value: function content() { + return prosemirrorModel.Slice.empty; + } + }, { + key: "eq", + value: function eq(other) { + return other instanceof GapCursor && other.head == this.head; + } + }, { + key: "toJSON", + value: function toJSON() { + return { + type: "gapcursor", + pos: this.head + }; + } + }, { + key: "getBookmark", + value: function getBookmark() { + return new GapBookmark(this.anchor); + } + }], [{ + key: "fromJSON", + value: function fromJSON(doc, json) { + if (typeof json.pos != "number") throw new RangeError("Invalid input for GapCursor.fromJSON"); + return new GapCursor(doc.resolve(json.pos)); + } + }, { + key: "valid", + value: function valid($pos) { + var parent = $pos.parent; + if (parent.isTextblock || !closedBefore($pos) || !closedAfter($pos)) return false; + var override = parent.type.spec.allowGapCursor; + if (override != null) return override; + var deflt = parent.contentMatchAt($pos.index()).defaultType; + return deflt && deflt.isTextblock; + } + }, { + key: "findGapCursorFrom", + value: function findGapCursorFrom($pos, dir) { + var mustMove = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + search: for (;;) { + if (!mustMove && GapCursor.valid($pos)) return $pos; + var pos = $pos.pos, + next = null; + + for (var d = $pos.depth;; d--) { + var parent = $pos.node(d); + + if (dir > 0 ? $pos.indexAfter(d) < parent.childCount : $pos.index(d) > 0) { + next = parent.child(dir > 0 ? $pos.indexAfter(d) : $pos.index(d) - 1); + break; + } else if (d == 0) { + return null; + } + + pos += dir; + var $cur = $pos.doc.resolve(pos); + if (GapCursor.valid($cur)) return $cur; + } + + for (;;) { + var inside = dir > 0 ? next.firstChild : next.lastChild; + + if (!inside) { + if (next.isAtom && !next.isText && !prosemirrorState.NodeSelection.isSelectable(next)) { + $pos = $pos.doc.resolve(pos + next.nodeSize * dir); + mustMove = false; + continue search; + } + + break; + } + + next = inside; + pos += dir; + + var _$cur = $pos.doc.resolve(pos); + + if (GapCursor.valid(_$cur)) return _$cur; + } + + return null; + } + } + }]); + + return GapCursor; +}(prosemirrorState.Selection); + +GapCursor.prototype.visible = false; +GapCursor.findFrom = GapCursor.findGapCursorFrom; +prosemirrorState.Selection.jsonID("gapcursor", GapCursor); + +var GapBookmark = function () { + function GapBookmark(pos) { + _classCallCheck(this, GapBookmark); + + this.pos = pos; + } + + _createClass(GapBookmark, [{ + key: "map", + value: function map(mapping) { + return new GapBookmark(mapping.map(this.pos)); + } + }, { + key: "resolve", + value: function resolve(doc) { + var $pos = doc.resolve(this.pos); + return GapCursor.valid($pos) ? new GapCursor($pos) : prosemirrorState.Selection.near($pos); + } + }]); + + return GapBookmark; +}(); + +function closedBefore($pos) { + for (var d = $pos.depth; d >= 0; d--) { + var index = $pos.index(d), + parent = $pos.node(d); + + if (index == 0) { + if (parent.type.spec.isolating) return true; + continue; + } + + for (var before = parent.child(index - 1);; before = before.lastChild) { + if (before.childCount == 0 && !before.inlineContent || before.isAtom || before.type.spec.isolating) return true; + if (before.inlineContent) return false; + } + } + + return true; +} + +function closedAfter($pos) { + for (var d = $pos.depth; d >= 0; d--) { + var index = $pos.indexAfter(d), + parent = $pos.node(d); + + if (index == parent.childCount) { + if (parent.type.spec.isolating) return true; + continue; + } + + for (var after = parent.child(index);; after = after.firstChild) { + if (after.childCount == 0 && !after.inlineContent || after.isAtom || after.type.spec.isolating) return true; + if (after.inlineContent) return false; + } + } + + return true; +} + +function gapCursor() { + return new prosemirrorState.Plugin({ + props: { + decorations: drawGapCursor, + createSelectionBetween: function createSelectionBetween(_view, $anchor, $head) { + return $anchor.pos == $head.pos && GapCursor.valid($head) ? new GapCursor($head) : null; + }, + handleClick: handleClick, + handleKeyDown: handleKeyDown, + handleDOMEvents: { + beforeinput: beforeinput + } + } + }); +} + +var handleKeyDown = prosemirrorKeymap.keydownHandler({ + "ArrowLeft": arrow("horiz", -1), + "ArrowRight": arrow("horiz", 1), + "ArrowUp": arrow("vert", -1), + "ArrowDown": arrow("vert", 1) +}); + +function arrow(axis, dir) { + var dirStr = axis == "vert" ? dir > 0 ? "down" : "up" : dir > 0 ? "right" : "left"; + return function (state, dispatch, view) { + var sel = state.selection; + var $start = dir > 0 ? sel.$to : sel.$from, + mustMove = sel.empty; + + if (sel instanceof prosemirrorState.TextSelection) { + if (!view.endOfTextblock(dirStr) || $start.depth == 0) return false; + mustMove = false; + $start = state.doc.resolve(dir > 0 ? $start.after() : $start.before()); + } + + var $found = GapCursor.findGapCursorFrom($start, dir, mustMove); + if (!$found) return false; + if (dispatch) dispatch(state.tr.setSelection(new GapCursor($found))); + return true; + }; +} + +function handleClick(view, pos, event) { + if (!view || !view.editable) return false; + var $pos = view.state.doc.resolve(pos); + if (!GapCursor.valid($pos)) return false; + var clickPos = view.posAtCoords({ + left: event.clientX, + top: event.clientY + }); + if (clickPos && clickPos.inside > -1 && prosemirrorState.NodeSelection.isSelectable(view.state.doc.nodeAt(clickPos.inside))) return false; + view.dispatch(view.state.tr.setSelection(new GapCursor($pos))); + return true; +} + +function beforeinput(view, event) { + if (event.inputType != "insertCompositionText" || !(view.state.selection instanceof GapCursor)) return false; + var $from = view.state.selection.$from; + var insert = $from.parent.contentMatchAt($from.index()).findWrapping(view.state.schema.nodes.text); + if (!insert) return false; + var frag = prosemirrorModel.Fragment.empty; + + for (var i = insert.length - 1; i >= 0; i--) { + frag = prosemirrorModel.Fragment.from(insert[i].createAndFill(null, frag)); + } + + var tr = view.state.tr.replace($from.pos, $from.pos, new prosemirrorModel.Slice(frag, 0, 0)); + tr.setSelection(prosemirrorState.TextSelection.near(tr.doc.resolve($from.pos + 1))); + view.dispatch(tr); + return false; +} + +function drawGapCursor(state) { + if (!(state.selection instanceof GapCursor)) return null; + var node = document.createElement("div"); + node.className = "ProseMirror-gapcursor"; + return prosemirrorView.DecorationSet.create(state.doc, [prosemirrorView.Decoration.widget(state.selection.head, node, { + key: "gapcursor" + })]); +} + +exports.GapCursor = GapCursor; +exports.gapCursor = gapCursor; diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-history.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-history.cjs new file mode 100644 index 000000000..f6103781f --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-history.cjs @@ -0,0 +1,378 @@ +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var RopeSequence = require('rope-sequence'); +var prosemirrorTransform = require('prosemirror-transform'); +var prosemirrorState = require('prosemirror-state'); +var max_empty_items = 500; +var Branch = function () { + function Branch(items, eventCount) { + _classCallCheck(this, Branch); + this.items = items; + this.eventCount = eventCount; + } + _createClass(Branch, [{ + key: "popEvent", + value: function popEvent(state, preserveItems) { + var _this = this; + if (this.eventCount == 0) return null; + var end = this.items.length; + for (;; end--) { + var next = this.items.get(end - 1); + if (next.selection) { + --end; + break; + } + } + var remap, mapFrom; + if (preserveItems) { + remap = this.remapping(end, this.items.length); + mapFrom = remap.maps.length; + } + var transform = state.tr; + var selection, remaining; + var addAfter = [], + addBefore = []; + this.items.forEach(function (item, i) { + if (!item.step) { + if (!remap) { + remap = _this.remapping(end, i + 1); + mapFrom = remap.maps.length; + } + mapFrom--; + addBefore.push(item); + return; + } + if (remap) { + addBefore.push(new Item(item.map)); + var step = item.step.map(remap.slice(mapFrom)), + map; + if (step && transform.maybeStep(step).doc) { + map = transform.mapping.maps[transform.mapping.maps.length - 1]; + addAfter.push(new Item(map, undefined, undefined, addAfter.length + addBefore.length)); + } + mapFrom--; + if (map) remap.appendMap(map, mapFrom); + } else { + transform.maybeStep(item.step); + } + if (item.selection) { + selection = remap ? item.selection.map(remap.slice(mapFrom)) : item.selection; + remaining = new Branch(_this.items.slice(0, end).append(addBefore.reverse().concat(addAfter)), _this.eventCount - 1); + return false; + } + }, this.items.length, 0); + return { + remaining: remaining, + transform: transform, + selection: selection + }; + } + }, { + key: "addTransform", + value: function addTransform(transform, selection, histOptions, preserveItems) { + var newItems = [], + eventCount = this.eventCount; + var oldItems = this.items, + lastItem = !preserveItems && oldItems.length ? oldItems.get(oldItems.length - 1) : null; + for (var i = 0; i < transform.steps.length; i++) { + var step = transform.steps[i].invert(transform.docs[i]); + var item = new Item(transform.mapping.maps[i], step, selection), + merged = void 0; + if (merged = lastItem && lastItem.merge(item)) { + item = merged; + if (i) newItems.pop();else oldItems = oldItems.slice(0, oldItems.length - 1); + } + newItems.push(item); + if (selection) { + eventCount++; + selection = undefined; + } + if (!preserveItems) lastItem = item; + } + var overflow = eventCount - histOptions.depth; + if (overflow > DEPTH_OVERFLOW) { + oldItems = cutOffEvents(oldItems, overflow); + eventCount -= overflow; + } + return new Branch(oldItems.append(newItems), eventCount); + } + }, { + key: "remapping", + value: function remapping(from, to) { + var maps = new prosemirrorTransform.Mapping(); + this.items.forEach(function (item, i) { + var mirrorPos = item.mirrorOffset != null && i - item.mirrorOffset >= from ? maps.maps.length - item.mirrorOffset : undefined; + maps.appendMap(item.map, mirrorPos); + }, from, to); + return maps; + } + }, { + key: "addMaps", + value: function addMaps(array) { + if (this.eventCount == 0) return this; + return new Branch(this.items.append(array.map(function (map) { + return new Item(map); + })), this.eventCount); + } + }, { + key: "rebased", + value: function rebased(rebasedTransform, rebasedCount) { + if (!this.eventCount) return this; + var rebasedItems = [], + start = Math.max(0, this.items.length - rebasedCount); + var mapping = rebasedTransform.mapping; + var newUntil = rebasedTransform.steps.length; + var eventCount = this.eventCount; + this.items.forEach(function (item) { + if (item.selection) eventCount--; + }, start); + var iRebased = rebasedCount; + this.items.forEach(function (item) { + var pos = mapping.getMirror(--iRebased); + if (pos == null) return; + newUntil = Math.min(newUntil, pos); + var map = mapping.maps[pos]; + if (item.step) { + var step = rebasedTransform.steps[pos].invert(rebasedTransform.docs[pos]); + var selection = item.selection && item.selection.map(mapping.slice(iRebased + 1, pos)); + if (selection) eventCount++; + rebasedItems.push(new Item(map, step, selection)); + } else { + rebasedItems.push(new Item(map)); + } + }, start); + var newMaps = []; + for (var i = rebasedCount; i < newUntil; i++) newMaps.push(new Item(mapping.maps[i])); + var items = this.items.slice(0, start).append(newMaps).append(rebasedItems); + var branch = new Branch(items, eventCount); + if (branch.emptyItemCount() > max_empty_items) branch = branch.compress(this.items.length - rebasedItems.length); + return branch; + } + }, { + key: "emptyItemCount", + value: function emptyItemCount() { + var count = 0; + this.items.forEach(function (item) { + if (!item.step) count++; + }); + return count; + } + }, { + key: "compress", + value: function compress() { + var upto = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.items.length; + var remap = this.remapping(0, upto), + mapFrom = remap.maps.length; + var items = [], + events = 0; + this.items.forEach(function (item, i) { + if (i >= upto) { + items.push(item); + if (item.selection) events++; + } else if (item.step) { + var step = item.step.map(remap.slice(mapFrom)), + map = step && step.getMap(); + mapFrom--; + if (map) remap.appendMap(map, mapFrom); + if (step) { + var selection = item.selection && item.selection.map(remap.slice(mapFrom)); + if (selection) events++; + var newItem = new Item(map.invert(), step, selection), + merged, + last = items.length - 1; + if (merged = items.length && items[last].merge(newItem)) items[last] = merged;else items.push(newItem); + } + } else if (item.map) { + mapFrom--; + } + }, this.items.length, 0); + return new Branch(RopeSequence.from(items.reverse()), events); + } + }]); + return Branch; +}(); +Branch.empty = new Branch(RopeSequence.empty, 0); +function cutOffEvents(items, n) { + var cutPoint; + items.forEach(function (item, i) { + if (item.selection && n-- == 0) { + cutPoint = i; + return false; + } + }); + return items.slice(cutPoint); +} +var Item = function () { + function Item(map, step, selection, mirrorOffset) { + _classCallCheck(this, Item); + this.map = map; + this.step = step; + this.selection = selection; + this.mirrorOffset = mirrorOffset; + } + _createClass(Item, [{ + key: "merge", + value: function merge(other) { + if (this.step && other.step && !other.selection) { + var step = other.step.merge(this.step); + if (step) return new Item(step.getMap().invert(), step, this.selection); + } + } + }]); + return Item; +}(); +var HistoryState = _createClass(function HistoryState(done, undone, prevRanges, prevTime, prevComposition) { + _classCallCheck(this, HistoryState); + this.done = done; + this.undone = undone; + this.prevRanges = prevRanges; + this.prevTime = prevTime; + this.prevComposition = prevComposition; +}); +var DEPTH_OVERFLOW = 20; +function applyTransaction(history, state, tr, options) { + var historyTr = tr.getMeta(historyKey), + rebased; + if (historyTr) return historyTr.historyState; + if (tr.getMeta(closeHistoryKey)) history = new HistoryState(history.done, history.undone, null, 0, -1); + var appended = tr.getMeta("appendedTransaction"); + if (tr.steps.length == 0) { + return history; + } else if (appended && appended.getMeta(historyKey)) { + if (appended.getMeta(historyKey).redo) return new HistoryState(history.done.addTransform(tr, undefined, options, mustPreserveItems(state)), history.undone, rangesFor(tr.mapping.maps), history.prevTime, history.prevComposition);else return new HistoryState(history.done, history.undone.addTransform(tr, undefined, options, mustPreserveItems(state)), null, history.prevTime, history.prevComposition); + } else if (tr.getMeta("addToHistory") !== false && !(appended && appended.getMeta("addToHistory") === false)) { + var composition = tr.getMeta("composition"); + var newGroup = history.prevTime == 0 || !appended && history.prevComposition != composition && (history.prevTime < (tr.time || 0) - options.newGroupDelay || !isAdjacentTo(tr, history.prevRanges)); + var prevRanges = appended ? mapRanges(history.prevRanges, tr.mapping) : rangesFor(tr.mapping.maps); + return new HistoryState(history.done.addTransform(tr, newGroup ? state.selection.getBookmark() : undefined, options, mustPreserveItems(state)), Branch.empty, prevRanges, tr.time, composition == null ? history.prevComposition : composition); + } else if (rebased = tr.getMeta("rebased")) { + return new HistoryState(history.done.rebased(tr, rebased), history.undone.rebased(tr, rebased), mapRanges(history.prevRanges, tr.mapping), history.prevTime, history.prevComposition); + } else { + return new HistoryState(history.done.addMaps(tr.mapping.maps), history.undone.addMaps(tr.mapping.maps), mapRanges(history.prevRanges, tr.mapping), history.prevTime, history.prevComposition); + } +} +function isAdjacentTo(transform, prevRanges) { + if (!prevRanges) return false; + if (!transform.docChanged) return true; + var adjacent = false; + transform.mapping.maps[0].forEach(function (start, end) { + for (var i = 0; i < prevRanges.length; i += 2) if (start <= prevRanges[i + 1] && end >= prevRanges[i]) adjacent = true; + }); + return adjacent; +} +function rangesFor(maps) { + var result = []; + for (var i = maps.length - 1; i >= 0 && result.length == 0; i--) maps[i].forEach(function (_from, _to, from, to) { + return result.push(from, to); + }); + return result; +} +function mapRanges(ranges, mapping) { + if (!ranges) return null; + var result = []; + for (var i = 0; i < ranges.length; i += 2) { + var from = mapping.map(ranges[i], 1), + to = mapping.map(ranges[i + 1], -1); + if (from <= to) result.push(from, to); + } + return result; +} +function histTransaction(history, state, redo) { + var preserveItems = mustPreserveItems(state); + var histOptions = historyKey.get(state).spec.config; + var pop = (redo ? history.undone : history.done).popEvent(state, preserveItems); + if (!pop) return null; + var selection = pop.selection.resolve(pop.transform.doc); + var added = (redo ? history.done : history.undone).addTransform(pop.transform, state.selection.getBookmark(), histOptions, preserveItems); + var newHist = new HistoryState(redo ? added : pop.remaining, redo ? pop.remaining : added, null, 0, -1); + return pop.transform.setSelection(selection).setMeta(historyKey, { + redo: redo, + historyState: newHist + }); +} +var cachedPreserveItems = false, + cachedPreserveItemsPlugins = null; +function mustPreserveItems(state) { + var plugins = state.plugins; + if (cachedPreserveItemsPlugins != plugins) { + cachedPreserveItems = false; + cachedPreserveItemsPlugins = plugins; + for (var i = 0; i < plugins.length; i++) if (plugins[i].spec.historyPreserveItems) { + cachedPreserveItems = true; + break; + } + } + return cachedPreserveItems; +} +function closeHistory(tr) { + return tr.setMeta(closeHistoryKey, true); +} +var historyKey = new prosemirrorState.PluginKey("history"); +var closeHistoryKey = new prosemirrorState.PluginKey("closeHistory"); +function history() { + var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + config = { + depth: config.depth || 100, + newGroupDelay: config.newGroupDelay || 500 + }; + return new prosemirrorState.Plugin({ + key: historyKey, + state: { + init: function init() { + return new HistoryState(Branch.empty, Branch.empty, null, 0, -1); + }, + apply: function apply(tr, hist, state) { + return applyTransaction(hist, state, tr, config); + } + }, + config: config, + props: { + handleDOMEvents: { + beforeinput: function beforeinput(view, e) { + var inputType = e.inputType; + var command = inputType == "historyUndo" ? undo : inputType == "historyRedo" ? redo : null; + if (!command) return false; + e.preventDefault(); + return command(view.state, view.dispatch); + } + } + } + }); +} +function buildCommand(redo, scroll) { + return function (state, dispatch) { + var hist = historyKey.getState(state); + if (!hist || (redo ? hist.undone : hist.done).eventCount == 0) return false; + if (dispatch) { + var tr = histTransaction(hist, state, redo); + if (tr) dispatch(scroll ? tr.scrollIntoView() : tr); + } + return true; + }; +} +var undo = buildCommand(false, true); +var redo = buildCommand(true, true); +var undoNoScroll = buildCommand(false, false); +var redoNoScroll = buildCommand(true, false); +function undoDepth(state) { + var hist = historyKey.getState(state); + return hist ? hist.done.eventCount : 0; +} +function redoDepth(state) { + var hist = historyKey.getState(state); + return hist ? hist.undone.eventCount : 0; +} +exports.closeHistory = closeHistory; +exports.history = history; +exports.redo = redo; +exports.redoDepth = redoDepth; +exports.redoNoScroll = redoNoScroll; +exports.undo = undo; +exports.undoDepth = undoDepth; +exports.undoNoScroll = undoNoScroll; diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-inputrules.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-inputrules.cjs new file mode 100644 index 000000000..67ac43022 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-inputrules.cjs @@ -0,0 +1,175 @@ +'use strict'; + +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +var prosemirrorState = require('prosemirror-state'); +var prosemirrorTransform = require('prosemirror-transform'); +var InputRule = _createClass(function InputRule(match, handler) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + _classCallCheck(this, InputRule); + this.match = match; + this.match = match; + this.handler = typeof handler == "string" ? stringHandler(handler) : handler; + this.undoable = options.undoable !== false; + this.inCode = options.inCode || false; + this.inCodeMark = options.inCodeMark !== false; +}); +function stringHandler(string) { + return function (state, match, start, end) { + var insert = string; + if (match[1]) { + var offset = match[0].lastIndexOf(match[1]); + insert += match[0].slice(offset + match[1].length); + start += offset; + var cutOff = start - end; + if (cutOff > 0) { + insert = match[0].slice(offset - cutOff, offset) + insert; + start = end; + } + } + return state.tr.insertText(insert, start, end); + }; +} +var MAX_MATCH = 500; +function inputRules(_ref) { + var rules = _ref.rules; + var plugin = new prosemirrorState.Plugin({ + state: { + init: function init() { + return null; + }, + apply: function apply(tr, prev) { + var stored = tr.getMeta(this); + if (stored) return stored; + return tr.selectionSet || tr.docChanged ? null : prev; + } + }, + props: { + handleTextInput: function handleTextInput(view, from, to, text) { + return run(view, from, to, text, rules, plugin); + }, + handleDOMEvents: { + compositionend: function compositionend(view) { + setTimeout(function () { + var $cursor = view.state.selection.$cursor; + if ($cursor) run(view, $cursor.pos, $cursor.pos, "", rules, plugin); + }); + } + } + }, + isInputRules: true + }); + return plugin; +} +function run(view, from, to, text, rules, plugin) { + if (view.composing) return false; + var state = view.state, + $from = state.doc.resolve(from); + var textBefore = $from.parent.textBetween(Math.max(0, $from.parentOffset - MAX_MATCH), $from.parentOffset, null, "\uFFFC") + text; + for (var i = 0; i < rules.length; i++) { + var rule = rules[i]; + if (!rule.inCodeMark && $from.marks().some(function (m) { + return m.type.spec.code; + })) continue; + if ($from.parent.type.spec.code) { + if (!rule.inCode) continue; + } else if (rule.inCode === "only") { + continue; + } + var match = rule.match.exec(textBefore); + var tr = match && match[0].length >= text.length && rule.handler(state, match, from - (match[0].length - text.length), to); + if (!tr) continue; + if (rule.undoable) tr.setMeta(plugin, { + transform: tr, + from: from, + to: to, + text: text + }); + view.dispatch(tr); + return true; + } + return false; +} +var undoInputRule = function undoInputRule(state, dispatch) { + var plugins = state.plugins; + for (var i = 0; i < plugins.length; i++) { + var plugin = plugins[i], + undoable = void 0; + if (plugin.spec.isInputRules && (undoable = plugin.getState(state))) { + if (dispatch) { + var tr = state.tr, + toUndo = undoable.transform; + for (var j = toUndo.steps.length - 1; j >= 0; j--) tr.step(toUndo.steps[j].invert(toUndo.docs[j])); + if (undoable.text) { + var marks = tr.doc.resolve(undoable.from).marks(); + tr.replaceWith(undoable.from, undoable.to, state.schema.text(undoable.text, marks)); + } else { + tr["delete"](undoable.from, undoable.to); + } + dispatch(tr); + } + return true; + } + } + return false; +}; +var emDash = new InputRule(/--$/, "—", { + inCodeMark: false +}); +var ellipsis = new InputRule(/\.\.\.$/, "…", { + inCodeMark: false +}); +var openDoubleQuote = new InputRule(/(?:^|[\s\{\[\(\<'"\u2018\u201C])(")$/, "“", { + inCodeMark: false +}); +var closeDoubleQuote = new InputRule(/"$/, "”", { + inCodeMark: false +}); +var openSingleQuote = new InputRule(/(?:^|[\s\{\[\(\<'"\u2018\u201C])(')$/, "‘", { + inCodeMark: false +}); +var closeSingleQuote = new InputRule(/'$/, "’", { + inCodeMark: false +}); +var smartQuotes = [openDoubleQuote, closeDoubleQuote, openSingleQuote, closeSingleQuote]; +function wrappingInputRule(regexp, nodeType) { + var getAttrs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + var joinPredicate = arguments.length > 3 ? arguments[3] : undefined; + return new InputRule(regexp, function (state, match, start, end) { + var attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs; + var tr = state.tr["delete"](start, end); + var $start = tr.doc.resolve(start), + range = $start.blockRange(), + wrapping = range && prosemirrorTransform.findWrapping(range, nodeType, attrs); + if (!wrapping) return null; + tr.wrap(range, wrapping); + var before = tr.doc.resolve(start - 1).nodeBefore; + if (before && before.type == nodeType && prosemirrorTransform.canJoin(tr.doc, start - 1) && (!joinPredicate || joinPredicate(match, before))) tr.join(start - 1); + return tr; + }); +} +function textblockTypeInputRule(regexp, nodeType) { + var getAttrs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + return new InputRule(regexp, function (state, match, start, end) { + var $start = state.doc.resolve(start); + var attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs; + if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), nodeType)) return null; + return state.tr["delete"](start, end).setBlockType(start, start, nodeType, attrs); + }); +} +exports.InputRule = InputRule; +exports.closeDoubleQuote = closeDoubleQuote; +exports.closeSingleQuote = closeSingleQuote; +exports.ellipsis = ellipsis; +exports.emDash = emDash; +exports.inputRules = inputRules; +exports.openDoubleQuote = openDoubleQuote; +exports.openSingleQuote = openSingleQuote; +exports.smartQuotes = smartQuotes; +exports.textblockTypeInputRule = textblockTypeInputRule; +exports.undoInputRule = undoInputRule; +exports.wrappingInputRule = wrappingInputRule; diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-keymap.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-keymap.cjs new file mode 100644 index 000000000..2d0111f94 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-keymap.cjs @@ -0,0 +1,85 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true +}); + +var w3cKeyname = require('w3c-keyname'); + +var prosemirrorState = require('prosemirror-state'); + +var mac = typeof navigator != "undefined" ? /Mac|iP(hone|[oa]d)/.test(navigator.platform) : false; + +function normalizeKeyName(name) { + var parts = name.split(/-(?!$)/), + result = parts[parts.length - 1]; + if (result == "Space") result = " "; + var alt, ctrl, shift, meta; + + for (var i = 0; i < parts.length - 1; i++) { + var mod = parts[i]; + if (/^(cmd|meta|m)$/i.test(mod)) meta = true;else if (/^a(lt)?$/i.test(mod)) alt = true;else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true;else if (/^s(hift)?$/i.test(mod)) shift = true;else if (/^mod$/i.test(mod)) { + if (mac) meta = true;else ctrl = true; + } else throw new Error("Unrecognized modifier name: " + mod); + } + + if (alt) result = "Alt-" + result; + if (ctrl) result = "Ctrl-" + result; + if (meta) result = "Meta-" + result; + if (shift) result = "Shift-" + result; + return result; +} + +function normalize(map) { + var copy = Object.create(null); + + for (var prop in map) { + copy[normalizeKeyName(prop)] = map[prop]; + } + + return copy; +} + +function modifiers(name, event) { + var shift = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + if (event.altKey) name = "Alt-" + name; + if (event.ctrlKey) name = "Ctrl-" + name; + if (event.metaKey) name = "Meta-" + name; + if (shift && event.shiftKey) name = "Shift-" + name; + return name; +} + +function keymap(bindings) { + return new prosemirrorState.Plugin({ + props: { + handleKeyDown: keydownHandler(bindings) + } + }); +} + +function keydownHandler(bindings) { + var map = normalize(bindings); + return function (view, event) { + var name = w3cKeyname.keyName(event), + baseName, + direct = map[modifiers(name, event)]; + if (direct && direct(view.state, view.dispatch, view)) return true; + + if (name.length == 1 && name != " ") { + if (event.shiftKey) { + var noShift = map[modifiers(name, event, false)]; + if (noShift && noShift(view.state, view.dispatch, view)) return true; + } + + if ((event.shiftKey || event.altKey || event.metaKey || name.charCodeAt(0) > 127) && (baseName = w3cKeyname.base[event.keyCode]) && baseName != name) { + var fromCode = map[modifiers(baseName, event)]; + if (fromCode && fromCode(view.state, view.dispatch, view)) return true; + } + } + + return false; + }; +} + +exports.keydownHandler = keydownHandler; +exports.keymap = keymap; diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-menu.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-menu.cjs new file mode 100644 index 000000000..a837b6c22 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-menu.cjs @@ -0,0 +1,726 @@ +'use strict'; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } + +function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } + +function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } + +function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + +function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } + +var crel = require('crelt'); + +var prosemirrorCommands = require('prosemirror-commands'); + +var prosemirrorHistory = require('prosemirror-history'); + +var prosemirrorState = require('prosemirror-state'); + +var SVG = "http://www.w3.org/2000/svg"; +var XLINK = "http://www.w3.org/1999/xlink"; +var prefix$2 = "ProseMirror-icon"; + +function hashPath(path) { + var hash = 0; + + for (var i = 0; i < path.length; i++) { + hash = (hash << 5) - hash + path.charCodeAt(i) | 0; + } + + return hash; +} + +function getIcon(root, icon) { + var doc = (root.nodeType == 9 ? root : root.ownerDocument) || document; + var node = doc.createElement("div"); + node.className = prefix$2; + + if (icon.path) { + var path = icon.path, + width = icon.width, + height = icon.height; + var name = "pm-icon-" + hashPath(path).toString(16); + if (!doc.getElementById(name)) buildSVG(root, name, icon); + var svg = node.appendChild(doc.createElementNS(SVG, "svg")); + svg.style.width = width / height + "em"; + var use = svg.appendChild(doc.createElementNS(SVG, "use")); + use.setAttributeNS(XLINK, "href", /([^#]*)/.exec(doc.location.toString())[1] + "#" + name); + } else if (icon.dom) { + node.appendChild(icon.dom.cloneNode(true)); + } else { + var text = icon.text, + css = icon.css; + node.appendChild(doc.createElement("span")).textContent = text || ''; + if (css) node.firstChild.style.cssText = css; + } + + return node; +} + +function buildSVG(root, name, data) { + var _ref = root.nodeType == 9 ? [root, root.body] : [root.ownerDocument || document, root], + _ref2 = _slicedToArray(_ref, 2), + doc = _ref2[0], + top = _ref2[1]; + + var collection = doc.getElementById(prefix$2 + "-collection"); + + if (!collection) { + collection = doc.createElementNS(SVG, "svg"); + collection.id = prefix$2 + "-collection"; + collection.style.display = "none"; + top.insertBefore(collection, top.firstChild); + } + + var sym = doc.createElementNS(SVG, "symbol"); + sym.id = name; + sym.setAttribute("viewBox", "0 0 " + data.width + " " + data.height); + var path = sym.appendChild(doc.createElementNS(SVG, "path")); + path.setAttribute("d", data.path); + collection.appendChild(sym); +} + +var prefix$1 = "ProseMirror-menu"; + +var MenuItem = function () { + function MenuItem(spec) { + _classCallCheck(this, MenuItem); + + this.spec = spec; + } + + _createClass(MenuItem, [{ + key: "render", + value: function render(view) { + var spec = this.spec; + var dom = spec.render ? spec.render(view) : spec.icon ? getIcon(view.root, spec.icon) : spec.label ? crel("div", null, translate(view, spec.label)) : null; + if (!dom) throw new RangeError("MenuItem without icon or label property"); + + if (spec.title) { + var title = typeof spec.title === "function" ? spec.title(view.state) : spec.title; + dom.setAttribute("title", translate(view, title)); + } + + if (spec["class"]) dom.classList.add(spec["class"]); + if (spec.css) dom.style.cssText += spec.css; + dom.addEventListener("mousedown", function (e) { + e.preventDefault(); + if (!dom.classList.contains(prefix$1 + "-disabled")) spec.run(view.state, view.dispatch, view, e); + }); + + function update(state) { + if (spec.select) { + var selected = spec.select(state); + dom.style.display = selected ? "" : "none"; + if (!selected) return false; + } + + var enabled = true; + + if (spec.enable) { + enabled = spec.enable(state) || false; + setClass(dom, prefix$1 + "-disabled", !enabled); + } + + if (spec.active) { + var active = enabled && spec.active(state) || false; + setClass(dom, prefix$1 + "-active", active); + } + + return true; + } + + return { + dom: dom, + update: update + }; + } + }]); + + return MenuItem; +}(); + +function translate(view, text) { + return view._props.translate ? view._props.translate(text) : text; +} + +var lastMenuEvent = { + time: 0, + node: null +}; + +function markMenuEvent(e) { + lastMenuEvent.time = Date.now(); + lastMenuEvent.node = e.target; +} + +function isMenuEvent(wrapper) { + return Date.now() - 100 < lastMenuEvent.time && lastMenuEvent.node && wrapper.contains(lastMenuEvent.node); +} + +var Dropdown = function () { + function Dropdown(content) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + _classCallCheck(this, Dropdown); + + this.options = options; + this.options = options || {}; + this.content = Array.isArray(content) ? content : [content]; + } + + _createClass(Dropdown, [{ + key: "render", + value: function render(view) { + var _this = this; + + var content = renderDropdownItems(this.content, view); + var win = view.dom.ownerDocument.defaultView || window; + var label = crel("div", { + "class": prefix$1 + "-dropdown " + (this.options["class"] || ""), + style: this.options.css + }, translate(view, this.options.label || "")); + if (this.options.title) label.setAttribute("title", translate(view, this.options.title)); + var wrap = crel("div", { + "class": prefix$1 + "-dropdown-wrap" + }, label); + var open = null; + var listeningOnClose = null; + + var close = function close() { + if (open && open.close()) { + open = null; + win.removeEventListener("mousedown", listeningOnClose); + } + }; + + label.addEventListener("mousedown", function (e) { + e.preventDefault(); + markMenuEvent(e); + + if (open) { + close(); + } else { + open = _this.expand(wrap, content.dom); + win.addEventListener("mousedown", listeningOnClose = function listeningOnClose() { + if (!isMenuEvent(wrap)) close(); + }); + } + }); + + function update(state) { + var inner = content.update(state); + wrap.style.display = inner ? "" : "none"; + return inner; + } + + return { + dom: wrap, + update: update + }; + } + }, { + key: "expand", + value: function expand(dom, items) { + var menuDOM = crel("div", { + "class": prefix$1 + "-dropdown-menu " + (this.options["class"] || "") + }, items); + var done = false; + + function close() { + if (done) return false; + done = true; + dom.removeChild(menuDOM); + return true; + } + + dom.appendChild(menuDOM); + return { + close: close, + node: menuDOM + }; + } + }]); + + return Dropdown; +}(); + +function renderDropdownItems(items, view) { + var rendered = [], + updates = []; + + for (var i = 0; i < items.length; i++) { + var _items$i$render = items[i].render(view), + dom = _items$i$render.dom, + update = _items$i$render.update; + + rendered.push(crel("div", { + "class": prefix$1 + "-dropdown-item" + }, dom)); + updates.push(update); + } + + return { + dom: rendered, + update: combineUpdates(updates, rendered) + }; +} + +function combineUpdates(updates, nodes) { + return function (state) { + var something = false; + + for (var i = 0; i < updates.length; i++) { + var up = updates[i](state); + nodes[i].style.display = up ? "" : "none"; + if (up) something = true; + } + + return something; + }; +} + +var DropdownSubmenu = function () { + function DropdownSubmenu(content) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + _classCallCheck(this, DropdownSubmenu); + + this.options = options; + this.content = Array.isArray(content) ? content : [content]; + } + + _createClass(DropdownSubmenu, [{ + key: "render", + value: function render(view) { + var items = renderDropdownItems(this.content, view); + var win = view.dom.ownerDocument.defaultView || window; + var label = crel("div", { + "class": prefix$1 + "-submenu-label" + }, translate(view, this.options.label || "")); + var wrap = crel("div", { + "class": prefix$1 + "-submenu-wrap" + }, label, crel("div", { + "class": prefix$1 + "-submenu" + }, items.dom)); + var _listeningOnClose = null; + label.addEventListener("mousedown", function (e) { + e.preventDefault(); + markMenuEvent(e); + setClass(wrap, prefix$1 + "-submenu-wrap-active", false); + if (!_listeningOnClose) win.addEventListener("mousedown", _listeningOnClose = function listeningOnClose() { + if (!isMenuEvent(wrap)) { + wrap.classList.remove(prefix$1 + "-submenu-wrap-active"); + win.removeEventListener("mousedown", _listeningOnClose); + _listeningOnClose = null; + } + }); + }); + + function update(state) { + var inner = items.update(state); + wrap.style.display = inner ? "" : "none"; + return inner; + } + + return { + dom: wrap, + update: update + }; + } + }]); + + return DropdownSubmenu; +}(); + +function renderGrouped(view, content) { + var result = document.createDocumentFragment(); + var updates = [], + separators = []; + + for (var i = 0; i < content.length; i++) { + var items = content[i], + localUpdates = [], + localNodes = []; + + for (var j = 0; j < items.length; j++) { + var _items$j$render = items[j].render(view), + dom = _items$j$render.dom, + _update = _items$j$render.update; + + var span = crel("span", { + "class": prefix$1 + "item" + }, dom); + result.appendChild(span); + localNodes.push(span); + localUpdates.push(_update); + } + + if (localUpdates.length) { + updates.push(combineUpdates(localUpdates, localNodes)); + if (i < content.length - 1) separators.push(result.appendChild(separator())); + } + } + + function update(state) { + var something = false, + needSep = false; + + for (var _i2 = 0; _i2 < updates.length; _i2++) { + var hasContent = updates[_i2](state); + + if (_i2) separators[_i2 - 1].style.display = needSep && hasContent ? "" : "none"; + needSep = hasContent; + if (hasContent) something = true; + } + + return something; + } + + return { + dom: result, + update: update + }; +} + +function separator() { + return crel("span", { + "class": prefix$1 + "separator" + }); +} + +var icons = { + join: { + width: 800, + height: 900, + path: "M0 75h800v125h-800z M0 825h800v-125h-800z M250 400h100v-100h100v100h100v100h-100v100h-100v-100h-100z" + }, + lift: { + width: 1024, + height: 1024, + path: "M219 310v329q0 7-5 12t-12 5q-8 0-13-5l-164-164q-5-5-5-13t5-13l164-164q5-5 13-5 7 0 12 5t5 12zM1024 749v109q0 7-5 12t-12 5h-987q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h987q7 0 12 5t5 12zM1024 530v109q0 7-5 12t-12 5h-621q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h621q7 0 12 5t5 12zM1024 310v109q0 7-5 12t-12 5h-621q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h621q7 0 12 5t5 12zM1024 91v109q0 7-5 12t-12 5h-987q-7 0-12-5t-5-12v-109q0-7 5-12t12-5h987q7 0 12 5t5 12z" + }, + selectParentNode: { + text: "\u2B1A", + css: "font-weight: bold" + }, + undo: { + width: 1024, + height: 1024, + path: "M761 1024c113-206 132-520-313-509v253l-384-384 384-384v248c534-13 594 472 313 775z" + }, + redo: { + width: 1024, + height: 1024, + path: "M576 248v-248l384 384-384 384v-253c-446-10-427 303-313 509-280-303-221-789 313-775z" + }, + strong: { + width: 805, + height: 1024, + path: "M317 869q42 18 80 18 214 0 214-191 0-65-23-102-15-25-35-42t-38-26-46-14-48-6-54-1q-41 0-57 5 0 30-0 90t-0 90q0 4-0 38t-0 55 2 47 6 38zM309 442q24 4 62 4 46 0 81-7t62-25 42-51 14-81q0-40-16-70t-45-46-61-24-70-8q-28 0-74 7 0 28 2 86t2 86q0 15-0 45t-0 45q0 26 0 39zM0 950l1-53q8-2 48-9t60-15q4-6 7-15t4-19 3-18 1-21 0-19v-37q0-561-12-585-2-4-12-8t-25-6-28-4-27-2-17-1l-2-47q56-1 194-6t213-5q13 0 39 0t38 0q40 0 78 7t73 24 61 40 42 59 16 78q0 29-9 54t-22 41-36 32-41 25-48 22q88 20 146 76t58 141q0 57-20 102t-53 74-78 48-93 27-100 8q-25 0-75-1t-75-1q-60 0-175 6t-132 6z" + }, + em: { + width: 585, + height: 1024, + path: "M0 949l9-48q3-1 46-12t63-21q16-20 23-57 0-4 35-165t65-310 29-169v-14q-13-7-31-10t-39-4-33-3l10-58q18 1 68 3t85 4 68 1q27 0 56-1t69-4 56-3q-2 22-10 50-17 5-58 16t-62 19q-4 10-8 24t-5 22-4 26-3 24q-15 84-50 239t-44 203q-1 5-7 33t-11 51-9 47-3 32l0 10q9 2 105 17-1 25-9 56-6 0-18 0t-18 0q-16 0-49-5t-49-5q-78-1-117-1-29 0-81 5t-69 6z" + }, + code: { + width: 896, + height: 1024, + path: "M608 192l-96 96 224 224-224 224 96 96 288-320-288-320zM288 192l-288 320 288 320 96-96-224-224 224-224-96-96z" + }, + link: { + width: 951, + height: 1024, + path: "M832 694q0-22-16-38l-118-118q-16-16-38-16-24 0-41 18 1 1 10 10t12 12 8 10 7 14 2 15q0 22-16 38t-38 16q-8 0-15-2t-14-7-10-8-12-12-10-10q-18 17-18 41 0 22 16 38l117 118q15 15 38 15 22 0 38-14l84-83q16-16 16-38zM430 292q0-22-16-38l-117-118q-16-16-38-16-22 0-38 15l-84 83q-16 16-16 38 0 22 16 38l118 118q15 15 38 15 24 0 41-17-1-1-10-10t-12-12-8-10-7-14-2-15q0-22 16-38t38-16q8 0 15 2t14 7 10 8 12 12 10 10q18-17 18-41zM941 694q0 68-48 116l-84 83q-47 47-116 47-69 0-116-48l-117-118q-47-47-47-116 0-70 50-119l-50-50q-49 50-118 50-68 0-116-48l-118-118q-48-48-48-116t48-116l84-83q47-47 116-47 69 0 116 48l117 118q47 47 47 116 0 70-50 119l50 50q49-50 118-50 68 0 116 48l118 118q48 48 48 116z" + }, + bulletList: { + width: 768, + height: 896, + path: "M0 512h128v-128h-128v128zM0 256h128v-128h-128v128zM0 768h128v-128h-128v128zM256 512h512v-128h-512v128zM256 256h512v-128h-512v128zM256 768h512v-128h-512v128z" + }, + orderedList: { + width: 768, + height: 896, + path: "M320 512h448v-128h-448v128zM320 768h448v-128h-448v128zM320 128v128h448v-128h-448zM79 384h78v-256h-36l-85 23v50l43-2v185zM189 590c0-36-12-78-96-78-33 0-64 6-83 16l1 66c21-10 42-15 67-15s32 11 32 28c0 26-30 58-110 112v50h192v-67l-91 2c49-30 87-66 87-113l1-1z" + }, + blockquote: { + width: 640, + height: 896, + path: "M0 448v256h256v-256h-128c0 0 0-128 128-128v-128c0 0-256 0-256 256zM640 320v-128c0 0-256 0-256 256v256h256v-256h-128c0 0 0-128 128-128z" + } +}; +var joinUpItem = new MenuItem({ + title: "Join with above block", + run: prosemirrorCommands.joinUp, + select: function select(state) { + return prosemirrorCommands.joinUp(state); + }, + icon: icons.join +}); +var liftItem = new MenuItem({ + title: "Lift out of enclosing block", + run: prosemirrorCommands.lift, + select: function select(state) { + return prosemirrorCommands.lift(state); + }, + icon: icons.lift +}); +var selectParentNodeItem = new MenuItem({ + title: "Select parent node", + run: prosemirrorCommands.selectParentNode, + select: function select(state) { + return prosemirrorCommands.selectParentNode(state); + }, + icon: icons.selectParentNode +}); +var undoItem = new MenuItem({ + title: "Undo last change", + run: prosemirrorHistory.undo, + enable: function enable(state) { + return prosemirrorHistory.undo(state); + }, + icon: icons.undo +}); +var redoItem = new MenuItem({ + title: "Redo last undone change", + run: prosemirrorHistory.redo, + enable: function enable(state) { + return prosemirrorHistory.redo(state); + }, + icon: icons.redo +}); + +function wrapItem(nodeType, options) { + var passedOptions = { + run: function run(state, dispatch) { + return prosemirrorCommands.wrapIn(nodeType, options.attrs)(state, dispatch); + }, + select: function select(state) { + return prosemirrorCommands.wrapIn(nodeType, options.attrs)(state); + } + }; + + for (var prop in options) { + passedOptions[prop] = options[prop]; + } + + return new MenuItem(passedOptions); +} + +function blockTypeItem(nodeType, options) { + var command = prosemirrorCommands.setBlockType(nodeType, options.attrs); + var passedOptions = { + run: command, + enable: function enable(state) { + return command(state); + }, + active: function active(state) { + var _state$selection = state.selection, + $from = _state$selection.$from, + to = _state$selection.to, + node = _state$selection.node; + if (node) return node.hasMarkup(nodeType, options.attrs); + return to <= $from.end() && $from.parent.hasMarkup(nodeType, options.attrs); + } + }; + + for (var prop in options) { + passedOptions[prop] = options[prop]; + } + + return new MenuItem(passedOptions); +} + +function setClass(dom, cls, on) { + if (on) dom.classList.add(cls);else dom.classList.remove(cls); +} + +var prefix = "ProseMirror-menubar"; + +function isIOS() { + if (typeof navigator == "undefined") return false; + var agent = navigator.userAgent; + return !/Edge\/\d/.test(agent) && /AppleWebKit/.test(agent) && /Mobile\/\w+/.test(agent); +} + +function menuBar(options) { + return new prosemirrorState.Plugin({ + view: function view(editorView) { + return new MenuBarView(editorView, options); + } + }); +} + +var MenuBarView = function () { + function MenuBarView(editorView, options) { + var _this2 = this; + + _classCallCheck(this, MenuBarView); + + this.editorView = editorView; + this.options = options; + this.spacer = null; + this.maxHeight = 0; + this.widthForMaxHeight = 0; + this.floating = false; + this.scrollHandler = null; + this.wrapper = crel("div", { + "class": prefix + "-wrapper" + }); + this.menu = this.wrapper.appendChild(crel("div", { + "class": prefix + })); + this.menu.className = prefix; + if (editorView.dom.parentNode) editorView.dom.parentNode.replaceChild(this.wrapper, editorView.dom); + this.wrapper.appendChild(editorView.dom); + + var _renderGrouped = renderGrouped(this.editorView, this.options.content), + dom = _renderGrouped.dom, + update = _renderGrouped.update; + + this.contentUpdate = update; + this.menu.appendChild(dom); + this.update(); + + if (options.floating && !isIOS()) { + this.updateFloat(); + var potentialScrollers = getAllWrapping(this.wrapper); + + this.scrollHandler = function (e) { + var root = _this2.editorView.root; + if (!(root.body || root).contains(_this2.wrapper)) potentialScrollers.forEach(function (el) { + return el.removeEventListener("scroll", _this2.scrollHandler); + });else _this2.updateFloat(e.target.getBoundingClientRect ? e.target : undefined); + }; + + potentialScrollers.forEach(function (el) { + return el.addEventListener('scroll', _this2.scrollHandler); + }); + } + } + + _createClass(MenuBarView, [{ + key: "update", + value: function update() { + this.contentUpdate(this.editorView.state); + + if (this.floating) { + this.updateScrollCursor(); + } else { + if (this.menu.offsetWidth != this.widthForMaxHeight) { + this.widthForMaxHeight = this.menu.offsetWidth; + this.maxHeight = 0; + } + + if (this.menu.offsetHeight > this.maxHeight) { + this.maxHeight = this.menu.offsetHeight; + this.menu.style.minHeight = this.maxHeight + "px"; + } + } + } + }, { + key: "updateScrollCursor", + value: function updateScrollCursor() { + var selection = this.editorView.root.getSelection(); + if (!selection.focusNode) return; + var rects = selection.getRangeAt(0).getClientRects(); + var selRect = rects[selectionIsInverted(selection) ? 0 : rects.length - 1]; + if (!selRect) return; + var menuRect = this.menu.getBoundingClientRect(); + + if (selRect.top < menuRect.bottom && selRect.bottom > menuRect.top) { + var scrollable = findWrappingScrollable(this.wrapper); + if (scrollable) scrollable.scrollTop -= menuRect.bottom - selRect.top; + } + } + }, { + key: "updateFloat", + value: function updateFloat(scrollAncestor) { + var parent = this.wrapper, + editorRect = parent.getBoundingClientRect(), + top = scrollAncestor ? Math.max(0, scrollAncestor.getBoundingClientRect().top) : 0; + + if (this.floating) { + if (editorRect.top >= top || editorRect.bottom < this.menu.offsetHeight + 10) { + this.floating = false; + this.menu.style.position = this.menu.style.left = this.menu.style.top = this.menu.style.width = ""; + this.menu.style.display = ""; + this.spacer.parentNode.removeChild(this.spacer); + this.spacer = null; + } else { + var border = (parent.offsetWidth - parent.clientWidth) / 2; + this.menu.style.left = editorRect.left + border + "px"; + this.menu.style.display = editorRect.top > (this.editorView.dom.ownerDocument.defaultView || window).innerHeight ? "none" : ""; + if (scrollAncestor) this.menu.style.top = top + "px"; + } + } else { + if (editorRect.top < top && editorRect.bottom >= this.menu.offsetHeight + 10) { + this.floating = true; + var menuRect = this.menu.getBoundingClientRect(); + this.menu.style.left = menuRect.left + "px"; + this.menu.style.width = menuRect.width + "px"; + if (scrollAncestor) this.menu.style.top = top + "px"; + this.menu.style.position = "fixed"; + this.spacer = crel("div", { + "class": prefix + "-spacer", + style: "height: ".concat(menuRect.height, "px") + }); + parent.insertBefore(this.spacer, this.menu); + } + } + } + }, { + key: "destroy", + value: function destroy() { + if (this.wrapper.parentNode) this.wrapper.parentNode.replaceChild(this.editorView.dom, this.wrapper); + } + }]); + + return MenuBarView; +}(); + +function selectionIsInverted(selection) { + if (selection.anchorNode == selection.focusNode) return selection.anchorOffset > selection.focusOffset; + return selection.anchorNode.compareDocumentPosition(selection.focusNode) == Node.DOCUMENT_POSITION_FOLLOWING; +} + +function findWrappingScrollable(node) { + for (var cur = node.parentNode; cur; cur = cur.parentNode) { + if (cur.scrollHeight > cur.clientHeight) return cur; + } +} + +function getAllWrapping(node) { + var res = [node.ownerDocument.defaultView || window]; + + for (var cur = node.parentNode; cur; cur = cur.parentNode) { + res.push(cur); + } + + return res; +} + +exports.Dropdown = Dropdown; +exports.DropdownSubmenu = DropdownSubmenu; +exports.MenuItem = MenuItem; +exports.blockTypeItem = blockTypeItem; +exports.icons = icons; +exports.joinUpItem = joinUpItem; +exports.liftItem = liftItem; +exports.menuBar = menuBar; +exports.redoItem = redoItem; +exports.renderGrouped = renderGrouped; +exports.selectParentNodeItem = selectParentNodeItem; +exports.undoItem = undoItem; +exports.wrapItem = wrapItem; diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-transform.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-transform.cjs new file mode 100644 index 000000000..97dff305d --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-transform.cjs @@ -0,0 +1,1858 @@ +'use strict'; + +function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); } +function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct.bind(); } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } +function _isNativeFunction(fn) { try { return Function.toString.call(fn).indexOf("[native code]") !== -1; } catch (e) { return typeof fn === "function"; } } +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } +function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } +function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var prosemirrorModel = require('prosemirror-model'); +var lower16 = 0xffff; +var factor16 = Math.pow(2, 16); +function makeRecover(index, offset) { + return index + offset * factor16; +} +function recoverIndex(value) { + return value & lower16; +} +function recoverOffset(value) { + return (value - (value & lower16)) / factor16; +} +var DEL_BEFORE = 1, + DEL_AFTER = 2, + DEL_ACROSS = 4, + DEL_SIDE = 8; +var MapResult = function () { + function MapResult(pos, delInfo, recover) { + _classCallCheck(this, MapResult); + this.pos = pos; + this.delInfo = delInfo; + this.recover = recover; + } + _createClass(MapResult, [{ + key: "deleted", + get: function get() { + return (this.delInfo & DEL_SIDE) > 0; + } + }, { + key: "deletedBefore", + get: function get() { + return (this.delInfo & (DEL_BEFORE | DEL_ACROSS)) > 0; + } + }, { + key: "deletedAfter", + get: function get() { + return (this.delInfo & (DEL_AFTER | DEL_ACROSS)) > 0; + } + }, { + key: "deletedAcross", + get: function get() { + return (this.delInfo & DEL_ACROSS) > 0; + } + }]); + return MapResult; +}(); +var StepMap = function () { + function StepMap(ranges) { + var inverted = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + _classCallCheck(this, StepMap); + this.ranges = ranges; + this.inverted = inverted; + if (!ranges.length && StepMap.empty) return StepMap.empty; + } + _createClass(StepMap, [{ + key: "recover", + value: function recover(value) { + var diff = 0, + index = recoverIndex(value); + if (!this.inverted) for (var i = 0; i < index; i++) diff += this.ranges[i * 3 + 2] - this.ranges[i * 3 + 1]; + return this.ranges[index * 3] + diff + recoverOffset(value); + } + }, { + key: "mapResult", + value: function mapResult(pos) { + var assoc = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + return this._map(pos, assoc, false); + } + }, { + key: "map", + value: function map(pos) { + var assoc = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + return this._map(pos, assoc, true); + } + }, { + key: "_map", + value: function _map(pos, assoc, simple) { + var diff = 0, + oldIndex = this.inverted ? 2 : 1, + newIndex = this.inverted ? 1 : 2; + for (var i = 0; i < this.ranges.length; i += 3) { + var start = this.ranges[i] - (this.inverted ? diff : 0); + if (start > pos) break; + var oldSize = this.ranges[i + oldIndex], + newSize = this.ranges[i + newIndex], + end = start + oldSize; + if (pos <= end) { + var side = !oldSize ? assoc : pos == start ? -1 : pos == end ? 1 : assoc; + var result = start + diff + (side < 0 ? 0 : newSize); + if (simple) return result; + var recover = pos == (assoc < 0 ? start : end) ? null : makeRecover(i / 3, pos - start); + var del = pos == start ? DEL_AFTER : pos == end ? DEL_BEFORE : DEL_ACROSS; + if (assoc < 0 ? pos != start : pos != end) del |= DEL_SIDE; + return new MapResult(result, del, recover); + } + diff += newSize - oldSize; + } + return simple ? pos + diff : new MapResult(pos + diff, 0, null); + } + }, { + key: "touches", + value: function touches(pos, recover) { + var diff = 0, + index = recoverIndex(recover); + var oldIndex = this.inverted ? 2 : 1, + newIndex = this.inverted ? 1 : 2; + for (var i = 0; i < this.ranges.length; i += 3) { + var start = this.ranges[i] - (this.inverted ? diff : 0); + if (start > pos) break; + var oldSize = this.ranges[i + oldIndex], + end = start + oldSize; + if (pos <= end && i == index * 3) return true; + diff += this.ranges[i + newIndex] - oldSize; + } + return false; + } + }, { + key: "forEach", + value: function forEach(f) { + var oldIndex = this.inverted ? 2 : 1, + newIndex = this.inverted ? 1 : 2; + for (var i = 0, diff = 0; i < this.ranges.length; i += 3) { + var start = this.ranges[i], + oldStart = start - (this.inverted ? diff : 0), + newStart = start + (this.inverted ? 0 : diff); + var oldSize = this.ranges[i + oldIndex], + newSize = this.ranges[i + newIndex]; + f(oldStart, oldStart + oldSize, newStart, newStart + newSize); + diff += newSize - oldSize; + } + } + }, { + key: "invert", + value: function invert() { + return new StepMap(this.ranges, !this.inverted); + } + }, { + key: "toString", + value: function toString() { + return (this.inverted ? "-" : "") + JSON.stringify(this.ranges); + } + }], [{ + key: "offset", + value: function offset(n) { + return n == 0 ? StepMap.empty : new StepMap(n < 0 ? [0, -n, 0] : [0, 0, n]); + } + }]); + return StepMap; +}(); +StepMap.empty = new StepMap([]); +var Mapping = function () { + function Mapping(maps, mirror) { + var from = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var to = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : maps ? maps.length : 0; + _classCallCheck(this, Mapping); + this.mirror = mirror; + this.from = from; + this.to = to; + this._maps = maps || []; + this.ownData = !(maps || mirror); + } + _createClass(Mapping, [{ + key: "maps", + get: function get() { + return this._maps; + } + }, { + key: "slice", + value: function slice() { + var from = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var to = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.maps.length; + return new Mapping(this._maps, this.mirror, from, to); + } + }, { + key: "appendMap", + value: function appendMap(map, mirrors) { + if (!this.ownData) { + this._maps = this._maps.slice(); + this.mirror = this.mirror && this.mirror.slice(); + this.ownData = true; + } + this.to = this._maps.push(map); + if (mirrors != null) this.setMirror(this._maps.length - 1, mirrors); + } + }, { + key: "appendMapping", + value: function appendMapping(mapping) { + for (var i = 0, startSize = this._maps.length; i < mapping._maps.length; i++) { + var mirr = mapping.getMirror(i); + this.appendMap(mapping._maps[i], mirr != null && mirr < i ? startSize + mirr : undefined); + } + } + }, { + key: "getMirror", + value: function getMirror(n) { + if (this.mirror) for (var i = 0; i < this.mirror.length; i++) if (this.mirror[i] == n) return this.mirror[i + (i % 2 ? -1 : 1)]; + } + }, { + key: "setMirror", + value: function setMirror(n, m) { + if (!this.mirror) this.mirror = []; + this.mirror.push(n, m); + } + }, { + key: "appendMappingInverted", + value: function appendMappingInverted(mapping) { + for (var i = mapping.maps.length - 1, totalSize = this._maps.length + mapping._maps.length; i >= 0; i--) { + var mirr = mapping.getMirror(i); + this.appendMap(mapping._maps[i].invert(), mirr != null && mirr > i ? totalSize - mirr - 1 : undefined); + } + } + }, { + key: "invert", + value: function invert() { + var inverse = new Mapping(); + inverse.appendMappingInverted(this); + return inverse; + } + }, { + key: "map", + value: function map(pos) { + var assoc = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + if (this.mirror) return this._map(pos, assoc, true); + for (var i = this.from; i < this.to; i++) pos = this._maps[i].map(pos, assoc); + return pos; + } + }, { + key: "mapResult", + value: function mapResult(pos) { + var assoc = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + return this._map(pos, assoc, false); + } + }, { + key: "_map", + value: function _map(pos, assoc, simple) { + var delInfo = 0; + for (var i = this.from; i < this.to; i++) { + var map = this._maps[i], + result = map.mapResult(pos, assoc); + if (result.recover != null) { + var corr = this.getMirror(i); + if (corr != null && corr > i && corr < this.to) { + i = corr; + pos = this._maps[corr].recover(result.recover); + continue; + } + } + delInfo |= result.delInfo; + pos = result.pos; + } + return simple ? pos : new MapResult(pos, delInfo, null); + } + }]); + return Mapping; +}(); +var stepsByID = Object.create(null); +var Step = function () { + function Step() { + _classCallCheck(this, Step); + } + _createClass(Step, [{ + key: "getMap", + value: function getMap() { + return StepMap.empty; + } + }, { + key: "merge", + value: function merge(other) { + return null; + } + }], [{ + key: "fromJSON", + value: function fromJSON(schema, json) { + if (!json || !json.stepType) throw new RangeError("Invalid input for Step.fromJSON"); + var type = stepsByID[json.stepType]; + if (!type) throw new RangeError("No step type ".concat(json.stepType, " defined")); + return type.fromJSON(schema, json); + } + }, { + key: "jsonID", + value: function jsonID(id, stepClass) { + if (id in stepsByID) throw new RangeError("Duplicate use of step JSON ID " + id); + stepsByID[id] = stepClass; + stepClass.prototype.jsonID = id; + return stepClass; + } + }]); + return Step; +}(); +var StepResult = function () { + function StepResult(doc, failed) { + _classCallCheck(this, StepResult); + this.doc = doc; + this.failed = failed; + } + _createClass(StepResult, null, [{ + key: "ok", + value: function ok(doc) { + return new StepResult(doc, null); + } + }, { + key: "fail", + value: function fail(message) { + return new StepResult(null, message); + } + }, { + key: "fromReplace", + value: function fromReplace(doc, from, to, slice) { + try { + return StepResult.ok(doc.replace(from, to, slice)); + } catch (e) { + if (e instanceof prosemirrorModel.ReplaceError) return StepResult.fail(e.message); + throw e; + } + } + }]); + return StepResult; +}(); +function mapFragment(fragment, f, parent) { + var mapped = []; + for (var i = 0; i < fragment.childCount; i++) { + var child = fragment.child(i); + if (child.content.size) child = child.copy(mapFragment(child.content, f, child)); + if (child.isInline) child = f(child, parent, i); + mapped.push(child); + } + return prosemirrorModel.Fragment.fromArray(mapped); +} +var AddMarkStep = function (_Step) { + _inherits(AddMarkStep, _Step); + var _super = _createSuper(AddMarkStep); + function AddMarkStep(from, to, mark) { + var _this; + _classCallCheck(this, AddMarkStep); + _this = _super.call(this); + _this.from = from; + _this.to = to; + _this.mark = mark; + return _this; + } + _createClass(AddMarkStep, [{ + key: "apply", + value: function apply(doc) { + var _this2 = this; + var oldSlice = doc.slice(this.from, this.to), + $from = doc.resolve(this.from); + var parent = $from.node($from.sharedDepth(this.to)); + var slice = new prosemirrorModel.Slice(mapFragment(oldSlice.content, function (node, parent) { + if (!node.isAtom || !parent.type.allowsMarkType(_this2.mark.type)) return node; + return node.mark(_this2.mark.addToSet(node.marks)); + }, parent), oldSlice.openStart, oldSlice.openEnd); + return StepResult.fromReplace(doc, this.from, this.to, slice); + } + }, { + key: "invert", + value: function invert() { + return new RemoveMarkStep(this.from, this.to, this.mark); + } + }, { + key: "map", + value: function map(mapping) { + var from = mapping.mapResult(this.from, 1), + to = mapping.mapResult(this.to, -1); + if (from.deleted && to.deleted || from.pos >= to.pos) return null; + return new AddMarkStep(from.pos, to.pos, this.mark); + } + }, { + key: "merge", + value: function merge(other) { + if (other instanceof AddMarkStep && other.mark.eq(this.mark) && this.from <= other.to && this.to >= other.from) return new AddMarkStep(Math.min(this.from, other.from), Math.max(this.to, other.to), this.mark); + return null; + } + }, { + key: "toJSON", + value: function toJSON() { + return { + stepType: "addMark", + mark: this.mark.toJSON(), + from: this.from, + to: this.to + }; + } + }], [{ + key: "fromJSON", + value: function fromJSON(schema, json) { + if (typeof json.from != "number" || typeof json.to != "number") throw new RangeError("Invalid input for AddMarkStep.fromJSON"); + return new AddMarkStep(json.from, json.to, schema.markFromJSON(json.mark)); + } + }]); + return AddMarkStep; +}(Step); +Step.jsonID("addMark", AddMarkStep); +var RemoveMarkStep = function (_Step2) { + _inherits(RemoveMarkStep, _Step2); + var _super2 = _createSuper(RemoveMarkStep); + function RemoveMarkStep(from, to, mark) { + var _this3; + _classCallCheck(this, RemoveMarkStep); + _this3 = _super2.call(this); + _this3.from = from; + _this3.to = to; + _this3.mark = mark; + return _this3; + } + _createClass(RemoveMarkStep, [{ + key: "apply", + value: function apply(doc) { + var _this4 = this; + var oldSlice = doc.slice(this.from, this.to); + var slice = new prosemirrorModel.Slice(mapFragment(oldSlice.content, function (node) { + return node.mark(_this4.mark.removeFromSet(node.marks)); + }, doc), oldSlice.openStart, oldSlice.openEnd); + return StepResult.fromReplace(doc, this.from, this.to, slice); + } + }, { + key: "invert", + value: function invert() { + return new AddMarkStep(this.from, this.to, this.mark); + } + }, { + key: "map", + value: function map(mapping) { + var from = mapping.mapResult(this.from, 1), + to = mapping.mapResult(this.to, -1); + if (from.deleted && to.deleted || from.pos >= to.pos) return null; + return new RemoveMarkStep(from.pos, to.pos, this.mark); + } + }, { + key: "merge", + value: function merge(other) { + if (other instanceof RemoveMarkStep && other.mark.eq(this.mark) && this.from <= other.to && this.to >= other.from) return new RemoveMarkStep(Math.min(this.from, other.from), Math.max(this.to, other.to), this.mark); + return null; + } + }, { + key: "toJSON", + value: function toJSON() { + return { + stepType: "removeMark", + mark: this.mark.toJSON(), + from: this.from, + to: this.to + }; + } + }], [{ + key: "fromJSON", + value: function fromJSON(schema, json) { + if (typeof json.from != "number" || typeof json.to != "number") throw new RangeError("Invalid input for RemoveMarkStep.fromJSON"); + return new RemoveMarkStep(json.from, json.to, schema.markFromJSON(json.mark)); + } + }]); + return RemoveMarkStep; +}(Step); +Step.jsonID("removeMark", RemoveMarkStep); +var AddNodeMarkStep = function (_Step3) { + _inherits(AddNodeMarkStep, _Step3); + var _super3 = _createSuper(AddNodeMarkStep); + function AddNodeMarkStep(pos, mark) { + var _this5; + _classCallCheck(this, AddNodeMarkStep); + _this5 = _super3.call(this); + _this5.pos = pos; + _this5.mark = mark; + return _this5; + } + _createClass(AddNodeMarkStep, [{ + key: "apply", + value: function apply(doc) { + var node = doc.nodeAt(this.pos); + if (!node) return StepResult.fail("No node at mark step's position"); + var updated = node.type.create(node.attrs, null, this.mark.addToSet(node.marks)); + return StepResult.fromReplace(doc, this.pos, this.pos + 1, new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(updated), 0, node.isLeaf ? 0 : 1)); + } + }, { + key: "invert", + value: function invert(doc) { + var node = doc.nodeAt(this.pos); + if (node) { + var newSet = this.mark.addToSet(node.marks); + if (newSet.length == node.marks.length) { + for (var i = 0; i < node.marks.length; i++) if (!node.marks[i].isInSet(newSet)) return new AddNodeMarkStep(this.pos, node.marks[i]); + return new AddNodeMarkStep(this.pos, this.mark); + } + } + return new RemoveNodeMarkStep(this.pos, this.mark); + } + }, { + key: "map", + value: function map(mapping) { + var pos = mapping.mapResult(this.pos, 1); + return pos.deletedAfter ? null : new AddNodeMarkStep(pos.pos, this.mark); + } + }, { + key: "toJSON", + value: function toJSON() { + return { + stepType: "addNodeMark", + pos: this.pos, + mark: this.mark.toJSON() + }; + } + }], [{ + key: "fromJSON", + value: function fromJSON(schema, json) { + if (typeof json.pos != "number") throw new RangeError("Invalid input for AddNodeMarkStep.fromJSON"); + return new AddNodeMarkStep(json.pos, schema.markFromJSON(json.mark)); + } + }]); + return AddNodeMarkStep; +}(Step); +Step.jsonID("addNodeMark", AddNodeMarkStep); +var RemoveNodeMarkStep = function (_Step4) { + _inherits(RemoveNodeMarkStep, _Step4); + var _super4 = _createSuper(RemoveNodeMarkStep); + function RemoveNodeMarkStep(pos, mark) { + var _this6; + _classCallCheck(this, RemoveNodeMarkStep); + _this6 = _super4.call(this); + _this6.pos = pos; + _this6.mark = mark; + return _this6; + } + _createClass(RemoveNodeMarkStep, [{ + key: "apply", + value: function apply(doc) { + var node = doc.nodeAt(this.pos); + if (!node) return StepResult.fail("No node at mark step's position"); + var updated = node.type.create(node.attrs, null, this.mark.removeFromSet(node.marks)); + return StepResult.fromReplace(doc, this.pos, this.pos + 1, new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(updated), 0, node.isLeaf ? 0 : 1)); + } + }, { + key: "invert", + value: function invert(doc) { + var node = doc.nodeAt(this.pos); + if (!node || !this.mark.isInSet(node.marks)) return this; + return new AddNodeMarkStep(this.pos, this.mark); + } + }, { + key: "map", + value: function map(mapping) { + var pos = mapping.mapResult(this.pos, 1); + return pos.deletedAfter ? null : new RemoveNodeMarkStep(pos.pos, this.mark); + } + }, { + key: "toJSON", + value: function toJSON() { + return { + stepType: "removeNodeMark", + pos: this.pos, + mark: this.mark.toJSON() + }; + } + }], [{ + key: "fromJSON", + value: function fromJSON(schema, json) { + if (typeof json.pos != "number") throw new RangeError("Invalid input for RemoveNodeMarkStep.fromJSON"); + return new RemoveNodeMarkStep(json.pos, schema.markFromJSON(json.mark)); + } + }]); + return RemoveNodeMarkStep; +}(Step); +Step.jsonID("removeNodeMark", RemoveNodeMarkStep); +var ReplaceStep = function (_Step5) { + _inherits(ReplaceStep, _Step5); + var _super5 = _createSuper(ReplaceStep); + function ReplaceStep(from, to, slice) { + var _this7; + var structure = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + _classCallCheck(this, ReplaceStep); + _this7 = _super5.call(this); + _this7.from = from; + _this7.to = to; + _this7.slice = slice; + _this7.structure = structure; + return _this7; + } + _createClass(ReplaceStep, [{ + key: "apply", + value: function apply(doc) { + if (this.structure && contentBetween(doc, this.from, this.to)) return StepResult.fail("Structure replace would overwrite content"); + return StepResult.fromReplace(doc, this.from, this.to, this.slice); + } + }, { + key: "getMap", + value: function getMap() { + return new StepMap([this.from, this.to - this.from, this.slice.size]); + } + }, { + key: "invert", + value: function invert(doc) { + return new ReplaceStep(this.from, this.from + this.slice.size, doc.slice(this.from, this.to)); + } + }, { + key: "map", + value: function map(mapping) { + var from = mapping.mapResult(this.from, 1), + to = mapping.mapResult(this.to, -1); + if (from.deletedAcross && to.deletedAcross) return null; + return new ReplaceStep(from.pos, Math.max(from.pos, to.pos), this.slice); + } + }, { + key: "merge", + value: function merge(other) { + if (!(other instanceof ReplaceStep) || other.structure || this.structure) return null; + if (this.from + this.slice.size == other.from && !this.slice.openEnd && !other.slice.openStart) { + var slice = this.slice.size + other.slice.size == 0 ? prosemirrorModel.Slice.empty : new prosemirrorModel.Slice(this.slice.content.append(other.slice.content), this.slice.openStart, other.slice.openEnd); + return new ReplaceStep(this.from, this.to + (other.to - other.from), slice, this.structure); + } else if (other.to == this.from && !this.slice.openStart && !other.slice.openEnd) { + var _slice = this.slice.size + other.slice.size == 0 ? prosemirrorModel.Slice.empty : new prosemirrorModel.Slice(other.slice.content.append(this.slice.content), other.slice.openStart, this.slice.openEnd); + return new ReplaceStep(other.from, this.to, _slice, this.structure); + } else { + return null; + } + } + }, { + key: "toJSON", + value: function toJSON() { + var json = { + stepType: "replace", + from: this.from, + to: this.to + }; + if (this.slice.size) json.slice = this.slice.toJSON(); + if (this.structure) json.structure = true; + return json; + } + }], [{ + key: "fromJSON", + value: function fromJSON(schema, json) { + if (typeof json.from != "number" || typeof json.to != "number") throw new RangeError("Invalid input for ReplaceStep.fromJSON"); + return new ReplaceStep(json.from, json.to, prosemirrorModel.Slice.fromJSON(schema, json.slice), !!json.structure); + } + }]); + return ReplaceStep; +}(Step); +Step.jsonID("replace", ReplaceStep); +var ReplaceAroundStep = function (_Step6) { + _inherits(ReplaceAroundStep, _Step6); + var _super6 = _createSuper(ReplaceAroundStep); + function ReplaceAroundStep(from, to, gapFrom, gapTo, slice, insert) { + var _this8; + var structure = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false; + _classCallCheck(this, ReplaceAroundStep); + _this8 = _super6.call(this); + _this8.from = from; + _this8.to = to; + _this8.gapFrom = gapFrom; + _this8.gapTo = gapTo; + _this8.slice = slice; + _this8.insert = insert; + _this8.structure = structure; + return _this8; + } + _createClass(ReplaceAroundStep, [{ + key: "apply", + value: function apply(doc) { + if (this.structure && (contentBetween(doc, this.from, this.gapFrom) || contentBetween(doc, this.gapTo, this.to))) return StepResult.fail("Structure gap-replace would overwrite content"); + var gap = doc.slice(this.gapFrom, this.gapTo); + if (gap.openStart || gap.openEnd) return StepResult.fail("Gap is not a flat range"); + var inserted = this.slice.insertAt(this.insert, gap.content); + if (!inserted) return StepResult.fail("Content does not fit in gap"); + return StepResult.fromReplace(doc, this.from, this.to, inserted); + } + }, { + key: "getMap", + value: function getMap() { + return new StepMap([this.from, this.gapFrom - this.from, this.insert, this.gapTo, this.to - this.gapTo, this.slice.size - this.insert]); + } + }, { + key: "invert", + value: function invert(doc) { + var gap = this.gapTo - this.gapFrom; + return new ReplaceAroundStep(this.from, this.from + this.slice.size + gap, this.from + this.insert, this.from + this.insert + gap, doc.slice(this.from, this.to).removeBetween(this.gapFrom - this.from, this.gapTo - this.from), this.gapFrom - this.from, this.structure); + } + }, { + key: "map", + value: function map(mapping) { + var from = mapping.mapResult(this.from, 1), + to = mapping.mapResult(this.to, -1); + var gapFrom = this.from == this.gapFrom ? from.pos : mapping.map(this.gapFrom, -1); + var gapTo = this.to == this.gapTo ? to.pos : mapping.map(this.gapTo, 1); + if (from.deletedAcross && to.deletedAcross || gapFrom < from.pos || gapTo > to.pos) return null; + return new ReplaceAroundStep(from.pos, to.pos, gapFrom, gapTo, this.slice, this.insert, this.structure); + } + }, { + key: "toJSON", + value: function toJSON() { + var json = { + stepType: "replaceAround", + from: this.from, + to: this.to, + gapFrom: this.gapFrom, + gapTo: this.gapTo, + insert: this.insert + }; + if (this.slice.size) json.slice = this.slice.toJSON(); + if (this.structure) json.structure = true; + return json; + } + }], [{ + key: "fromJSON", + value: function fromJSON(schema, json) { + if (typeof json.from != "number" || typeof json.to != "number" || typeof json.gapFrom != "number" || typeof json.gapTo != "number" || typeof json.insert != "number") throw new RangeError("Invalid input for ReplaceAroundStep.fromJSON"); + return new ReplaceAroundStep(json.from, json.to, json.gapFrom, json.gapTo, prosemirrorModel.Slice.fromJSON(schema, json.slice), json.insert, !!json.structure); + } + }]); + return ReplaceAroundStep; +}(Step); +Step.jsonID("replaceAround", ReplaceAroundStep); +function contentBetween(doc, from, to) { + var $from = doc.resolve(from), + dist = to - from, + depth = $from.depth; + while (dist > 0 && depth > 0 && $from.indexAfter(depth) == $from.node(depth).childCount) { + depth--; + dist--; + } + if (dist > 0) { + var next = $from.node(depth).maybeChild($from.indexAfter(depth)); + while (dist > 0) { + if (!next || next.isLeaf) return true; + next = next.firstChild; + dist--; + } + } + return false; +} +function _addMark(tr, from, to, mark) { + var removed = [], + added = []; + var removing, adding; + tr.doc.nodesBetween(from, to, function (node, pos, parent) { + if (!node.isInline) return; + var marks = node.marks; + if (!mark.isInSet(marks) && parent.type.allowsMarkType(mark.type)) { + var start = Math.max(pos, from), + end = Math.min(pos + node.nodeSize, to); + var newSet = mark.addToSet(marks); + for (var i = 0; i < marks.length; i++) { + if (!marks[i].isInSet(newSet)) { + if (removing && removing.to == start && removing.mark.eq(marks[i])) removing.to = end;else removed.push(removing = new RemoveMarkStep(start, end, marks[i])); + } + } + if (adding && adding.to == start) adding.to = end;else added.push(adding = new AddMarkStep(start, end, mark)); + } + }); + removed.forEach(function (s) { + return tr.step(s); + }); + added.forEach(function (s) { + return tr.step(s); + }); +} +function _removeMark(tr, from, to, mark) { + var matched = [], + step = 0; + tr.doc.nodesBetween(from, to, function (node, pos) { + if (!node.isInline) return; + step++; + var toRemove = null; + if (mark instanceof prosemirrorModel.MarkType) { + var set = node.marks, + found; + while (found = mark.isInSet(set)) { + (toRemove || (toRemove = [])).push(found); + set = found.removeFromSet(set); + } + } else if (mark) { + if (mark.isInSet(node.marks)) toRemove = [mark]; + } else { + toRemove = node.marks; + } + if (toRemove && toRemove.length) { + var end = Math.min(pos + node.nodeSize, to); + for (var i = 0; i < toRemove.length; i++) { + var style = toRemove[i], + _found = void 0; + for (var j = 0; j < matched.length; j++) { + var m = matched[j]; + if (m.step == step - 1 && style.eq(matched[j].style)) _found = m; + } + if (_found) { + _found.to = end; + _found.step = step; + } else { + matched.push({ + style: style, + from: Math.max(pos, from), + to: end, + step: step + }); + } + } + } + }); + matched.forEach(function (m) { + return tr.step(new RemoveMarkStep(m.from, m.to, m.style)); + }); +} +function _clearIncompatible(tr, pos, parentType) { + var match = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : parentType.contentMatch; + var clearNewlines = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + var node = tr.doc.nodeAt(pos); + var replSteps = [], + cur = pos + 1; + for (var i = 0; i < node.childCount; i++) { + var child = node.child(i), + end = cur + child.nodeSize; + var allowed = match.matchType(child.type); + if (!allowed) { + replSteps.push(new ReplaceStep(cur, end, prosemirrorModel.Slice.empty)); + } else { + match = allowed; + for (var j = 0; j < child.marks.length; j++) if (!parentType.allowsMarkType(child.marks[j].type)) tr.step(new RemoveMarkStep(cur, end, child.marks[j])); + if (clearNewlines && child.isText && parentType.whitespace != "pre") { + var m = void 0, + newline = /\r?\n|\r/g, + slice = void 0; + while (m = newline.exec(child.text)) { + if (!slice) slice = new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(parentType.schema.text(" ", parentType.allowedMarks(child.marks))), 0, 0); + replSteps.push(new ReplaceStep(cur + m.index, cur + m.index + m[0].length, slice)); + } + } + } + cur = end; + } + if (!match.validEnd) { + var fill = match.fillBefore(prosemirrorModel.Fragment.empty, true); + tr.replace(cur, cur, new prosemirrorModel.Slice(fill, 0, 0)); + } + for (var _i = replSteps.length - 1; _i >= 0; _i--) tr.step(replSteps[_i]); +} +function canCut(node, start, end) { + return (start == 0 || node.canReplace(start, node.childCount)) && (end == node.childCount || node.canReplace(0, end)); +} +function liftTarget(range) { + var parent = range.parent; + var content = parent.content.cutByIndex(range.startIndex, range.endIndex); + for (var depth = range.depth;; --depth) { + var node = range.$from.node(depth); + var index = range.$from.index(depth), + endIndex = range.$to.indexAfter(depth); + if (depth < range.depth && node.canReplace(index, endIndex, content)) return depth; + if (depth == 0 || node.type.spec.isolating || !canCut(node, index, endIndex)) break; + } + return null; +} +function _lift(tr, range, target) { + var $from = range.$from, + $to = range.$to, + depth = range.depth; + var gapStart = $from.before(depth + 1), + gapEnd = $to.after(depth + 1); + var start = gapStart, + end = gapEnd; + var before = prosemirrorModel.Fragment.empty, + openStart = 0; + for (var d = depth, splitting = false; d > target; d--) if (splitting || $from.index(d) > 0) { + splitting = true; + before = prosemirrorModel.Fragment.from($from.node(d).copy(before)); + openStart++; + } else { + start--; + } + var after = prosemirrorModel.Fragment.empty, + openEnd = 0; + for (var _d = depth, _splitting = false; _d > target; _d--) if (_splitting || $to.after(_d + 1) < $to.end(_d)) { + _splitting = true; + after = prosemirrorModel.Fragment.from($to.node(_d).copy(after)); + openEnd++; + } else { + end++; + } + tr.step(new ReplaceAroundStep(start, end, gapStart, gapEnd, new prosemirrorModel.Slice(before.append(after), openStart, openEnd), before.size - openStart, true)); +} +function findWrapping(range, nodeType) { + var attrs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + var innerRange = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : range; + var around = findWrappingOutside(range, nodeType); + var inner = around && findWrappingInside(innerRange, nodeType); + if (!inner) return null; + return around.map(withAttrs).concat({ + type: nodeType, + attrs: attrs + }).concat(inner.map(withAttrs)); +} +function withAttrs(type) { + return { + type: type, + attrs: null + }; +} +function findWrappingOutside(range, type) { + var parent = range.parent, + startIndex = range.startIndex, + endIndex = range.endIndex; + var around = parent.contentMatchAt(startIndex).findWrapping(type); + if (!around) return null; + var outer = around.length ? around[0] : type; + return parent.canReplaceWith(startIndex, endIndex, outer) ? around : null; +} +function findWrappingInside(range, type) { + var parent = range.parent, + startIndex = range.startIndex, + endIndex = range.endIndex; + var inner = parent.child(startIndex); + var inside = type.contentMatch.findWrapping(inner.type); + if (!inside) return null; + var lastType = inside.length ? inside[inside.length - 1] : type; + var innerMatch = lastType.contentMatch; + for (var i = startIndex; innerMatch && i < endIndex; i++) innerMatch = innerMatch.matchType(parent.child(i).type); + if (!innerMatch || !innerMatch.validEnd) return null; + return inside; +} +function _wrap2(tr, range, wrappers) { + var content = prosemirrorModel.Fragment.empty; + for (var i = wrappers.length - 1; i >= 0; i--) { + if (content.size) { + var match = wrappers[i].type.contentMatch.matchFragment(content); + if (!match || !match.validEnd) throw new RangeError("Wrapper type given to Transform.wrap does not form valid content of its parent wrapper"); + } + content = prosemirrorModel.Fragment.from(wrappers[i].type.create(wrappers[i].attrs, content)); + } + var start = range.start, + end = range.end; + tr.step(new ReplaceAroundStep(start, end, start, end, new prosemirrorModel.Slice(content, 0, 0), wrappers.length, true)); +} +function _setBlockType(tr, from, to, type, attrs) { + if (!type.isTextblock) throw new RangeError("Type given to setBlockType should be a textblock"); + var mapFrom = tr.steps.length; + tr.doc.nodesBetween(from, to, function (node, pos) { + var attrsHere = typeof attrs == "function" ? attrs(node) : attrs; + if (node.isTextblock && !node.hasMarkup(type, attrsHere) && canChangeType(tr.doc, tr.mapping.slice(mapFrom).map(pos), type)) { + var convertNewlines = null; + if (type.schema.linebreakReplacement) { + var pre = type.whitespace == "pre", + supportLinebreak = !!type.contentMatch.matchType(type.schema.linebreakReplacement); + if (pre && !supportLinebreak) convertNewlines = false;else if (!pre && supportLinebreak) convertNewlines = true; + } + if (convertNewlines === false) replaceLinebreaks(tr, node, pos, mapFrom); + _clearIncompatible(tr, tr.mapping.slice(mapFrom).map(pos, 1), type, undefined, convertNewlines === null); + var mapping = tr.mapping.slice(mapFrom); + var startM = mapping.map(pos, 1), + endM = mapping.map(pos + node.nodeSize, 1); + tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(type.create(attrsHere, null, node.marks)), 0, 0), 1, true)); + if (convertNewlines === true) replaceNewlines(tr, node, pos, mapFrom); + return false; + } + }); +} +function replaceNewlines(tr, node, pos, mapFrom) { + node.forEach(function (child, offset) { + if (child.isText) { + var m, + newline = /\r?\n|\r/g; + while (m = newline.exec(child.text)) { + var start = tr.mapping.slice(mapFrom).map(pos + 1 + offset + m.index); + tr.replaceWith(start, start + 1, node.type.schema.linebreakReplacement.create()); + } + } + }); +} +function replaceLinebreaks(tr, node, pos, mapFrom) { + node.forEach(function (child, offset) { + if (child.type == child.type.schema.linebreakReplacement) { + var start = tr.mapping.slice(mapFrom).map(pos + 1 + offset); + tr.replaceWith(start, start + 1, node.type.schema.text("\n")); + } + }); +} +function canChangeType(doc, pos, type) { + var $pos = doc.resolve(pos), + index = $pos.index(); + return $pos.parent.canReplaceWith(index, index + 1, type); +} +function _setNodeMarkup(tr, pos, type, attrs, marks) { + var node = tr.doc.nodeAt(pos); + if (!node) throw new RangeError("No node at given position"); + if (!type) type = node.type; + var newNode = type.create(attrs, null, marks || node.marks); + if (node.isLeaf) return tr.replaceWith(pos, pos + node.nodeSize, newNode); + if (!type.validContent(node.content)) throw new RangeError("Invalid content for node type " + type.name); + tr.step(new ReplaceAroundStep(pos, pos + node.nodeSize, pos + 1, pos + node.nodeSize - 1, new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(newNode), 0, 0), 1, true)); +} +function canSplit(doc, pos) { + var depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; + var typesAfter = arguments.length > 3 ? arguments[3] : undefined; + var $pos = doc.resolve(pos), + base = $pos.depth - depth; + var innerType = typesAfter && typesAfter[typesAfter.length - 1] || $pos.parent; + if (base < 0 || $pos.parent.type.spec.isolating || !$pos.parent.canReplace($pos.index(), $pos.parent.childCount) || !innerType.type.validContent($pos.parent.content.cutByIndex($pos.index(), $pos.parent.childCount))) return false; + for (var d = $pos.depth - 1, i = depth - 2; d > base; d--, i--) { + var node = $pos.node(d), + _index = $pos.index(d); + if (node.type.spec.isolating) return false; + var rest = node.content.cutByIndex(_index, node.childCount); + var overrideChild = typesAfter && typesAfter[i + 1]; + if (overrideChild) rest = rest.replaceChild(0, overrideChild.type.create(overrideChild.attrs)); + var after = typesAfter && typesAfter[i] || node; + if (!node.canReplace(_index + 1, node.childCount) || !after.type.validContent(rest)) return false; + } + var index = $pos.indexAfter(base); + var baseType = typesAfter && typesAfter[0]; + return $pos.node(base).canReplaceWith(index, index, baseType ? baseType.type : $pos.node(base + 1).type); +} +function _split(tr, pos) { + var depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; + var typesAfter = arguments.length > 3 ? arguments[3] : undefined; + var $pos = tr.doc.resolve(pos), + before = prosemirrorModel.Fragment.empty, + after = prosemirrorModel.Fragment.empty; + for (var d = $pos.depth, e = $pos.depth - depth, i = depth - 1; d > e; d--, i--) { + before = prosemirrorModel.Fragment.from($pos.node(d).copy(before)); + var typeAfter = typesAfter && typesAfter[i]; + after = prosemirrorModel.Fragment.from(typeAfter ? typeAfter.type.create(typeAfter.attrs, after) : $pos.node(d).copy(after)); + } + tr.step(new ReplaceStep(pos, pos, new prosemirrorModel.Slice(before.append(after), depth, depth), true)); +} +function canJoin(doc, pos) { + var $pos = doc.resolve(pos), + index = $pos.index(); + return joinable($pos.nodeBefore, $pos.nodeAfter) && $pos.parent.canReplace(index, index + 1); +} +function canAppendWithSubstitutedLinebreaks(a, b) { + if (!b.content.size) a.type.compatibleContent(b.type); + var match = a.contentMatchAt(a.childCount); + var linebreakReplacement = a.type.schema.linebreakReplacement; + for (var i = 0; i < b.childCount; i++) { + var child = b.child(i); + var type = child.type == linebreakReplacement ? a.type.schema.nodes.text : child.type; + match = match.matchType(type); + if (!match) return false; + if (!a.type.allowsMarks(child.marks)) return false; + } + return match.validEnd; +} +function joinable(a, b) { + return !!(a && b && !a.isLeaf && canAppendWithSubstitutedLinebreaks(a, b)); +} +function joinPoint(doc, pos) { + var dir = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -1; + var $pos = doc.resolve(pos); + for (var d = $pos.depth;; d--) { + var before = void 0, + after = void 0, + index = $pos.index(d); + if (d == $pos.depth) { + before = $pos.nodeBefore; + after = $pos.nodeAfter; + } else if (dir > 0) { + before = $pos.node(d + 1); + index++; + after = $pos.node(d).maybeChild(index); + } else { + before = $pos.node(d).maybeChild(index - 1); + after = $pos.node(d + 1); + } + if (before && !before.isTextblock && joinable(before, after) && $pos.node(d).canReplace(index, index + 1)) return pos; + if (d == 0) break; + pos = dir < 0 ? $pos.before(d) : $pos.after(d); + } +} +function _join(tr, pos, depth) { + var convertNewlines = null; + var linebreakReplacement = tr.doc.type.schema.linebreakReplacement; + var $before = tr.doc.resolve(pos - depth), + beforeType = $before.node().type; + if (linebreakReplacement && beforeType.inlineContent) { + var pre = beforeType.whitespace == "pre"; + var supportLinebreak = !!beforeType.contentMatch.matchType(linebreakReplacement); + if (pre && !supportLinebreak) convertNewlines = false;else if (!pre && supportLinebreak) convertNewlines = true; + } + var mapFrom = tr.steps.length; + if (convertNewlines === false) { + var $after = tr.doc.resolve(pos + depth); + replaceLinebreaks(tr, $after.node(), $after.before(), mapFrom); + } + if (beforeType.inlineContent) _clearIncompatible(tr, pos + depth - 1, beforeType, $before.node().contentMatchAt($before.index()), convertNewlines == null); + var mapping = tr.mapping.slice(mapFrom), + start = mapping.map(pos - depth); + tr.step(new ReplaceStep(start, mapping.map(pos + depth, -1), prosemirrorModel.Slice.empty, true)); + if (convertNewlines === true) { + var $full = tr.doc.resolve(start); + replaceNewlines(tr, $full.node(), $full.before(), tr.steps.length); + } + return tr; +} +function insertPoint(doc, pos, nodeType) { + var $pos = doc.resolve(pos); + if ($pos.parent.canReplaceWith($pos.index(), $pos.index(), nodeType)) return pos; + if ($pos.parentOffset == 0) for (var d = $pos.depth - 1; d >= 0; d--) { + var index = $pos.index(d); + if ($pos.node(d).canReplaceWith(index, index, nodeType)) return $pos.before(d + 1); + if (index > 0) return null; + } + if ($pos.parentOffset == $pos.parent.content.size) for (var _d2 = $pos.depth - 1; _d2 >= 0; _d2--) { + var _index2 = $pos.indexAfter(_d2); + if ($pos.node(_d2).canReplaceWith(_index2, _index2, nodeType)) return $pos.after(_d2 + 1); + if (_index2 < $pos.node(_d2).childCount) return null; + } + return null; +} +function dropPoint(doc, pos, slice) { + var $pos = doc.resolve(pos); + if (!slice.content.size) return pos; + var content = slice.content; + for (var i = 0; i < slice.openStart; i++) content = content.firstChild.content; + for (var pass = 1; pass <= (slice.openStart == 0 && slice.size ? 2 : 1); pass++) { + for (var d = $pos.depth; d >= 0; d--) { + var bias = d == $pos.depth ? 0 : $pos.pos <= ($pos.start(d + 1) + $pos.end(d + 1)) / 2 ? -1 : 1; + var insertPos = $pos.index(d) + (bias > 0 ? 1 : 0); + var parent = $pos.node(d), + fits = false; + if (pass == 1) { + fits = parent.canReplace(insertPos, insertPos, content); + } else { + var wrapping = parent.contentMatchAt(insertPos).findWrapping(content.firstChild.type); + fits = wrapping && parent.canReplaceWith(insertPos, insertPos, wrapping[0]); + } + if (fits) return bias == 0 ? $pos.pos : bias < 0 ? $pos.before(d + 1) : $pos.after(d + 1); + } + } + return null; +} +function replaceStep(doc, from) { + var to = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : from; + var slice = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : prosemirrorModel.Slice.empty; + if (from == to && !slice.size) return null; + var $from = doc.resolve(from), + $to = doc.resolve(to); + if (fitsTrivially($from, $to, slice)) return new ReplaceStep(from, to, slice); + return new Fitter($from, $to, slice).fit(); +} +function fitsTrivially($from, $to, slice) { + return !slice.openStart && !slice.openEnd && $from.start() == $to.start() && $from.parent.canReplace($from.index(), $to.index(), slice.content); +} +var Fitter = function () { + function Fitter($from, $to, unplaced) { + _classCallCheck(this, Fitter); + this.$from = $from; + this.$to = $to; + this.unplaced = unplaced; + this.frontier = []; + this.placed = prosemirrorModel.Fragment.empty; + for (var i = 0; i <= $from.depth; i++) { + var node = $from.node(i); + this.frontier.push({ + type: node.type, + match: node.contentMatchAt($from.indexAfter(i)) + }); + } + for (var _i2 = $from.depth; _i2 > 0; _i2--) this.placed = prosemirrorModel.Fragment.from($from.node(_i2).copy(this.placed)); + } + _createClass(Fitter, [{ + key: "depth", + get: function get() { + return this.frontier.length - 1; + } + }, { + key: "fit", + value: function fit() { + while (this.unplaced.size) { + var fit = this.findFittable(); + if (fit) this.placeNodes(fit);else this.openMore() || this.dropNode(); + } + var moveInline = this.mustMoveInline(), + placedSize = this.placed.size - this.depth - this.$from.depth; + var $from = this.$from, + $to = this.close(moveInline < 0 ? this.$to : $from.doc.resolve(moveInline)); + if (!$to) return null; + var content = this.placed, + openStart = $from.depth, + openEnd = $to.depth; + while (openStart && openEnd && content.childCount == 1) { + content = content.firstChild.content; + openStart--; + openEnd--; + } + var slice = new prosemirrorModel.Slice(content, openStart, openEnd); + if (moveInline > -1) return new ReplaceAroundStep($from.pos, moveInline, this.$to.pos, this.$to.end(), slice, placedSize); + if (slice.size || $from.pos != this.$to.pos) return new ReplaceStep($from.pos, $to.pos, slice); + return null; + } + }, { + key: "findFittable", + value: function findFittable() { + var startDepth = this.unplaced.openStart; + for (var cur = this.unplaced.content, d = 0, openEnd = this.unplaced.openEnd; d < startDepth; d++) { + var node = cur.firstChild; + if (cur.childCount > 1) openEnd = 0; + if (node.type.spec.isolating && openEnd <= d) { + startDepth = d; + break; + } + cur = node.content; + } + for (var pass = 1; pass <= 2; pass++) { + for (var sliceDepth = pass == 1 ? startDepth : this.unplaced.openStart; sliceDepth >= 0; sliceDepth--) { + var fragment = void 0, + parent = null; + if (sliceDepth) { + parent = contentAt(this.unplaced.content, sliceDepth - 1).firstChild; + fragment = parent.content; + } else { + fragment = this.unplaced.content; + } + var first = fragment.firstChild; + for (var frontierDepth = this.depth; frontierDepth >= 0; frontierDepth--) { + var _this$frontier$fronti = this.frontier[frontierDepth], + type = _this$frontier$fronti.type, + match = _this$frontier$fronti.match, + _wrap = void 0, + inject = null; + if (pass == 1 && (first ? match.matchType(first.type) || (inject = match.fillBefore(prosemirrorModel.Fragment.from(first), false)) : parent && type.compatibleContent(parent.type))) return { + sliceDepth: sliceDepth, + frontierDepth: frontierDepth, + parent: parent, + inject: inject + };else if (pass == 2 && first && (_wrap = match.findWrapping(first.type))) return { + sliceDepth: sliceDepth, + frontierDepth: frontierDepth, + parent: parent, + wrap: _wrap + }; + if (parent && match.matchType(parent.type)) break; + } + } + } + } + }, { + key: "openMore", + value: function openMore() { + var _this$unplaced = this.unplaced, + content = _this$unplaced.content, + openStart = _this$unplaced.openStart, + openEnd = _this$unplaced.openEnd; + var inner = contentAt(content, openStart); + if (!inner.childCount || inner.firstChild.isLeaf) return false; + this.unplaced = new prosemirrorModel.Slice(content, openStart + 1, Math.max(openEnd, inner.size + openStart >= content.size - openEnd ? openStart + 1 : 0)); + return true; + } + }, { + key: "dropNode", + value: function dropNode() { + var _this$unplaced2 = this.unplaced, + content = _this$unplaced2.content, + openStart = _this$unplaced2.openStart, + openEnd = _this$unplaced2.openEnd; + var inner = contentAt(content, openStart); + if (inner.childCount <= 1 && openStart > 0) { + var openAtEnd = content.size - openStart <= openStart + inner.size; + this.unplaced = new prosemirrorModel.Slice(dropFromFragment(content, openStart - 1, 1), openStart - 1, openAtEnd ? openStart - 1 : openEnd); + } else { + this.unplaced = new prosemirrorModel.Slice(dropFromFragment(content, openStart, 1), openStart, openEnd); + } + } + }, { + key: "placeNodes", + value: function placeNodes(_ref) { + var sliceDepth = _ref.sliceDepth, + frontierDepth = _ref.frontierDepth, + parent = _ref.parent, + inject = _ref.inject, + wrap = _ref.wrap; + while (this.depth > frontierDepth) this.closeFrontierNode(); + if (wrap) for (var i = 0; i < wrap.length; i++) this.openFrontierNode(wrap[i]); + var slice = this.unplaced, + fragment = parent ? parent.content : slice.content; + var openStart = slice.openStart - sliceDepth; + var taken = 0, + add = []; + var _this$frontier$fronti2 = this.frontier[frontierDepth], + match = _this$frontier$fronti2.match, + type = _this$frontier$fronti2.type; + if (inject) { + for (var _i3 = 0; _i3 < inject.childCount; _i3++) add.push(inject.child(_i3)); + match = match.matchFragment(inject); + } + var openEndCount = fragment.size + sliceDepth - (slice.content.size - slice.openEnd); + while (taken < fragment.childCount) { + var next = fragment.child(taken), + matches = match.matchType(next.type); + if (!matches) break; + taken++; + if (taken > 1 || openStart == 0 || next.content.size) { + match = matches; + add.push(closeNodeStart(next.mark(type.allowedMarks(next.marks)), taken == 1 ? openStart : 0, taken == fragment.childCount ? openEndCount : -1)); + } + } + var toEnd = taken == fragment.childCount; + if (!toEnd) openEndCount = -1; + this.placed = addToFragment(this.placed, frontierDepth, prosemirrorModel.Fragment.from(add)); + this.frontier[frontierDepth].match = match; + if (toEnd && openEndCount < 0 && parent && parent.type == this.frontier[this.depth].type && this.frontier.length > 1) this.closeFrontierNode(); + for (var _i4 = 0, cur = fragment; _i4 < openEndCount; _i4++) { + var node = cur.lastChild; + this.frontier.push({ + type: node.type, + match: node.contentMatchAt(node.childCount) + }); + cur = node.content; + } + this.unplaced = !toEnd ? new prosemirrorModel.Slice(dropFromFragment(slice.content, sliceDepth, taken), slice.openStart, slice.openEnd) : sliceDepth == 0 ? prosemirrorModel.Slice.empty : new prosemirrorModel.Slice(dropFromFragment(slice.content, sliceDepth - 1, 1), sliceDepth - 1, openEndCount < 0 ? slice.openEnd : sliceDepth - 1); + } + }, { + key: "mustMoveInline", + value: function mustMoveInline() { + if (!this.$to.parent.isTextblock) return -1; + var top = this.frontier[this.depth], + level; + if (!top.type.isTextblock || !contentAfterFits(this.$to, this.$to.depth, top.type, top.match, false) || this.$to.depth == this.depth && (level = this.findCloseLevel(this.$to)) && level.depth == this.depth) return -1; + var depth = this.$to.depth, + after = this.$to.after(depth); + while (depth > 1 && after == this.$to.end(--depth)) ++after; + return after; + } + }, { + key: "findCloseLevel", + value: function findCloseLevel($to) { + scan: for (var i = Math.min(this.depth, $to.depth); i >= 0; i--) { + var _this$frontier$i = this.frontier[i], + match = _this$frontier$i.match, + type = _this$frontier$i.type; + var dropInner = i < $to.depth && $to.end(i + 1) == $to.pos + ($to.depth - (i + 1)); + var fit = contentAfterFits($to, i, type, match, dropInner); + if (!fit) continue; + for (var d = i - 1; d >= 0; d--) { + var _this$frontier$d = this.frontier[d], + _match = _this$frontier$d.match, + _type = _this$frontier$d.type; + var matches = contentAfterFits($to, d, _type, _match, true); + if (!matches || matches.childCount) continue scan; + } + return { + depth: i, + fit: fit, + move: dropInner ? $to.doc.resolve($to.after(i + 1)) : $to + }; + } + } + }, { + key: "close", + value: function close($to) { + var close = this.findCloseLevel($to); + if (!close) return null; + while (this.depth > close.depth) this.closeFrontierNode(); + if (close.fit.childCount) this.placed = addToFragment(this.placed, close.depth, close.fit); + $to = close.move; + for (var d = close.depth + 1; d <= $to.depth; d++) { + var node = $to.node(d), + add = node.type.contentMatch.fillBefore(node.content, true, $to.index(d)); + this.openFrontierNode(node.type, node.attrs, add); + } + return $to; + } + }, { + key: "openFrontierNode", + value: function openFrontierNode(type) { + var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + var content = arguments.length > 2 ? arguments[2] : undefined; + var top = this.frontier[this.depth]; + top.match = top.match.matchType(type); + this.placed = addToFragment(this.placed, this.depth, prosemirrorModel.Fragment.from(type.create(attrs, content))); + this.frontier.push({ + type: type, + match: type.contentMatch + }); + } + }, { + key: "closeFrontierNode", + value: function closeFrontierNode() { + var open = this.frontier.pop(); + var add = open.match.fillBefore(prosemirrorModel.Fragment.empty, true); + if (add.childCount) this.placed = addToFragment(this.placed, this.frontier.length, add); + } + }]); + return Fitter; +}(); +function dropFromFragment(fragment, depth, count) { + if (depth == 0) return fragment.cutByIndex(count, fragment.childCount); + return fragment.replaceChild(0, fragment.firstChild.copy(dropFromFragment(fragment.firstChild.content, depth - 1, count))); +} +function addToFragment(fragment, depth, content) { + if (depth == 0) return fragment.append(content); + return fragment.replaceChild(fragment.childCount - 1, fragment.lastChild.copy(addToFragment(fragment.lastChild.content, depth - 1, content))); +} +function contentAt(fragment, depth) { + for (var i = 0; i < depth; i++) fragment = fragment.firstChild.content; + return fragment; +} +function closeNodeStart(node, openStart, openEnd) { + if (openStart <= 0) return node; + var frag = node.content; + if (openStart > 1) frag = frag.replaceChild(0, closeNodeStart(frag.firstChild, openStart - 1, frag.childCount == 1 ? openEnd - 1 : 0)); + if (openStart > 0) { + frag = node.type.contentMatch.fillBefore(frag).append(frag); + if (openEnd <= 0) frag = frag.append(node.type.contentMatch.matchFragment(frag).fillBefore(prosemirrorModel.Fragment.empty, true)); + } + return node.copy(frag); +} +function contentAfterFits($to, depth, type, match, open) { + var node = $to.node(depth), + index = open ? $to.indexAfter(depth) : $to.index(depth); + if (index == node.childCount && !type.compatibleContent(node.type)) return null; + var fit = match.fillBefore(node.content, true, index); + return fit && !invalidMarks(type, node.content, index) ? fit : null; +} +function invalidMarks(type, fragment, start) { + for (var i = start; i < fragment.childCount; i++) if (!type.allowsMarks(fragment.child(i).marks)) return true; + return false; +} +function definesContent(type) { + return type.spec.defining || type.spec.definingForContent; +} +function _replaceRange(tr, from, to, slice) { + if (!slice.size) return tr.deleteRange(from, to); + var $from = tr.doc.resolve(from), + $to = tr.doc.resolve(to); + if (fitsTrivially($from, $to, slice)) return tr.step(new ReplaceStep(from, to, slice)); + var targetDepths = coveredDepths($from, tr.doc.resolve(to)); + if (targetDepths[targetDepths.length - 1] == 0) targetDepths.pop(); + var preferredTarget = -($from.depth + 1); + targetDepths.unshift(preferredTarget); + for (var d = $from.depth, pos = $from.pos - 1; d > 0; d--, pos--) { + var spec = $from.node(d).type.spec; + if (spec.defining || spec.definingAsContext || spec.isolating) break; + if (targetDepths.indexOf(d) > -1) preferredTarget = d;else if ($from.before(d) == pos) targetDepths.splice(1, 0, -d); + } + var preferredTargetIndex = targetDepths.indexOf(preferredTarget); + var leftNodes = [], + preferredDepth = slice.openStart; + for (var content = slice.content, i = 0;; i++) { + var node = content.firstChild; + leftNodes.push(node); + if (i == slice.openStart) break; + content = node.content; + } + for (var _d3 = preferredDepth - 1; _d3 >= 0; _d3--) { + var leftNode = leftNodes[_d3], + def = definesContent(leftNode.type); + if (def && !leftNode.sameMarkup($from.node(Math.abs(preferredTarget) - 1))) preferredDepth = _d3;else if (def || !leftNode.type.isTextblock) break; + } + for (var j = slice.openStart; j >= 0; j--) { + var openDepth = (j + preferredDepth + 1) % (slice.openStart + 1); + var insert = leftNodes[openDepth]; + if (!insert) continue; + for (var _i5 = 0; _i5 < targetDepths.length; _i5++) { + var targetDepth = targetDepths[(_i5 + preferredTargetIndex) % targetDepths.length], + expand = true; + if (targetDepth < 0) { + expand = false; + targetDepth = -targetDepth; + } + var parent = $from.node(targetDepth - 1), + index = $from.index(targetDepth - 1); + if (parent.canReplaceWith(index, index, insert.type, insert.marks)) return tr.replace($from.before(targetDepth), expand ? $to.after(targetDepth) : to, new prosemirrorModel.Slice(closeFragment(slice.content, 0, slice.openStart, openDepth), openDepth, slice.openEnd)); + } + } + var startSteps = tr.steps.length; + for (var _i6 = targetDepths.length - 1; _i6 >= 0; _i6--) { + tr.replace(from, to, slice); + if (tr.steps.length > startSteps) break; + var depth = targetDepths[_i6]; + if (depth < 0) continue; + from = $from.before(depth); + to = $to.after(depth); + } +} +function closeFragment(fragment, depth, oldOpen, newOpen, parent) { + if (depth < oldOpen) { + var first = fragment.firstChild; + fragment = fragment.replaceChild(0, first.copy(closeFragment(first.content, depth + 1, oldOpen, newOpen, first))); + } + if (depth > newOpen) { + var match = parent.contentMatchAt(0); + var start = match.fillBefore(fragment).append(fragment); + fragment = start.append(match.matchFragment(start).fillBefore(prosemirrorModel.Fragment.empty, true)); + } + return fragment; +} +function _replaceRangeWith(tr, from, to, node) { + if (!node.isInline && from == to && tr.doc.resolve(from).parent.content.size) { + var point = insertPoint(tr.doc, from, node.type); + if (point != null) from = to = point; + } + tr.replaceRange(from, to, new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(node), 0, 0)); +} +function _deleteRange(tr, from, to) { + var $from = tr.doc.resolve(from), + $to = tr.doc.resolve(to); + var covered = coveredDepths($from, $to); + for (var i = 0; i < covered.length; i++) { + var depth = covered[i], + last = i == covered.length - 1; + if (last && depth == 0 || $from.node(depth).type.contentMatch.validEnd) return tr["delete"]($from.start(depth), $to.end(depth)); + if (depth > 0 && (last || $from.node(depth - 1).canReplace($from.index(depth - 1), $to.indexAfter(depth - 1)))) return tr["delete"]($from.before(depth), $to.after(depth)); + } + for (var d = 1; d <= $from.depth && d <= $to.depth; d++) { + if (from - $from.start(d) == $from.depth - d && to > $from.end(d) && $to.end(d) - to != $to.depth - d && $from.start(d - 1) == $to.start(d - 1) && $from.node(d - 1).canReplace($from.index(d - 1), $to.index(d - 1))) return tr["delete"]($from.before(d), to); + } + tr["delete"](from, to); +} +function coveredDepths($from, $to) { + var result = [], + minDepth = Math.min($from.depth, $to.depth); + for (var d = minDepth; d >= 0; d--) { + var start = $from.start(d); + if (start < $from.pos - ($from.depth - d) || $to.end(d) > $to.pos + ($to.depth - d) || $from.node(d).type.spec.isolating || $to.node(d).type.spec.isolating) break; + if (start == $to.start(d) || d == $from.depth && d == $to.depth && $from.parent.inlineContent && $to.parent.inlineContent && d && $to.start(d - 1) == start - 1) result.push(d); + } + return result; +} +var AttrStep = function (_Step7) { + _inherits(AttrStep, _Step7); + var _super7 = _createSuper(AttrStep); + function AttrStep(pos, attr, value) { + var _this9; + _classCallCheck(this, AttrStep); + _this9 = _super7.call(this); + _this9.pos = pos; + _this9.attr = attr; + _this9.value = value; + return _this9; + } + _createClass(AttrStep, [{ + key: "apply", + value: function apply(doc) { + var node = doc.nodeAt(this.pos); + if (!node) return StepResult.fail("No node at attribute step's position"); + var attrs = Object.create(null); + for (var name in node.attrs) attrs[name] = node.attrs[name]; + attrs[this.attr] = this.value; + var updated = node.type.create(attrs, null, node.marks); + return StepResult.fromReplace(doc, this.pos, this.pos + 1, new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(updated), 0, node.isLeaf ? 0 : 1)); + } + }, { + key: "getMap", + value: function getMap() { + return StepMap.empty; + } + }, { + key: "invert", + value: function invert(doc) { + return new AttrStep(this.pos, this.attr, doc.nodeAt(this.pos).attrs[this.attr]); + } + }, { + key: "map", + value: function map(mapping) { + var pos = mapping.mapResult(this.pos, 1); + return pos.deletedAfter ? null : new AttrStep(pos.pos, this.attr, this.value); + } + }, { + key: "toJSON", + value: function toJSON() { + return { + stepType: "attr", + pos: this.pos, + attr: this.attr, + value: this.value + }; + } + }], [{ + key: "fromJSON", + value: function fromJSON(schema, json) { + if (typeof json.pos != "number" || typeof json.attr != "string") throw new RangeError("Invalid input for AttrStep.fromJSON"); + return new AttrStep(json.pos, json.attr, json.value); + } + }]); + return AttrStep; +}(Step); +Step.jsonID("attr", AttrStep); +var DocAttrStep = function (_Step8) { + _inherits(DocAttrStep, _Step8); + var _super8 = _createSuper(DocAttrStep); + function DocAttrStep(attr, value) { + var _this10; + _classCallCheck(this, DocAttrStep); + _this10 = _super8.call(this); + _this10.attr = attr; + _this10.value = value; + return _this10; + } + _createClass(DocAttrStep, [{ + key: "apply", + value: function apply(doc) { + var attrs = Object.create(null); + for (var name in doc.attrs) attrs[name] = doc.attrs[name]; + attrs[this.attr] = this.value; + var updated = doc.type.create(attrs, doc.content, doc.marks); + return StepResult.ok(updated); + } + }, { + key: "getMap", + value: function getMap() { + return StepMap.empty; + } + }, { + key: "invert", + value: function invert(doc) { + return new DocAttrStep(this.attr, doc.attrs[this.attr]); + } + }, { + key: "map", + value: function map(mapping) { + return this; + } + }, { + key: "toJSON", + value: function toJSON() { + return { + stepType: "docAttr", + attr: this.attr, + value: this.value + }; + } + }], [{ + key: "fromJSON", + value: function fromJSON(schema, json) { + if (typeof json.attr != "string") throw new RangeError("Invalid input for DocAttrStep.fromJSON"); + return new DocAttrStep(json.attr, json.value); + } + }]); + return DocAttrStep; +}(Step); +Step.jsonID("docAttr", DocAttrStep); +exports.TransformError = function (_Error) { + _inherits(TransformError, _Error); + var _super9 = _createSuper(TransformError); + function TransformError() { + _classCallCheck(this, TransformError); + return _super9.apply(this, arguments); + } + return _createClass(TransformError); +}(_wrapNativeSuper(Error)); +exports.TransformError = function TransformError(message) { + var err = Error.call(this, message); + err.__proto__ = TransformError.prototype; + return err; +}; +exports.TransformError.prototype = Object.create(Error.prototype); +exports.TransformError.prototype.constructor = exports.TransformError; +exports.TransformError.prototype.name = "TransformError"; +var Transform = function () { + function Transform(doc) { + _classCallCheck(this, Transform); + this.doc = doc; + this.steps = []; + this.docs = []; + this.mapping = new Mapping(); + } + _createClass(Transform, [{ + key: "before", + get: function get() { + return this.docs.length ? this.docs[0] : this.doc; + } + }, { + key: "step", + value: function step(_step) { + var result = this.maybeStep(_step); + if (result.failed) throw new exports.TransformError(result.failed); + return this; + } + }, { + key: "maybeStep", + value: function maybeStep(step) { + var result = step.apply(this.doc); + if (!result.failed) this.addStep(step, result.doc); + return result; + } + }, { + key: "docChanged", + get: function get() { + return this.steps.length > 0; + } + }, { + key: "addStep", + value: function addStep(step, doc) { + this.docs.push(this.doc); + this.steps.push(step); + this.mapping.appendMap(step.getMap()); + this.doc = doc; + } + }, { + key: "replace", + value: function replace(from) { + var to = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : from; + var slice = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : prosemirrorModel.Slice.empty; + var step = replaceStep(this.doc, from, to, slice); + if (step) this.step(step); + return this; + } + }, { + key: "replaceWith", + value: function replaceWith(from, to, content) { + return this.replace(from, to, new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(content), 0, 0)); + } + }, { + key: "delete", + value: function _delete(from, to) { + return this.replace(from, to, prosemirrorModel.Slice.empty); + } + }, { + key: "insert", + value: function insert(pos, content) { + return this.replaceWith(pos, pos, content); + } + }, { + key: "replaceRange", + value: function replaceRange(from, to, slice) { + _replaceRange(this, from, to, slice); + return this; + } + }, { + key: "replaceRangeWith", + value: function replaceRangeWith(from, to, node) { + _replaceRangeWith(this, from, to, node); + return this; + } + }, { + key: "deleteRange", + value: function deleteRange(from, to) { + _deleteRange(this, from, to); + return this; + } + }, { + key: "lift", + value: function lift(range, target) { + _lift(this, range, target); + return this; + } + }, { + key: "join", + value: function join(pos) { + var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + _join(this, pos, depth); + return this; + } + }, { + key: "wrap", + value: function wrap(range, wrappers) { + _wrap2(this, range, wrappers); + return this; + } + }, { + key: "setBlockType", + value: function setBlockType(from) { + var to = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : from; + var type = arguments.length > 2 ? arguments[2] : undefined; + var attrs = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + _setBlockType(this, from, to, type, attrs); + return this; + } + }, { + key: "setNodeMarkup", + value: function setNodeMarkup(pos, type) { + var attrs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + var marks = arguments.length > 3 ? arguments[3] : undefined; + _setNodeMarkup(this, pos, type, attrs, marks); + return this; + } + }, { + key: "setNodeAttribute", + value: function setNodeAttribute(pos, attr, value) { + this.step(new AttrStep(pos, attr, value)); + return this; + } + }, { + key: "setDocAttribute", + value: function setDocAttribute(attr, value) { + this.step(new DocAttrStep(attr, value)); + return this; + } + }, { + key: "addNodeMark", + value: function addNodeMark(pos, mark) { + this.step(new AddNodeMarkStep(pos, mark)); + return this; + } + }, { + key: "removeNodeMark", + value: function removeNodeMark(pos, mark) { + if (!(mark instanceof prosemirrorModel.Mark)) { + var node = this.doc.nodeAt(pos); + if (!node) throw new RangeError("No node at position " + pos); + mark = mark.isInSet(node.marks); + if (!mark) return this; + } + this.step(new RemoveNodeMarkStep(pos, mark)); + return this; + } + }, { + key: "split", + value: function split(pos) { + var depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + var typesAfter = arguments.length > 2 ? arguments[2] : undefined; + _split(this, pos, depth, typesAfter); + return this; + } + }, { + key: "addMark", + value: function addMark(from, to, mark) { + _addMark(this, from, to, mark); + return this; + } + }, { + key: "removeMark", + value: function removeMark(from, to, mark) { + _removeMark(this, from, to, mark); + return this; + } + }, { + key: "clearIncompatible", + value: function clearIncompatible(pos, parentType, match) { + _clearIncompatible(this, pos, parentType, match); + return this; + } + }]); + return Transform; +}(); +exports.AddMarkStep = AddMarkStep; +exports.AddNodeMarkStep = AddNodeMarkStep; +exports.AttrStep = AttrStep; +exports.DocAttrStep = DocAttrStep; +exports.MapResult = MapResult; +exports.Mapping = Mapping; +exports.RemoveMarkStep = RemoveMarkStep; +exports.RemoveNodeMarkStep = RemoveNodeMarkStep; +exports.ReplaceAroundStep = ReplaceAroundStep; +exports.ReplaceStep = ReplaceStep; +exports.Step = Step; +exports.StepMap = StepMap; +exports.StepResult = StepResult; +exports.Transform = Transform; +exports.canJoin = canJoin; +exports.canSplit = canSplit; +exports.dropPoint = dropPoint; +exports.findWrapping = findWrapping; +exports.insertPoint = insertPoint; +exports.joinPoint = joinPoint; +exports.liftTarget = liftTarget; +exports.replaceStep = replaceStep; diff --git a/plugins/tiddlywiki/prosemirror/files/rope-sequence.cjs b/plugins/tiddlywiki/prosemirror/files/rope-sequence.cjs new file mode 100644 index 000000000..4c28aaa65 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/rope-sequence.cjs @@ -0,0 +1,209 @@ +'use strict'; + +var GOOD_LEAF_SIZE = 200; + +// :: class A rope sequence is a persistent sequence data structure +// that supports appending, prepending, and slicing without doing a +// full copy. It is represented as a mostly-balanced tree. +var RopeSequence = function RopeSequence () {}; + +RopeSequence.prototype.append = function append (other) { + if (!other.length) { return this } + other = RopeSequence.from(other); + + return (!this.length && other) || + (other.length < GOOD_LEAF_SIZE && this.leafAppend(other)) || + (this.length < GOOD_LEAF_SIZE && other.leafPrepend(this)) || + this.appendInner(other) +}; + +// :: (union<[T], RopeSequence>) → RopeSequence +// Prepend an array or other rope to this one, returning a new rope. +RopeSequence.prototype.prepend = function prepend (other) { + if (!other.length) { return this } + return RopeSequence.from(other).append(this) +}; + +RopeSequence.prototype.appendInner = function appendInner (other) { + return new Append(this, other) +}; + +// :: (?number, ?number) → RopeSequence +// Create a rope repesenting a sub-sequence of this rope. +RopeSequence.prototype.slice = function slice (from, to) { + if ( from === void 0 ) from = 0; + if ( to === void 0 ) to = this.length; + + if (from >= to) { return RopeSequence.empty } + return this.sliceInner(Math.max(0, from), Math.min(this.length, to)) +}; + +// :: (number) → T +// Retrieve the element at the given position from this rope. +RopeSequence.prototype.get = function get (i) { + if (i < 0 || i >= this.length) { return undefined } + return this.getInner(i) +}; + +// :: ((element: T, index: number) → ?bool, ?number, ?number) +// Call the given function for each element between the given +// indices. This tends to be more efficient than looping over the +// indices and calling `get`, because it doesn't have to descend the +// tree for every element. +RopeSequence.prototype.forEach = function forEach (f, from, to) { + if ( from === void 0 ) from = 0; + if ( to === void 0 ) to = this.length; + + if (from <= to) + { this.forEachInner(f, from, to, 0); } + else + { this.forEachInvertedInner(f, from, to, 0); } +}; + +// :: ((element: T, index: number) → U, ?number, ?number) → [U] +// Map the given functions over the elements of the rope, producing +// a flat array. +RopeSequence.prototype.map = function map (f, from, to) { + if ( from === void 0 ) from = 0; + if ( to === void 0 ) to = this.length; + + var result = []; + this.forEach(function (elt, i) { return result.push(f(elt, i)); }, from, to); + return result +}; + +// :: (?union<[T], RopeSequence>) → RopeSequence +// Create a rope representing the given array, or return the rope +// itself if a rope was given. +RopeSequence.from = function from (values) { + if (values instanceof RopeSequence) { return values } + return values && values.length ? new Leaf(values) : RopeSequence.empty +}; + +var Leaf = /*@__PURE__*/(function (RopeSequence) { + function Leaf(values) { + RopeSequence.call(this); + this.values = values; + } + + if ( RopeSequence ) Leaf.__proto__ = RopeSequence; + Leaf.prototype = Object.create( RopeSequence && RopeSequence.prototype ); + Leaf.prototype.constructor = Leaf; + + var prototypeAccessors = { length: { configurable: true },depth: { configurable: true } }; + + Leaf.prototype.flatten = function flatten () { + return this.values + }; + + Leaf.prototype.sliceInner = function sliceInner (from, to) { + if (from == 0 && to == this.length) { return this } + return new Leaf(this.values.slice(from, to)) + }; + + Leaf.prototype.getInner = function getInner (i) { + return this.values[i] + }; + + Leaf.prototype.forEachInner = function forEachInner (f, from, to, start) { + for (var i = from; i < to; i++) + { if (f(this.values[i], start + i) === false) { return false } } + }; + + Leaf.prototype.forEachInvertedInner = function forEachInvertedInner (f, from, to, start) { + for (var i = from - 1; i >= to; i--) + { if (f(this.values[i], start + i) === false) { return false } } + }; + + Leaf.prototype.leafAppend = function leafAppend (other) { + if (this.length + other.length <= GOOD_LEAF_SIZE) + { return new Leaf(this.values.concat(other.flatten())) } + }; + + Leaf.prototype.leafPrepend = function leafPrepend (other) { + if (this.length + other.length <= GOOD_LEAF_SIZE) + { return new Leaf(other.flatten().concat(this.values)) } + }; + + prototypeAccessors.length.get = function () { return this.values.length }; + + prototypeAccessors.depth.get = function () { return 0 }; + + Object.defineProperties( Leaf.prototype, prototypeAccessors ); + + return Leaf; +}(RopeSequence)); + +// :: RopeSequence +// The empty rope sequence. +RopeSequence.empty = new Leaf([]); + +var Append = /*@__PURE__*/(function (RopeSequence) { + function Append(left, right) { + RopeSequence.call(this); + this.left = left; + this.right = right; + this.length = left.length + right.length; + this.depth = Math.max(left.depth, right.depth) + 1; + } + + if ( RopeSequence ) Append.__proto__ = RopeSequence; + Append.prototype = Object.create( RopeSequence && RopeSequence.prototype ); + Append.prototype.constructor = Append; + + Append.prototype.flatten = function flatten () { + return this.left.flatten().concat(this.right.flatten()) + }; + + Append.prototype.getInner = function getInner (i) { + return i < this.left.length ? this.left.get(i) : this.right.get(i - this.left.length) + }; + + Append.prototype.forEachInner = function forEachInner (f, from, to, start) { + var leftLen = this.left.length; + if (from < leftLen && + this.left.forEachInner(f, from, Math.min(to, leftLen), start) === false) + { return false } + if (to > leftLen && + this.right.forEachInner(f, Math.max(from - leftLen, 0), Math.min(this.length, to) - leftLen, start + leftLen) === false) + { return false } + }; + + Append.prototype.forEachInvertedInner = function forEachInvertedInner (f, from, to, start) { + var leftLen = this.left.length; + if (from > leftLen && + this.right.forEachInvertedInner(f, from - leftLen, Math.max(to, leftLen) - leftLen, start + leftLen) === false) + { return false } + if (to < leftLen && + this.left.forEachInvertedInner(f, Math.min(from, leftLen), to, start) === false) + { return false } + }; + + Append.prototype.sliceInner = function sliceInner (from, to) { + if (from == 0 && to == this.length) { return this } + var leftLen = this.left.length; + if (to <= leftLen) { return this.left.slice(from, to) } + if (from >= leftLen) { return this.right.slice(from - leftLen, to - leftLen) } + return this.left.slice(from, leftLen).append(this.right.slice(0, to - leftLen)) + }; + + Append.prototype.leafAppend = function leafAppend (other) { + var inner = this.right.leafAppend(other); + if (inner) { return new Append(this.left, inner) } + }; + + Append.prototype.leafPrepend = function leafPrepend (other) { + var inner = this.left.leafPrepend(other); + if (inner) { return new Append(inner, this.right) } + }; + + Append.prototype.appendInner = function appendInner (other) { + if (this.left.depth >= Math.max(this.right.depth, other.depth) + 1) + { return new Append(this.left, new Append(this.right, other)) } + return new Append(this, other) + }; + + return Append; +}(RopeSequence)); + +module.exports = RopeSequence; diff --git a/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files b/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files index 1913e1b7f..7f6031148 100755 --- a/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files +++ b/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files @@ -42,6 +42,102 @@ "title": "prosemirror-schema-basic", "module-type": "library" } + }, + { + "file": "orderedmap.cjs", + "fields": { + "type": "application/javascript", + "title": "orderedmap", + "module-type": "library" + } + }, + { + "file": "prosemirror-transform.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-transform", + "module-type": "library" + } + }, + { + "file": "prosemirror-keymap.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-keymap", + "module-type": "library" + } + }, + { + "file": "prosemirror-history.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-history", + "module-type": "library" + } + }, + { + "file": "prosemirror-commands.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-commands", + "module-type": "library" + } + }, + { + "file": "prosemirror-dropcursor.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-dropcursor", + "module-type": "library" + } + }, + { + "file": "prosemirror-gapcursor.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-gapcursor", + "module-type": "library" + } + }, + { + "file": "prosemirror-menu.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-menu", + "module-type": "library" + } + }, + { + "file": "prosemirror-inputrules.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-inputrules", + "module-type": "library" + } + }, + { + "file": "w3c-keyname.cjs", + "fields": { + "type": "application/javascript", + "title": "w3c-keyname", + "module-type": "library" + } + }, + { + "file": "crelt.cjs", + "fields": { + "type": "application/javascript", + "title": "crelt", + "module-type": "library" + } + }, + { + "file": "rope-sequence.cjs", + "fields": { + "type": "application/javascript", + "title": "rope-sequence", + "module-type": "library" + } } ] } diff --git a/plugins/tiddlywiki/prosemirror/files/w3c-keyname.cjs b/plugins/tiddlywiki/prosemirror/files/w3c-keyname.cjs new file mode 100644 index 000000000..0f5ecd076 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/w3c-keyname.cjs @@ -0,0 +1,127 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var base = { + 8: "Backspace", + 9: "Tab", + 10: "Enter", + 12: "NumLock", + 13: "Enter", + 16: "Shift", + 17: "Control", + 18: "Alt", + 20: "CapsLock", + 27: "Escape", + 32: " ", + 33: "PageUp", + 34: "PageDown", + 35: "End", + 36: "Home", + 37: "ArrowLeft", + 38: "ArrowUp", + 39: "ArrowRight", + 40: "ArrowDown", + 44: "PrintScreen", + 45: "Insert", + 46: "Delete", + 59: ";", + 61: "=", + 91: "Meta", + 92: "Meta", + 106: "*", + 107: "+", + 108: ",", + 109: "-", + 110: ".", + 111: "/", + 144: "NumLock", + 145: "ScrollLock", + 160: "Shift", + 161: "Shift", + 162: "Control", + 163: "Control", + 164: "Alt", + 165: "Alt", + 173: "-", + 186: ";", + 187: "=", + 188: ",", + 189: "-", + 190: ".", + 191: "/", + 192: "`", + 219: "[", + 220: "\\", + 221: "]", + 222: "'" +}; + +var shift = { + 48: ")", + 49: "!", + 50: "@", + 51: "#", + 52: "$", + 53: "%", + 54: "^", + 55: "&", + 56: "*", + 57: "(", + 59: ":", + 61: "+", + 173: "_", + 186: ":", + 187: "+", + 188: "<", + 189: "_", + 190: ">", + 191: "?", + 192: "~", + 219: "{", + 220: "|", + 221: "}", + 222: "\"" +}; + +var mac = typeof navigator != "undefined" && /Mac/.test(navigator.platform); +var ie = typeof navigator != "undefined" && /MSIE \d|Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent); + +// Fill in the digit keys +for (var i = 0; i < 10; i++) base[48 + i] = base[96 + i] = String(i); + +// The function keys +for (var i = 1; i <= 24; i++) base[i + 111] = "F" + i; + +// And the alphabetic keys +for (var i = 65; i <= 90; i++) { + base[i] = String.fromCharCode(i + 32); + shift[i] = String.fromCharCode(i); +} + +// For each code that doesn't have a shift-equivalent, copy the base name +for (var code in base) if (!shift.hasOwnProperty(code)) shift[code] = base[code]; + +function keyName(event) { + // On macOS, keys held with Shift and Cmd don't reflect the effect of Shift in `.key`. + // On IE, shift effect is never included in `.key`. + var ignoreKey = mac && event.metaKey && event.shiftKey && !event.ctrlKey && !event.altKey || + ie && event.shiftKey && event.key && event.key.length == 1 || + event.key == "Unidentified"; + var name = (!ignoreKey && event.key) || + (event.shiftKey ? shift : base)[event.keyCode] || + event.key || "Unidentified"; + // Edge sometimes produces wrong names (Issue #3) + if (name == "Esc") name = "Escape"; + if (name == "Del") name = "Delete"; + // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8860571/ + if (name == "Left") name = "ArrowLeft"; + if (name == "Up") name = "ArrowUp"; + if (name == "Right") name = "ArrowRight"; + if (name == "Down") name = "ArrowDown"; + return name +} + +exports.base = base; +exports.keyName = keyName; +exports.shift = shift; diff --git a/plugins/tiddlywiki/prosemirror/readme.tid b/plugins/tiddlywiki/prosemirror/readme.tid index b77ad6a8a..b676b99dd 100755 --- a/plugins/tiddlywiki/prosemirror/readme.tid +++ b/plugins/tiddlywiki/prosemirror/readme.tid @@ -6,18 +6,21 @@ Test Test Downloaded from JsDelivr CDN (like `https://cdn.jsdelivr.net/npm/prosemirror-state@latest/dist/index.cjs` and store as `prosemirror-state.js`): -* [ext[prosemirror-state|https://cdn.jsdelivr.net/npm/prosemirror-state@latest/dist/index.cjs]]: 1.4.3 -* [ext[prosemirror-view|https://cdn.jsdelivr.net/npm/prosemirror-view@latest/dist/index.cjs]]: 1.38.1 -* [ext[prosemirror-model|https://cdn.jsdelivr.net/npm/prosemirror-model@latest/dist/index.cjs]]: 1.25.0 -* [ext[prosemirror-schema-basic|https://cdn.jsdelivr.net/npm/prosemirror-schema-basic@latest/dist/index.cjs]]: 1.2.4 -* [ext[prosemirror-schema-list|https://cdn.jsdelivr.net/npm/prosemirror-schema-list@latest/dist/index.cjs]]: 1.5.1 -* [ext[prosemirror-example-setup|https://cdn.jsdelivr.net/npm/prosemirror-example-setup@latest/dist/index.cjs]]: 1.2.3 -* [ext[orderedmap|https://cdn.jsdelivr.net/npm/orderedmap@latest/dist/index.cjs]]: latest -* [ext[prosemirror-transform|https://cdn.jsdelivr.net/npm/prosemirror-transform@latest/dist/index.cjs]]: latest -* [ext[prosemirror-keymap|https://cdn.jsdelivr.net/npm/prosemirror-keymap@latest/dist/index.cjs]]: latest -* [ext[prosemirror-history|https://cdn.jsdelivr.net/npm/prosemirror-history@latest/dist/index.cjs]]: latest -* [ext[prosemirror-commands|https://cdn.jsdelivr.net/npm/prosemirror-commands@latest/dist/index.cjs]]: latest -* [ext[prosemirror-dropcursor|https://cdn.jsdelivr.net/npm/prosemirror-dropcursor@latest/dist/index.cjs]]: latest -* [ext[prosemirror-gapcursor|https://cdn.jsdelivr.net/npm/prosemirror-gapcursor@latest/dist/index.cjs]]: latest -* [ext[prosemirror-menu|https://cdn.jsdelivr.net/npm/prosemirror-menu@latest/dist/index.cjs]]: latest -* [ext[prosemirror-inputrules|https://cdn.jsdelivr.net/npm/prosemirror-inputrules@latest/dist/index.cjs]]: latest +* [ext[prosemirror-state|https://cdn.jsdelivr.net/npm/prosemirror-state@latest/dist/index.cjs]]: v1.4.3 +* [ext[prosemirror-view|https://cdn.jsdelivr.net/npm/prosemirror-view@latest/dist/index.cjs]]: v1.38.1 +* [ext[prosemirror-model|https://cdn.jsdelivr.net/npm/prosemirror-model@latest/dist/index.cjs]]: v1.25.0 +* [ext[prosemirror-schema-basic|https://cdn.jsdelivr.net/npm/prosemirror-schema-basic@latest/dist/index.cjs]]: v1.2.4 +* [ext[prosemirror-schema-list|https://cdn.jsdelivr.net/npm/prosemirror-schema-list@latest/dist/index.cjs]]: v1.5.1 +* [ext[prosemirror-example-setup|https://cdn.jsdelivr.net/npm/prosemirror-example-setup@latest/dist/index.cjs]]: v1.2.3 +* [ext[orderedmap|https://cdn.jsdelivr.net/npm/orderedmap@latest/dist/index.cjs]]: v2.1.1 +* [ext[prosemirror-transform|https://cdn.jsdelivr.net/npm/prosemirror-transform@latest/dist/index.cjs]]: v1.10.3 +* [ext[prosemirror-keymap|https://cdn.jsdelivr.net/npm/prosemirror-keymap@latest/dist/index.cjs]]: v1.2.2 +* [ext[prosemirror-history|https://cdn.jsdelivr.net/npm/prosemirror-history@latest/dist/index.cjs]]: v1.4.1 +* [ext[prosemirror-commands|https://cdn.jsdelivr.net/npm/prosemirror-commands@latest/dist/index.cjs]]: v1.7.0 +* [ext[prosemirror-dropcursor|https://cdn.jsdelivr.net/npm/prosemirror-dropcursor@latest/dist/index.cjs]]: v1.8.1 +* [ext[prosemirror-gapcursor|https://cdn.jsdelivr.net/npm/prosemirror-gapcursor@latest/dist/index.cjs]]: v1.3.2 +* [ext[prosemirror-menu|https://cdn.jsdelivr.net/npm/prosemirror-menu@latest/dist/index.cjs]]: v1.2.4 +* [ext[prosemirror-inputrules|https://cdn.jsdelivr.net/npm/prosemirror-inputrules@latest/dist/index.cjs]]: v1.5.0 +* [ext[w3c-keyname|https://cdn.jsdelivr.net/npm/w3c-keyname@latest/dist/index.cjs]]: v2.2.8 +* [ext[crelt|https://cdn.jsdelivr.net/npm/crelt@latest/dist/index.cjs]]: v1.0.6 +* [ext[rope-sequence|https://cdn.jsdelivr.net/npm/rope-sequence@latest/dist/index.cjs]]: v1.3.4 From 06a8751939e85b9bb6045b73a280d794ad257e5f Mon Sep 17 00:00:00 2001 From: linonetwo Date: Sun, 23 Mar 2025 22:13:46 +0800 Subject: [PATCH 82/98] feat: add css from prosemirror-view and prosemirror-menu --- .../tiddlywiki/prosemirror/development.tid | 24 +++ plugins/tiddlywiki/prosemirror/files/menu.css | 148 ++++++++++++++++++ .../prosemirror/files/prosemirror.css | 54 +++++++ .../prosemirror/files/tiddlywiki.files | 15 ++ plugins/tiddlywiki/prosemirror/plugin.info | 2 +- plugins/tiddlywiki/prosemirror/readme.tid | 23 +-- plugins/tiddlywiki/prosemirror/tree.tid | 3 + plugins/tiddlywiki/prosemirror/widget.js | 9 +- 8 files changed, 249 insertions(+), 29 deletions(-) create mode 100755 plugins/tiddlywiki/prosemirror/development.tid create mode 100644 plugins/tiddlywiki/prosemirror/files/menu.css create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror.css create mode 100644 plugins/tiddlywiki/prosemirror/tree.tid diff --git a/plugins/tiddlywiki/prosemirror/development.tid b/plugins/tiddlywiki/prosemirror/development.tid new file mode 100755 index 000000000..6a14269e5 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/development.tid @@ -0,0 +1,24 @@ +title: $:/plugins/tiddlywiki/prosemirror/development + +Downloaded from JsDelivr CDN (like `https://cdn.jsdelivr.net/npm/prosemirror-state@latest/dist/index.cjs` and store as `prosemirror-state.js`): + +* [ext[prosemirror-state|https://cdn.jsdelivr.net/npm/prosemirror-state@latest/dist/index.cjs]]: v1.4.3 +* [ext[prosemirror-view|https://cdn.jsdelivr.net/npm/prosemirror-view@latest/dist/index.cjs]]: v1.38.1 +** [ext[prosemirror.css|https://cdn.jsdelivr.net/npm/prosemirror-view@latest/style/prosemirror.css]] +* [ext[prosemirror-model|https://cdn.jsdelivr.net/npm/prosemirror-model@latest/dist/index.cjs]]: v1.25.0 +* [ext[prosemirror-schema-basic|https://cdn.jsdelivr.net/npm/prosemirror-schema-basic@latest/dist/index.cjs]]: v1.2.4 +* [ext[prosemirror-schema-list|https://cdn.jsdelivr.net/npm/prosemirror-schema-list@latest/dist/index.cjs]]: v1.5.1 +* [ext[prosemirror-example-setup|https://cdn.jsdelivr.net/npm/prosemirror-example-setup@latest/dist/index.cjs]]: v1.2.3 +* [ext[orderedmap|https://cdn.jsdelivr.net/npm/orderedmap@latest/dist/index.cjs]]: v2.1.1 +* [ext[prosemirror-transform|https://cdn.jsdelivr.net/npm/prosemirror-transform@latest/dist/index.cjs]]: v1.10.3 +* [ext[prosemirror-keymap|https://cdn.jsdelivr.net/npm/prosemirror-keymap@latest/dist/index.cjs]]: v1.2.2 +* [ext[prosemirror-history|https://cdn.jsdelivr.net/npm/prosemirror-history@latest/dist/index.cjs]]: v1.4.1 +* [ext[prosemirror-commands|https://cdn.jsdelivr.net/npm/prosemirror-commands@latest/dist/index.cjs]]: v1.7.0 +* [ext[prosemirror-dropcursor|https://cdn.jsdelivr.net/npm/prosemirror-dropcursor@latest/dist/index.cjs]]: v1.8.1 +* [ext[prosemirror-gapcursor|https://cdn.jsdelivr.net/npm/prosemirror-gapcursor@latest/dist/index.cjs]]: v1.3.2 +* [ext[prosemirror-menu|https://cdn.jsdelivr.net/npm/prosemirror-menu@latest/dist/index.cjs]]: v1.2.4 +** [ext[menu.css|https://cdn.jsdelivr.net/npm/prosemirror-menu@latest/style/menu.css]] +* [ext[prosemirror-inputrules|https://cdn.jsdelivr.net/npm/prosemirror-inputrules@latest/dist/index.cjs]]: v1.5.0 +* [ext[w3c-keyname|https://cdn.jsdelivr.net/npm/w3c-keyname@latest/dist/index.cjs]]: v2.2.8 +* [ext[crelt|https://cdn.jsdelivr.net/npm/crelt@latest/dist/index.cjs]]: v1.0.6 +* [ext[rope-sequence|https://cdn.jsdelivr.net/npm/rope-sequence@latest/dist/index.cjs]]: v1.3.4 diff --git a/plugins/tiddlywiki/prosemirror/files/menu.css b/plugins/tiddlywiki/prosemirror/files/menu.css new file mode 100644 index 000000000..488350a58 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/menu.css @@ -0,0 +1,148 @@ +.ProseMirror-textblock-dropdown { + min-width: 3em; +} + +.ProseMirror-menu { + margin: 0 -4px; + line-height: 1; +} + +.ProseMirror-tooltip .ProseMirror-menu { + width: -webkit-fit-content; + width: fit-content; + white-space: pre; +} + +.ProseMirror-menuitem { + margin-right: 3px; + display: inline-block; +} + +.ProseMirror-menuseparator { + border-right: 1px solid #ddd; + margin-right: 3px; +} + +.ProseMirror-menu-dropdown, .ProseMirror-menu-dropdown-menu { + font-size: 90%; + white-space: nowrap; +} + +.ProseMirror-menu-dropdown { + vertical-align: 1px; + cursor: pointer; + position: relative; + padding-right: 15px; +} + +.ProseMirror-menu-dropdown-wrap { + padding: 1px 0 1px 4px; + display: inline-block; + position: relative; +} + +.ProseMirror-menu-dropdown:after { + content: ""; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid currentColor; + opacity: .6; + position: absolute; + right: 4px; + top: calc(50% - 2px); +} + +.ProseMirror-menu-dropdown-menu, .ProseMirror-menu-submenu { + position: absolute; + background: white; + color: #666; + border: 1px solid #aaa; + padding: 2px; +} + +.ProseMirror-menu-dropdown-menu { + z-index: 15; + min-width: 6em; +} + +.ProseMirror-menu-dropdown-item { + cursor: pointer; + padding: 2px 8px 2px 4px; +} + +.ProseMirror-menu-dropdown-item:hover { + background: #f2f2f2; +} + +.ProseMirror-menu-submenu-wrap { + position: relative; + margin-right: -4px; +} + +.ProseMirror-menu-submenu-label:after { + content: ""; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-left: 4px solid currentColor; + opacity: .6; + position: absolute; + right: 4px; + top: calc(50% - 4px); +} + +.ProseMirror-menu-submenu { + display: none; + min-width: 4em; + left: 100%; + top: -3px; +} + +.ProseMirror-menu-active { + background: #eee; + border-radius: 4px; +} + +.ProseMirror-menu-disabled { + opacity: .3; +} + +.ProseMirror-menu-submenu-wrap:hover .ProseMirror-menu-submenu, .ProseMirror-menu-submenu-wrap-active .ProseMirror-menu-submenu { + display: block; +} + +.ProseMirror-menubar { + border-top-left-radius: inherit; + border-top-right-radius: inherit; + position: relative; + min-height: 1em; + color: #666; + padding: 1px 6px; + top: 0; left: 0; right: 0; + border-bottom: 1px solid silver; + background: white; + z-index: 10; + -moz-box-sizing: border-box; + box-sizing: border-box; + overflow: visible; +} + +.ProseMirror-icon { + display: inline-block; + line-height: .8; + vertical-align: -2px; /* Compensate for padding */ + padding: 2px 8px; + cursor: pointer; +} + +.ProseMirror-menu-disabled.ProseMirror-icon { + cursor: default; +} + +.ProseMirror-icon svg { + fill: currentColor; + height: 1em; +} + +.ProseMirror-icon span { + vertical-align: text-top; +} diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror.css b/plugins/tiddlywiki/prosemirror/files/prosemirror.css new file mode 100644 index 000000000..75a90b240 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror.css @@ -0,0 +1,54 @@ +.ProseMirror { + position: relative; +} + +.ProseMirror { + word-wrap: break-word; + white-space: pre-wrap; + white-space: break-spaces; + -webkit-font-variant-ligatures: none; + font-variant-ligatures: none; + font-feature-settings: "liga" 0; /* the above doesn't seem to work in Edge */ +} + +.ProseMirror pre { + white-space: pre-wrap; +} + +.ProseMirror li { + position: relative; +} + +.ProseMirror-hideselection *::selection { background: transparent; } +.ProseMirror-hideselection *::-moz-selection { background: transparent; } +.ProseMirror-hideselection { caret-color: transparent; } + +/* See https://github.com/ProseMirror/prosemirror/issues/1421#issuecomment-1759320191 */ +.ProseMirror [draggable][contenteditable=false] { user-select: text } + +.ProseMirror-selectednode { + outline: 2px solid #8cf; +} + +/* Make sure li selections wrap around markers */ + +li.ProseMirror-selectednode { + outline: none; +} + +li.ProseMirror-selectednode:after { + content: ""; + position: absolute; + left: -32px; + right: -2px; top: -2px; bottom: -2px; + border: 2px solid #8cf; + pointer-events: none; +} + +/* Protect against generic img rules */ + +img.ProseMirror-separator { + display: inline !important; + border: none !important; + margin: 0 !important; +} diff --git a/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files b/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files index 7f6031148..395f8fc2e 100755 --- a/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files +++ b/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files @@ -21,6 +21,13 @@ "title": "prosemirror-view", "module-type": "library" } + },{ + "file": "prosemirror.css", + "fields": { + "type": "text/css", + "title": "$:/plugins/tiddlywiki/prosemirror/lib/prosemirror.css", + "tags": "[[$:/tags/Stylesheet]]" + } },{ "file": "prosemirror-schema-list.cjs", "fields": { @@ -107,6 +114,14 @@ "module-type": "library" } }, + { + "file": "menu.css", + "fields": { + "type": "text/css", + "title": "$:/plugins/tiddlywiki/prosemirror/lib/menu.css", + "tags": "[[$:/tags/Stylesheet]]" + } + }, { "file": "prosemirror-inputrules.cjs", "fields": { diff --git a/plugins/tiddlywiki/prosemirror/plugin.info b/plugins/tiddlywiki/prosemirror/plugin.info index 6476cc369..d708de136 100755 --- a/plugins/tiddlywiki/prosemirror/plugin.info +++ b/plugins/tiddlywiki/prosemirror/plugin.info @@ -2,6 +2,6 @@ "title": "$:/plugins/tiddlywiki/prosemirror", "name": "Prosemirror Visual Editor", "description": "WYSIWYG editor (What You See Is What You Get) for TiddlyWiki", - "list": "readme", + "list": "readme development tree", "stability": "STABILITY_1_EXPERIMENTAL" } diff --git a/plugins/tiddlywiki/prosemirror/readme.tid b/plugins/tiddlywiki/prosemirror/readme.tid index b676b99dd..a61db1e7d 100755 --- a/plugins/tiddlywiki/prosemirror/readme.tid +++ b/plugins/tiddlywiki/prosemirror/readme.tid @@ -1,26 +1,5 @@ title: $:/plugins/tiddlywiki/prosemirror/readme -Test Test +Test `<$prosemirror />`, see console for content JSON. <$prosemirror /> - -Downloaded from JsDelivr CDN (like `https://cdn.jsdelivr.net/npm/prosemirror-state@latest/dist/index.cjs` and store as `prosemirror-state.js`): - -* [ext[prosemirror-state|https://cdn.jsdelivr.net/npm/prosemirror-state@latest/dist/index.cjs]]: v1.4.3 -* [ext[prosemirror-view|https://cdn.jsdelivr.net/npm/prosemirror-view@latest/dist/index.cjs]]: v1.38.1 -* [ext[prosemirror-model|https://cdn.jsdelivr.net/npm/prosemirror-model@latest/dist/index.cjs]]: v1.25.0 -* [ext[prosemirror-schema-basic|https://cdn.jsdelivr.net/npm/prosemirror-schema-basic@latest/dist/index.cjs]]: v1.2.4 -* [ext[prosemirror-schema-list|https://cdn.jsdelivr.net/npm/prosemirror-schema-list@latest/dist/index.cjs]]: v1.5.1 -* [ext[prosemirror-example-setup|https://cdn.jsdelivr.net/npm/prosemirror-example-setup@latest/dist/index.cjs]]: v1.2.3 -* [ext[orderedmap|https://cdn.jsdelivr.net/npm/orderedmap@latest/dist/index.cjs]]: v2.1.1 -* [ext[prosemirror-transform|https://cdn.jsdelivr.net/npm/prosemirror-transform@latest/dist/index.cjs]]: v1.10.3 -* [ext[prosemirror-keymap|https://cdn.jsdelivr.net/npm/prosemirror-keymap@latest/dist/index.cjs]]: v1.2.2 -* [ext[prosemirror-history|https://cdn.jsdelivr.net/npm/prosemirror-history@latest/dist/index.cjs]]: v1.4.1 -* [ext[prosemirror-commands|https://cdn.jsdelivr.net/npm/prosemirror-commands@latest/dist/index.cjs]]: v1.7.0 -* [ext[prosemirror-dropcursor|https://cdn.jsdelivr.net/npm/prosemirror-dropcursor@latest/dist/index.cjs]]: v1.8.1 -* [ext[prosemirror-gapcursor|https://cdn.jsdelivr.net/npm/prosemirror-gapcursor@latest/dist/index.cjs]]: v1.3.2 -* [ext[prosemirror-menu|https://cdn.jsdelivr.net/npm/prosemirror-menu@latest/dist/index.cjs]]: v1.2.4 -* [ext[prosemirror-inputrules|https://cdn.jsdelivr.net/npm/prosemirror-inputrules@latest/dist/index.cjs]]: v1.5.0 -* [ext[w3c-keyname|https://cdn.jsdelivr.net/npm/w3c-keyname@latest/dist/index.cjs]]: v2.2.8 -* [ext[crelt|https://cdn.jsdelivr.net/npm/crelt@latest/dist/index.cjs]]: v1.0.6 -* [ext[rope-sequence|https://cdn.jsdelivr.net/npm/rope-sequence@latest/dist/index.cjs]]: v1.3.4 diff --git a/plugins/tiddlywiki/prosemirror/tree.tid b/plugins/tiddlywiki/prosemirror/tree.tid new file mode 100644 index 000000000..b0649663a --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/tree.tid @@ -0,0 +1,3 @@ +title: $:/plugins/tiddlywiki/prosemirror/tree + +<> \ No newline at end of file diff --git a/plugins/tiddlywiki/prosemirror/widget.js b/plugins/tiddlywiki/prosemirror/widget.js index 1be2c7a65..16d47ab8a 100644 --- a/plugins/tiddlywiki/prosemirror/widget.js +++ b/plugins/tiddlywiki/prosemirror/widget.js @@ -49,7 +49,7 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { var self = this; this.view = new EditorView(container, { state: EditorState.create({ - doc: DOMParser.fromSchema(mySchema).parse(document.querySelector("#content")), + doc: mySchema.node("doc", null, [mySchema.node("paragraph")]), plugins: exampleSetup({schema: mySchema}) }), dispatchTransaction: function(transaction) { @@ -64,11 +64,8 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { }; ProsemirrorWidget.prototype.saveEditorContent = function() { - this.editor.save().then((outputData) => { - console.log('Article data: ', outputData) - }).catch((error) => { - console.log('Saving failed: ', error) - }); + const content = this.view.state.doc.toJSON(); + console.log(JSON.stringify(content)); } // Debounced save function for performance From c208e6741f7146da930474a9d4f63b52c9806e04 Mon Sep 17 00:00:00 2001 From: linonetwo Date: Sun, 23 Mar 2025 22:38:13 +0800 Subject: [PATCH 83/98] chore: trigger preview page build --- plugins/tiddlywiki/prosemirror/readme.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tiddlywiki/prosemirror/readme.tid b/plugins/tiddlywiki/prosemirror/readme.tid index a61db1e7d..48468cfe9 100755 --- a/plugins/tiddlywiki/prosemirror/readme.tid +++ b/plugins/tiddlywiki/prosemirror/readme.tid @@ -1,5 +1,5 @@ title: $:/plugins/tiddlywiki/prosemirror/readme -Test `<$prosemirror />`, see console for content JSON. +Test `<$prosemirror />` widget below, see console for content JSON. <$prosemirror /> From 323e4c941f9f9e892b310792c794dff2a0cc985a Mon Sep 17 00:00:00 2001 From: linonetwo Date: Sun, 23 Mar 2025 22:47:46 +0800 Subject: [PATCH 84/98] chore: rename to trigger netlify --- .../ast/{wikiAstFromEditorJSAst.js => from-prosemirror.js} | 0 .../ast/{wikiAstToEditorJSAst.js => to-prosemirror.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename plugins/tiddlywiki/prosemirror/ast/{wikiAstFromEditorJSAst.js => from-prosemirror.js} (100%) rename plugins/tiddlywiki/prosemirror/ast/{wikiAstToEditorJSAst.js => to-prosemirror.js} (100%) diff --git a/plugins/tiddlywiki/prosemirror/ast/wikiAstFromEditorJSAst.js b/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js similarity index 100% rename from plugins/tiddlywiki/prosemirror/ast/wikiAstFromEditorJSAst.js rename to plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js diff --git a/plugins/tiddlywiki/prosemirror/ast/wikiAstToEditorJSAst.js b/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js similarity index 100% rename from plugins/tiddlywiki/prosemirror/ast/wikiAstToEditorJSAst.js rename to plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js From de0c98978cf4353bcc1fd2c777066957b292fd65 Mon Sep 17 00:00:00 2001 From: linonetwo Date: Sun, 23 Mar 2025 22:29:06 +0800 Subject: [PATCH 85/98] DEBUG: add "tiddlywiki/prosemirror" to preview website DEBUG: add "tiddlywiki/prosemirror" to preview website --- editions/prerelease/tiddlers/system/DefaultTiddlers.tid | 9 +-------- editions/prerelease/tiddlywiki.info | 3 ++- editions/tw5.com/tiddlers/system/DefaultTiddlers.tid | 8 +------- editions/tw5.com/tiddlywiki.info | 3 ++- 4 files changed, 6 insertions(+), 17 deletions(-) diff --git a/editions/prerelease/tiddlers/system/DefaultTiddlers.tid b/editions/prerelease/tiddlers/system/DefaultTiddlers.tid index 66d1c9bab..05fa6d46c 100644 --- a/editions/prerelease/tiddlers/system/DefaultTiddlers.tid +++ b/editions/prerelease/tiddlers/system/DefaultTiddlers.tid @@ -2,11 +2,4 @@ created: 20131127215321439 modified: 20140912135951542 title: $:/DefaultTiddlers -[[TiddlyWiki Pre-release]] -HelloThere -[[Quick Start]] -[[Find Out More]] -[[TiddlyWiki on the Web]] -[[Testimonials and Reviews]] -GettingStarted -Community +$:/plugins/tiddlywiki/prosemirror diff --git a/editions/prerelease/tiddlywiki.info b/editions/prerelease/tiddlywiki.info index c469dcf99..72a98dc0e 100644 --- a/editions/prerelease/tiddlywiki.info +++ b/editions/prerelease/tiddlywiki.info @@ -17,7 +17,8 @@ "tiddlywiki/jszip", "tiddlywiki/confetti", "tiddlywiki/dynannotate", - "tiddlywiki/tour" + "tiddlywiki/tour", + "tiddlywiki/prosemirror" ], "themes": [ "tiddlywiki/vanilla", diff --git a/editions/tw5.com/tiddlers/system/DefaultTiddlers.tid b/editions/tw5.com/tiddlers/system/DefaultTiddlers.tid index 7b9e94cbc..8810aa2c1 100644 --- a/editions/tw5.com/tiddlers/system/DefaultTiddlers.tid +++ b/editions/tw5.com/tiddlers/system/DefaultTiddlers.tid @@ -3,10 +3,4 @@ modified: 20140912135951542 title: $:/DefaultTiddlers type: text/vnd.tiddlywiki -HelloThere -[[Quick Start]] -[[Find Out More]] -[[TiddlyWiki on the Web]] -[[Testimonials and Reviews]] -GettingStarted -Community +$:/plugins/tiddlywiki/prosemirror diff --git a/editions/tw5.com/tiddlywiki.info b/editions/tw5.com/tiddlywiki.info index 2f3ddade8..873fbdb82 100644 --- a/editions/tw5.com/tiddlywiki.info +++ b/editions/tw5.com/tiddlywiki.info @@ -7,7 +7,8 @@ "tiddlywiki/menubar", "tiddlywiki/confetti", "tiddlywiki/dynannotate", - "tiddlywiki/tour" + "tiddlywiki/tour", + "tiddlywiki/prosemirror" ], "themes": [ "tiddlywiki/vanilla", From 2941bf6af3e2f9788d6d15defaa8be50b7940f8b Mon Sep 17 00:00:00 2001 From: linonetwo Date: Sun, 23 Mar 2025 23:01:39 +0800 Subject: [PATCH 86/98] fix: document is not defined by checking !$tw.browser ReferenceError: document is not defined at $tw.utils.domMaker ($:/boot/boot.js:181:32) at ProsemirrorWidget.render ($:/plugins/tiddlywiki/prosemirror/widget.js:36:29) --- plugins/tiddlywiki/prosemirror/widget-loader.js | 15 +++++++++++++++ plugins/tiddlywiki/prosemirror/widget.js | 4 +--- 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 plugins/tiddlywiki/prosemirror/widget-loader.js diff --git a/plugins/tiddlywiki/prosemirror/widget-loader.js b/plugins/tiddlywiki/prosemirror/widget-loader.js new file mode 100644 index 000000000..849c7c98c --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/widget-loader.js @@ -0,0 +1,15 @@ +/*\ +title: $:/plugins/tiddlywiki/prosemirror/widget-loader.js +type: application/javascript +module-type: widget + +\*/ + +if (!$tw.browser) { + return; +} +// separate the widget from the exports here, so we can skip the require of react code if `!$tw.browser`. Those ts code will error if loaded in the nodejs side. +const components = require('$:/plugins/tiddlywiki/prosemirror/widget.js'); +const { prosemirror } = components; +exports.prosemirror = prosemirror; +exports['edit-prosemirror'] = prosemirror; \ No newline at end of file diff --git a/plugins/tiddlywiki/prosemirror/widget.js b/plugins/tiddlywiki/prosemirror/widget.js index 16d47ab8a..fe1924cd9 100644 --- a/plugins/tiddlywiki/prosemirror/widget.js +++ b/plugins/tiddlywiki/prosemirror/widget.js @@ -1,9 +1,7 @@ /*\ title: $:/plugins/tiddlywiki/prosemirror/widget.js type: application/javascript -module-type: widget - -Text node widget +module-type: library \*/ From e2414094f66c4b5c4044c386f762cefa27137528 Mon Sep 17 00:00:00 2001 From: linonetwo Date: Mon, 24 Mar 2025 00:38:03 +0800 Subject: [PATCH 87/98] feat: example ast round trip --- .../prosemirror/ast/from-prosemirror.js | 118 ++++++--- .../prosemirror/ast/to-prosemirror.js | 226 +++++++++++++----- plugins/tiddlywiki/prosemirror/widget.js | 27 ++- 3 files changed, 269 insertions(+), 102 deletions(-) diff --git a/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js b/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js index 00bd23701..a552340f9 100644 --- a/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js +++ b/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js @@ -1,40 +1,89 @@ /*\ -title: $:/plugins/tiddlywiki/prosemirror/ast/wikiAstFromProsemirrorAst.js +title: $:/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js type: application/javascript module-type: library -Get the Prosemirror AST from a Wiki AST +Get the Wiki AST from a Prosemirror AST \*/ +function doc(context, node) { + return convertNodes(context, node.content); +} + +function paragraph(context, node) { + return { + type: "element", + tag: "p", + rule: "parseblock", + children: convertNodes(context, node.content) + }; +} + +function text(context, node) { + return { + type: "text", + text: node.text + } +} + +function heading(context, node) { + return { + type: "element", + tag: "h" + node.attrs.level, + rule: "heading", + attributes: { + // TODO: restore class if any + }, + children: convertNodes(context, node.content) + }; +} + +function bullet_list(context, node) { + return { + type: "element", + tag: "ul", + rule: "list", + children: convertNodes(context, node.content) + }; +} + +function ordered_list(context, node) { + return { + type: "element", + tag: "ol", + rule: "list", + children: convertNodes(context, node.content) + }; +} + +function list_item(context, node) { + return { + type: "element", + tag: "li", + rule: "list", + children: convertNodes(context, node.content) + }; +} /** * Key is `node.type`, value is node converter function. */ const builders = { - // auto parse basic element nodes - // eslint-disable-next-line unicorn/prefer-object-from-entries - ...(htmlTags).reduce( - (previousValue, currentValue) => { - previousValue[currentValue] = element; - return previousValue; - }, - // eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter, @typescript-eslint/consistent-type-assertions - {}, - ), - [ELEMENT_CODE_BLOCK]: codeblock, - [ELEMENT_LIC]: lic, + doc, + paragraph, text, - widget, - macro: widget, - set, + heading, + bullet_list, + ordered_list, + list_item, }; -function wikiAstFromProsemirrorAst(input) { +function wikiAstFromProseMirrorAst(input) { return convertNodes(builders, Array.isArray(input) ? input : [input]); } -exports.wikiAstFromProsemirrorAst = wikiAstFromProsemirrorAst; +exports.from = wikiAstFromProseMirrorAst; function convertNodes(builders, nodes) { if (nodes === undefined || nodes.length === 0) { @@ -42,27 +91,22 @@ function convertNodes(builders, nodes) { } return nodes.reduce((accumulator, node) => { - return [...accumulator, ...convertWikiAstNode(builders, node)]; + return [...accumulator, ...convertANode(builders, node)]; }, []); } -function convertWikiAstNode(builders, node) { - // only text and root node don't have a `type` field, deal with it first - if (isText(node)) { - return [builders.text(builders, node)]; - } - if (isElement(node)) { - const builder = builders[node.type]; - if (typeof builder === 'function') { - const builtSlateNodeOrNodes = builder(builders, node); - return Array.isArray(builtSlateNodeOrNodes) - ? builtSlateNodeOrNodes.map((child) => ({ ...getSlatePlateASTAdditionalProperties(node), ...child })) - : ([{ ...getSlatePlateASTAdditionalProperties(node), ...builtSlateNodeOrNodes }]); - } - } - // it might be a root or pure parent node, reduce it - if ('children' in node) { - return convertNodes(builders, node.children); +function restoreMetadata(node) { + // TODO: restore attributes, orderedAttributes, isBlock + return {}; +} +function convertANode(builders, node) { + var builder = builders[node.type]; + if (typeof builder === 'function') { + var convertedNode = builder(builders, node); + var arrayOfNodes = (Array.isArray(convertedNode) + ? convertedNode : [convertedNode]); + return arrayOfNodes.map((child) => ({ ...restoreMetadata(node), ...child })); } + console.warn(`WikiAst get Unknown node type: ${JSON.stringify(node)}`); return []; } diff --git a/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js b/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js index 3d5b9c0e3..21263c3f7 100644 --- a/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js +++ b/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js @@ -1,83 +1,189 @@ /*\ -title: $:/plugins/tiddlywiki/prosemirror/ast/wikiAstToProsemirrorAst.js +title: $:/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js type: application/javascript module-type: library Get the Prosemirror AST from a Wiki AST \*/ -function wikiAstToProsemirrorAst(node, options) { - return convertNodes({ ...initialContext, ...options }, Array.isArray(node) ? node : [node]); + +/** + * Many node shares same type `element` in wikiAst, we need to distinguish them by tag. + */ +const elementBuilders = { + p: function(context, node) { + return { + type: "paragraph", + content: convertNodes(context, node.children) + }; + }, + h1: function(context, node) { + return { + type: "heading", + attrs: { level: 1 }, + content: convertNodes(context, node.children) + }; + }, + h2: function(context, node) { + return { + type: "heading", + attrs: { level: 2 }, + content: convertNodes(context, node.children) + }; + }, + h3: function(context, node) { + return { + type: "heading", + attrs: { level: 3 }, + content: convertNodes(context, node.children) + }; + }, + h4: function(context, node) { + return { + type: "heading", + attrs: { level: 4 }, + content: convertNodes(context, node.children) + }; + }, + h5: function(context, node) { + return { + type: "heading", + attrs: { level: 5 }, + content: convertNodes(context, node.children) + }; + }, + h6: function(context, node) { + return { + type: "heading", + attrs: { level: 6 }, + content: convertNodes(context, node.children) + }; + }, + ul: function(context, node) { + return { + type: "bullet_list", + content: convertNodes(context, node.children) + }; + }, + ol: function(context, node) { + return { + type: "ordered_list", + content: convertNodes(context, node.children) + }; + }, + li: function(context, node) { + // In ProseMirror, list items must contain block content (not bare text) + // TODO: find solution to https://discuss.prosemirror.net/t/removing-the-default-paragraph-p-inside-a-list-item-li/2745/17 + const processedContent = convertNodes(context, node.children); + const wrappedContent = wrapTextNodesInParagraphs(context, processedContent); + + return { + type: "list_item", + content: wrappedContent + }; + } +}; + +/** + * Helper function to ensure text nodes in list items are wrapped in paragraphs + * ProseMirror requires list items to contain block content, not bare text + */ +function wrapTextNodesInParagraphs(context, nodes) { + if (!nodes || nodes.length === 0) { + return []; + } + + const result = []; + let currentTextNodes = []; + + function flushTextNodes() { + if (currentTextNodes.length > 0) { + result.push({ + type: "paragraph", + content: currentTextNodes + }); + currentTextNodes = []; + } + } + + nodes.forEach(node => { + // If it's a text node, collect it + if (node.type === "text") { + currentTextNodes.push(node); + } else { + // If we encounter a non-text node, flush any collected text nodes + flushTextNodes(); + // Add the non-text node as is + result.push(node); + } + }); + + // Flush any remaining text nodes + flushTextNodes(); + + return result; } -exports.wikiAstToProsemirrorAst = wikiAstToProsemirrorAst; +function element(context, node) { + const builder = elementBuilders[node.tag]; + if (builder) { + return builder(context, node); + } else { + console.warn(`Unknown element tag: ${node.tag}`); + return []; + } +} -const initialContext = { - builders, - marks: {}, +function text(context, node) { + return { + type: "text", + text: node.text + }; +} + +/** + * Key is wikiAst node type, value is node converter function. + */ +const builders = { + element, + text }; +function wikiAstToProsemirrorAst(node, options) { + const context = { ...builders, ...options }; + const result = convertNodes(context, Array.isArray(node) ? node : [node]); + + // Wrap in a doc if needed + if (result.length > 0 && result[0].type !== "doc") { + return { + type: "doc", + content: result + }; + } + + return result; +} + +exports.to = wikiAstToProsemirrorAst; + function convertNodes(context, nodes) { if (nodes === undefined || nodes.length === 0) { - return [{ text: '' }]; + return []; } return nodes.reduce((accumulator, node) => { - return [...accumulator, ...prosemirrorNode(context, node)]; + return [...accumulator, ...convertANode(context, node)]; }, []); } -function prosemirrorNode(context, node) { - const id = context.idCreator?.(); - const withId = (nodeToAddId) => (id === undefined ? nodeToAddId : { ...nodeToAddId, id }); - if ('rule' in node && node.rule !== undefined && node.rule in context.builders) { - const builder = context.builders[node.rule]; - if (typeof builder === 'function') { - // basic elements - const builtProsemirrorNodeOrNodes = builder(context, node); - return Array.isArray(builtProsemirrorNodeOrNodes) - ? builtProsemirrorNodeOrNodes.map((child) => withId(child)) - : ([withId(builtProsemirrorNodeOrNodes)]); - } - } else if ('text' in node) { - // text node - return [withId({ text: node.text })]; - } else { - console.warn(`WikiAst get Unknown node type: ${JSON.stringify(node)}`); - return []; +function convertANode(context, node) { + var builder = context[node.type]; + if (typeof builder === 'function') { + var convertedNode = builder(context, node); + var arrayOfNodes = (Array.isArray(convertedNode) + ? convertedNode : [convertedNode]); + return arrayOfNodes; } + console.warn(`ProseMirror get Unknown node type: ${JSON.stringify(node)}`); return []; } - -const builders = { - element, - text, -}; - -/** Slate node is compact, we need to filter out some keys from wikiast */ -const textLevelKeysToOmit = ['type', 'start', 'end']; - -function text(context, text) { - return { - text: '', // provides default text - ...omit(text, textLevelKeysToOmit), - ...context.marks, - }; -} - -const elementBuilders = { ul, ol: ul, li, ...marks }; - -function element(context, node) { - const { tag, children } = node; - if (typeof elementBuilders[tag] === 'function') { - return elementBuilders[tag](context, node); - } - const result = { - type: tag, - children: convertNodes(context, children), - }; - if (node.rule) { - result.rule = node.rule; - } - return result; -} diff --git a/plugins/tiddlywiki/prosemirror/widget.js b/plugins/tiddlywiki/prosemirror/widget.js index fe1924cd9..8279baa47 100644 --- a/plugins/tiddlywiki/prosemirror/widget.js +++ b/plugins/tiddlywiki/prosemirror/widget.js @@ -9,6 +9,8 @@ module-type: library var Widget = require("$:/core/modules/widgets/widget.js").widget; var debounce = require("$:/core/modules/utils/debounce.js").debounce; +var wikiAstFromProseMirrorAst = require("$:/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js").from; +var wikiAstToProseMirrorAst = require("$:/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js").to; var { EditorState } = require("prosemirror-state"); var { EditorView } = require("prosemirror-view"); @@ -39,15 +41,26 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { // Mix the nodes from prosemirror-schema-list into the basic schema to // create a schema with list support. - const mySchema = new Schema({ - nodes: addListNodes(schema.spec.nodes, "paragraph block*", "block"), + var mySchema = new Schema({ + // nodes: addListNodes(schema.spec.nodes, "paragraph block*", "block"), + nodes: addListNodes(schema.spec.nodes, "block*", "block"), marks: schema.spec.marks }) var self = this; + var wikiAst = $tw.wiki.parseText(null, `* This is an unordered list +* It has two items + +# This is a numbered list +## With a subitem +# And a third item`).tree; + var doc = wikiAstToProseMirrorAst(wikiAst); + // DEBUG: console doc + console.log(`initial doc`, doc); this.view = new EditorView(container, { state: EditorState.create({ - doc: mySchema.node("doc", null, [mySchema.node("paragraph")]), + // doc: mySchema.node("doc", null, [mySchema.node("paragraph")]), + doc: mySchema.nodeFromJSON(doc), plugins: exampleSetup({schema: mySchema}) }), dispatchTransaction: function(transaction) { @@ -62,8 +75,12 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { }; ProsemirrorWidget.prototype.saveEditorContent = function() { - const content = this.view.state.doc.toJSON(); - console.log(JSON.stringify(content)); + var content = this.view.state.doc.toJSON(); + console.log(`ProseMirror: ${JSON.stringify(content)}`); + var wikiast = wikiAstFromProseMirrorAst(content); + console.log(`WikiAST: ${JSON.stringify(wikiast)}`); + var wikiText = $tw.utils.serializeParseTree(wikiast); + console.log(`WikiText: ${wikiText}`); } // Debounced save function for performance From eecab2c0b80ea905ce6757effbe48a3b0e5d2d78 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 24 Mar 2025 02:34:54 +0800 Subject: [PATCH 88/98] feat: replace prosemirror-schema-list to prosemirror-flat-list --- .../prosemirror/ast/from-prosemirror.js | 38 +- .../prosemirror/ast/to-prosemirror.js | 28 +- .../tiddlywiki/prosemirror/development.tid | 10 +- .../files/prosemirror-flat-list.cjs | 1779 +++++++++++++++++ .../files/prosemirror-flat-list.css | 87 + .../files/prosemirror-safari-ime-span.cjs | 74 + .../prosemirror/files/tiddlywiki.files | 60 +- plugins/tiddlywiki/prosemirror/widget.js | 35 +- 8 files changed, 2039 insertions(+), 72 deletions(-) create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.cjs create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.css create mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-safari-ime-span.cjs diff --git a/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js b/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js index a552340f9..cfa4a66f6 100644 --- a/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js +++ b/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js @@ -39,30 +39,22 @@ function heading(context, node) { }; } -function bullet_list(context, node) { +function list(context, node) { + const listType = node.attrs && node.attrs.kind === "ordered" ? "ol" : "ul"; + + const listItems = node.content.map(item => { + return { + type: "element", + tag: "li", + children: convertANode(context, item) + }; + }); + return { type: "element", - tag: "ul", + tag: listType, rule: "list", - children: convertNodes(context, node.content) - }; -} - -function ordered_list(context, node) { - return { - type: "element", - tag: "ol", - rule: "list", - children: convertNodes(context, node.content) - }; -} - -function list_item(context, node) { - return { - type: "element", - tag: "li", - rule: "list", - children: convertNodes(context, node.content) + children: listItems }; } @@ -74,9 +66,7 @@ const builders = { paragraph, text, heading, - bullet_list, - ordered_list, - list_item, + list, }; function wikiAstFromProseMirrorAst(input) { diff --git a/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js b/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js index 21263c3f7..14ecbfe67 100644 --- a/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js +++ b/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js @@ -61,26 +61,34 @@ const elementBuilders = { }, ul: function(context, node) { return { - type: "bullet_list", + type: "list", + attrs: { + kind: "bullet", + order: null, + checked: false, + collapsed: false + }, content: convertNodes(context, node.children) }; }, ol: function(context, node) { return { - type: "ordered_list", + type: "list", + attrs: { + kind: "ordered", + order: null, + checked: false, + collapsed: false + }, content: convertNodes(context, node.children) }; }, li: function(context, node) { - // In ProseMirror, list items must contain block content (not bare text) - // TODO: find solution to https://discuss.prosemirror.net/t/removing-the-default-paragraph-p-inside-a-list-item-li/2745/17 + // In ProseMirror, list items are converted to paragraphs or other block content + // directly under the list node, no special list_item type needed const processedContent = convertNodes(context, node.children); - const wrappedContent = wrapTextNodesInParagraphs(context, processedContent); - - return { - type: "list_item", - content: wrappedContent - }; + // Ensure content starts with a block element (typically paragraph) + return wrapTextNodesInParagraphs(context, processedContent); } }; diff --git a/plugins/tiddlywiki/prosemirror/development.tid b/plugins/tiddlywiki/prosemirror/development.tid index 6a14269e5..8d50f720b 100755 --- a/plugins/tiddlywiki/prosemirror/development.tid +++ b/plugins/tiddlywiki/prosemirror/development.tid @@ -7,7 +7,9 @@ Downloaded from JsDelivr CDN (like `https://cdn.jsdelivr.net/npm/prosemirror-sta ** [ext[prosemirror.css|https://cdn.jsdelivr.net/npm/prosemirror-view@latest/style/prosemirror.css]] * [ext[prosemirror-model|https://cdn.jsdelivr.net/npm/prosemirror-model@latest/dist/index.cjs]]: v1.25.0 * [ext[prosemirror-schema-basic|https://cdn.jsdelivr.net/npm/prosemirror-schema-basic@latest/dist/index.cjs]]: v1.2.4 -* [ext[prosemirror-schema-list|https://cdn.jsdelivr.net/npm/prosemirror-schema-list@latest/dist/index.cjs]]: v1.5.1 +* [ext[prosemirror-flat-list|https://cdn.jsdelivr.net/npm/prosemirror-flat-list@latest/dist/prosemirror-flat-list.cjs]]: v0.5.4 +** [ext[prosemirror-flat-list.css|https://cdn.jsdelivr.net/npm/prosemirror-flat-list@latest/dist/style.css]] +** (Instead of [ext[prosemirror-schema-list|https://cdn.jsdelivr.net/npm/prosemirror-schema-list@latest/dist/index.cjs]]) * [ext[prosemirror-example-setup|https://cdn.jsdelivr.net/npm/prosemirror-example-setup@latest/dist/index.cjs]]: v1.2.3 * [ext[orderedmap|https://cdn.jsdelivr.net/npm/orderedmap@latest/dist/index.cjs]]: v2.1.1 * [ext[prosemirror-transform|https://cdn.jsdelivr.net/npm/prosemirror-transform@latest/dist/index.cjs]]: v1.10.3 @@ -22,3 +24,9 @@ Downloaded from JsDelivr CDN (like `https://cdn.jsdelivr.net/npm/prosemirror-sta * [ext[w3c-keyname|https://cdn.jsdelivr.net/npm/w3c-keyname@latest/dist/index.cjs]]: v2.2.8 * [ext[crelt|https://cdn.jsdelivr.net/npm/crelt@latest/dist/index.cjs]]: v1.0.6 * [ext[rope-sequence|https://cdn.jsdelivr.net/npm/rope-sequence@latest/dist/index.cjs]]: v1.3.4 +* [ext[prosemirror-safari-ime-span|https://cdn.jsdelivr.net/npm/prosemirror-safari-ime-span@latest/dist/index.cjs]]: v1.0.2 + +!! TODO + +* remove prosemirror-example-setup, move all configs here. And remove `prosemirror-schema-list` that it depends on. +* prosemirror-flat-list only add dot style to list container, not each list item. Make it looks weird. And when creating new list, it will make each item to be a full new list, which is also weird. diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.cjs new file mode 100644 index 000000000..e19361fcd --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.cjs @@ -0,0 +1,1779 @@ +"use strict"; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + ListDOMSerializer: () => ListDOMSerializer, + backspaceCommand: () => backspaceCommand, + createDedentListCommand: () => createDedentListCommand, + createIndentListCommand: () => createIndentListCommand, + createListClipboardPlugin: () => createListClipboardPlugin, + createListEventPlugin: () => createListEventPlugin, + createListNodeView: () => createListNodeView, + createListPlugins: () => createListPlugins, + createListRenderingPlugin: () => createListRenderingPlugin, + createListSpec: () => createListSpec, + createMoveListCommand: () => createMoveListCommand, + createParseDomRules: () => createParseDomRules, + createSafariInputMethodWorkaroundPlugin: () => createSafariInputMethodWorkaroundPlugin, + createSplitListCommand: () => createSplitListCommand, + createToggleCollapsedCommand: () => createToggleCollapsedCommand, + createToggleListCommand: () => createToggleListCommand, + createUnwrapListCommand: () => createUnwrapListCommand, + createWrapInListCommand: () => createWrapInListCommand, + defaultAttributesGetter: () => defaultAttributesGetter, + defaultListClickHandler: () => defaultListClickHandler, + defaultMarkerGetter: () => defaultMarkerGetter, + deleteCommand: () => deleteCommand, + doSplitList: () => doSplitList, + enterCommand: () => enterCommand, + enterWithoutLift: () => enterWithoutLift, + findListsRange: () => findListsRange, + flatListGroup: () => flatListGroup, + getListType: () => getListType, + handleListMarkerMouseDown: () => handleListMarkerMouseDown, + isCollapsedListNode: () => isCollapsedListNode, + isListNode: () => isListNode, + isListType: () => isListType, + isListsRange: () => isListsRange, + joinCollapsedListBackward: () => joinCollapsedListBackward, + joinListElements: () => joinListElements, + joinListUp: () => joinListUp, + listInputRules: () => listInputRules, + listKeymap: () => listKeymap, + listToDOM: () => listToDOM, + migrateDocJSON: () => migrateDocJSON, + parseInteger: () => parseInteger, + protectCollapsed: () => protectCollapsed, + rangeToString: () => rangeToString, + setSafeSelection: () => setSafeSelection, + unwrapListSlice: () => unwrapListSlice, + wrappingListInputRule: () => wrappingListInputRule +}); +module.exports = __toCommonJS(src_exports); + +// src/commands/dedent-list.ts +var import_prosemirror_model2 = require("prosemirror-model"); +var import_prosemirror_transform3 = require("prosemirror-transform"); + +// src/utils/auto-fix-list.ts +var import_prosemirror_transform = require("prosemirror-transform"); + +// src/utils/parse-integer.ts +function parseInteger(attr) { + if (attr == null) return null; + const int = Number.parseInt(attr, 10); + if (Number.isInteger(int)) return int; + return null; +} + +// src/schema/parse-dom.ts +function createParseDomRules() { + return [ + { + tag: "div[data-list-kind]", + getAttrs: (element) => { + if (typeof element === "string") { + return {}; + } + return { + kind: element.getAttribute("data-list-kind") || "bullet", + order: parseInteger(element.getAttribute("data-list-order")), + checked: element.hasAttribute("data-list-checked"), + collapsed: element.hasAttribute("data-list-collapsed") + }; + } + }, + { + tag: "div[data-list]", + getAttrs: (element) => { + if (typeof element === "string") { + return {}; + } + return { + kind: element.getAttribute("data-list-kind") || "bullet", + order: parseInteger(element.getAttribute("data-list-order")), + checked: element.hasAttribute("data-list-checked"), + collapsed: element.hasAttribute("data-list-collapsed") + }; + } + }, + { + tag: "ul > li", + getAttrs: (element) => { + var _a; + if (typeof element !== "string") { + let checkbox = element.firstChild; + for (let i = 0; i < 3 && checkbox; i++) { + if (["INPUT", "UL", "OL", "LI"].includes(checkbox.nodeName)) { + break; + } + checkbox = checkbox.firstChild; + } + if (checkbox && checkbox.nodeName === "INPUT" && checkbox.getAttribute("type") === "checkbox") { + return { + kind: "task", + checked: checkbox.hasAttribute("checked") + }; + } + if (element.hasAttribute("data-task-list-item") || element.getAttribute("data-list-kind") === "task") { + return { + kind: "task", + checked: element.hasAttribute("data-list-checked") || element.hasAttribute("data-checked") + }; + } + if (element.hasAttribute("data-toggle-list-item") || element.getAttribute("data-list-kind") === "toggle") { + return { + kind: "toggle", + collapsed: element.hasAttribute("data-list-collapsed") + }; + } + if (((_a = element.firstChild) == null ? void 0 : _a.nodeType) === 3) { + const textContent = element.firstChild.textContent; + if (textContent && /^\[[\sx|]]\s{1,2}/.test(textContent)) { + element.firstChild.textContent = textContent.replace( + /^\[[\sx|]]\s{1,2}/, + "" + ); + return { + kind: "task", + checked: textContent.startsWith("[x]") + }; + } + } + } + return { + kind: "bullet" + }; + } + }, + { + tag: "ol > li", + getAttrs: (element) => { + if (typeof element === "string") { + return { + kind: "ordered" + }; + } + return { + kind: "ordered", + order: parseInteger(element.getAttribute("data-list-order")) + }; + } + }, + { + // This rule is for handling nested lists copied from Dropbox Paper. It's + // technically invalid HTML structure. + tag: ":is(ul, ol) > :is(ul, ol)", + getAttrs: () => { + return { + kind: "bullet" + }; + } + } + ]; +} + +// src/schema/to-dom.ts +function listToDOM({ + node, + nativeList = false, + getMarkers = defaultMarkerGetter, + getAttributes = defaultAttributesGetter +}) { + var _a; + const attrs = node.attrs; + const markerHidden = ((_a = node.firstChild) == null ? void 0 : _a.type) === node.type; + const markers = markerHidden ? null : getMarkers(node); + const domAttrs = getAttributes(node); + const contentContainer = ["div", { class: "list-content" }, 0]; + const markerContainer = markers && [ + "div", + { + class: "list-marker list-marker-click-target", + // Set `contenteditable` to `false` so that the cursor won't be + // moved into the mark container when clicking on it. + contenteditable: "false" + }, + ...markers + ]; + if (nativeList) { + const listTag = attrs.kind === "ordered" ? "ol" : "ul"; + if (markerContainer) { + return [listTag, ["li", domAttrs, markerContainer, contentContainer]]; + } else { + return [listTag, ["li", domAttrs, 0]]; + } + } else { + if (markerContainer) { + return ["div", domAttrs, markerContainer, contentContainer]; + } else { + return ["div", domAttrs, contentContainer]; + } + } +} +function defaultMarkerGetter(node) { + const attrs = node.attrs; + switch (attrs.kind) { + case "task": + return [ + [ + "label", + [ + "input", + { type: "checkbox", checked: attrs.checked ? "" : void 0 } + ] + ] + ]; + case "toggle": + return []; + default: + return null; + } +} +function defaultAttributesGetter(node) { + var _a; + const attrs = node.attrs; + const markerHidden = ((_a = node.firstChild) == null ? void 0 : _a.type) === node.type; + const markerType = markerHidden ? void 0 : attrs.kind || "bullet"; + const domAttrs = { + class: "prosemirror-flat-list", + "data-list-kind": markerType, + "data-list-order": attrs.order != null ? String(attrs.order) : void 0, + "data-list-checked": attrs.checked ? "" : void 0, + "data-list-collapsed": attrs.collapsed ? "" : void 0, + "data-list-collapsable": node.childCount >= 2 ? "" : void 0, + style: attrs.order != null ? `--prosemirror-flat-list-order: ${attrs.order};` : void 0 + }; + return domAttrs; +} + +// src/schema/node-spec.ts +var flatListGroup = "flatList"; +function createListSpec() { + return { + content: "block+", + group: `${flatListGroup} block`, + definingForContent: true, + definingAsContext: false, + attrs: { + kind: { + default: "bullet" + }, + order: { + default: null + }, + checked: { + default: false + }, + collapsed: { + default: false + } + }, + toDOM: (node) => { + return listToDOM({ node }); + }, + parseDOM: createParseDomRules() + }; +} + +// src/utils/get-list-type.ts +function getListType(schema) { + let name = schema.cached["PROSEMIRROR_FLAT_LIST_LIST_TYPE_NAME"]; + if (!name) { + for (const type of Object.values(schema.nodes)) { + if ((type.spec.group || "").split(" ").includes(flatListGroup)) { + name = type.name; + break; + } + } + if (!name) { + throw new TypeError( + "[prosemirror-flat-list] Unable to find a flat list type in the schema" + ); + } + schema.cached["PROSEMIRROR_FLAT_LIST_LIST_TYPE_NAME"] = name; + } + return schema.nodes[name]; +} + +// src/utils/is-list-type.ts +function isListType(type) { + return getListType(type.schema) === type; +} + +// src/utils/is-list-node.ts +function isListNode(node) { + if (!node) return false; + return isListType(node.type); +} + +// src/utils/patch-command.ts +function patchCommand(patch) { + const withPatch = (command) => { + const patchedCommand = (state, dispatch, view) => { + return command( + state, + dispatch ? (tr) => dispatch(patch(tr)) : void 0, + view + ); + }; + return patchedCommand; + }; + return withPatch; +} + +// src/utils/auto-fix-list.ts +function* getTransactionRanges(tr) { + const ranges = []; + let i = 0; + while (true) { + for (; i < tr.mapping.maps.length; i++) { + const map = tr.mapping.maps[i]; + for (let j = 0; j < ranges.length; j++) { + ranges[j] = map.map(ranges[j]); + } + map.forEach( + (_oldStart, _oldEnd, newStart, newEnd) => ranges.push(newStart, newEnd) + ); + } + yield ranges; + } +} +function findBoundaries(positions, doc, prediction) { + const boundaries = /* @__PURE__ */ new Set(); + const joinable = []; + for (const pos of positions) { + const $pos = doc.resolve(pos); + for (let depth = $pos.depth; depth >= 0; depth--) { + const boundary = $pos.before(depth + 1); + if (boundaries.has(boundary)) { + break; + } + boundaries.add(boundary); + const index = $pos.index(depth); + const parent = $pos.node(depth); + const before = parent.maybeChild(index - 1); + if (!before) continue; + const after = parent.maybeChild(index); + if (!after) continue; + if (prediction(before, after, parent, index)) { + joinable.push(boundary); + } + } + } + return joinable.sort((a, b) => b - a); +} +function isListJoinable(before, after) { + return isListNode(before) && isListNode(after) && isListNode(after.firstChild); +} +function isListSplitable(before, after, parent, index) { + if (index === 1 && isListNode(parent) && isListNode(before) && !isListNode(after)) { + return true; + } + return false; +} +function fixList(tr) { + const ranges = getTransactionRanges(tr); + const joinable = findBoundaries(ranges.next().value, tr.doc, isListJoinable); + for (const pos of joinable) { + if ((0, import_prosemirror_transform.canJoin)(tr.doc, pos)) { + tr.join(pos); + } + } + const splitable = findBoundaries(ranges.next().value, tr.doc, isListSplitable); + for (const pos of splitable) { + if ((0, import_prosemirror_transform.canSplit)(tr.doc, pos)) { + tr.split(pos); + } + } + return tr; +} +var withAutoFixList = patchCommand(fixList); + +// src/utils/block-boundary.ts +function atStartBlockBoundary($pos, depth) { + for (let d = depth; d <= $pos.depth; d++) { + if ($pos.node(d).isTextblock) { + continue; + } + const index = $pos.index(d); + if (index !== 0) { + return false; + } + } + return true; +} +function atEndBlockBoundary($pos, depth) { + for (let d = depth; d <= $pos.depth; d++) { + if ($pos.node(d).isTextblock) { + continue; + } + const index = $pos.index(d); + if (index !== $pos.node(d).childCount - 1) { + return false; + } + } + return true; +} + +// src/utils/list-range.ts +var import_prosemirror_model = require("prosemirror-model"); +function findListsRange($from, $to = $from) { + if ($to.pos < $from.pos) { + return findListsRange($to, $from); + } + let range = $from.blockRange($to); + while (range) { + if (isListsRange(range)) { + return range; + } + if (range.depth <= 0) { + break; + } + range = new import_prosemirror_model.NodeRange($from, $to, range.depth - 1); + } + return null; +} +function isListsRange(range) { + const { startIndex, endIndex, parent } = range; + for (let i = startIndex; i < endIndex; i++) { + if (!isListNode(parent.child(i))) { + return false; + } + } + return true; +} + +// src/utils/map-pos.ts +function mapPos(tr, pos) { + let nextStepIndex = tr.steps.length; + const getPos = () => { + if (nextStepIndex < tr.steps.length) { + const mapping = tr.mapping.slice(nextStepIndex); + nextStepIndex = tr.steps.length; + pos = mapping.map(pos); + } + return pos; + }; + return getPos; +} + +// src/utils/safe-lift.ts +var import_prosemirror_transform2 = require("prosemirror-transform"); +function safeLift(tr, range) { + const target = (0, import_prosemirror_transform2.liftTarget)(range); + if (target == null) { + return false; + } + tr.lift(range, target); + return true; +} +function safeLiftFromTo(tr, from, to) { + const $from = tr.doc.resolve(from); + const $to = tr.doc.resolve(to); + const range = $from.blockRange($to); + if (!range) return false; + return safeLift(tr, range); +} + +// src/utils/zoom-in-range.ts +function zoomInRange(range) { + const { $from, $to, depth, start, end } = range; + const doc = $from.doc; + const deeper = ($from.pos > start ? $from : doc.resolve(start + 1)).blockRange($to.pos < end ? $to : doc.resolve(end - 1)); + if (deeper && deeper.depth > depth) { + return deeper; + } + return null; +} + +// src/commands/set-safe-selection.ts +var import_prosemirror_state = require("prosemirror-state"); + +// src/utils/is-collapsed-list-node.ts +function isCollapsedListNode(node) { + return !!(isListNode(node) && node.attrs.collapsed); +} + +// src/utils/set-node-attributes.ts +function setNodeAttributes(tr, pos, oldAttrs, newAttrs) { + let needUpdate = false; + for (const key of Object.keys(newAttrs)) { + if (newAttrs[key] !== oldAttrs[key]) { + tr.setNodeAttribute(pos, key, newAttrs[key]); + needUpdate = true; + } + } + return needUpdate; +} + +// src/utils/set-list-attributes.ts +function setListAttributes(tr, pos, attrs) { + const $pos = tr.doc.resolve(pos); + const node = $pos.nodeAfter; + if (node && isListNode(node)) { + const oldAttrs = node.attrs; + const newAttrs = { ...oldAttrs, ...attrs }; + return setNodeAttributes(tr, pos, oldAttrs, newAttrs); + } + return false; +} + +// src/commands/set-safe-selection.ts +function moveOutOfCollapsed($pos, minDepth) { + for (let depth = minDepth; depth <= $pos.depth; depth++) { + if (isCollapsedListNode($pos.node(depth)) && $pos.index(depth) >= 1) { + const before = $pos.posAtIndex(1, depth); + const $before = $pos.doc.resolve(before); + return import_prosemirror_state.TextSelection.near($before, -1); + } + } + return null; +} +function setSafeSelection(tr) { + const { $from, $to, to } = tr.selection; + const selection = moveOutOfCollapsed($from, 0) || moveOutOfCollapsed($to, $from.sharedDepth(to)); + if (selection) { + tr.setSelection(selection); + } + return tr; +} +var withSafeSelection = patchCommand(setSafeSelection); +function getCollapsedPosition($pos, minDepth) { + for (let depth = minDepth; depth <= $pos.depth; depth++) { + if (isCollapsedListNode($pos.node(depth)) && $pos.index(depth) >= 1) { + return $pos.before(depth); + } + } + return null; +} +function setVisibleSelection(tr) { + var _a; + const { $from, $to, to } = tr.selection; + const pos = (_a = getCollapsedPosition($from, 0)) != null ? _a : getCollapsedPosition($to, $from.sharedDepth(to)); + if (pos != null) { + tr.doc.resolve(pos); + setListAttributes(tr, pos, { collapsed: false }); + } + return tr; +} +var withVisibleSelection = patchCommand(setVisibleSelection); + +// src/commands/dedent-list.ts +function createDedentListCommand(options) { + const dedentListCommand = (state, dispatch) => { + const tr = state.tr; + const $from = (options == null ? void 0 : options.from) == null ? tr.selection.$from : tr.doc.resolve(options.from); + const $to = (options == null ? void 0 : options.to) == null ? tr.selection.$to : tr.doc.resolve(options.to); + const range = findListsRange($from, $to); + if (!range) return false; + if (dedentRange(range, tr)) { + dispatch == null ? void 0 : dispatch(tr); + return true; + } + return false; + }; + return withVisibleSelection(withAutoFixList(dedentListCommand)); +} +function dedentRange(range, tr, startBoundary, endBoundary) { + const { depth, $from, $to } = range; + startBoundary = startBoundary || atStartBlockBoundary($from, depth + 1); + if (!startBoundary) { + const { startIndex, endIndex } = range; + if (endIndex - startIndex === 1) { + const contentRange = zoomInRange(range); + return contentRange ? dedentRange(contentRange, tr) : false; + } else { + return splitAndDedentRange(range, tr, startIndex + 1); + } + } + endBoundary = endBoundary || atEndBlockBoundary($to, depth + 1); + if (!endBoundary) { + fixEndBoundary(range, tr); + const endOfParent = $to.end(depth); + range = new import_prosemirror_model2.NodeRange( + tr.doc.resolve($from.pos), + tr.doc.resolve(endOfParent), + depth + ); + return dedentRange(range, tr, void 0, true); + } + if (range.startIndex === 0 && range.endIndex === range.parent.childCount && isListNode(range.parent)) { + return dedentNodeRange(new import_prosemirror_model2.NodeRange($from, $to, depth - 1), tr); + } + return dedentNodeRange(range, tr); +} +function splitAndDedentRange(range, tr, splitIndex) { + const { $from, $to, depth } = range; + const splitPos = $from.posAtIndex(splitIndex, depth); + const range1 = $from.blockRange(tr.doc.resolve(splitPos - 1)); + if (!range1) return false; + const getRange2From = mapPos(tr, splitPos + 1); + const getRange2To = mapPos(tr, $to.pos); + dedentRange(range1, tr, void 0, true); + let range2 = tr.doc.resolve(getRange2From()).blockRange(tr.doc.resolve(getRange2To())); + if (range2 && range2.depth >= depth) { + range2 = new import_prosemirror_model2.NodeRange(range2.$from, range2.$to, depth); + dedentRange(range2, tr, true, void 0); + } + return true; +} +function dedentNodeRange(range, tr) { + if (isListNode(range.parent)) { + return safeLiftRange(tr, range); + } else if (isListsRange(range)) { + return dedentOutOfList(tr, range); + } else { + return safeLiftRange(tr, range); + } +} +function safeLiftRange(tr, range) { + if (moveRangeSiblings(tr, range)) { + const $from = tr.doc.resolve(range.$from.pos); + const $to = tr.doc.resolve(range.$to.pos); + range = new import_prosemirror_model2.NodeRange($from, $to, range.depth); + } + return safeLift(tr, range); +} +function moveRangeSiblings(tr, range) { + const listType = getListType(tr.doc.type.schema); + const { $to, depth, end, parent, endIndex } = range; + const endOfParent = $to.end(depth); + if (end < endOfParent) { + const lastChild = parent.maybeChild(endIndex - 1); + if (!lastChild) return false; + const canAppend = endIndex < parent.childCount && lastChild.canReplace( + lastChild.childCount, + lastChild.childCount, + parent.content, + endIndex, + parent.childCount + ); + if (canAppend) { + tr.step( + new import_prosemirror_transform3.ReplaceAroundStep( + end - 1, + endOfParent, + end, + endOfParent, + new import_prosemirror_model2.Slice(import_prosemirror_model2.Fragment.from(listType.create(null)), 1, 0), + 0, + true + ) + ); + return true; + } else { + tr.step( + new import_prosemirror_transform3.ReplaceAroundStep( + end, + endOfParent, + end, + endOfParent, + new import_prosemirror_model2.Slice(import_prosemirror_model2.Fragment.from(listType.create(null)), 0, 0), + 1, + true + ) + ); + return true; + } + } + return false; +} +function fixEndBoundary(range, tr) { + if (range.endIndex - range.startIndex >= 2) { + range = new import_prosemirror_model2.NodeRange( + range.$to.doc.resolve( + range.$to.posAtIndex(range.endIndex - 1, range.depth) + ), + range.$to, + range.depth + ); + } + const contentRange = zoomInRange(range); + if (contentRange) { + fixEndBoundary(contentRange, tr); + range = new import_prosemirror_model2.NodeRange( + tr.doc.resolve(range.$from.pos), + tr.doc.resolve(range.$to.pos), + range.depth + ); + } + moveRangeSiblings(tr, range); +} +function dedentOutOfList(tr, range) { + const { startIndex, endIndex, parent } = range; + const getRangeStart = mapPos(tr, range.start); + const getRangeEnd = mapPos(tr, range.end); + for (let end2 = getRangeEnd(), i = endIndex - 1; i > startIndex; i--) { + end2 -= parent.child(i).nodeSize; + tr.delete(end2 - 1, end2 + 1); + } + const $start = tr.doc.resolve(getRangeStart()); + const listNode = $start.nodeAfter; + if (!listNode) return false; + const start = range.start; + const end = start + listNode.nodeSize; + if (getRangeEnd() !== end) return false; + if (!$start.parent.canReplace( + startIndex, + startIndex + 1, + import_prosemirror_model2.Fragment.from(listNode) + )) { + return false; + } + tr.step( + new import_prosemirror_transform3.ReplaceAroundStep( + start, + end, + start + 1, + end - 1, + new import_prosemirror_model2.Slice(import_prosemirror_model2.Fragment.empty, 0, 0), + 0, + true + ) + ); + return true; +} + +// src/commands/enter-without-lift.ts +var import_prosemirror_commands = require("prosemirror-commands"); +var enterWithoutLift = (0, import_prosemirror_commands.chainCommands)( + import_prosemirror_commands.newlineInCode, + import_prosemirror_commands.createParagraphNear, + import_prosemirror_commands.splitBlock +); + +// src/commands/indent-list.ts +var import_prosemirror_model3 = require("prosemirror-model"); +var import_prosemirror_transform4 = require("prosemirror-transform"); + +// src/utils/in-collapsed-list.ts +function inCollapsedList($pos) { + for (let depth = $pos.depth; depth >= 0; depth--) { + const node = $pos.node(depth); + if (isListNode(node)) { + const attrs = node.attrs; + if (attrs.collapsed) { + return true; + } + } + } + return false; +} + +// src/commands/indent-list.ts +function createIndentListCommand(options) { + const indentListCommand = (state, dispatch) => { + const tr = state.tr; + const $from = (options == null ? void 0 : options.from) == null ? tr.selection.$from : tr.doc.resolve(options.from); + const $to = (options == null ? void 0 : options.to) == null ? tr.selection.$to : tr.doc.resolve(options.to); + const range = findListsRange($from, $to) || $from.blockRange($to); + if (!range) return false; + if (indentRange(range, tr)) { + dispatch == null ? void 0 : dispatch(tr); + return true; + } + return false; + }; + return withVisibleSelection(withAutoFixList(indentListCommand)); +} +function indentRange(range, tr, startBoundary, endBoundary) { + const { depth, $from, $to } = range; + startBoundary = startBoundary || atStartBlockBoundary($from, depth + 1); + if (!startBoundary) { + const { startIndex, endIndex } = range; + if (endIndex - startIndex === 1) { + const contentRange = zoomInRange(range); + return contentRange ? indentRange(contentRange, tr) : false; + } else { + return splitAndIndentRange(range, tr, startIndex + 1); + } + } + endBoundary = endBoundary || atEndBlockBoundary($to, depth + 1); + if (!endBoundary && !inCollapsedList($to)) { + const { startIndex, endIndex } = range; + if (endIndex - startIndex === 1) { + const contentRange = zoomInRange(range); + return contentRange ? indentRange(contentRange, tr) : false; + } else { + return splitAndIndentRange(range, tr, endIndex - 1); + } + } + return indentNodeRange(range, tr); +} +function splitAndIndentRange(range, tr, splitIndex) { + const { $from, $to, depth } = range; + const splitPos = $from.posAtIndex(splitIndex, depth); + const range1 = $from.blockRange(tr.doc.resolve(splitPos - 1)); + if (!range1) return false; + const getRange2From = mapPos(tr, splitPos + 1); + const getRange2To = mapPos(tr, $to.pos); + indentRange(range1, tr, void 0, true); + const range2 = tr.doc.resolve(getRange2From()).blockRange(tr.doc.resolve(getRange2To())); + range2 && indentRange(range2, tr, true, void 0); + return true; +} +function indentNodeRange(range, tr) { + const listType = getListType(tr.doc.type.schema); + const { parent, startIndex } = range; + const prevChild = startIndex >= 1 && parent.child(startIndex - 1); + if (prevChild && isListNode(prevChild)) { + const { start, end } = range; + tr.step( + new import_prosemirror_transform4.ReplaceAroundStep( + start - 1, + end, + start, + end, + new import_prosemirror_model3.Slice(import_prosemirror_model3.Fragment.from(listType.create(null)), 1, 0), + 0, + true + ) + ); + return true; + } + const isParentListNode = isListNode(parent); + const isFirstChildListNode = isListNode(parent.maybeChild(startIndex)); + if (startIndex === 0 && isParentListNode || isFirstChildListNode) { + const { start, end } = range; + const listAttrs = isFirstChildListNode ? parent.child(startIndex).attrs : isParentListNode ? parent.attrs : null; + tr.step( + new import_prosemirror_transform4.ReplaceAroundStep( + start, + end, + start, + end, + new import_prosemirror_model3.Slice(import_prosemirror_model3.Fragment.from(listType.create(listAttrs)), 0, 0), + 1, + true + ) + ); + return true; + } + return false; +} + +// src/commands/join-collapsed-backward.ts +var import_prosemirror_state3 = require("prosemirror-state"); + +// src/utils/at-textblock-start.ts +function atTextblockStart(state, view) { + const { $cursor } = state.selection; + if (!$cursor || (view ? !view.endOfTextblock("backward", state) : $cursor.parentOffset > 0)) + return null; + return $cursor; +} + +// src/commands/join-textblocks-around.ts +var import_prosemirror_model4 = require("prosemirror-model"); +var import_prosemirror_state2 = require("prosemirror-state"); +var import_prosemirror_transform5 = require("prosemirror-transform"); +function joinTextblocksAround(tr, $cut, dispatch) { + let before = $cut.nodeBefore, beforeText = before, beforePos = $cut.pos - 1; + for (; !beforeText.isTextblock; beforePos--) { + if (beforeText.type.spec.isolating) return false; + let child = beforeText.lastChild; + if (!child) return false; + beforeText = child; + } + let after = $cut.nodeAfter, afterText = after, afterPos = $cut.pos + 1; + for (; !afterText.isTextblock; afterPos++) { + if (afterText.type.spec.isolating) return false; + let child = afterText.firstChild; + if (!child) return false; + afterText = child; + } + let step = (0, import_prosemirror_transform5.replaceStep)(tr.doc, beforePos, afterPos, import_prosemirror_model4.Slice.empty); + if (!step || step.from != beforePos || step instanceof import_prosemirror_transform5.ReplaceStep && step.slice.size >= afterPos - beforePos) return false; + if (dispatch) { + tr.step(step); + tr.setSelection(import_prosemirror_state2.TextSelection.create(tr.doc, beforePos)); + dispatch(tr.scrollIntoView()); + } + return true; +} + +// src/commands/join-collapsed-backward.ts +var joinCollapsedListBackward = (state, dispatch, view) => { + const $cursor = atTextblockStart(state, view); + if (!$cursor) return false; + const $cut = findCutBefore($cursor); + if (!$cut) return false; + const { nodeBefore, nodeAfter } = $cut; + if (nodeBefore && nodeAfter && isListNode(nodeBefore) && nodeBefore.attrs.collapsed && nodeAfter.isBlock) { + const tr = state.tr; + const listPos = $cut.pos - nodeBefore.nodeSize; + tr.delete($cut.pos, $cut.pos + nodeAfter.nodeSize); + const insert = listPos + 1 + nodeBefore.child(0).nodeSize; + tr.insert(insert, nodeAfter); + const $insert = tr.doc.resolve(insert); + tr.setSelection(import_prosemirror_state3.TextSelection.near($insert)); + if (joinTextblocksAround(tr, $insert, dispatch)) { + return true; + } + } + return false; +}; +function findCutBefore($pos) { + if (!$pos.parent.type.spec.isolating) + for (let i = $pos.depth - 1; i >= 0; i--) { + if ($pos.index(i) > 0) return $pos.doc.resolve($pos.before(i + 1)); + if ($pos.node(i).type.spec.isolating) break; + } + return null; +} + +// src/commands/join-list-up.ts +var import_prosemirror_model5 = require("prosemirror-model"); +var joinListUp = (state, dispatch, view) => { + const $cursor = atTextblockStart(state, view); + if (!$cursor) return false; + const { depth } = $cursor; + if (depth < 2) return false; + const listDepth = depth - 1; + const listNode = $cursor.node(listDepth); + if (!isListNode(listNode)) return false; + const indexInList = $cursor.index(listDepth); + if (indexInList === 0) { + if (dispatch) { + liftListContent(state, dispatch, $cursor); + } + return true; + } + if (indexInList === listNode.childCount - 1) { + if (dispatch) { + liftParent(state, dispatch, $cursor); + } + return true; + } + return false; +}; +function liftListContent(state, dispatch, $cursor) { + const tr = state.tr; + const listDepth = $cursor.depth - 1; + const range = new import_prosemirror_model5.NodeRange( + $cursor, + tr.doc.resolve($cursor.end(listDepth)), + listDepth + ); + if (safeLift(tr, range)) { + dispatch(tr); + } +} +function liftParent(state, dispatch, $cursor) { + const tr = state.tr; + const range = $cursor.blockRange(); + if (range && safeLift(tr, range)) { + dispatch(tr); + } +} + +// src/commands/keymap.ts +var import_prosemirror_commands3 = require("prosemirror-commands"); + +// src/commands/protect-collapsed.ts +var protectCollapsed = (state, dispatch) => { + const tr = state.tr; + let found = false; + const { from, to } = state.selection; + state.doc.nodesBetween(from, to, (node, pos, parent, index) => { + if (found && !dispatch) { + return false; + } + if (parent && isCollapsedListNode(parent) && index >= 1) { + found = true; + if (!dispatch) { + return false; + } + const $pos = state.doc.resolve(pos); + tr.setNodeAttribute($pos.before($pos.depth), "collapsed", false); + } + }); + if (found) { + dispatch == null ? void 0 : dispatch(tr); + } + return found; +}; + +// src/commands/split-list.ts +var import_prosemirror_commands2 = require("prosemirror-commands"); +var import_prosemirror_model6 = require("prosemirror-model"); +var import_prosemirror_state5 = require("prosemirror-state"); +var import_prosemirror_transform6 = require("prosemirror-transform"); + +// src/utils/create-and-fill.ts +function createAndFill(type, attrs, content, marks) { + const node = type.createAndFill(attrs, content, marks); + if (!node) { + throw new RangeError(`Failed to create '${type.name}' node`); + } + node.check(); + return node; +} + +// src/utils/is-node-selection.ts +function isNodeSelection(selection) { + return Boolean(selection.node); +} + +// src/utils/is-block-node-selection.ts +function isBlockNodeSelection(selection) { + return isNodeSelection(selection) && selection.node.type.isBlock; +} + +// src/utils/is-text-selection.ts +var import_prosemirror_state4 = require("prosemirror-state"); +function isTextSelection(value) { + return Boolean(value && value instanceof import_prosemirror_state4.TextSelection); +} + +// src/commands/split-list.ts +function createSplitListCommand() { + return withAutoFixList( + (0, import_prosemirror_commands2.chainCommands)(splitBlockNodeSelectionInListCommand, splitListCommand) + ); +} +function deriveListAttributes(listNode) { + return { kind: listNode.attrs.kind }; +} +var splitBlockNodeSelectionInListCommand = (state, dispatch) => { + if (!isBlockNodeSelection(state.selection)) { + return false; + } + const selection = state.selection; + const { $to, node } = selection; + const parent = $to.parent; + if (isListNode(node) || !isListNode(parent) || parent.childCount !== 1 || parent.firstChild !== node) { + return false; + } + const listType = parent.type; + const nextList = listType.createAndFill(deriveListAttributes(parent)); + if (!nextList) { + return false; + } + if (dispatch) { + const tr = state.tr; + const cutPoint = $to.pos; + tr.replace( + cutPoint, + cutPoint, + new import_prosemirror_model6.Slice(import_prosemirror_model6.Fragment.fromArray([listType.create(), nextList]), 1, 1) + ); + const newSelection = import_prosemirror_state5.TextSelection.near(tr.doc.resolve(cutPoint)); + if (isTextSelection(newSelection)) { + tr.setSelection(newSelection); + dispatch(tr); + } + } + return true; +}; +var splitListCommand = (state, dispatch) => { + if (isBlockNodeSelection(state.selection)) { + return false; + } + const { $from, $to } = state.selection; + if (!$from.sameParent($to)) { + return false; + } + if ($from.depth < 2) { + return false; + } + const listDepth = $from.depth - 1; + const listNode = $from.node(listDepth); + if (!isListNode(listNode)) { + return false; + } + const parent = $from.parent; + const indexInList = $from.index(listDepth); + const parentEmpty = parent.content.size === 0; + if (indexInList === 0) { + if (parentEmpty) { + const $listEnd = state.doc.resolve($from.end(listDepth)); + const listParentDepth = listDepth - 1; + const listParent = $from.node(listParentDepth); + const indexInListParent = $from.index(listParentDepth); + const isLastChildInListParent = indexInListParent === listParent.childCount - 1; + const range = isLastChildInListParent ? new import_prosemirror_model6.NodeRange($from, $listEnd, listParentDepth) : new import_prosemirror_model6.NodeRange($from, $listEnd, listDepth); + const tr = state.tr; + if (range && dedentNodeRange(range, tr)) { + dispatch == null ? void 0 : dispatch(tr); + return true; + } + return false; + } else { + return doSplitList(state, listNode, dispatch); + } + } else { + if (parentEmpty) { + return enterWithoutLift(state, dispatch); + } else { + return false; + } + } +}; +function doSplitList(state, listNode, dispatch) { + const tr = state.tr; + const listType = listNode.type; + const attrs = listNode.attrs; + const newAttrs = deriveListAttributes(listNode); + tr.delete(tr.selection.from, tr.selection.to); + const { $from, $to } = tr.selection; + const { parentOffset } = $to; + const atStart = parentOffset == 0; + const atEnd = parentOffset == $to.parent.content.size; + if (atStart) { + if (dispatch) { + const pos = $from.before(-1); + tr.insert(pos, createAndFill(listType, newAttrs)); + dispatch(tr.scrollIntoView()); + } + return true; + } + if (atEnd && attrs.collapsed) { + if (dispatch) { + const pos = $from.after(-1); + tr.insert(pos, createAndFill(listType, newAttrs)); + tr.setSelection(import_prosemirror_state5.Selection.near(tr.doc.resolve(pos))); + dispatch(tr.scrollIntoView()); + } + return true; + } + const nextType = atEnd ? listNode.contentMatchAt(0).defaultType : void 0; + const typesAfter = [ + { type: listType, attrs: newAttrs }, + nextType ? { type: nextType } : null + ]; + if (!(0, import_prosemirror_transform6.canSplit)(tr.doc, $from.pos, 2, typesAfter)) { + return false; + } + dispatch == null ? void 0 : dispatch(tr.split($from.pos, 2, typesAfter).scrollIntoView()); + return true; +} + +// src/commands/keymap.ts +var enterCommand = (0, import_prosemirror_commands3.chainCommands)( + protectCollapsed, + createSplitListCommand() +); +var backspaceCommand = (0, import_prosemirror_commands3.chainCommands)( + protectCollapsed, + import_prosemirror_commands3.deleteSelection, + joinListUp, + joinCollapsedListBackward, + import_prosemirror_commands3.joinTextblockBackward, + import_prosemirror_commands3.selectNodeBackward +); +var deleteCommand = (0, import_prosemirror_commands3.chainCommands)( + protectCollapsed, + import_prosemirror_commands3.deleteSelection, + import_prosemirror_commands3.joinTextblockForward, + import_prosemirror_commands3.selectNodeForward +); +var listKeymap = { + Enter: enterCommand, + Backspace: backspaceCommand, + Delete: deleteCommand, + "Mod-[": createDedentListCommand(), + "Mod-]": createIndentListCommand() +}; + +// src/utils/cut-by-index.ts +function cutByIndex(fragment, from, to) { + return fragment.cutByIndex(from, to); +} + +// src/commands/move-list.ts +function createMoveListCommand(direction) { + const moveList = (state, dispatch) => { + const tr = state.tr; + if (doMoveList(tr, direction, true, !!dispatch)) { + dispatch == null ? void 0 : dispatch(tr); + return true; + } + return false; + }; + return withAutoFixList(moveList); +} +function doMoveList(tr, direction, canDedent, dispatch) { + const { $from, $to } = tr.selection; + const range = findListsRange($from, $to); + if (!range) return false; + const { parent, depth, startIndex, endIndex } = range; + if (direction === "up") { + if (startIndex >= 2 || startIndex === 1 && isListNode(parent.child(0))) { + const before = cutByIndex(parent.content, startIndex - 1, startIndex); + const selected = cutByIndex(parent.content, startIndex, endIndex); + if (parent.canReplace(startIndex - 1, endIndex, selected.append(before))) { + if (dispatch) { + tr.insert($from.posAtIndex(endIndex, depth), before); + tr.delete( + $from.posAtIndex(startIndex - 1, depth), + $from.posAtIndex(startIndex, depth) + ); + } + return true; + } else { + return false; + } + } else if (canDedent && isListNode(parent)) { + return safeLift(tr, range) && doMoveList(tr, direction, false, dispatch); + } else { + return false; + } + } else { + if (endIndex < parent.childCount) { + const selected = cutByIndex(parent.content, startIndex, endIndex); + const after = cutByIndex(parent.content, endIndex, endIndex + 1); + if (parent.canReplace(startIndex, endIndex + 1, after.append(selected))) { + if (dispatch) { + tr.delete( + $from.posAtIndex(endIndex, depth), + $from.posAtIndex(endIndex + 1, depth) + ); + tr.insert($from.posAtIndex(startIndex, depth), after); + } + return true; + } else { + return false; + } + } else if (canDedent && isListNode(parent)) { + return safeLift(tr, range) && doMoveList(tr, direction, false, dispatch); + } else { + return false; + } + } +} + +// src/commands/toggle-collapsed.ts +function createToggleCollapsedCommand({ + collapsed = void 0, + isToggleable = defaultIsToggleable +} = {}) { + const toggleCollapsed = (state, dispatch) => { + const { $from } = state.selection; + for (let depth = $from.depth; depth >= 0; depth--) { + const node = $from.node(depth); + if (isListNode(node) && isToggleable(node)) { + if (dispatch) { + const pos = $from.before(depth); + const attrs = node.attrs; + const tr = state.tr; + tr.setNodeAttribute(pos, "collapsed", collapsed != null ? collapsed : !attrs.collapsed); + dispatch(setSafeSelection(tr)); + } + return true; + } + } + return false; + }; + return toggleCollapsed; +} +function defaultIsToggleable(node) { + const attrs = node.attrs; + return attrs.kind === "toggle" && node.childCount >= 2 && !isListNode(node.firstChild); +} + +// src/commands/toggle-list.ts +var import_prosemirror_commands4 = require("prosemirror-commands"); + +// src/commands/unwrap-list.ts +function createUnwrapListCommand(options) { + const kind = options == null ? void 0 : options.kind; + const unwrapList = (state, dispatch) => { + const selection = state.selection; + if (isNodeSelection(selection) && isTargetList(selection.node, kind)) { + if (dispatch) { + const tr = state.tr; + safeLiftFromTo(tr, tr.selection.from + 1, tr.selection.to - 1); + dispatch(tr.scrollIntoView()); + } + return true; + } + const range = selection.$from.blockRange(selection.$to); + if (range && isTargetListsRange(range, kind)) { + const tr = state.tr; + if (dedentOutOfList(tr, range)) { + dispatch == null ? void 0 : dispatch(tr); + return true; + } + } + if (range && isTargetList(range.parent, kind)) { + if (dispatch) { + const tr = state.tr; + safeLiftFromTo( + tr, + range.$from.start(range.depth), + range.$to.end(range.depth) + ); + dispatch(tr.scrollIntoView()); + } + return true; + } + return false; + }; + return unwrapList; +} +function isTargetList(node, kind) { + if (isListNode(node)) { + if (kind) { + return node.attrs.kind === kind; + } + return true; + } + return false; +} +function isTargetListsRange(range, kind) { + const { startIndex, endIndex, parent } = range; + for (let i = startIndex; i < endIndex; i++) { + if (!isTargetList(parent.child(i), kind)) { + return false; + } + } + return true; +} + +// src/commands/wrap-in-list.ts +var import_prosemirror_model7 = require("prosemirror-model"); +var import_prosemirror_transform7 = require("prosemirror-transform"); +function createWrapInListCommand(getAttrs) { + const wrapInList = (state, dispatch) => { + const { $from, $to } = state.selection; + let range = $from.blockRange($to); + if (!range) { + return false; + } + if (rangeAllowInlineContent(range) && isListNode(range.parent) && range.depth > 0 && range.startIndex === 0) { + range = new import_prosemirror_model7.NodeRange($from, $to, range.depth - 1); + } + const attrs = typeof getAttrs === "function" ? getAttrs(range) : getAttrs; + if (!attrs) { + return false; + } + const { parent, startIndex, endIndex, depth } = range; + const tr = state.tr; + const listType = getListType(state.schema); + for (let i = endIndex - 1; i >= startIndex; i--) { + const node = parent.child(i); + if (isListNode(node)) { + const oldAttrs = node.attrs; + const newAttrs = { ...oldAttrs, ...attrs }; + setNodeAttributes(tr, $from.posAtIndex(i, depth), oldAttrs, newAttrs); + } else { + const beforeNode = $from.posAtIndex(i, depth); + const afterNode = $from.posAtIndex(i + 1, depth); + let nodeStart = beforeNode + 1; + let nodeEnd = afterNode - 1; + if (nodeStart > nodeEnd) { + ; + [nodeStart, nodeEnd] = [nodeEnd, nodeStart]; + } + const range2 = new import_prosemirror_model7.NodeRange( + tr.doc.resolve(nodeStart), + tr.doc.resolve(nodeEnd), + depth + ); + const wrapping = (0, import_prosemirror_transform7.findWrapping)(range2, listType, attrs); + if (wrapping) { + tr.wrap(range2, wrapping); + } + } + } + dispatch == null ? void 0 : dispatch(tr); + return true; + }; + return wrapInList; +} +function rangeAllowInlineContent(range) { + const { parent, startIndex, endIndex } = range; + for (let i = startIndex; i < endIndex; i++) { + if (parent.child(i).inlineContent) { + return true; + } + } + return false; +} + +// src/commands/toggle-list.ts +function createToggleListCommand(attrs) { + const unwrapList = createUnwrapListCommand({ kind: attrs.kind }); + const wrapInList = createWrapInListCommand(attrs); + return (0, import_prosemirror_commands4.chainCommands)(unwrapList, wrapInList); +} + +// src/dom-events.ts +function handleListMarkerMouseDown({ + view, + event, + onListClick = defaultListClickHandler +}) { + const target = event.target; + if (target == null ? void 0 : target.closest(".list-marker-click-target")) { + event.preventDefault(); + const pos = view.posAtDOM(target, -10, -10); + return handleMouseDown(pos, onListClick)( + view.state, + (tr) => view.dispatch(tr) + ); + } + return false; +} +function handleMouseDown(pos, onListClick) { + const mouseDown = (state, dispatch) => { + const tr = state.tr; + const $pos = tr.doc.resolve(pos); + const list = $pos.parent; + if (!isListNode(list)) { + return false; + } + const listPos = $pos.before($pos.depth); + const attrs = onListClick(list); + if (setNodeAttributes(tr, listPos, list.attrs, attrs)) { + dispatch == null ? void 0 : dispatch(tr); + } + return true; + }; + return withSafeSelection(mouseDown); +} +var defaultListClickHandler = (node) => { + const attrs = node.attrs; + if (attrs.kind === "task") { + return { ...attrs, checked: !attrs.checked }; + } else if (attrs.kind === "toggle") { + return { ...attrs, collapsed: !attrs.collapsed }; + } else { + return attrs; + } +}; + +// src/input-rule.ts +var import_prosemirror_inputrules = require("prosemirror-inputrules"); +var import_prosemirror_transform8 = require("prosemirror-transform"); +function wrappingListInputRule(regexp, getAttrs) { + return new import_prosemirror_inputrules.InputRule( + regexp, + (state, match, start, end) => { + const tr = state.tr; + tr.deleteRange(start, end); + const $pos = tr.selection.$from; + const listNode = $pos.index(-1) === 0 && $pos.node(-1); + if (listNode && isListNode(listNode)) { + const oldAttrs = listNode.attrs; + const newAttrs2 = typeof getAttrs === "function" ? getAttrs({ match, attributes: oldAttrs }) : getAttrs; + const entries = Object.entries(newAttrs2).filter(([key, value]) => { + return oldAttrs[key] !== value; + }); + if (entries.length === 0) { + return null; + } else { + const pos = $pos.before(-1); + for (const [key, value] of entries) { + tr.setNodeAttribute(pos, key, value); + } + return tr; + } + } + const $start = tr.doc.resolve(start); + const range = $start.blockRange(); + if (!range) { + return null; + } + const newAttrs = typeof getAttrs === "function" ? getAttrs({ match }) : getAttrs; + const wrapping = (0, import_prosemirror_transform8.findWrapping)(range, getListType(state.schema), newAttrs); + if (!wrapping) { + return null; + } + return tr.wrap(range, wrapping); + } + ); +} +var listInputRules = [ + wrappingListInputRule(/^\s?([*-])\s$/, { + kind: "bullet", + collapsed: false + }), + wrappingListInputRule(/^\s?(\d+)\.\s$/, ({ match }) => { + const order = parseInteger(match[1]); + return { + kind: "ordered", + collapsed: false, + order: order != null && order >= 2 ? order : null + }; + }), + wrappingListInputRule(/^\s?\[([\sXx]?)]\s$/, ({ match }) => { + return { + kind: "task", + checked: ["x", "X"].includes(match[1]), + collapsed: false + }; + }), + wrappingListInputRule(/^\s?>>\s$/, { + kind: "toggle" + }) +]; + +// src/migrate.ts +function migrateNodes(nodes) { + var _a, _b, _c; + const content = []; + let updated = false; + for (const node of nodes) { + if (node.type === "bullet_list" || node.type === "bulletList") { + updated = true; + for (const child of (_a = node.content) != null ? _a : []) { + content.push(migrateNode(child, { kind: "bullet" })[0]); + } + } else if (node.type === "ordered_list" || node.type === "orderedList") { + updated = true; + for (const child of (_b = node.content) != null ? _b : []) { + content.push(migrateNode(child, { kind: "ordered" })[0]); + } + } else if (node.type === "task_list" || node.type === "taskList") { + updated = true; + for (const child of (_c = node.content) != null ? _c : []) { + content.push(migrateNode(child, { kind: "task" })[0]); + } + } else { + content.push(node); + } + } + return [content, updated]; +} +function migrateNode(node, { kind } = {}) { + var _a; + if (node.type === "list_item" || node.type === "listItem" || node.type === "taskListItem") { + return [ + { + ...node, + type: "list", + attrs: { + collapsed: Boolean((_a = node.attrs) == null ? void 0 : _a.closed), + ...node.attrs, + kind: kind != null ? kind : "bullet" + }, + content: node.content ? migrateNodes(node.content)[0] : void 0 + }, + true + ]; + } else if (node.content) { + const [content, updated] = migrateNodes(node.content); + return [{ ...node, content }, updated]; + } else { + return [node, false]; + } +} +function migrateDocJSON(docJSON) { + const [migrated, updated] = migrateNode(docJSON); + return updated ? migrated : null; +} + +// src/node-view.ts +var import_prosemirror_model8 = require("prosemirror-model"); + +// src/utils/browser.ts +var nav = typeof navigator != "undefined" ? navigator : null; +var agent = nav && nav.userAgent || ""; +var ie_edge = /Edge\/(\d+)/.exec(agent); +var ie_upto10 = /MSIE \d/.exec(agent); +var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(agent); +var ie = !!(ie_upto10 || ie_11up || ie_edge); +var safari = !ie && !!nav && /Apple Computer/.test(nav.vendor); + +// src/node-view.ts +var createListNodeView = (node) => { + var _a, _b; + let prevNode = node; + const prevNested = ((_a = node.firstChild) == null ? void 0 : _a.type) === node.type; + const prevSingleChild = node.childCount === 1; + const spec = node.type.spec.toDOM(node); + const { dom, contentDOM } = import_prosemirror_model8.DOMSerializer.renderSpec(document, spec); + if (safari && node.attrs.kind === "toggle") { + ; + (_b = dom.querySelector(".list-marker-click-target")) == null ? void 0 : _b.appendChild(document.createElement("span")); + } + const update = (node2) => { + var _a2; + if (!node2.sameMarkup(prevNode)) return false; + const nested = ((_a2 = node2.firstChild) == null ? void 0 : _a2.type) === node2.type; + const singleChild = node2.childCount === 1; + if (prevNested !== nested || prevSingleChild !== singleChild) return false; + prevNode = node2; + return true; + }; + return { dom, contentDOM, update }; +}; + +// src/plugins/clipboard.ts +var import_prosemirror_state6 = require("prosemirror-state"); + +// src/utils/list-serializer.ts +var import_prosemirror_model9 = require("prosemirror-model"); +var ListDOMSerializer = class _ListDOMSerializer extends import_prosemirror_model9.DOMSerializer { + static nodesFromSchema(schema) { + const nodes = import_prosemirror_model9.DOMSerializer.nodesFromSchema(schema); + return { + ...nodes, + list: (node) => listToDOM({ node, nativeList: true, getMarkers: () => null }) + }; + } + static fromSchema(schema) { + return schema.cached.listDomSerializer || (schema.cached.listDomSerializer = new _ListDOMSerializer( + this.nodesFromSchema(schema), + this.marksFromSchema(schema) + )); + } + serializeFragment(fragment, options, target) { + const dom = super.serializeFragment(fragment, options, target); + return joinListElements(dom); + } +}; +function joinListElements(parent) { + for (let i = 0; i < parent.childNodes.length; i++) { + const child = parent.children.item(i); + if (!child) continue; + if (child.tagName === "UL" || child.tagName === "OL") { + let next = null; + while (next = child.nextElementSibling, (next == null ? void 0 : next.tagName) === child.tagName) { + child.append(...Array.from(next.children)); + next.remove(); + } + } + joinListElements(child); + } + return parent; +} + +// src/utils/unwrap-list-slice.ts +var import_prosemirror_model10 = require("prosemirror-model"); +function unwrapListSlice(slice) { + while (slice.openStart >= 2 && slice.openEnd >= 2 && slice.content.childCount === 1 && isListNode(slice.content.child(0))) { + slice = new import_prosemirror_model10.Slice( + slice.content.child(0).content, + slice.openStart - 1, + slice.openEnd - 1 + ); + } + return slice; +} + +// src/plugins/clipboard.ts +function createListClipboardPlugin(schema) { + return new import_prosemirror_state6.Plugin({ + props: { + clipboardSerializer: ListDOMSerializer.fromSchema(schema), + transformCopied: unwrapListSlice + } + }); +} + +// src/plugins/event.ts +var import_prosemirror_state7 = require("prosemirror-state"); +function createListEventPlugin() { + return new import_prosemirror_state7.Plugin({ + props: { + handleDOMEvents: { + mousedown: (view, event) => handleListMarkerMouseDown({ view, event }) + } + } + }); +} + +// src/plugins/rendering.ts +var import_prosemirror_state8 = require("prosemirror-state"); +function createListRenderingPlugin() { + return new import_prosemirror_state8.Plugin({ + props: { + nodeViews: { + list: createListNodeView + } + } + }); +} + +// src/plugins/safari-workaround.ts +var import_prosemirror_safari_ime_span = require("prosemirror-safari-ime-span"); +function createSafariInputMethodWorkaroundPlugin() { + return import_prosemirror_safari_ime_span.imeSpan; +} + +// src/plugins/index.ts +function createListPlugins({ schema }) { + return [ + createListEventPlugin(), + createListRenderingPlugin(), + createListClipboardPlugin(schema), + createSafariInputMethodWorkaroundPlugin() + ]; +} + +// src/utils/range-to-string.ts +function rangeToString(range) { + const { parent, startIndex, endIndex } = range; + return cutByIndex(parent.content, startIndex, endIndex).toString(); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + ListDOMSerializer, + backspaceCommand, + createDedentListCommand, + createIndentListCommand, + createListClipboardPlugin, + createListEventPlugin, + createListNodeView, + createListPlugins, + createListRenderingPlugin, + createListSpec, + createMoveListCommand, + createParseDomRules, + createSafariInputMethodWorkaroundPlugin, + createSplitListCommand, + createToggleCollapsedCommand, + createToggleListCommand, + createUnwrapListCommand, + createWrapInListCommand, + defaultAttributesGetter, + defaultListClickHandler, + defaultMarkerGetter, + deleteCommand, + doSplitList, + enterCommand, + enterWithoutLift, + findListsRange, + flatListGroup, + getListType, + handleListMarkerMouseDown, + isCollapsedListNode, + isListNode, + isListType, + isListsRange, + joinCollapsedListBackward, + joinListElements, + joinListUp, + listInputRules, + listKeymap, + listToDOM, + migrateDocJSON, + parseInteger, + protectCollapsed, + rangeToString, + setSafeSelection, + unwrapListSlice, + wrappingListInputRule +}); diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.css b/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.css new file mode 100644 index 000000000..53a7d6229 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.css @@ -0,0 +1,87 @@ +/* src/style.css */ +.prosemirror-flat-list { + padding: 0; + margin-top: 0; + margin-bottom: 0; + margin-left: 32px; + margin-bottom: 0; + position: relative; + display: list-item; + list-style: none; +} +.prosemirror-flat-list.ProseMirror-selectednode { + outline: none; +} +.prosemirror-flat-list.ProseMirror-selectednode:after { + content: ""; + position: absolute; + left: -32px; + right: -2px; + top: -2px; + bottom: -2px; + border: 2px solid #8cf; + pointer-events: none; +} +.prosemirror-flat-list[data-list-kind=bullet] { + list-style: disc; +} +.prosemirror-flat-list[data-list-kind=ordered] { + counter-increment: prosemirror-flat-list-counter; +} +.prosemirror-flat-list[data-list-kind=ordered] > * { + contain: style; +} +.prosemirror-flat-list[data-list-kind=ordered]::before { + position: absolute; + right: 100%; + font-variant-numeric: tabular-nums; + content: counter(prosemirror-flat-list-counter, decimal) ". "; +} +.prosemirror-flat-list[data-list-kind=ordered]:first-child, +:not(.prosemirror-flat-list[data-list-kind=ordered]) + .prosemirror-flat-list[data-list-kind=ordered] { + counter-reset: prosemirror-flat-list-counter; +} +@supports (counter-set: prosemirror-flat-list-counter 1) { + [data-list-order]:is(.prosemirror-flat-list[data-list-kind=ordered]:first-child, :not(.prosemirror-flat-list[data-list-kind=ordered]) + .prosemirror-flat-list[data-list-kind=ordered]) { + counter-set: prosemirror-flat-list-counter var(--prosemirror-flat-list-order); + } +} +@supports not (counter-set: prosemirror-flat-list-counter 1) { + [data-list-order]:is(.prosemirror-flat-list[data-list-kind=ordered]:first-child, :not(.prosemirror-flat-list[data-list-kind=ordered]) + .prosemirror-flat-list[data-list-kind=ordered]) { + counter-increment: prosemirror-flat-list-counter var(--prosemirror-flat-list-order); + } +} +.prosemirror-flat-list[data-list-kind=task] > .list-marker { + position: absolute; + right: 100%; + text-align: center; + width: 1.5em; + width: 1lh; +} +.prosemirror-flat-list[data-list-kind=task] > .list-marker, +.prosemirror-flat-list[data-list-kind=task] > .list-marker * { + cursor: pointer; +} +.prosemirror-flat-list[data-list-kind=toggle] > .list-marker { + position: absolute; + right: 100%; + text-align: center; + width: 1.5em; + width: 1lh; +} +.prosemirror-flat-list[data-list-kind=toggle] > .list-marker::before { + content: "\23f7"; +} +.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable][data-list-collapsed] > .list-marker::before { + content: "\23f5"; +} +.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable] > .list-marker { + cursor: pointer; +} +.prosemirror-flat-list[data-list-kind=toggle]:not([data-list-collapsable]) > .list-marker { + opacity: 40%; + pointer-events: none; +} +.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable][data-list-collapsed] > .list-content > *:nth-child(n+2) { + display: none; +} diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-safari-ime-span.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-safari-ime-span.cjs new file mode 100644 index 000000000..6f6a9da3d --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-safari-ime-span.cjs @@ -0,0 +1,74 @@ +"use strict"; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key2 of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key2) && key2 !== except) + __defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + imeSpan: () => imeSpan +}); +module.exports = __toCommonJS(src_exports); +var import_prosemirror_state = require("prosemirror-state"); +var import_prosemirror_view = require("prosemirror-view"); + +// src/browser.ts +var nav = typeof navigator != "undefined" ? navigator : null; +var agent = nav && nav.userAgent || ""; +var ie_edge = /Edge\/(\d+)/.exec(agent); +var ie_upto10 = /MSIE \d/.exec(agent); +var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(agent); +var ie = !!(ie_upto10 || ie_11up || ie_edge); +var safari = !ie && !!nav && /Apple Computer/.test(nav.vendor); + +// src/index.ts +var key = new import_prosemirror_state.PluginKey("safari-ime-span"); +var isComposing = false; +var spec = { + key, + props: { + decorations: createDecorations, + handleDOMEvents: { + compositionstart: () => { + isComposing = true; + }, + compositionend: () => { + isComposing = false; + } + } + } +}; +function createDecorations(state) { + const { $from, $to, to } = state.selection; + if (isComposing && $from.sameParent($to)) { + const deco = import_prosemirror_view.Decoration.widget(to, createSpan, { + ignoreSelection: true, + key: "safari-ime-span" + }); + return import_prosemirror_view.DecorationSet.create(state.doc, [deco]); + } +} +function createSpan(view) { + const span = view.dom.ownerDocument.createElement("span"); + span.className = "ProseMirror-safari-ime-span"; + return span; +} +var imeSpan = new import_prosemirror_state.Plugin(safari ? spec : { key }); +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + imeSpan +}); diff --git a/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files b/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files index 395f8fc2e..acb522071 100755 --- a/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files +++ b/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files @@ -28,6 +28,13 @@ "title": "$:/plugins/tiddlywiki/prosemirror/lib/prosemirror.css", "tags": "[[$:/tags/Stylesheet]]" } + },{ + "file": "prosemirror-flat-list.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-flat-list", + "module-type": "library" + } },{ "file": "prosemirror-schema-list.cjs", "fields": { @@ -35,6 +42,13 @@ "title": "prosemirror-schema-list", "module-type": "library" } + },{ + "file": "prosemirror-flat-list.css", + "fields": { + "type": "text/css", + "title": "$:/plugins/tiddlywiki/prosemirror/lib/prosemirror-flat-list.css", + "tags": "[[$:/tags/Stylesheet]]" + } },{ "file": "prosemirror-example-setup.cjs", "fields": { @@ -49,110 +63,104 @@ "title": "prosemirror-schema-basic", "module-type": "library" } - }, - { + },{ "file": "orderedmap.cjs", "fields": { "type": "application/javascript", "title": "orderedmap", "module-type": "library" } - }, - { + },{ "file": "prosemirror-transform.cjs", "fields": { "type": "application/javascript", "title": "prosemirror-transform", "module-type": "library" } - }, - { + },{ "file": "prosemirror-keymap.cjs", "fields": { "type": "application/javascript", "title": "prosemirror-keymap", "module-type": "library" } - }, - { + },{ "file": "prosemirror-history.cjs", "fields": { "type": "application/javascript", "title": "prosemirror-history", "module-type": "library" } - }, - { + },{ "file": "prosemirror-commands.cjs", "fields": { "type": "application/javascript", "title": "prosemirror-commands", "module-type": "library" } - }, - { + },{ "file": "prosemirror-dropcursor.cjs", "fields": { "type": "application/javascript", "title": "prosemirror-dropcursor", "module-type": "library" } - }, - { + },{ "file": "prosemirror-gapcursor.cjs", "fields": { "type": "application/javascript", "title": "prosemirror-gapcursor", "module-type": "library" } - }, - { + },{ "file": "prosemirror-menu.cjs", "fields": { "type": "application/javascript", "title": "prosemirror-menu", "module-type": "library" } - }, - { + },{ "file": "menu.css", "fields": { "type": "text/css", "title": "$:/plugins/tiddlywiki/prosemirror/lib/menu.css", "tags": "[[$:/tags/Stylesheet]]" } - }, - { + },{ "file": "prosemirror-inputrules.cjs", "fields": { "type": "application/javascript", "title": "prosemirror-inputrules", "module-type": "library" } - }, - { + },{ "file": "w3c-keyname.cjs", "fields": { "type": "application/javascript", "title": "w3c-keyname", "module-type": "library" } - }, - { + },{ "file": "crelt.cjs", "fields": { "type": "application/javascript", "title": "crelt", "module-type": "library" } - }, - { + },{ "file": "rope-sequence.cjs", "fields": { "type": "application/javascript", "title": "rope-sequence", "module-type": "library" } + },{ + "file": "prosemirror-safari-ime-span.cjs", + "fields": { + "type": "application/javascript", + "title": "prosemirror-safari-ime-span", + "module-type": "library" + } } ] } diff --git a/plugins/tiddlywiki/prosemirror/widget.js b/plugins/tiddlywiki/prosemirror/widget.js index 8279baa47..29b85bb76 100644 --- a/plugins/tiddlywiki/prosemirror/widget.js +++ b/plugins/tiddlywiki/prosemirror/widget.js @@ -15,9 +15,16 @@ var wikiAstToProseMirrorAst = require("$:/plugins/tiddlywiki/prosemirror/ast/to- var { EditorState } = require("prosemirror-state"); var { EditorView } = require("prosemirror-view"); var { Schema, DOMParser } = require("prosemirror-model"); -var { schema } = require("prosemirror-schema-basic"); -var { addListNodes } = require("prosemirror-schema-list"); +var { schema: basicSchema } = require("prosemirror-schema-basic"); +var { + createListPlugins, + createListSpec, + listInputRules, + listKeymap +} = require("prosemirror-flat-list"); var { exampleSetup } = require("prosemirror-example-setup"); +var { keymap } = require("prosemirror-keymap"); +var { inputRules } = require("prosemirror-inputrules"); var ProsemirrorWidget = function(parseTreeNode,options) { this.initialise(parseTreeNode,options); @@ -39,13 +46,14 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { class: 'tc-prosemirror-container', }); - // Mix the nodes from prosemirror-schema-list into the basic schema to - // create a schema with list support. - var mySchema = new Schema({ - // nodes: addListNodes(schema.spec.nodes, "paragraph block*", "block"), - nodes: addListNodes(schema.spec.nodes, "block*", "block"), - marks: schema.spec.marks + var schema = new Schema({ + nodes: basicSchema.spec.nodes.append({ list: createListSpec() }), + marks: basicSchema.spec.marks, }) + + var listKeymapPlugin = keymap(listKeymap) + var listInputRulePlugin = inputRules({ rules: listInputRules }) + var listPlugins = createListPlugins({ schema }) var self = this; var wikiAst = $tw.wiki.parseText(null, `* This is an unordered list @@ -59,9 +67,14 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { console.log(`initial doc`, doc); this.view = new EditorView(container, { state: EditorState.create({ - // doc: mySchema.node("doc", null, [mySchema.node("paragraph")]), - doc: mySchema.nodeFromJSON(doc), - plugins: exampleSetup({schema: mySchema}) + // doc: schema.node("doc", null, [schema.node("paragraph")]), + doc: schema.nodeFromJSON(doc), + plugins: [ + listKeymapPlugin, + listInputRulePlugin, + ...listPlugins, + ...exampleSetup({ schema }), + ], }), dispatchTransaction: function(transaction) { var newState = self.view.state.apply(transaction); From 8c320892f558de08fa029fff81b0d60a8b4ae6c1 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 24 Mar 2025 16:49:14 +0800 Subject: [PATCH 89/98] feat: remove prosemirror-example-setup, and allow Tab indent * remove prosemirror-example-setup, move all configs here. And remove `prosemirror-schema-list` that it depends on. * prosemirror-flat-list only add dot style to list container, not each list item. Make it looks weird. And when creating new list, it will make each item to be a full new list, which is also weird. --- menu.js | 0 .../tiddlywiki/prosemirror/development.tid | 5 - .../files/prosemirror-example-setup.cjs | 469 ------------------ .../prosemirror/files/tiddlywiki.files | 14 - .../prosemirror/setup/inputrules.js | 44 ++ .../tiddlywiki/prosemirror/setup/keymap.js | 84 ++++ plugins/tiddlywiki/prosemirror/setup/menu.js | 171 +++++++ .../tiddlywiki/prosemirror/setup/prompt.js | 161 ++++++ plugins/tiddlywiki/prosemirror/setup/setup.js | 47 ++ plugins/tiddlywiki/prosemirror/widget.js | 2 +- 10 files changed, 508 insertions(+), 489 deletions(-) create mode 100644 menu.js delete mode 100644 plugins/tiddlywiki/prosemirror/files/prosemirror-example-setup.cjs create mode 100644 plugins/tiddlywiki/prosemirror/setup/inputrules.js create mode 100644 plugins/tiddlywiki/prosemirror/setup/keymap.js create mode 100644 plugins/tiddlywiki/prosemirror/setup/menu.js create mode 100644 plugins/tiddlywiki/prosemirror/setup/prompt.js create mode 100644 plugins/tiddlywiki/prosemirror/setup/setup.js diff --git a/menu.js b/menu.js new file mode 100644 index 000000000..e69de29bb diff --git a/plugins/tiddlywiki/prosemirror/development.tid b/plugins/tiddlywiki/prosemirror/development.tid index 8d50f720b..6e660187e 100755 --- a/plugins/tiddlywiki/prosemirror/development.tid +++ b/plugins/tiddlywiki/prosemirror/development.tid @@ -25,8 +25,3 @@ Downloaded from JsDelivr CDN (like `https://cdn.jsdelivr.net/npm/prosemirror-sta * [ext[crelt|https://cdn.jsdelivr.net/npm/crelt@latest/dist/index.cjs]]: v1.0.6 * [ext[rope-sequence|https://cdn.jsdelivr.net/npm/rope-sequence@latest/dist/index.cjs]]: v1.3.4 * [ext[prosemirror-safari-ime-span|https://cdn.jsdelivr.net/npm/prosemirror-safari-ime-span@latest/dist/index.cjs]]: v1.0.2 - -!! TODO - -* remove prosemirror-example-setup, move all configs here. And remove `prosemirror-schema-list` that it depends on. -* prosemirror-flat-list only add dot style to list container, not each list item. Make it looks weird. And when creating new list, it will make each item to be a full new list, which is also weird. diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-example-setup.cjs b/plugins/tiddlywiki/prosemirror/files/prosemirror-example-setup.cjs deleted file mode 100644 index 2bab07c32..000000000 --- a/plugins/tiddlywiki/prosemirror/files/prosemirror-example-setup.cjs +++ /dev/null @@ -1,469 +0,0 @@ -'use strict'; - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } -function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } -function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } -function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } -function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } -function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } -function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } -function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } -function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } -function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } -function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } -var prosemirrorKeymap = require('prosemirror-keymap'); -var prosemirrorHistory = require('prosemirror-history'); -var prosemirrorCommands = require('prosemirror-commands'); -var prosemirrorState = require('prosemirror-state'); -var prosemirrorDropcursor = require('prosemirror-dropcursor'); -var prosemirrorGapcursor = require('prosemirror-gapcursor'); -var prosemirrorMenu = require('prosemirror-menu'); -var prosemirrorSchemaList = require('prosemirror-schema-list'); -var prosemirrorInputrules = require('prosemirror-inputrules'); -var prefix = "ProseMirror-prompt"; -function openPrompt(options) { - var wrapper = document.body.appendChild(document.createElement("div")); - wrapper.className = prefix; - var mouseOutside = function mouseOutside(e) { - if (!wrapper.contains(e.target)) close(); - }; - setTimeout(function () { - return window.addEventListener("mousedown", mouseOutside); - }, 50); - var close = function close() { - window.removeEventListener("mousedown", mouseOutside); - if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper); - }; - var domFields = []; - for (var name in options.fields) domFields.push(options.fields[name].render()); - var submitButton = document.createElement("button"); - submitButton.type = "submit"; - submitButton.className = prefix + "-submit"; - submitButton.textContent = "OK"; - var cancelButton = document.createElement("button"); - cancelButton.type = "button"; - cancelButton.className = prefix + "-cancel"; - cancelButton.textContent = "Cancel"; - cancelButton.addEventListener("click", close); - var form = wrapper.appendChild(document.createElement("form")); - if (options.title) form.appendChild(document.createElement("h5")).textContent = options.title; - domFields.forEach(function (field) { - form.appendChild(document.createElement("div")).appendChild(field); - }); - var buttons = form.appendChild(document.createElement("div")); - buttons.className = prefix + "-buttons"; - buttons.appendChild(submitButton); - buttons.appendChild(document.createTextNode(" ")); - buttons.appendChild(cancelButton); - var box = wrapper.getBoundingClientRect(); - wrapper.style.top = (window.innerHeight - box.height) / 2 + "px"; - wrapper.style.left = (window.innerWidth - box.width) / 2 + "px"; - var submit = function submit() { - var params = getValues(options.fields, domFields); - if (params) { - close(); - options.callback(params); - } - }; - form.addEventListener("submit", function (e) { - e.preventDefault(); - submit(); - }); - form.addEventListener("keydown", function (e) { - if (e.keyCode == 27) { - e.preventDefault(); - close(); - } else if (e.keyCode == 13 && !(e.ctrlKey || e.metaKey || e.shiftKey)) { - e.preventDefault(); - submit(); - } else if (e.keyCode == 9) { - window.setTimeout(function () { - if (!wrapper.contains(document.activeElement)) close(); - }, 500); - } - }); - var input = form.elements[0]; - if (input) input.focus(); -} -function getValues(fields, domFields) { - var result = Object.create(null), - i = 0; - for (var name in fields) { - var field = fields[name], - dom = domFields[i++]; - var value = field.read(dom), - bad = field.validate(value); - if (bad) { - reportInvalid(dom, bad); - return null; - } - result[name] = field.clean(value); - } - return result; -} -function reportInvalid(dom, message) { - var parent = dom.parentNode; - var msg = parent.appendChild(document.createElement("div")); - msg.style.left = dom.offsetLeft + dom.offsetWidth + 2 + "px"; - msg.style.top = dom.offsetTop - 5 + "px"; - msg.className = "ProseMirror-invalid"; - msg.textContent = message; - setTimeout(function () { - return parent.removeChild(msg); - }, 1500); -} -var Field = function () { - function Field(options) { - _classCallCheck(this, Field); - this.options = options; - } - _createClass(Field, [{ - key: "read", - value: function read(dom) { - return dom.value; - } - }, { - key: "validateType", - value: function validateType(value) { - return null; - } - }, { - key: "validate", - value: function validate(value) { - if (!value && this.options.required) return "Required field"; - return this.validateType(value) || (this.options.validate ? this.options.validate(value) : null); - } - }, { - key: "clean", - value: function clean(value) { - return this.options.clean ? this.options.clean(value) : value; - } - }]); - return Field; -}(); -var TextField = function (_Field) { - _inherits(TextField, _Field); - var _super = _createSuper(TextField); - function TextField() { - _classCallCheck(this, TextField); - return _super.apply(this, arguments); - } - _createClass(TextField, [{ - key: "render", - value: function render() { - var input = document.createElement("input"); - input.type = "text"; - input.placeholder = this.options.label; - input.value = this.options.value || ""; - input.autocomplete = "off"; - return input; - } - }]); - return TextField; -}(Field); -function canInsert(state, nodeType) { - var $from = state.selection.$from; - for (var d = $from.depth; d >= 0; d--) { - var index = $from.index(d); - if ($from.node(d).canReplaceWith(index, index, nodeType)) return true; - } - return false; -} -function insertImageItem(nodeType) { - return new prosemirrorMenu.MenuItem({ - title: "Insert image", - label: "Image", - enable: function enable(state) { - return canInsert(state, nodeType); - }, - run: function run(state, _, view) { - var _state$selection = state.selection, - from = _state$selection.from, - to = _state$selection.to, - attrs = null; - if (state.selection instanceof prosemirrorState.NodeSelection && state.selection.node.type == nodeType) attrs = state.selection.node.attrs; - openPrompt({ - title: "Insert image", - fields: { - src: new TextField({ - label: "Location", - required: true, - value: attrs && attrs.src - }), - title: new TextField({ - label: "Title", - value: attrs && attrs.title - }), - alt: new TextField({ - label: "Description", - value: attrs ? attrs.alt : state.doc.textBetween(from, to, " ") - }) - }, - callback: function callback(attrs) { - view.dispatch(view.state.tr.replaceSelectionWith(nodeType.createAndFill(attrs))); - view.focus(); - } - }); - } - }); -} -function cmdItem(cmd, options) { - var passedOptions = { - label: options.title, - run: cmd - }; - for (var prop in options) passedOptions[prop] = options[prop]; - if (!options.enable && !options.select) passedOptions[options.enable ? "enable" : "select"] = function (state) { - return cmd(state); - }; - return new prosemirrorMenu.MenuItem(passedOptions); -} -function markActive(state, type) { - var _state$selection2 = state.selection, - from = _state$selection2.from, - $from = _state$selection2.$from, - to = _state$selection2.to, - empty = _state$selection2.empty; - if (empty) return !!type.isInSet(state.storedMarks || $from.marks());else return state.doc.rangeHasMark(from, to, type); -} -function markItem(markType, options) { - var passedOptions = { - active: function active(state) { - return markActive(state, markType); - } - }; - for (var prop in options) passedOptions[prop] = options[prop]; - return cmdItem(prosemirrorCommands.toggleMark(markType), passedOptions); -} -function linkItem(markType) { - return new prosemirrorMenu.MenuItem({ - title: "Add or remove link", - icon: prosemirrorMenu.icons.link, - active: function active(state) { - return markActive(state, markType); - }, - enable: function enable(state) { - return !state.selection.empty; - }, - run: function run(state, dispatch, view) { - if (markActive(state, markType)) { - prosemirrorCommands.toggleMark(markType)(state, dispatch); - return true; - } - openPrompt({ - title: "Create a link", - fields: { - href: new TextField({ - label: "Link target", - required: true - }), - title: new TextField({ - label: "Title" - }) - }, - callback: function callback(attrs) { - prosemirrorCommands.toggleMark(markType, attrs)(view.state, view.dispatch); - view.focus(); - } - }); - } - }); -} -function wrapListItem(nodeType, options) { - return cmdItem(prosemirrorSchemaList.wrapInList(nodeType, options.attrs), options); -} -function buildMenuItems(schema) { - var r = {}; - var mark; - if (mark = schema.marks.strong) r.toggleStrong = markItem(mark, { - title: "Toggle strong style", - icon: prosemirrorMenu.icons.strong - }); - if (mark = schema.marks.em) r.toggleEm = markItem(mark, { - title: "Toggle emphasis", - icon: prosemirrorMenu.icons.em - }); - if (mark = schema.marks.code) r.toggleCode = markItem(mark, { - title: "Toggle code font", - icon: prosemirrorMenu.icons.code - }); - if (mark = schema.marks.link) r.toggleLink = linkItem(mark); - var node; - if (node = schema.nodes.image) r.insertImage = insertImageItem(node); - if (node = schema.nodes.bullet_list) r.wrapBulletList = wrapListItem(node, { - title: "Wrap in bullet list", - icon: prosemirrorMenu.icons.bulletList - }); - if (node = schema.nodes.ordered_list) r.wrapOrderedList = wrapListItem(node, { - title: "Wrap in ordered list", - icon: prosemirrorMenu.icons.orderedList - }); - if (node = schema.nodes.blockquote) r.wrapBlockQuote = prosemirrorMenu.wrapItem(node, { - title: "Wrap in block quote", - icon: prosemirrorMenu.icons.blockquote - }); - if (node = schema.nodes.paragraph) r.makeParagraph = prosemirrorMenu.blockTypeItem(node, { - title: "Change to paragraph", - label: "Plain" - }); - if (node = schema.nodes.code_block) r.makeCodeBlock = prosemirrorMenu.blockTypeItem(node, { - title: "Change to code block", - label: "Code" - }); - if (node = schema.nodes.heading) for (var i = 1; i <= 10; i++) r["makeHead" + i] = prosemirrorMenu.blockTypeItem(node, { - title: "Change to heading " + i, - label: "Level " + i, - attrs: { - level: i - } - }); - if (node = schema.nodes.horizontal_rule) { - var hr = node; - r.insertHorizontalRule = new prosemirrorMenu.MenuItem({ - title: "Insert horizontal rule", - label: "Horizontal rule", - enable: function enable(state) { - return canInsert(state, hr); - }, - run: function run(state, dispatch) { - dispatch(state.tr.replaceSelectionWith(hr.create())); - } - }); - } - var cut = function cut(arr) { - return arr.filter(function (x) { - return x; - }); - }; - r.insertMenu = new prosemirrorMenu.Dropdown(cut([r.insertImage, r.insertHorizontalRule]), { - label: "Insert" - }); - r.typeMenu = new prosemirrorMenu.Dropdown(cut([r.makeParagraph, r.makeCodeBlock, r.makeHead1 && new prosemirrorMenu.DropdownSubmenu(cut([r.makeHead1, r.makeHead2, r.makeHead3, r.makeHead4, r.makeHead5, r.makeHead6]), { - label: "Heading" - })]), { - label: "Type..." - }); - r.inlineMenu = [cut([r.toggleStrong, r.toggleEm, r.toggleCode, r.toggleLink])]; - r.blockMenu = [cut([r.wrapBulletList, r.wrapOrderedList, r.wrapBlockQuote, prosemirrorMenu.joinUpItem, prosemirrorMenu.liftItem, prosemirrorMenu.selectParentNodeItem])]; - r.fullMenu = r.inlineMenu.concat([[r.insertMenu, r.typeMenu]], [[prosemirrorMenu.undoItem, prosemirrorMenu.redoItem]], r.blockMenu); - return r; -} -var mac = typeof navigator != "undefined" ? /Mac|iP(hone|[oa]d)/.test(navigator.platform) : false; -function buildKeymap(schema, mapKeys) { - var keys = {}, - type; - function bind(key, cmd) { - if (mapKeys) { - var mapped = mapKeys[key]; - if (mapped === false) return; - if (mapped) key = mapped; - } - keys[key] = cmd; - } - bind("Mod-z", prosemirrorHistory.undo); - bind("Shift-Mod-z", prosemirrorHistory.redo); - bind("Backspace", prosemirrorInputrules.undoInputRule); - if (!mac) bind("Mod-y", prosemirrorHistory.redo); - bind("Alt-ArrowUp", prosemirrorCommands.joinUp); - bind("Alt-ArrowDown", prosemirrorCommands.joinDown); - bind("Mod-BracketLeft", prosemirrorCommands.lift); - bind("Escape", prosemirrorCommands.selectParentNode); - if (type = schema.marks.strong) { - bind("Mod-b", prosemirrorCommands.toggleMark(type)); - bind("Mod-B", prosemirrorCommands.toggleMark(type)); - } - if (type = schema.marks.em) { - bind("Mod-i", prosemirrorCommands.toggleMark(type)); - bind("Mod-I", prosemirrorCommands.toggleMark(type)); - } - if (type = schema.marks.code) bind("Mod-`", prosemirrorCommands.toggleMark(type)); - if (type = schema.nodes.bullet_list) bind("Shift-Ctrl-8", prosemirrorSchemaList.wrapInList(type)); - if (type = schema.nodes.ordered_list) bind("Shift-Ctrl-9", prosemirrorSchemaList.wrapInList(type)); - if (type = schema.nodes.blockquote) bind("Ctrl->", prosemirrorCommands.wrapIn(type)); - if (type = schema.nodes.hard_break) { - var br = type, - cmd = prosemirrorCommands.chainCommands(prosemirrorCommands.exitCode, function (state, dispatch) { - if (dispatch) dispatch(state.tr.replaceSelectionWith(br.create()).scrollIntoView()); - return true; - }); - bind("Mod-Enter", cmd); - bind("Shift-Enter", cmd); - if (mac) bind("Ctrl-Enter", cmd); - } - if (type = schema.nodes.list_item) { - bind("Enter", prosemirrorSchemaList.splitListItem(type)); - bind("Mod-[", prosemirrorSchemaList.liftListItem(type)); - bind("Mod-]", prosemirrorSchemaList.sinkListItem(type)); - } - if (type = schema.nodes.paragraph) bind("Shift-Ctrl-0", prosemirrorCommands.setBlockType(type)); - if (type = schema.nodes.code_block) bind("Shift-Ctrl-\\", prosemirrorCommands.setBlockType(type)); - if (type = schema.nodes.heading) for (var i = 1; i <= 6; i++) bind("Shift-Ctrl-" + i, prosemirrorCommands.setBlockType(type, { - level: i - })); - if (type = schema.nodes.horizontal_rule) { - var hr = type; - bind("Mod-_", function (state, dispatch) { - if (dispatch) dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView()); - return true; - }); - } - return keys; -} -function blockQuoteRule(nodeType) { - return prosemirrorInputrules.wrappingInputRule(/^\s*>\s$/, nodeType); -} -function orderedListRule(nodeType) { - return prosemirrorInputrules.wrappingInputRule(/^(\d+)\.\s$/, nodeType, function (match) { - return { - order: +match[1] - }; - }, function (match, node) { - return node.childCount + node.attrs.order == +match[1]; - }); -} -function bulletListRule(nodeType) { - return prosemirrorInputrules.wrappingInputRule(/^\s*([-+*])\s$/, nodeType); -} -function codeBlockRule(nodeType) { - return prosemirrorInputrules.textblockTypeInputRule(/^```$/, nodeType); -} -function headingRule(nodeType, maxLevel) { - return prosemirrorInputrules.textblockTypeInputRule(new RegExp("^(#{1," + maxLevel + "})\\s$"), nodeType, function (match) { - return { - level: match[1].length - }; - }); -} -function buildInputRules(schema) { - var rules = prosemirrorInputrules.smartQuotes.concat(prosemirrorInputrules.ellipsis, prosemirrorInputrules.emDash), - type; - if (type = schema.nodes.blockquote) rules.push(blockQuoteRule(type)); - if (type = schema.nodes.ordered_list) rules.push(orderedListRule(type)); - if (type = schema.nodes.bullet_list) rules.push(bulletListRule(type)); - if (type = schema.nodes.code_block) rules.push(codeBlockRule(type)); - if (type = schema.nodes.heading) rules.push(headingRule(type, 6)); - return prosemirrorInputrules.inputRules({ - rules: rules - }); -} -function exampleSetup(options) { - var plugins = [buildInputRules(options.schema), prosemirrorKeymap.keymap(buildKeymap(options.schema, options.mapKeys)), prosemirrorKeymap.keymap(prosemirrorCommands.baseKeymap), prosemirrorDropcursor.dropCursor(), prosemirrorGapcursor.gapCursor()]; - if (options.menuBar !== false) plugins.push(prosemirrorMenu.menuBar({ - floating: options.floatingMenu !== false, - content: options.menuContent || buildMenuItems(options.schema).fullMenu - })); - if (options.history !== false) plugins.push(prosemirrorHistory.history()); - return plugins.concat(new prosemirrorState.Plugin({ - props: { - attributes: { - "class": "ProseMirror-example-setup-style" - } - } - })); -} -exports.buildInputRules = buildInputRules; -exports.buildKeymap = buildKeymap; -exports.buildMenuItems = buildMenuItems; -exports.exampleSetup = exampleSetup; diff --git a/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files b/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files index acb522071..98eb820ae 100755 --- a/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files +++ b/plugins/tiddlywiki/prosemirror/files/tiddlywiki.files @@ -35,13 +35,6 @@ "title": "prosemirror-flat-list", "module-type": "library" } - },{ - "file": "prosemirror-schema-list.cjs", - "fields": { - "type": "application/javascript", - "title": "prosemirror-schema-list", - "module-type": "library" - } },{ "file": "prosemirror-flat-list.css", "fields": { @@ -49,13 +42,6 @@ "title": "$:/plugins/tiddlywiki/prosemirror/lib/prosemirror-flat-list.css", "tags": "[[$:/tags/Stylesheet]]" } - },{ - "file": "prosemirror-example-setup.cjs", - "fields": { - "type": "application/javascript", - "title": "prosemirror-example-setup", - "module-type": "library" - } },{ "file": "prosemirror-schema-basic.cjs", "fields": { diff --git a/plugins/tiddlywiki/prosemirror/setup/inputrules.js b/plugins/tiddlywiki/prosemirror/setup/inputrules.js new file mode 100644 index 000000000..ff62bf375 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/setup/inputrules.js @@ -0,0 +1,44 @@ +/*\ +title: $:/plugins/tiddlywiki/prosemirror/setup/inputrules.js +type: application/javascript +module-type: library + +\*/ + +"use strict"; + +var { inputRules, wrappingInputRule, textblockTypeInputRule, smartQuotes, emDash, ellipsis } = require("prosemirror-inputrules"); +var { NodeType, Schema } = require("prosemirror-model"); + +function blockQuoteRule(nodeType) { + return wrappingInputRule(/^\s*>\s$/, nodeType); +} + +function orderedListRule(nodeType) { + return wrappingInputRule(/^(\d+)\.\s$/, nodeType, function(match) { return { order: +match[1] }; }, + function(match, node) { return node.childCount + node.attrs.order == +match[1]; }); +} + +function bulletListRule(nodeType) { + return wrappingInputRule(/^\s*([-+*])\s$/, nodeType); +} + +function codeBlockRule(nodeType) { + return textblockTypeInputRule(/^```$/, nodeType); +} + +function headingRule(nodeType, maxLevel) { + return textblockTypeInputRule(new RegExp("^(#{1," + maxLevel + "})\\s$"), nodeType, function(match) { return { level: match[1].length }; }); +} + +function buildInputRules(schema) { + var rules = smartQuotes.concat(ellipsis, emDash), type; + if (type = schema.nodes.blockquote) rules.push(blockQuoteRule(type)); + if (type = schema.nodes.ordered_list) rules.push(orderedListRule(type)); + if (type = schema.nodes.bullet_list) rules.push(bulletListRule(type)); + if (type = schema.nodes.code_block) rules.push(codeBlockRule(type)); + if (type = schema.nodes.heading) rules.push(headingRule(type, 6)); + return inputRules({ rules: rules }); +} + +exports.buildInputRules = buildInputRules; diff --git a/plugins/tiddlywiki/prosemirror/setup/keymap.js b/plugins/tiddlywiki/prosemirror/setup/keymap.js new file mode 100644 index 000000000..d5ad980fd --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/setup/keymap.js @@ -0,0 +1,84 @@ +/*\ +title: $:/plugins/tiddlywiki/prosemirror/setup/keymap.js +type: application/javascript +module-type: library + +\*/ + +"use strict"; + +var prosemirrorCommands = require("prosemirror-commands"); +var prosemirrorFlatList = require("prosemirror-flat-list"); +var prosemirrorHistory = require("prosemirror-history"); +var prosemirrorInputrules = require("prosemirror-inputrules"); +var prosemirrorState = require("prosemirror-state"); +var prosemirrorModel = require("prosemirror-model"); + +var mac = typeof navigator != "undefined" ? /Mac|iP(hone|[oa]d)/.test(navigator.platform) : false; + +function buildKeymap(schema, mapKeys) { + var keys = {}, type; + function bind(key, cmd) { + if (mapKeys) { + var mapped = mapKeys[key]; + if (mapped === false) return; + if (mapped) key = mapped; + } + keys[key] = cmd; + } + + bind("Mod-z", prosemirrorHistory.undo); + bind("Shift-Mod-z", prosemirrorHistory.redo); + bind("Backspace", prosemirrorInputrules.undoInputRule); + if (!mac) bind("Mod-y", prosemirrorHistory.redo); + + bind("Alt-ArrowUp", prosemirrorCommands.joinUp); + bind("Alt-ArrowDown", prosemirrorCommands.joinDown); + bind("Mod-BracketLeft", prosemirrorCommands.lift); + bind("Escape", prosemirrorCommands.selectParentNode); + + if (type = schema.marks.strong) { + bind("Mod-b", prosemirrorCommands.toggleMark(type)); + bind("Mod-B", prosemirrorCommands.toggleMark(type)); + } + if (type = schema.marks.em) { + bind("Mod-i", prosemirrorCommands.toggleMark(type)); + bind("Mod-I", prosemirrorCommands.toggleMark(type)); + } + if (type = schema.marks.code) + bind("Mod-`", prosemirrorCommands.toggleMark(type)); + if (type = schema.nodes.blockquote) + bind("Ctrl->", prosemirrorCommands.wrapIn(type)); + if (type = schema.nodes.hard_break) { + var br = type, cmd = prosemirrorCommands.chainCommands(prosemirrorCommands.exitCode, function(state, dispatch) { + if (dispatch) dispatch(state.tr.replaceSelectionWith(br.create()).scrollIntoView()); + return true; + }); + bind("Mod-Enter", cmd); + bind("Shift-Enter", cmd); + if (mac) bind("Ctrl-Enter", cmd); + } + if (type = schema.nodes.list) { + bind("Shift-Tab", prosemirrorFlatList.createDedentListCommand(type)); + bind("Tab", prosemirrorFlatList.createIndentListCommand(type)); + } + if (type = schema.nodes.paragraph) + bind("Shift-Ctrl-0", prosemirrorCommands.setBlockType(type)); + if (type = schema.nodes.code_block) + bind("Shift-Ctrl-\\", prosemirrorCommands.setBlockType(type)); + if (type = schema.nodes.heading) + for (var i = 1; i <= 6; i++) bind("Shift-Ctrl-" + i, prosemirrorCommands.setBlockType(type, {level: i})); + if (type = schema.nodes.horizontal_rule) { + var hr = type; + bind("Mod-_", function(state, dispatch) { + if (dispatch) dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView()); + return true; + }); + } + + return keys; +} + +module.exports = { + buildKeymap: buildKeymap +}; diff --git a/plugins/tiddlywiki/prosemirror/setup/menu.js b/plugins/tiddlywiki/prosemirror/setup/menu.js new file mode 100644 index 000000000..a25c456b7 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/setup/menu.js @@ -0,0 +1,171 @@ +/*\ +title: $:/plugins/tiddlywiki/prosemirror/setup/menu.js +type: application/javascript +module-type: library + +\*/ + +"use strict"; + +var { + wrapItem, + blockTypeItem, + Dropdown, + DropdownSubmenu, + joinUpItem, + liftItem, + selectParentNodeItem, + undoItem, + redoItem, + icons, + MenuItem, + MenuElement +} = require("prosemirror-menu"); +var { NodeSelection, EditorState } = require("prosemirror-state"); +var { Schema, NodeType, MarkType } = require("prosemirror-model"); +var { toggleMark } = require("prosemirror-commands"); +var { wrapInList } = require("prosemirror-flat-list"); +var { TextField, openPrompt } = require("$:/plugins/tiddlywiki/prosemirror/setup/prompt.js"); + +function canInsert(state, nodeType) { + var $from = state.selection.$from; + for (var d = $from.depth; d >= 0; d--) { + var index = $from.index(d); + if ($from.node(d).canReplaceWith(index, index, nodeType)) return true; + } + return false; +} + +function insertImageItem(nodeType) { + return new MenuItem({ + title: "Insert image", + label: "Image", + enable: function(state) { return canInsert(state, nodeType); }, + run: function(state, _, view) { + var from = state.selection.from, to = state.selection.to, attrs = null; + if (state.selection instanceof NodeSelection && state.selection.node.type == nodeType) + attrs = state.selection.node.attrs; + openPrompt({ + title: "Insert image", + fields: { + src: new TextField({label: "Location", required: true, value: attrs && attrs.src}), + title: new TextField({label: "Title", value: attrs && attrs.title}), + alt: new TextField({label: "Description", value: attrs ? attrs.alt : state.doc.textBetween(from, to, " ")}) + }, + callback: function(attrs) { + view.dispatch(view.state.tr.replaceSelectionWith(nodeType.createAndFill(attrs))); + view.focus(); + } + }); + } + }); +} + +function cmdItem(cmd, options) { + var passedOptions = { + label: options.title, + run: cmd + }; + for (var prop in options) passedOptions[prop] = options[prop]; + if (!options.enable && !options.select) + passedOptions[options.enable ? "enable" : "select"] = function(state) { return cmd(state); }; + + return new MenuItem(passedOptions); +} + +function markActive(state, type) { + var from = state.selection.from, $from = state.selection.$from, to = state.selection.to, empty = state.selection.empty; + if (empty) return !!type.isInSet(state.storedMarks || $from.marks()); + else return state.doc.rangeHasMark(from, to, type); +} + +function markItem(markType, options) { + var passedOptions = { + active: function(state) { return markActive(state, markType); } + }; + for (var prop in options) passedOptions[prop] = options[prop]; + return cmdItem(toggleMark(markType), passedOptions); +} + +function linkItem(markType) { + return new MenuItem({ + title: "Add or remove link", + icon: icons.link, + active: function(state) { return markActive(state, markType); }, + enable: function(state) { return !state.selection.empty; }, + run: function(state, dispatch, view) { + if (markActive(state, markType)) { + toggleMark(markType)(state, dispatch); + return true; + } + openPrompt({ + title: "Create a link", + fields: { + href: new TextField({label: "Link target", required: true}), + title: new TextField({label: "Title"}) + }, + callback: function(attrs) { + toggleMark(markType, attrs)(view.state, view.dispatch); + view.focus(); + } + }); + } + }); +} + +function wrapListItem(nodeType, options) { + return cmdItem(wrapInList(nodeType, options.attrs), options); +} + +function buildMenuItems(schema) { + var r = {}; + var mark; + if (mark = schema.marks.strong) + r.toggleStrong = markItem(mark, {title: "Toggle strong style", icon: icons.strong}); + if (mark = schema.marks.em) + r.toggleEm = markItem(mark, {title: "Toggle emphasis", icon: icons.em}); + if (mark = schema.marks.code) + r.toggleCode = markItem(mark, {title: "Toggle code font", icon: icons.code}); + if (mark = schema.marks.link) + r.toggleLink = linkItem(mark); + + var node; + if (node = schema.nodes.image) + r.insertImage = insertImageItem(node); + if (node = schema.nodes.bullet_list) + r.wrapBulletList = wrapListItem(node, {title: "Wrap in bullet list", icon: icons.bulletList}); + if (node = schema.nodes.ordered_list) + r.wrapOrderedList = wrapListItem(node, {title: "Wrap in ordered list", icon: icons.orderedList}); + if (node = schema.nodes.blockquote) + r.wrapBlockQuote = wrapItem(node, {title: "Wrap in block quote", icon: icons.blockquote}); + if (node = schema.nodes.paragraph) + r.makeParagraph = blockTypeItem(node, {title: "Change to paragraph", label: "Plain"}); + if (node = schema.nodes.code_block) + r.makeCodeBlock = blockTypeItem(node, {title: "Change to code block", label: "Code"}); + if (node = schema.nodes.heading) + for (var i = 1; i <= 10; i++) + r["makeHead" + i] = blockTypeItem(node, {title: "Change to heading " + i, label: "Level " + i, attrs: {level: i}}); + if (node = schema.nodes.horizontal_rule) { + var hr = node; + r.insertHorizontalRule = new MenuItem({ + title: "Insert horizontal rule", + label: "Horizontal rule", + enable: function(state) { return canInsert(state, hr); }, + run: function(state, dispatch) { dispatch(state.tr.replaceSelectionWith(hr.create())); } + }); + } + + var cut = function(arr) { return arr.filter(function(x) { return x; }); }; + r.insertMenu = new Dropdown(cut([r.insertImage, r.insertHorizontalRule]), {label: "Insert"}); + r.typeMenu = new Dropdown(cut([r.makeParagraph, r.makeCodeBlock, r.makeHead1 && new DropdownSubmenu(cut([ + r.makeHead1, r.makeHead2, r.makeHead3, r.makeHead4, r.makeHead5, r.makeHead6 + ]), {label: "Heading"})]), {label: "Type..."}); + + r.inlineMenu = [cut([r.toggleStrong, r.toggleEm, r.toggleCode, r.toggleLink])]; + r.blockMenu = [cut([r.wrapBulletList, r.wrapOrderedList, r.wrapBlockQuote, joinUpItem, liftItem, selectParentNodeItem])]; + r.fullMenu = r.inlineMenu.concat([[r.insertMenu, r.typeMenu]], [[undoItem, redoItem]], r.blockMenu); + + return r; +} + +exports.buildMenuItems = buildMenuItems; diff --git a/plugins/tiddlywiki/prosemirror/setup/prompt.js b/plugins/tiddlywiki/prosemirror/setup/prompt.js new file mode 100644 index 000000000..fb0669a22 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/setup/prompt.js @@ -0,0 +1,161 @@ +/*\ +title: $:/plugins/tiddlywiki/prosemirror/setup/prompt.js +type: application/javascript +module-type: library + +\*/ + +"use strict"; + +var { Attrs } = require("prosemirror-model"); + +var prefix = "ProseMirror-prompt"; + +function openPrompt(options) { + var wrapper = document.body.appendChild(document.createElement("div")); + wrapper.className = prefix; + + var mouseOutside = function(e) { if (!wrapper.contains(e.target)) close(); }; + setTimeout(function() { window.addEventListener("mousedown", mouseOutside); }, 50); + var close = function() { + window.removeEventListener("mousedown", mouseOutside); + if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper); + }; + + var domFields = []; + for (var name in options.fields) domFields.push(options.fields[name].render()); + + var submitButton = document.createElement("button"); + submitButton.type = "submit"; + submitButton.className = prefix + "-submit"; + submitButton.textContent = "OK"; + var cancelButton = document.createElement("button"); + cancelButton.type = "button"; + cancelButton.className = prefix + "-cancel"; + cancelButton.textContent = "Cancel"; + cancelButton.addEventListener("click", close); + + var form = wrapper.appendChild(document.createElement("form")); + if (options.title) form.appendChild(document.createElement("h5")).textContent = options.title; + domFields.forEach(function(field) { + form.appendChild(document.createElement("div")).appendChild(field); + }); + var buttons = form.appendChild(document.createElement("div")); + buttons.className = prefix + "-buttons"; + buttons.appendChild(submitButton); + buttons.appendChild(document.createTextNode(" ")); + buttons.appendChild(cancelButton); + + var box = wrapper.getBoundingClientRect(); + wrapper.style.top = ((window.innerHeight - box.height) / 2) + "px"; + wrapper.style.left = ((window.innerWidth - box.width) / 2) + "px"; + + var submit = function() { + var params = getValues(options.fields, domFields); + if (params) { + close(); + options.callback(params); + } + }; + + form.addEventListener("submit", function(e) { + e.preventDefault(); + submit(); + }); + + form.addEventListener("keydown", function(e) { + if (e.keyCode == 27) { + e.preventDefault(); + close(); + } else if (e.keyCode == 13 && !(e.ctrlKey || e.metaKey || e.shiftKey)) { + e.preventDefault(); + submit(); + } else if (e.keyCode == 9) { + window.setTimeout(function() { + if (!wrapper.contains(document.activeElement)) close(); + }, 500); + } + }); + + var input = form.elements[0]; + if (input) input.focus(); +} + +function getValues(fields, domFields) { + var result = Object.create(null), i = 0; + for (var name in fields) { + var field = fields[name], dom = domFields[i++]; + var value = field.read(dom), bad = field.validate(value); + if (bad) { + reportInvalid(dom, bad); + return null; + } + result[name] = field.clean(value); + } + return result; +} + +function reportInvalid(dom, message) { + var parent = dom.parentNode; + var msg = parent.appendChild(document.createElement("div")); + msg.style.left = (dom.offsetLeft + dom.offsetWidth + 2) + "px"; + msg.style.top = (dom.offsetTop - 5) + "px"; + msg.className = "ProseMirror-invalid"; + msg.textContent = message; + setTimeout(function() { parent.removeChild(msg); }, 1500); +} + +function Field(options) { + this.options = options; +} + +Field.prototype.read = function(dom) { return dom.value; }; + +Field.prototype.validateType = function(value) { return null; }; + +Field.prototype.validate = function(value) { + if (!value && this.options.required) + return "Required field"; + return this.validateType(value) || (this.options.validate ? this.options.validate(value) : null); +}; + +Field.prototype.clean = function(value) { + return this.options.clean ? this.options.clean(value) : value; +}; + +function TextField(options) { + Field.call(this, options); +} + +TextField.prototype = Object.create(Field.prototype); + +TextField.prototype.render = function() { + var input = document.createElement("input"); + input.type = "text"; + input.placeholder = this.options.label; + input.value = this.options.value || ""; + input.autocomplete = "off"; + return input; +}; + +function SelectField(options) { + Field.call(this, options); +} + +SelectField.prototype = Object.create(Field.prototype); + +SelectField.prototype.render = function() { + var select = document.createElement("select"); + this.options.options.forEach(function(o) { + var opt = select.appendChild(document.createElement("option")); + opt.value = o.value; + opt.selected = o.value == this.options.value; + opt.label = o.label; + }, this); + return select; +}; + +exports.openPrompt = openPrompt; +exports.Field = Field; +exports.TextField = TextField; +exports.SelectField = SelectField; diff --git a/plugins/tiddlywiki/prosemirror/setup/setup.js b/plugins/tiddlywiki/prosemirror/setup/setup.js new file mode 100644 index 000000000..0affc0fe5 --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/setup/setup.js @@ -0,0 +1,47 @@ +/*\ +title: $:/plugins/tiddlywiki/prosemirror/setup/setup.js +type: application/javascript +module-type: library + +\*/ + +"use strict"; + +var { keymap } = require("prosemirror-keymap"); +var { history } = require("prosemirror-history"); +var { baseKeymap } = require("prosemirror-commands"); +var { Plugin } = require("prosemirror-state"); +var { dropCursor } = require("prosemirror-dropcursor"); +var { gapCursor } = require("prosemirror-gapcursor"); +var { menuBar } = require("prosemirror-menu"); +var { Schema } = require("prosemirror-model"); + +var { buildMenuItems } = require("$:/plugins/tiddlywiki/prosemirror/setup/menu.js"); +var { buildKeymap } = require("$:/plugins/tiddlywiki/prosemirror/setup/keymap.js"); +var { buildInputRules } = require("$:/plugins/tiddlywiki/prosemirror/setup/inputrules.js"); + +exports.buildMenuItems = buildMenuItems; +exports.buildKeymap = buildKeymap; +exports.buildInputRules = buildInputRules; + +function exampleSetup(options) { + var plugins = [ + buildInputRules(options.schema), + keymap(buildKeymap(options.schema, options.mapKeys)), + keymap(baseKeymap), + dropCursor(), + gapCursor() + ]; + if (options.menuBar !== false) + plugins.push(menuBar({ floating: options.floatingMenu !== false, content: options.menuContent || buildMenuItems(options.schema).fullMenu })); + if (options.history !== false) + plugins.push(history()); + + return plugins.concat(new Plugin({ + props: { + attributes: { class: "ProseMirror-example-setup-style" } + } + })); +} + +exports.exampleSetup = exampleSetup; diff --git a/plugins/tiddlywiki/prosemirror/widget.js b/plugins/tiddlywiki/prosemirror/widget.js index 29b85bb76..3a3afd2bd 100644 --- a/plugins/tiddlywiki/prosemirror/widget.js +++ b/plugins/tiddlywiki/prosemirror/widget.js @@ -22,7 +22,7 @@ var { listInputRules, listKeymap } = require("prosemirror-flat-list"); -var { exampleSetup } = require("prosemirror-example-setup"); +var { exampleSetup } = require("$:/plugins/tiddlywiki/prosemirror/setup/setup.js"); var { keymap } = require("prosemirror-keymap"); var { inputRules } = require("prosemirror-inputrules"); From d262030cf48197e8f2a49f374dc52936a7f7ac97 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 24 Mar 2025 17:00:49 +0800 Subject: [PATCH 90/98] Update widget.js --- plugins/tiddlywiki/prosemirror/widget.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/tiddlywiki/prosemirror/widget.js b/plugins/tiddlywiki/prosemirror/widget.js index 3a3afd2bd..cc5dba088 100644 --- a/plugins/tiddlywiki/prosemirror/widget.js +++ b/plugins/tiddlywiki/prosemirror/widget.js @@ -56,7 +56,10 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { var listPlugins = createListPlugins({ schema }) var self = this; - var wikiAst = $tw.wiki.parseText(null, `* This is an unordered list + var wikiAst = $tw.wiki.parseText(null, `# asdf +# asdf + +* This is an unordered list * It has two items # This is a numbered list @@ -89,9 +92,9 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { ProsemirrorWidget.prototype.saveEditorContent = function() { var content = this.view.state.doc.toJSON(); - console.log(`ProseMirror: ${JSON.stringify(content)}`); + console.log(`ProseMirror: ${JSON.stringify(content)}`, content); var wikiast = wikiAstFromProseMirrorAst(content); - console.log(`WikiAST: ${JSON.stringify(wikiast)}`); + console.log(`WikiAST: ${JSON.stringify(wikiast)}`, wikiast); var wikiText = $tw.utils.serializeParseTree(wikiast); console.log(`WikiText: ${wikiText}`); } From 348427733b056ca3dc7e83b7f5b4800aec93e804 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Tue, 25 Mar 2025 22:32:23 +0800 Subject: [PATCH 91/98] feat: write to a tiddler --- plugins/tiddlywiki/prosemirror/example.tid | 12 ++++++++++++ plugins/tiddlywiki/prosemirror/readme.tid | 4 +++- plugins/tiddlywiki/prosemirror/widget.js | 22 ++++++++++------------ 3 files changed, 25 insertions(+), 13 deletions(-) create mode 100644 plugins/tiddlywiki/prosemirror/example.tid diff --git a/plugins/tiddlywiki/prosemirror/example.tid b/plugins/tiddlywiki/prosemirror/example.tid new file mode 100644 index 000000000..ce9ad88cd --- /dev/null +++ b/plugins/tiddlywiki/prosemirror/example.tid @@ -0,0 +1,12 @@ +title: $:/plugins/tiddlywiki/prosemirror/example + +# asdf +# asdf + +* This is an unordered list +* It has two items + +# This is a numbered list +## With a subitem +## With second subitem +# And a third item diff --git a/plugins/tiddlywiki/prosemirror/readme.tid b/plugins/tiddlywiki/prosemirror/readme.tid index 48468cfe9..15d5db7af 100755 --- a/plugins/tiddlywiki/prosemirror/readme.tid +++ b/plugins/tiddlywiki/prosemirror/readme.tid @@ -2,4 +2,6 @@ title: $:/plugins/tiddlywiki/prosemirror/readme Test `<$prosemirror />` widget below, see console for content JSON. -<$prosemirror /> +<$edit-prosemirror tiddler="$:/plugins/tiddlywiki/prosemirror/example"/> + +<$edit-text tiddler="$:/plugins/tiddlywiki/prosemirror/example" class="tc-edit-texteditor"/> diff --git a/plugins/tiddlywiki/prosemirror/widget.js b/plugins/tiddlywiki/prosemirror/widget.js index cc5dba088..bd2982060 100644 --- a/plugins/tiddlywiki/prosemirror/widget.js +++ b/plugins/tiddlywiki/prosemirror/widget.js @@ -42,6 +42,14 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { this.parentDomNode = parent; this.computeAttributes(); this.execute(); + + var tiddler = this.getAttribute("tiddler"); + var initialText = this.wiki.getTiddlerText(tiddler, ""); + var initialWikiAst = $tw.wiki.parseText(null, initialText).tree; + var doc = wikiAstToProseMirrorAst(initialWikiAst); + // DEBUG: console doc + console.log(`initial doc`, doc); + var container = $tw.utils.domMaker('div', { class: 'tc-prosemirror-container', }); @@ -56,18 +64,6 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { var listPlugins = createListPlugins({ schema }) var self = this; - var wikiAst = $tw.wiki.parseText(null, `# asdf -# asdf - -* This is an unordered list -* It has two items - -# This is a numbered list -## With a subitem -# And a third item`).tree; - var doc = wikiAstToProseMirrorAst(wikiAst); - // DEBUG: console doc - console.log(`initial doc`, doc); this.view = new EditorView(container, { state: EditorState.create({ // doc: schema.node("doc", null, [schema.node("paragraph")]), @@ -97,6 +93,8 @@ ProsemirrorWidget.prototype.saveEditorContent = function() { console.log(`WikiAST: ${JSON.stringify(wikiast)}`, wikiast); var wikiText = $tw.utils.serializeParseTree(wikiast); console.log(`WikiText: ${wikiText}`); + var tiddler = this.getAttribute("tiddler"); + this.wiki.setText(tiddler, "text", undefined, wikiText); } // Debounced save function for performance From d32048fc6ead4f3229082fab587d93f6ed17cddc Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Tue, 25 Mar 2025 22:53:14 +0800 Subject: [PATCH 92/98] lint: indent with tab --- .../prosemirror/ast/from-prosemirror.js | 118 +++---- .../prosemirror/ast/to-prosemirror.js | 294 +++++++++--------- .../prosemirror/setup/inputrules.js | 30 +- .../tiddlywiki/prosemirror/setup/keymap.js | 114 +++---- plugins/tiddlywiki/prosemirror/setup/menu.js | 248 +++++++-------- .../tiddlywiki/prosemirror/setup/prompt.js | 194 ++++++------ plugins/tiddlywiki/prosemirror/setup/setup.js | 32 +- .../tiddlywiki/prosemirror/widget-loader.js | 2 +- plugins/tiddlywiki/prosemirror/widget.js | 98 +++--- 9 files changed, 567 insertions(+), 563 deletions(-) diff --git a/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js b/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js index cfa4a66f6..9cc969a96 100644 --- a/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js +++ b/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js @@ -8,95 +8,95 @@ Get the Wiki AST from a Prosemirror AST \*/ function doc(context, node) { - return convertNodes(context, node.content); + return convertNodes(context, node.content); } function paragraph(context, node) { - return { - type: "element", - tag: "p", - rule: "parseblock", - children: convertNodes(context, node.content) - }; + return { + type: "element", + tag: "p", + rule: "parseblock", + children: convertNodes(context, node.content) + }; } function text(context, node) { - return { - type: "text", - text: node.text - } + return { + type: "text", + text: node.text + } } function heading(context, node) { - return { - type: "element", - tag: "h" + node.attrs.level, - rule: "heading", - attributes: { - // TODO: restore class if any - }, - children: convertNodes(context, node.content) - }; + return { + type: "element", + tag: "h" + node.attrs.level, + rule: "heading", + attributes: { + // TODO: restore class if any + }, + children: convertNodes(context, node.content) + }; } function list(context, node) { - const listType = node.attrs && node.attrs.kind === "ordered" ? "ol" : "ul"; - - const listItems = node.content.map(item => { - return { - type: "element", - tag: "li", - children: convertANode(context, item) - }; - }); - - return { - type: "element", - tag: listType, - rule: "list", - children: listItems - }; + const listType = node.attrs && node.attrs.kind === "ordered" ? "ol" : "ul"; + + const listItems = node.content.map(item => { + return { + type: "element", + tag: "li", + children: convertANode(context, item) + }; + }); + + return { + type: "element", + tag: listType, + rule: "list", + children: listItems + }; } /** * Key is `node.type`, value is node converter function. */ const builders = { - doc, - paragraph, - text, - heading, - list, + doc, + paragraph, + text, + heading, + list, }; function wikiAstFromProseMirrorAst(input) { - return convertNodes(builders, Array.isArray(input) ? input : [input]); + return convertNodes(builders, Array.isArray(input) ? input : [input]); } exports.from = wikiAstFromProseMirrorAst; function convertNodes(builders, nodes) { - if (nodes === undefined || nodes.length === 0) { - return []; - } + if (nodes === undefined || nodes.length === 0) { + return []; + } - return nodes.reduce((accumulator, node) => { - return [...accumulator, ...convertANode(builders, node)]; - }, []); + return nodes.reduce((accumulator, node) => { + return [...accumulator, ...convertANode(builders, node)]; + }, []); } function restoreMetadata(node) { - // TODO: restore attributes, orderedAttributes, isBlock - return {}; + // TODO: restore attributes, orderedAttributes, isBlock + return {}; } function convertANode(builders, node) { - var builder = builders[node.type]; - if (typeof builder === 'function') { - var convertedNode = builder(builders, node); - var arrayOfNodes = (Array.isArray(convertedNode) - ? convertedNode : [convertedNode]); - return arrayOfNodes.map((child) => ({ ...restoreMetadata(node), ...child })); - } - console.warn(`WikiAst get Unknown node type: ${JSON.stringify(node)}`); - return []; + var builder = builders[node.type]; + if (typeof builder === 'function') { + var convertedNode = builder(builders, node); + var arrayOfNodes = (Array.isArray(convertedNode) + ? convertedNode : [convertedNode]); + return arrayOfNodes.map((child) => ({ ...restoreMetadata(node), ...child })); + } + console.warn(`WikiAst get Unknown node type: ${JSON.stringify(node)}`); + return []; } diff --git a/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js b/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js index 14ecbfe67..aac4117b3 100644 --- a/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js +++ b/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js @@ -11,85 +11,85 @@ Get the Prosemirror AST from a Wiki AST * Many node shares same type `element` in wikiAst, we need to distinguish them by tag. */ const elementBuilders = { - p: function(context, node) { - return { - type: "paragraph", - content: convertNodes(context, node.children) - }; - }, - h1: function(context, node) { - return { - type: "heading", - attrs: { level: 1 }, - content: convertNodes(context, node.children) - }; - }, - h2: function(context, node) { - return { - type: "heading", - attrs: { level: 2 }, - content: convertNodes(context, node.children) - }; - }, - h3: function(context, node) { - return { - type: "heading", - attrs: { level: 3 }, - content: convertNodes(context, node.children) - }; - }, - h4: function(context, node) { - return { - type: "heading", - attrs: { level: 4 }, - content: convertNodes(context, node.children) - }; - }, - h5: function(context, node) { - return { - type: "heading", - attrs: { level: 5 }, - content: convertNodes(context, node.children) - }; - }, - h6: function(context, node) { - return { - type: "heading", - attrs: { level: 6 }, - content: convertNodes(context, node.children) - }; - }, - ul: function(context, node) { - return { - type: "list", - attrs: { - kind: "bullet", - order: null, - checked: false, - collapsed: false - }, - content: convertNodes(context, node.children) - }; - }, - ol: function(context, node) { - return { - type: "list", - attrs: { - kind: "ordered", - order: null, - checked: false, - collapsed: false - }, - content: convertNodes(context, node.children) - }; - }, - li: function(context, node) { - // In ProseMirror, list items are converted to paragraphs or other block content - // directly under the list node, no special list_item type needed - const processedContent = convertNodes(context, node.children); - // Ensure content starts with a block element (typically paragraph) - return wrapTextNodesInParagraphs(context, processedContent); - } + p: function(context, node) { + return { + type: "paragraph", + content: convertNodes(context, node.children) + }; + }, + h1: function(context, node) { + return { + type: "heading", + attrs: { level: 1 }, + content: convertNodes(context, node.children) + }; + }, + h2: function(context, node) { + return { + type: "heading", + attrs: { level: 2 }, + content: convertNodes(context, node.children) + }; + }, + h3: function(context, node) { + return { + type: "heading", + attrs: { level: 3 }, + content: convertNodes(context, node.children) + }; + }, + h4: function(context, node) { + return { + type: "heading", + attrs: { level: 4 }, + content: convertNodes(context, node.children) + }; + }, + h5: function(context, node) { + return { + type: "heading", + attrs: { level: 5 }, + content: convertNodes(context, node.children) + }; + }, + h6: function(context, node) { + return { + type: "heading", + attrs: { level: 6 }, + content: convertNodes(context, node.children) + }; + }, + ul: function(context, node) { + return { + type: "list", + attrs: { + kind: "bullet", + order: null, + checked: false, + collapsed: false + }, + content: convertNodes(context, node.children) + }; + }, + ol: function(context, node) { + return { + type: "list", + attrs: { + kind: "ordered", + order: null, + checked: false, + collapsed: false + }, + content: convertNodes(context, node.children) + }; + }, + li: function(context, node) { + // In ProseMirror, list items are converted to paragraphs or other block content + // directly under the list node, no special list_item type needed + const processedContent = convertNodes(context, node.children); + // Ensure content starts with a block element (typically paragraph) + return wrapTextNodesInParagraphs(context, processedContent); + } }; /** @@ -97,101 +97,101 @@ const elementBuilders = { * ProseMirror requires list items to contain block content, not bare text */ function wrapTextNodesInParagraphs(context, nodes) { - if (!nodes || nodes.length === 0) { - return []; - } + if (!nodes || nodes.length === 0) { + return []; + } - const result = []; - let currentTextNodes = []; + const result = []; + let currentTextNodes = []; - function flushTextNodes() { - if (currentTextNodes.length > 0) { - result.push({ - type: "paragraph", - content: currentTextNodes - }); - currentTextNodes = []; - } - } + function flushTextNodes() { + if (currentTextNodes.length > 0) { + result.push({ + type: "paragraph", + content: currentTextNodes + }); + currentTextNodes = []; + } + } - nodes.forEach(node => { - // If it's a text node, collect it - if (node.type === "text") { - currentTextNodes.push(node); - } else { - // If we encounter a non-text node, flush any collected text nodes - flushTextNodes(); - // Add the non-text node as is - result.push(node); - } - }); + nodes.forEach(node => { + // If it's a text node, collect it + if (node.type === "text") { + currentTextNodes.push(node); + } else { + // If we encounter a non-text node, flush any collected text nodes + flushTextNodes(); + // Add the non-text node as is + result.push(node); + } + }); - // Flush any remaining text nodes - flushTextNodes(); + // Flush any remaining text nodes + flushTextNodes(); - return result; + return result; } function element(context, node) { - const builder = elementBuilders[node.tag]; - if (builder) { - return builder(context, node); - } else { - console.warn(`Unknown element tag: ${node.tag}`); - return []; - } + const builder = elementBuilders[node.tag]; + if (builder) { + return builder(context, node); + } else { + console.warn(`Unknown element tag: ${node.tag}`); + return []; + } } function text(context, node) { - return { - type: "text", - text: node.text - }; + return { + type: "text", + text: node.text + }; } /** * Key is wikiAst node type, value is node converter function. */ const builders = { - element, - text + element, + text }; function wikiAstToProsemirrorAst(node, options) { - const context = { ...builders, ...options }; - const result = convertNodes(context, Array.isArray(node) ? node : [node]); - - // Wrap in a doc if needed - if (result.length > 0 && result[0].type !== "doc") { - return { - type: "doc", - content: result - }; - } - - return result; + const context = { ...builders, ...options }; + const result = convertNodes(context, Array.isArray(node) ? node : [node]); + + // Wrap in a doc if needed + if (result.length > 0 && result[0].type !== "doc") { + return { + type: "doc", + content: result + }; + } + + return result; } exports.to = wikiAstToProsemirrorAst; function convertNodes(context, nodes) { - if (nodes === undefined || nodes.length === 0) { - return []; - } + if (nodes === undefined || nodes.length === 0) { + return []; + } - return nodes.reduce((accumulator, node) => { - return [...accumulator, ...convertANode(context, node)]; - }, []); + return nodes.reduce((accumulator, node) => { + return [...accumulator, ...convertANode(context, node)]; + }, []); } function convertANode(context, node) { - var builder = context[node.type]; - if (typeof builder === 'function') { - var convertedNode = builder(context, node); - var arrayOfNodes = (Array.isArray(convertedNode) - ? convertedNode : [convertedNode]); - return arrayOfNodes; - } - console.warn(`ProseMirror get Unknown node type: ${JSON.stringify(node)}`); - return []; + var builder = context[node.type]; + if (typeof builder === 'function') { + var convertedNode = builder(context, node); + var arrayOfNodes = (Array.isArray(convertedNode) + ? convertedNode : [convertedNode]); + return arrayOfNodes; + } + console.warn(`ProseMirror get Unknown node type: ${JSON.stringify(node)}`); + return []; } diff --git a/plugins/tiddlywiki/prosemirror/setup/inputrules.js b/plugins/tiddlywiki/prosemirror/setup/inputrules.js index ff62bf375..425af3c51 100644 --- a/plugins/tiddlywiki/prosemirror/setup/inputrules.js +++ b/plugins/tiddlywiki/prosemirror/setup/inputrules.js @@ -11,34 +11,38 @@ var { inputRules, wrappingInputRule, textblockTypeInputRule, smartQuotes, emDash var { NodeType, Schema } = require("prosemirror-model"); function blockQuoteRule(nodeType) { - return wrappingInputRule(/^\s*>\s$/, nodeType); + return wrappingInputRule(/^\s*>\s$/, nodeType); } function orderedListRule(nodeType) { - return wrappingInputRule(/^(\d+)\.\s$/, nodeType, function(match) { return { order: +match[1] }; }, - function(match, node) { return node.childCount + node.attrs.order == +match[1]; }); + return wrappingInputRule( + /^(\d+)\.\s$/, + nodeType, + function(match) { return { order: +match[1] }; }, + function(match, node) { return node.childCount + node.attrs.order == +match[1]; } + ); } function bulletListRule(nodeType) { - return wrappingInputRule(/^\s*([-+*])\s$/, nodeType); + return wrappingInputRule(/^\s*([-+*])\s$/, nodeType); } function codeBlockRule(nodeType) { - return textblockTypeInputRule(/^```$/, nodeType); + return textblockTypeInputRule(/^```$/, nodeType); } function headingRule(nodeType, maxLevel) { - return textblockTypeInputRule(new RegExp("^(#{1," + maxLevel + "})\\s$"), nodeType, function(match) { return { level: match[1].length }; }); + return textblockTypeInputRule(new RegExp("^(#{1," + maxLevel + "})\\s$"), nodeType, function(match) { return { level: match[1].length }; }); } function buildInputRules(schema) { - var rules = smartQuotes.concat(ellipsis, emDash), type; - if (type = schema.nodes.blockquote) rules.push(blockQuoteRule(type)); - if (type = schema.nodes.ordered_list) rules.push(orderedListRule(type)); - if (type = schema.nodes.bullet_list) rules.push(bulletListRule(type)); - if (type = schema.nodes.code_block) rules.push(codeBlockRule(type)); - if (type = schema.nodes.heading) rules.push(headingRule(type, 6)); - return inputRules({ rules: rules }); + var rules = smartQuotes.concat(ellipsis, emDash), type; + if (type = schema.nodes.blockquote) rules.push(blockQuoteRule(type)); + if (type = schema.nodes.ordered_list) rules.push(orderedListRule(type)); + if (type = schema.nodes.bullet_list) rules.push(bulletListRule(type)); + if (type = schema.nodes.code_block) rules.push(codeBlockRule(type)); + if (type = schema.nodes.heading) rules.push(headingRule(type, 6)); + return inputRules({ rules: rules }); } exports.buildInputRules = buildInputRules; diff --git a/plugins/tiddlywiki/prosemirror/setup/keymap.js b/plugins/tiddlywiki/prosemirror/setup/keymap.js index d5ad980fd..ddf683d78 100644 --- a/plugins/tiddlywiki/prosemirror/setup/keymap.js +++ b/plugins/tiddlywiki/prosemirror/setup/keymap.js @@ -17,68 +17,68 @@ var prosemirrorModel = require("prosemirror-model"); var mac = typeof navigator != "undefined" ? /Mac|iP(hone|[oa]d)/.test(navigator.platform) : false; function buildKeymap(schema, mapKeys) { - var keys = {}, type; - function bind(key, cmd) { - if (mapKeys) { - var mapped = mapKeys[key]; - if (mapped === false) return; - if (mapped) key = mapped; - } - keys[key] = cmd; - } + var keys = {}, type; + function bind(key, cmd) { + if (mapKeys) { + var mapped = mapKeys[key]; + if (mapped === false) return; + if (mapped) key = mapped; + } + keys[key] = cmd; + } - bind("Mod-z", prosemirrorHistory.undo); - bind("Shift-Mod-z", prosemirrorHistory.redo); - bind("Backspace", prosemirrorInputrules.undoInputRule); - if (!mac) bind("Mod-y", prosemirrorHistory.redo); + bind("Mod-z", prosemirrorHistory.undo); + bind("Shift-Mod-z", prosemirrorHistory.redo); + bind("Backspace", prosemirrorInputrules.undoInputRule); + if (!mac) bind("Mod-y", prosemirrorHistory.redo); - bind("Alt-ArrowUp", prosemirrorCommands.joinUp); - bind("Alt-ArrowDown", prosemirrorCommands.joinDown); - bind("Mod-BracketLeft", prosemirrorCommands.lift); - bind("Escape", prosemirrorCommands.selectParentNode); + bind("Alt-ArrowUp", prosemirrorCommands.joinUp); + bind("Alt-ArrowDown", prosemirrorCommands.joinDown); + bind("Mod-BracketLeft", prosemirrorCommands.lift); + bind("Escape", prosemirrorCommands.selectParentNode); - if (type = schema.marks.strong) { - bind("Mod-b", prosemirrorCommands.toggleMark(type)); - bind("Mod-B", prosemirrorCommands.toggleMark(type)); - } - if (type = schema.marks.em) { - bind("Mod-i", prosemirrorCommands.toggleMark(type)); - bind("Mod-I", prosemirrorCommands.toggleMark(type)); - } - if (type = schema.marks.code) - bind("Mod-`", prosemirrorCommands.toggleMark(type)); - if (type = schema.nodes.blockquote) - bind("Ctrl->", prosemirrorCommands.wrapIn(type)); - if (type = schema.nodes.hard_break) { - var br = type, cmd = prosemirrorCommands.chainCommands(prosemirrorCommands.exitCode, function(state, dispatch) { - if (dispatch) dispatch(state.tr.replaceSelectionWith(br.create()).scrollIntoView()); - return true; - }); - bind("Mod-Enter", cmd); - bind("Shift-Enter", cmd); - if (mac) bind("Ctrl-Enter", cmd); - } - if (type = schema.nodes.list) { - bind("Shift-Tab", prosemirrorFlatList.createDedentListCommand(type)); - bind("Tab", prosemirrorFlatList.createIndentListCommand(type)); - } - if (type = schema.nodes.paragraph) - bind("Shift-Ctrl-0", prosemirrorCommands.setBlockType(type)); - if (type = schema.nodes.code_block) - bind("Shift-Ctrl-\\", prosemirrorCommands.setBlockType(type)); - if (type = schema.nodes.heading) - for (var i = 1; i <= 6; i++) bind("Shift-Ctrl-" + i, prosemirrorCommands.setBlockType(type, {level: i})); - if (type = schema.nodes.horizontal_rule) { - var hr = type; - bind("Mod-_", function(state, dispatch) { - if (dispatch) dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView()); - return true; - }); - } + if (type = schema.marks.strong) { + bind("Mod-b", prosemirrorCommands.toggleMark(type)); + bind("Mod-B", prosemirrorCommands.toggleMark(type)); + } + if (type = schema.marks.em) { + bind("Mod-i", prosemirrorCommands.toggleMark(type)); + bind("Mod-I", prosemirrorCommands.toggleMark(type)); + } + if (type = schema.marks.code) + bind("Mod-`", prosemirrorCommands.toggleMark(type)); + if (type = schema.nodes.blockquote) + bind("Ctrl->", prosemirrorCommands.wrapIn(type)); + if (type = schema.nodes.hard_break) { + var br = type, cmd = prosemirrorCommands.chainCommands(prosemirrorCommands.exitCode, function(state, dispatch) { + if (dispatch) dispatch(state.tr.replaceSelectionWith(br.create()).scrollIntoView()); + return true; + }); + bind("Mod-Enter", cmd); + bind("Shift-Enter", cmd); + if (mac) bind("Ctrl-Enter", cmd); + } + if (type = schema.nodes.list) { + bind("Shift-Tab", prosemirrorFlatList.createDedentListCommand(type)); + bind("Tab", prosemirrorFlatList.createIndentListCommand(type)); + } + if (type = schema.nodes.paragraph) + bind("Shift-Ctrl-0", prosemirrorCommands.setBlockType(type)); + if (type = schema.nodes.code_block) + bind("Shift-Ctrl-\\", prosemirrorCommands.setBlockType(type)); + if (type = schema.nodes.heading) + for (var i = 1; i <= 6; i++) bind("Shift-Ctrl-" + i, prosemirrorCommands.setBlockType(type, {level: i})); + if (type = schema.nodes.horizontal_rule) { + var hr = type; + bind("Mod-_", function(state, dispatch) { + if (dispatch) dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView()); + return true; + }); + } - return keys; + return keys; } module.exports = { - buildKeymap: buildKeymap + buildKeymap: buildKeymap }; diff --git a/plugins/tiddlywiki/prosemirror/setup/menu.js b/plugins/tiddlywiki/prosemirror/setup/menu.js index a25c456b7..e209cc4ab 100644 --- a/plugins/tiddlywiki/prosemirror/setup/menu.js +++ b/plugins/tiddlywiki/prosemirror/setup/menu.js @@ -8,18 +8,18 @@ module-type: library "use strict"; var { - wrapItem, - blockTypeItem, - Dropdown, - DropdownSubmenu, - joinUpItem, - liftItem, - selectParentNodeItem, - undoItem, - redoItem, - icons, - MenuItem, - MenuElement + wrapItem, + blockTypeItem, + Dropdown, + DropdownSubmenu, + joinUpItem, + liftItem, + selectParentNodeItem, + undoItem, + redoItem, + icons, + MenuItem, + MenuElement } = require("prosemirror-menu"); var { NodeSelection, EditorState } = require("prosemirror-state"); var { Schema, NodeType, MarkType } = require("prosemirror-model"); @@ -28,144 +28,144 @@ var { wrapInList } = require("prosemirror-flat-list"); var { TextField, openPrompt } = require("$:/plugins/tiddlywiki/prosemirror/setup/prompt.js"); function canInsert(state, nodeType) { - var $from = state.selection.$from; - for (var d = $from.depth; d >= 0; d--) { - var index = $from.index(d); - if ($from.node(d).canReplaceWith(index, index, nodeType)) return true; - } - return false; + var $from = state.selection.$from; + for (var d = $from.depth; d >= 0; d--) { + var index = $from.index(d); + if ($from.node(d).canReplaceWith(index, index, nodeType)) return true; + } + return false; } function insertImageItem(nodeType) { - return new MenuItem({ - title: "Insert image", - label: "Image", - enable: function(state) { return canInsert(state, nodeType); }, - run: function(state, _, view) { - var from = state.selection.from, to = state.selection.to, attrs = null; - if (state.selection instanceof NodeSelection && state.selection.node.type == nodeType) - attrs = state.selection.node.attrs; - openPrompt({ - title: "Insert image", - fields: { - src: new TextField({label: "Location", required: true, value: attrs && attrs.src}), - title: new TextField({label: "Title", value: attrs && attrs.title}), - alt: new TextField({label: "Description", value: attrs ? attrs.alt : state.doc.textBetween(from, to, " ")}) - }, - callback: function(attrs) { - view.dispatch(view.state.tr.replaceSelectionWith(nodeType.createAndFill(attrs))); - view.focus(); - } - }); - } - }); + return new MenuItem({ + title: "Insert image", + label: "Image", + enable: function(state) { return canInsert(state, nodeType); }, + run: function(state, _, view) { + var from = state.selection.from, to = state.selection.to, attrs = null; + if (state.selection instanceof NodeSelection && state.selection.node.type == nodeType) + attrs = state.selection.node.attrs; + openPrompt({ + title: "Insert image", + fields: { + src: new TextField({label: "Location", required: true, value: attrs && attrs.src}), + title: new TextField({label: "Title", value: attrs && attrs.title}), + alt: new TextField({label: "Description", value: attrs ? attrs.alt : state.doc.textBetween(from, to, " ")}) + }, + callback: function(attrs) { + view.dispatch(view.state.tr.replaceSelectionWith(nodeType.createAndFill(attrs))); + view.focus(); + } + }); + } + }); } function cmdItem(cmd, options) { - var passedOptions = { - label: options.title, - run: cmd - }; - for (var prop in options) passedOptions[prop] = options[prop]; - if (!options.enable && !options.select) - passedOptions[options.enable ? "enable" : "select"] = function(state) { return cmd(state); }; + var passedOptions = { + label: options.title, + run: cmd + }; + for (var prop in options) passedOptions[prop] = options[prop]; + if (!options.enable && !options.select) + passedOptions[options.enable ? "enable" : "select"] = function(state) { return cmd(state); }; - return new MenuItem(passedOptions); + return new MenuItem(passedOptions); } function markActive(state, type) { - var from = state.selection.from, $from = state.selection.$from, to = state.selection.to, empty = state.selection.empty; - if (empty) return !!type.isInSet(state.storedMarks || $from.marks()); - else return state.doc.rangeHasMark(from, to, type); + var from = state.selection.from, $from = state.selection.$from, to = state.selection.to, empty = state.selection.empty; + if (empty) return !!type.isInSet(state.storedMarks || $from.marks()); + else return state.doc.rangeHasMark(from, to, type); } function markItem(markType, options) { - var passedOptions = { - active: function(state) { return markActive(state, markType); } - }; - for (var prop in options) passedOptions[prop] = options[prop]; - return cmdItem(toggleMark(markType), passedOptions); + var passedOptions = { + active: function(state) { return markActive(state, markType); } + }; + for (var prop in options) passedOptions[prop] = options[prop]; + return cmdItem(toggleMark(markType), passedOptions); } function linkItem(markType) { - return new MenuItem({ - title: "Add or remove link", - icon: icons.link, - active: function(state) { return markActive(state, markType); }, - enable: function(state) { return !state.selection.empty; }, - run: function(state, dispatch, view) { - if (markActive(state, markType)) { - toggleMark(markType)(state, dispatch); - return true; - } - openPrompt({ - title: "Create a link", - fields: { - href: new TextField({label: "Link target", required: true}), - title: new TextField({label: "Title"}) - }, - callback: function(attrs) { - toggleMark(markType, attrs)(view.state, view.dispatch); - view.focus(); - } - }); - } - }); + return new MenuItem({ + title: "Add or remove link", + icon: icons.link, + active: function(state) { return markActive(state, markType); }, + enable: function(state) { return !state.selection.empty; }, + run: function(state, dispatch, view) { + if (markActive(state, markType)) { + toggleMark(markType)(state, dispatch); + return true; + } + openPrompt({ + title: "Create a link", + fields: { + href: new TextField({label: "Link target", required: true}), + title: new TextField({label: "Title"}) + }, + callback: function(attrs) { + toggleMark(markType, attrs)(view.state, view.dispatch); + view.focus(); + } + }); + } + }); } function wrapListItem(nodeType, options) { - return cmdItem(wrapInList(nodeType, options.attrs), options); + return cmdItem(wrapInList(nodeType, options.attrs), options); } function buildMenuItems(schema) { - var r = {}; - var mark; - if (mark = schema.marks.strong) - r.toggleStrong = markItem(mark, {title: "Toggle strong style", icon: icons.strong}); - if (mark = schema.marks.em) - r.toggleEm = markItem(mark, {title: "Toggle emphasis", icon: icons.em}); - if (mark = schema.marks.code) - r.toggleCode = markItem(mark, {title: "Toggle code font", icon: icons.code}); - if (mark = schema.marks.link) - r.toggleLink = linkItem(mark); + var r = {}; + var mark; + if (mark = schema.marks.strong) + r.toggleStrong = markItem(mark, {title: "Toggle strong style", icon: icons.strong}); + if (mark = schema.marks.em) + r.toggleEm = markItem(mark, {title: "Toggle emphasis", icon: icons.em}); + if (mark = schema.marks.code) + r.toggleCode = markItem(mark, {title: "Toggle code font", icon: icons.code}); + if (mark = schema.marks.link) + r.toggleLink = linkItem(mark); - var node; - if (node = schema.nodes.image) - r.insertImage = insertImageItem(node); - if (node = schema.nodes.bullet_list) - r.wrapBulletList = wrapListItem(node, {title: "Wrap in bullet list", icon: icons.bulletList}); - if (node = schema.nodes.ordered_list) - r.wrapOrderedList = wrapListItem(node, {title: "Wrap in ordered list", icon: icons.orderedList}); - if (node = schema.nodes.blockquote) - r.wrapBlockQuote = wrapItem(node, {title: "Wrap in block quote", icon: icons.blockquote}); - if (node = schema.nodes.paragraph) - r.makeParagraph = blockTypeItem(node, {title: "Change to paragraph", label: "Plain"}); - if (node = schema.nodes.code_block) - r.makeCodeBlock = blockTypeItem(node, {title: "Change to code block", label: "Code"}); - if (node = schema.nodes.heading) - for (var i = 1; i <= 10; i++) - r["makeHead" + i] = blockTypeItem(node, {title: "Change to heading " + i, label: "Level " + i, attrs: {level: i}}); - if (node = schema.nodes.horizontal_rule) { - var hr = node; - r.insertHorizontalRule = new MenuItem({ - title: "Insert horizontal rule", - label: "Horizontal rule", - enable: function(state) { return canInsert(state, hr); }, - run: function(state, dispatch) { dispatch(state.tr.replaceSelectionWith(hr.create())); } - }); - } + var node; + if (node = schema.nodes.image) + r.insertImage = insertImageItem(node); + if (node = schema.nodes.bullet_list) + r.wrapBulletList = wrapListItem(node, {title: "Wrap in bullet list", icon: icons.bulletList}); + if (node = schema.nodes.ordered_list) + r.wrapOrderedList = wrapListItem(node, {title: "Wrap in ordered list", icon: icons.orderedList}); + if (node = schema.nodes.blockquote) + r.wrapBlockQuote = wrapItem(node, {title: "Wrap in block quote", icon: icons.blockquote}); + if (node = schema.nodes.paragraph) + r.makeParagraph = blockTypeItem(node, {title: "Change to paragraph", label: "Plain"}); + if (node = schema.nodes.code_block) + r.makeCodeBlock = blockTypeItem(node, {title: "Change to code block", label: "Code"}); + if (node = schema.nodes.heading) + for (var i = 1; i <= 10; i++) + r["makeHead" + i] = blockTypeItem(node, {title: "Change to heading " + i, label: "Level " + i, attrs: {level: i}}); + if (node = schema.nodes.horizontal_rule) { + var hr = node; + r.insertHorizontalRule = new MenuItem({ + title: "Insert horizontal rule", + label: "Horizontal rule", + enable: function(state) { return canInsert(state, hr); }, + run: function(state, dispatch) { dispatch(state.tr.replaceSelectionWith(hr.create())); } + }); + } - var cut = function(arr) { return arr.filter(function(x) { return x; }); }; - r.insertMenu = new Dropdown(cut([r.insertImage, r.insertHorizontalRule]), {label: "Insert"}); - r.typeMenu = new Dropdown(cut([r.makeParagraph, r.makeCodeBlock, r.makeHead1 && new DropdownSubmenu(cut([ - r.makeHead1, r.makeHead2, r.makeHead3, r.makeHead4, r.makeHead5, r.makeHead6 - ]), {label: "Heading"})]), {label: "Type..."}); + var cut = function(arr) { return arr.filter(function(x) { return x; }); }; + r.insertMenu = new Dropdown(cut([r.insertImage, r.insertHorizontalRule]), {label: "Insert"}); + r.typeMenu = new Dropdown(cut([r.makeParagraph, r.makeCodeBlock, r.makeHead1 && new DropdownSubmenu(cut([ + r.makeHead1, r.makeHead2, r.makeHead3, r.makeHead4, r.makeHead5, r.makeHead6 + ]), {label: "Heading"})]), {label: "Type..."}); - r.inlineMenu = [cut([r.toggleStrong, r.toggleEm, r.toggleCode, r.toggleLink])]; - r.blockMenu = [cut([r.wrapBulletList, r.wrapOrderedList, r.wrapBlockQuote, joinUpItem, liftItem, selectParentNodeItem])]; - r.fullMenu = r.inlineMenu.concat([[r.insertMenu, r.typeMenu]], [[undoItem, redoItem]], r.blockMenu); + r.inlineMenu = [cut([r.toggleStrong, r.toggleEm, r.toggleCode, r.toggleLink])]; + r.blockMenu = [cut([r.wrapBulletList, r.wrapOrderedList, r.wrapBlockQuote, joinUpItem, liftItem, selectParentNodeItem])]; + r.fullMenu = r.inlineMenu.concat([[r.insertMenu, r.typeMenu]], [[undoItem, redoItem]], r.blockMenu); - return r; + return r; } exports.buildMenuItems = buildMenuItems; diff --git a/plugins/tiddlywiki/prosemirror/setup/prompt.js b/plugins/tiddlywiki/prosemirror/setup/prompt.js index fb0669a22..2078ea51e 100644 --- a/plugins/tiddlywiki/prosemirror/setup/prompt.js +++ b/plugins/tiddlywiki/prosemirror/setup/prompt.js @@ -12,101 +12,101 @@ var { Attrs } = require("prosemirror-model"); var prefix = "ProseMirror-prompt"; function openPrompt(options) { - var wrapper = document.body.appendChild(document.createElement("div")); - wrapper.className = prefix; + var wrapper = document.body.appendChild(document.createElement("div")); + wrapper.className = prefix; - var mouseOutside = function(e) { if (!wrapper.contains(e.target)) close(); }; - setTimeout(function() { window.addEventListener("mousedown", mouseOutside); }, 50); - var close = function() { - window.removeEventListener("mousedown", mouseOutside); - if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper); - }; + var mouseOutside = function(e) { if (!wrapper.contains(e.target)) close(); }; + setTimeout(function() { window.addEventListener("mousedown", mouseOutside); }, 50); + var close = function() { + window.removeEventListener("mousedown", mouseOutside); + if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper); + }; - var domFields = []; - for (var name in options.fields) domFields.push(options.fields[name].render()); + var domFields = []; + for (var name in options.fields) domFields.push(options.fields[name].render()); - var submitButton = document.createElement("button"); - submitButton.type = "submit"; - submitButton.className = prefix + "-submit"; - submitButton.textContent = "OK"; - var cancelButton = document.createElement("button"); - cancelButton.type = "button"; - cancelButton.className = prefix + "-cancel"; - cancelButton.textContent = "Cancel"; - cancelButton.addEventListener("click", close); + var submitButton = document.createElement("button"); + submitButton.type = "submit"; + submitButton.className = prefix + "-submit"; + submitButton.textContent = "OK"; + var cancelButton = document.createElement("button"); + cancelButton.type = "button"; + cancelButton.className = prefix + "-cancel"; + cancelButton.textContent = "Cancel"; + cancelButton.addEventListener("click", close); - var form = wrapper.appendChild(document.createElement("form")); - if (options.title) form.appendChild(document.createElement("h5")).textContent = options.title; - domFields.forEach(function(field) { - form.appendChild(document.createElement("div")).appendChild(field); - }); - var buttons = form.appendChild(document.createElement("div")); - buttons.className = prefix + "-buttons"; - buttons.appendChild(submitButton); - buttons.appendChild(document.createTextNode(" ")); - buttons.appendChild(cancelButton); + var form = wrapper.appendChild(document.createElement("form")); + if (options.title) form.appendChild(document.createElement("h5")).textContent = options.title; + domFields.forEach(function(field) { + form.appendChild(document.createElement("div")).appendChild(field); + }); + var buttons = form.appendChild(document.createElement("div")); + buttons.className = prefix + "-buttons"; + buttons.appendChild(submitButton); + buttons.appendChild(document.createTextNode(" ")); + buttons.appendChild(cancelButton); - var box = wrapper.getBoundingClientRect(); - wrapper.style.top = ((window.innerHeight - box.height) / 2) + "px"; - wrapper.style.left = ((window.innerWidth - box.width) / 2) + "px"; + var box = wrapper.getBoundingClientRect(); + wrapper.style.top = ((window.innerHeight - box.height) / 2) + "px"; + wrapper.style.left = ((window.innerWidth - box.width) / 2) + "px"; - var submit = function() { - var params = getValues(options.fields, domFields); - if (params) { - close(); - options.callback(params); - } - }; + var submit = function() { + var params = getValues(options.fields, domFields); + if (params) { + close(); + options.callback(params); + } + }; - form.addEventListener("submit", function(e) { - e.preventDefault(); - submit(); - }); + form.addEventListener("submit", function(e) { + e.preventDefault(); + submit(); + }); - form.addEventListener("keydown", function(e) { - if (e.keyCode == 27) { - e.preventDefault(); - close(); - } else if (e.keyCode == 13 && !(e.ctrlKey || e.metaKey || e.shiftKey)) { - e.preventDefault(); - submit(); - } else if (e.keyCode == 9) { - window.setTimeout(function() { - if (!wrapper.contains(document.activeElement)) close(); - }, 500); - } - }); + form.addEventListener("keydown", function(e) { + if (e.keyCode == 27) { + e.preventDefault(); + close(); + } else if (e.keyCode == 13 && !(e.ctrlKey || e.metaKey || e.shiftKey)) { + e.preventDefault(); + submit(); + } else if (e.keyCode == 9) { + window.setTimeout(function() { + if (!wrapper.contains(document.activeElement)) close(); + }, 500); + } + }); - var input = form.elements[0]; - if (input) input.focus(); + var input = form.elements[0]; + if (input) input.focus(); } function getValues(fields, domFields) { - var result = Object.create(null), i = 0; - for (var name in fields) { - var field = fields[name], dom = domFields[i++]; - var value = field.read(dom), bad = field.validate(value); - if (bad) { - reportInvalid(dom, bad); - return null; - } - result[name] = field.clean(value); - } - return result; + var result = Object.create(null), i = 0; + for (var name in fields) { + var field = fields[name], dom = domFields[i++]; + var value = field.read(dom), bad = field.validate(value); + if (bad) { + reportInvalid(dom, bad); + return null; + } + result[name] = field.clean(value); + } + return result; } function reportInvalid(dom, message) { - var parent = dom.parentNode; - var msg = parent.appendChild(document.createElement("div")); - msg.style.left = (dom.offsetLeft + dom.offsetWidth + 2) + "px"; - msg.style.top = (dom.offsetTop - 5) + "px"; - msg.className = "ProseMirror-invalid"; - msg.textContent = message; - setTimeout(function() { parent.removeChild(msg); }, 1500); + var parent = dom.parentNode; + var msg = parent.appendChild(document.createElement("div")); + msg.style.left = (dom.offsetLeft + dom.offsetWidth + 2) + "px"; + msg.style.top = (dom.offsetTop - 5) + "px"; + msg.className = "ProseMirror-invalid"; + msg.textContent = message; + setTimeout(function() { parent.removeChild(msg); }, 1500); } function Field(options) { - this.options = options; + this.options = options; } Field.prototype.read = function(dom) { return dom.value; }; @@ -114,45 +114,45 @@ Field.prototype.read = function(dom) { return dom.value; }; Field.prototype.validateType = function(value) { return null; }; Field.prototype.validate = function(value) { - if (!value && this.options.required) - return "Required field"; - return this.validateType(value) || (this.options.validate ? this.options.validate(value) : null); + if (!value && this.options.required) + return "Required field"; + return this.validateType(value) || (this.options.validate ? this.options.validate(value) : null); }; Field.prototype.clean = function(value) { - return this.options.clean ? this.options.clean(value) : value; + return this.options.clean ? this.options.clean(value) : value; }; function TextField(options) { - Field.call(this, options); + Field.call(this, options); } TextField.prototype = Object.create(Field.prototype); TextField.prototype.render = function() { - var input = document.createElement("input"); - input.type = "text"; - input.placeholder = this.options.label; - input.value = this.options.value || ""; - input.autocomplete = "off"; - return input; + var input = document.createElement("input"); + input.type = "text"; + input.placeholder = this.options.label; + input.value = this.options.value || ""; + input.autocomplete = "off"; + return input; }; function SelectField(options) { - Field.call(this, options); + Field.call(this, options); } SelectField.prototype = Object.create(Field.prototype); SelectField.prototype.render = function() { - var select = document.createElement("select"); - this.options.options.forEach(function(o) { - var opt = select.appendChild(document.createElement("option")); - opt.value = o.value; - opt.selected = o.value == this.options.value; - opt.label = o.label; - }, this); - return select; + var select = document.createElement("select"); + this.options.options.forEach(function(o) { + var opt = select.appendChild(document.createElement("option")); + opt.value = o.value; + opt.selected = o.value == this.options.value; + opt.label = o.label; + }, this); + return select; }; exports.openPrompt = openPrompt; diff --git a/plugins/tiddlywiki/prosemirror/setup/setup.js b/plugins/tiddlywiki/prosemirror/setup/setup.js index 0affc0fe5..83efc2010 100644 --- a/plugins/tiddlywiki/prosemirror/setup/setup.js +++ b/plugins/tiddlywiki/prosemirror/setup/setup.js @@ -25,23 +25,23 @@ exports.buildKeymap = buildKeymap; exports.buildInputRules = buildInputRules; function exampleSetup(options) { - var plugins = [ - buildInputRules(options.schema), - keymap(buildKeymap(options.schema, options.mapKeys)), - keymap(baseKeymap), - dropCursor(), - gapCursor() - ]; - if (options.menuBar !== false) - plugins.push(menuBar({ floating: options.floatingMenu !== false, content: options.menuContent || buildMenuItems(options.schema).fullMenu })); - if (options.history !== false) - plugins.push(history()); + var plugins = [ + buildInputRules(options.schema), + keymap(buildKeymap(options.schema, options.mapKeys)), + keymap(baseKeymap), + dropCursor(), + gapCursor() + ]; + if (options.menuBar !== false) + plugins.push(menuBar({ floating: options.floatingMenu !== false, content: options.menuContent || buildMenuItems(options.schema).fullMenu })); + if (options.history !== false) + plugins.push(history()); - return plugins.concat(new Plugin({ - props: { - attributes: { class: "ProseMirror-example-setup-style" } - } - })); + return plugins.concat(new Plugin({ + props: { + attributes: { class: "ProseMirror-example-setup-style" } + } + })); } exports.exampleSetup = exampleSetup; diff --git a/plugins/tiddlywiki/prosemirror/widget-loader.js b/plugins/tiddlywiki/prosemirror/widget-loader.js index 849c7c98c..498b2d387 100644 --- a/plugins/tiddlywiki/prosemirror/widget-loader.js +++ b/plugins/tiddlywiki/prosemirror/widget-loader.js @@ -6,7 +6,7 @@ module-type: widget \*/ if (!$tw.browser) { - return; + return; } // separate the widget from the exports here, so we can skip the require of react code if `!$tw.browser`. Those ts code will error if loaded in the nodejs side. const components = require('$:/plugins/tiddlywiki/prosemirror/widget.js'); diff --git a/plugins/tiddlywiki/prosemirror/widget.js b/plugins/tiddlywiki/prosemirror/widget.js index bd2982060..3ca27809b 100644 --- a/plugins/tiddlywiki/prosemirror/widget.js +++ b/plugins/tiddlywiki/prosemirror/widget.js @@ -17,10 +17,10 @@ var { EditorView } = require("prosemirror-view"); var { Schema, DOMParser } = require("prosemirror-model"); var { schema: basicSchema } = require("prosemirror-schema-basic"); var { - createListPlugins, - createListSpec, - listInputRules, - listKeymap + createListPlugins, + createListSpec, + listInputRules, + listKeymap } = require("prosemirror-flat-list"); var { exampleSetup } = require("$:/plugins/tiddlywiki/prosemirror/setup/setup.js"); var { keymap } = require("prosemirror-keymap"); @@ -43,58 +43,58 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { this.computeAttributes(); this.execute(); - var tiddler = this.getAttribute("tiddler"); - var initialText = this.wiki.getTiddlerText(tiddler, ""); - var initialWikiAst = $tw.wiki.parseText(null, initialText).tree; - var doc = wikiAstToProseMirrorAst(initialWikiAst); - // DEBUG: console doc - console.log(`initial doc`, doc); + var tiddler = this.getAttribute("tiddler"); + var initialText = this.wiki.getTiddlerText(tiddler, ""); + var initialWikiAst = $tw.wiki.parseText(null, initialText).tree; + var doc = wikiAstToProseMirrorAst(initialWikiAst); + // DEBUG: console doc + console.log(`initial doc`, doc); - var container = $tw.utils.domMaker('div', { - class: 'tc-prosemirror-container', - }); - - var schema = new Schema({ - nodes: basicSchema.spec.nodes.append({ list: createListSpec() }), - marks: basicSchema.spec.marks, - }) - - var listKeymapPlugin = keymap(listKeymap) - var listInputRulePlugin = inputRules({ rules: listInputRules }) - var listPlugins = createListPlugins({ schema }) + var container = $tw.utils.domMaker('div', { + class: 'tc-prosemirror-container', + }); + + var schema = new Schema({ + nodes: basicSchema.spec.nodes.append({ list: createListSpec() }), + marks: basicSchema.spec.marks, + }) + + var listKeymapPlugin = keymap(listKeymap) + var listInputRulePlugin = inputRules({ rules: listInputRules }) + var listPlugins = createListPlugins({ schema }) - var self = this; - this.view = new EditorView(container, { - state: EditorState.create({ - // doc: schema.node("doc", null, [schema.node("paragraph")]), - doc: schema.nodeFromJSON(doc), - plugins: [ - listKeymapPlugin, - listInputRulePlugin, - ...listPlugins, - ...exampleSetup({ schema }), - ], - }), - dispatchTransaction: function(transaction) { - var newState = self.view.state.apply(transaction); - self.view.updateState(newState); - self.debouncedSaveEditorContent(); - } - }) - + var self = this; + this.view = new EditorView(container, { + state: EditorState.create({ + // doc: schema.node("doc", null, [schema.node("paragraph")]), + doc: schema.nodeFromJSON(doc), + plugins: [ + listKeymapPlugin, + listInputRulePlugin, + ...listPlugins, + ...exampleSetup({ schema }), + ], + }), + dispatchTransaction: function(transaction) { + var newState = self.view.state.apply(transaction); + self.view.updateState(newState); + self.debouncedSaveEditorContent(); + } + }) + parent.insertBefore(container,nextSibling); this.domNodes.push(container); }; ProsemirrorWidget.prototype.saveEditorContent = function() { - var content = this.view.state.doc.toJSON(); - console.log(`ProseMirror: ${JSON.stringify(content)}`, content); - var wikiast = wikiAstFromProseMirrorAst(content); - console.log(`WikiAST: ${JSON.stringify(wikiast)}`, wikiast); - var wikiText = $tw.utils.serializeParseTree(wikiast); - console.log(`WikiText: ${wikiText}`); - var tiddler = this.getAttribute("tiddler"); - this.wiki.setText(tiddler, "text", undefined, wikiText); + var content = this.view.state.doc.toJSON(); + console.log(`ProseMirror: ${JSON.stringify(content)}`, content); + var wikiast = wikiAstFromProseMirrorAst(content); + console.log(`WikiAST: ${JSON.stringify(wikiast)}`, wikiast); + var wikiText = $tw.utils.serializeParseTree(wikiast); + console.log(`WikiText: ${wikiText}`); + var tiddler = this.getAttribute("tiddler"); + this.wiki.setText(tiddler, "text", undefined, wikiText); } // Debounced save function for performance From 92a9bfc507c1c957f51bb97cc2424f8b5cb1236b Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Mon, 24 Mar 2025 17:01:01 +0800 Subject: [PATCH 93/98] fix: list dot missing --- .../tiddlywiki/prosemirror/development.tid | 2 +- .../files/prosemirror-flat-list.css | 52 +++---------------- 2 files changed, 7 insertions(+), 47 deletions(-) diff --git a/plugins/tiddlywiki/prosemirror/development.tid b/plugins/tiddlywiki/prosemirror/development.tid index 6e660187e..7a41bb2f7 100755 --- a/plugins/tiddlywiki/prosemirror/development.tid +++ b/plugins/tiddlywiki/prosemirror/development.tid @@ -8,7 +8,7 @@ Downloaded from JsDelivr CDN (like `https://cdn.jsdelivr.net/npm/prosemirror-sta * [ext[prosemirror-model|https://cdn.jsdelivr.net/npm/prosemirror-model@latest/dist/index.cjs]]: v1.25.0 * [ext[prosemirror-schema-basic|https://cdn.jsdelivr.net/npm/prosemirror-schema-basic@latest/dist/index.cjs]]: v1.2.4 * [ext[prosemirror-flat-list|https://cdn.jsdelivr.net/npm/prosemirror-flat-list@latest/dist/prosemirror-flat-list.cjs]]: v0.5.4 -** [ext[prosemirror-flat-list.css|https://cdn.jsdelivr.net/npm/prosemirror-flat-list@latest/dist/style.css]] +** [ext[prosemirror-flat-list.css|https://cdn.jsdelivr.net/npm/prosemirror-flat-list@latest/dist/style.css]] (modified, to solve its #243) ** (Instead of [ext[prosemirror-schema-list|https://cdn.jsdelivr.net/npm/prosemirror-schema-list@latest/dist/index.cjs]]) * [ext[prosemirror-example-setup|https://cdn.jsdelivr.net/npm/prosemirror-example-setup@latest/dist/index.cjs]]: v1.2.3 * [ext[orderedmap|https://cdn.jsdelivr.net/npm/orderedmap@latest/dist/index.cjs]]: v2.1.1 diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.css b/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.css index 53a7d6229..0f6fba562 100644 --- a/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.css +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.css @@ -22,16 +22,17 @@ border: 2px solid #8cf; pointer-events: none; } -.prosemirror-flat-list[data-list-kind=bullet] { +.prosemirror-flat-list[data-list-kind=bullet] > .list-content > p { + display: list-item; list-style: disc; } -.prosemirror-flat-list[data-list-kind=ordered] { +.prosemirror-flat-list[data-list-kind=ordered] > .list-content > p { counter-increment: prosemirror-flat-list-counter; } .prosemirror-flat-list[data-list-kind=ordered] > * { contain: style; } -.prosemirror-flat-list[data-list-kind=ordered]::before { +.prosemirror-flat-list[data-list-kind=ordered] > .list-content > p::before { position: absolute; right: 100%; font-variant-numeric: tabular-nums; @@ -41,47 +42,6 @@ :not(.prosemirror-flat-list[data-list-kind=ordered]) + .prosemirror-flat-list[data-list-kind=ordered] { counter-reset: prosemirror-flat-list-counter; } -@supports (counter-set: prosemirror-flat-list-counter 1) { - [data-list-order]:is(.prosemirror-flat-list[data-list-kind=ordered]:first-child, :not(.prosemirror-flat-list[data-list-kind=ordered]) + .prosemirror-flat-list[data-list-kind=ordered]) { - counter-set: prosemirror-flat-list-counter var(--prosemirror-flat-list-order); - } -} -@supports not (counter-set: prosemirror-flat-list-counter 1) { - [data-list-order]:is(.prosemirror-flat-list[data-list-kind=ordered]:first-child, :not(.prosemirror-flat-list[data-list-kind=ordered]) + .prosemirror-flat-list[data-list-kind=ordered]) { - counter-increment: prosemirror-flat-list-counter var(--prosemirror-flat-list-order); - } -} -.prosemirror-flat-list[data-list-kind=task] > .list-marker { - position: absolute; - right: 100%; - text-align: center; - width: 1.5em; - width: 1lh; -} -.prosemirror-flat-list[data-list-kind=task] > .list-marker, -.prosemirror-flat-list[data-list-kind=task] > .list-marker * { - cursor: pointer; -} -.prosemirror-flat-list[data-list-kind=toggle] > .list-marker { - position: absolute; - right: 100%; - text-align: center; - width: 1.5em; - width: 1lh; -} -.prosemirror-flat-list[data-list-kind=toggle] > .list-marker::before { - content: "\23f7"; -} -.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable][data-list-collapsed] > .list-marker::before { - content: "\23f5"; -} -.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable] > .list-marker { - cursor: pointer; -} -.prosemirror-flat-list[data-list-kind=toggle]:not([data-list-collapsable]) > .list-marker { - opacity: 40%; - pointer-events: none; -} -.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable][data-list-collapsed] > .list-content > *:nth-child(n+2) { - display: none; +[data-list-order]:is(.prosemirror-flat-list[data-list-kind=ordered]:first-child, :not(.prosemirror-flat-list[data-list-kind=ordered]) + .prosemirror-flat-list[data-list-kind=ordered]) { + counter-set: prosemirror-flat-list-counter var(--prosemirror-flat-list-order); } From 3605acb70e30fa7c4168b9f8218946bdbfd40c19 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Tue, 25 Mar 2025 22:53:38 +0800 Subject: [PATCH 94/98] Revert "fix: list dot missing" This reverts commit 92a9bfc507c1c957f51bb97cc2424f8b5cb1236b. --- .../tiddlywiki/prosemirror/development.tid | 2 +- .../files/prosemirror-flat-list.css | 52 ++++++++++++++++--- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/plugins/tiddlywiki/prosemirror/development.tid b/plugins/tiddlywiki/prosemirror/development.tid index 7a41bb2f7..6e660187e 100755 --- a/plugins/tiddlywiki/prosemirror/development.tid +++ b/plugins/tiddlywiki/prosemirror/development.tid @@ -8,7 +8,7 @@ Downloaded from JsDelivr CDN (like `https://cdn.jsdelivr.net/npm/prosemirror-sta * [ext[prosemirror-model|https://cdn.jsdelivr.net/npm/prosemirror-model@latest/dist/index.cjs]]: v1.25.0 * [ext[prosemirror-schema-basic|https://cdn.jsdelivr.net/npm/prosemirror-schema-basic@latest/dist/index.cjs]]: v1.2.4 * [ext[prosemirror-flat-list|https://cdn.jsdelivr.net/npm/prosemirror-flat-list@latest/dist/prosemirror-flat-list.cjs]]: v0.5.4 -** [ext[prosemirror-flat-list.css|https://cdn.jsdelivr.net/npm/prosemirror-flat-list@latest/dist/style.css]] (modified, to solve its #243) +** [ext[prosemirror-flat-list.css|https://cdn.jsdelivr.net/npm/prosemirror-flat-list@latest/dist/style.css]] ** (Instead of [ext[prosemirror-schema-list|https://cdn.jsdelivr.net/npm/prosemirror-schema-list@latest/dist/index.cjs]]) * [ext[prosemirror-example-setup|https://cdn.jsdelivr.net/npm/prosemirror-example-setup@latest/dist/index.cjs]]: v1.2.3 * [ext[orderedmap|https://cdn.jsdelivr.net/npm/orderedmap@latest/dist/index.cjs]]: v2.1.1 diff --git a/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.css b/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.css index 0f6fba562..53a7d6229 100644 --- a/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.css +++ b/plugins/tiddlywiki/prosemirror/files/prosemirror-flat-list.css @@ -22,17 +22,16 @@ border: 2px solid #8cf; pointer-events: none; } -.prosemirror-flat-list[data-list-kind=bullet] > .list-content > p { - display: list-item; +.prosemirror-flat-list[data-list-kind=bullet] { list-style: disc; } -.prosemirror-flat-list[data-list-kind=ordered] > .list-content > p { +.prosemirror-flat-list[data-list-kind=ordered] { counter-increment: prosemirror-flat-list-counter; } .prosemirror-flat-list[data-list-kind=ordered] > * { contain: style; } -.prosemirror-flat-list[data-list-kind=ordered] > .list-content > p::before { +.prosemirror-flat-list[data-list-kind=ordered]::before { position: absolute; right: 100%; font-variant-numeric: tabular-nums; @@ -42,6 +41,47 @@ :not(.prosemirror-flat-list[data-list-kind=ordered]) + .prosemirror-flat-list[data-list-kind=ordered] { counter-reset: prosemirror-flat-list-counter; } -[data-list-order]:is(.prosemirror-flat-list[data-list-kind=ordered]:first-child, :not(.prosemirror-flat-list[data-list-kind=ordered]) + .prosemirror-flat-list[data-list-kind=ordered]) { - counter-set: prosemirror-flat-list-counter var(--prosemirror-flat-list-order); +@supports (counter-set: prosemirror-flat-list-counter 1) { + [data-list-order]:is(.prosemirror-flat-list[data-list-kind=ordered]:first-child, :not(.prosemirror-flat-list[data-list-kind=ordered]) + .prosemirror-flat-list[data-list-kind=ordered]) { + counter-set: prosemirror-flat-list-counter var(--prosemirror-flat-list-order); + } +} +@supports not (counter-set: prosemirror-flat-list-counter 1) { + [data-list-order]:is(.prosemirror-flat-list[data-list-kind=ordered]:first-child, :not(.prosemirror-flat-list[data-list-kind=ordered]) + .prosemirror-flat-list[data-list-kind=ordered]) { + counter-increment: prosemirror-flat-list-counter var(--prosemirror-flat-list-order); + } +} +.prosemirror-flat-list[data-list-kind=task] > .list-marker { + position: absolute; + right: 100%; + text-align: center; + width: 1.5em; + width: 1lh; +} +.prosemirror-flat-list[data-list-kind=task] > .list-marker, +.prosemirror-flat-list[data-list-kind=task] > .list-marker * { + cursor: pointer; +} +.prosemirror-flat-list[data-list-kind=toggle] > .list-marker { + position: absolute; + right: 100%; + text-align: center; + width: 1.5em; + width: 1lh; +} +.prosemirror-flat-list[data-list-kind=toggle] > .list-marker::before { + content: "\23f7"; +} +.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable][data-list-collapsed] > .list-marker::before { + content: "\23f5"; +} +.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable] > .list-marker { + cursor: pointer; +} +.prosemirror-flat-list[data-list-kind=toggle]:not([data-list-collapsable]) > .list-marker { + opacity: 40%; + pointer-events: none; +} +.prosemirror-flat-list[data-list-kind=toggle][data-list-collapsable][data-list-collapsed] > .list-content > *:nth-child(n+2) { + display: none; } From dbe1c20c290a08d8ce8ee33e07fe36f7cd5a14f6 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Tue, 25 Mar 2025 23:55:52 +0800 Subject: [PATCH 95/98] feat: adapt prosemirror-flat-list --- .../prosemirror/ast/from-prosemirror.js | 70 +++++++--- .../prosemirror/ast/to-prosemirror.js | 121 ++++++++---------- plugins/tiddlywiki/prosemirror/readme.tid | 2 + plugins/tiddlywiki/prosemirror/widget.js | 2 + 4 files changed, 111 insertions(+), 84 deletions(-) diff --git a/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js b/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js index 9cc969a96..3521a2e0c 100644 --- a/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js +++ b/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js @@ -7,27 +7,27 @@ Get the Wiki AST from a Prosemirror AST \*/ -function doc(context, node) { - return convertNodes(context, node.content); +function doc(builder, node) { + return convertNodes(builder, node.content); } -function paragraph(context, node) { +function paragraph(builder, node) { return { type: "element", tag: "p", rule: "parseblock", - children: convertNodes(context, node.content) + children: convertNodes(builder, node.content) }; } -function text(context, node) { +function text(builder, node) { return { type: "text", text: node.text } } -function heading(context, node) { +function heading(builder, node) { return { type: "element", tag: "h" + node.attrs.level, @@ -35,21 +35,50 @@ function heading(context, node) { attributes: { // TODO: restore class if any }, - children: convertNodes(context, node.content) + children: convertNodes(builder, node.content) }; } -function list(context, node) { +function list(builder, node, context) { const listType = node.attrs && node.attrs.kind === "ordered" ? "ol" : "ul"; - const listItems = node.content.map(item => { - return { + // Prepare an array to store all list items + let listItems = []; + + // Add content from current node to list items + node.content.forEach(item => { + listItems.push({ type: "element", tag: "li", - children: convertANode(context, item) - }; + children: convertANode(builder, item) + }); }); + // Check if there are adjacent lists of the same type + while (context && context.nodes && context.nodes.length > 0) { + const nextNode = context.nodes[0]; + + // If next node is also a list of the same type + if (nextNode.type === 'list' && + ((node.attrs && node.attrs.kind) === (nextNode.attrs && nextNode.attrs.kind))) { + + // Remove and consume the next node + const consumedNode = context.nodes.shift(); + + // Merge its content into current list + consumedNode.content.forEach(item => { + listItems.push({ + type: "element", + tag: "li", + children: convertANode(builder, item) + }); + }); + } else { + // If next node is not a list of the same type, stop merging + break; + } + } + return { type: "element", tag: listType, @@ -80,19 +109,26 @@ function convertNodes(builders, nodes) { return []; } - return nodes.reduce((accumulator, node) => { - return [...accumulator, ...convertANode(builders, node)]; - }, []); + const result = []; + const nodesCopy = [...nodes]; // Create a copy to avoid modifying the original array + + while (nodesCopy.length > 0) { + const node = nodesCopy.shift(); // Get and remove the first node + const convertedNodes = convertANode(builders, node, { nodes: nodesCopy }); + result.push(...convertedNodes); + } + + return result; } function restoreMetadata(node) { // TODO: restore attributes, orderedAttributes, isBlock return {}; } -function convertANode(builders, node) { +function convertANode(builders, node, context) { var builder = builders[node.type]; if (typeof builder === 'function') { - var convertedNode = builder(builders, node); + var convertedNode = builder(builders, node, context); var arrayOfNodes = (Array.isArray(convertedNode) ? convertedNode : [convertedNode]); return arrayOfNodes.map((child) => ({ ...restoreMetadata(node), ...child })); diff --git a/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js b/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js index aac4117b3..3be1ea5a4 100644 --- a/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js +++ b/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js @@ -7,59 +7,25 @@ Get the Prosemirror AST from a Wiki AST \*/ -/** - * Many node shares same type `element` in wikiAst, we need to distinguish them by tag. - */ -const elementBuilders = { - p: function(context, node) { - return { - type: "paragraph", - content: convertNodes(context, node.children) - }; - }, - h1: function(context, node) { - return { - type: "heading", - attrs: { level: 1 }, - content: convertNodes(context, node.children) - }; - }, - h2: function(context, node) { - return { - type: "heading", - attrs: { level: 2 }, - content: convertNodes(context, node.children) - }; - }, - h3: function(context, node) { - return { - type: "heading", - attrs: { level: 3 }, - content: convertNodes(context, node.children) - }; - }, - h4: function(context, node) { - return { - type: "heading", - attrs: { level: 4 }, - content: convertNodes(context, node.children) - }; - }, - h5: function(context, node) { - return { - type: "heading", - attrs: { level: 5 }, - content: convertNodes(context, node.children) - }; - }, - h6: function(context, node) { - return { - type: "heading", - attrs: { level: 6 }, - content: convertNodes(context, node.children) - }; - }, - ul: function(context, node) { +function buildParagraph(context, node) { + return { + type: "paragraph", + content: convertNodes(context, node.children) + }; +} + +function buildHeading(context, node, level) { + return { + type: "heading", + attrs: { level: level }, + content: convertNodes(context, node.children) + }; +} + +function buildUnorderedList(context, node) { + // Prosemirror requires split all lists into separate lists with single items + return node.children.map(item => { + const processedItem = convertANode({...context, level: context.level + 1}, item); return { type: "list", attrs: { @@ -68,10 +34,14 @@ const elementBuilders = { checked: false, collapsed: false }, - content: convertNodes(context, node.children) + content: processedItem }; - }, - ol: function(context, node) { + }); +} + +function buildOrderedList(context, node) { + return node.children.map(item => { + const processedItem = convertANode({...context, level: context.level + 1}, item); return { type: "list", attrs: { @@ -80,17 +50,11 @@ const elementBuilders = { checked: false, collapsed: false }, - content: convertNodes(context, node.children) + content: processedItem }; - }, - li: function(context, node) { - // In ProseMirror, list items are converted to paragraphs or other block content - // directly under the list node, no special list_item type needed - const processedContent = convertNodes(context, node.children); - // Ensure content starts with a block element (typically paragraph) - return wrapTextNodesInParagraphs(context, processedContent); - } -}; + }); +} + /** * Helper function to ensure text nodes in list items are wrapped in paragraphs @@ -132,6 +96,28 @@ function wrapTextNodesInParagraphs(context, nodes) { return result; } +function buildListItem(context, node) { + const processedContent = convertNodes({...context, level: context.level + 1}, node.children); + // Ensure content starts with a block element (typically paragraph) + return wrapTextNodesInParagraphs(context, processedContent); +} + +/** + * Many node shares same type `element` in wikiAst, we need to distinguish them by tag. + */ +const elementBuilders = { + p: buildParagraph, + h1: (context, node) => buildHeading(context, node, 1), + h2: (context, node) => buildHeading(context, node, 2), + h3: (context, node) => buildHeading(context, node, 3), + h4: (context, node) => buildHeading(context, node, 4), + h5: (context, node) => buildHeading(context, node, 5), + h6: (context, node) => buildHeading(context, node, 6), + ul: buildUnorderedList, + ol: buildOrderedList, + li: buildListItem +}; + function element(context, node) { const builder = elementBuilders[node.tag]; if (builder) { @@ -158,7 +144,8 @@ const builders = { }; function wikiAstToProsemirrorAst(node, options) { - const context = { ...builders, ...options }; + // Initialize context with level tracking + const context = { ...builders, ...options, level: 0 }; const result = convertNodes(context, Array.isArray(node) ? node : [node]); // Wrap in a doc if needed diff --git a/plugins/tiddlywiki/prosemirror/readme.tid b/plugins/tiddlywiki/prosemirror/readme.tid index 15d5db7af..e0c23e05d 100755 --- a/plugins/tiddlywiki/prosemirror/readme.tid +++ b/plugins/tiddlywiki/prosemirror/readme.tid @@ -5,3 +5,5 @@ Test `<$prosemirror />` widget below, see console for content JSON. <$edit-prosemirror tiddler="$:/plugins/tiddlywiki/prosemirror/example"/> <$edit-text tiddler="$:/plugins/tiddlywiki/prosemirror/example" class="tc-edit-texteditor"/> + +{{$:/plugins/tiddlywiki/prosemirror/example}} diff --git a/plugins/tiddlywiki/prosemirror/widget.js b/plugins/tiddlywiki/prosemirror/widget.js index 3ca27809b..3edd8a560 100644 --- a/plugins/tiddlywiki/prosemirror/widget.js +++ b/plugins/tiddlywiki/prosemirror/widget.js @@ -46,6 +46,8 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { var tiddler = this.getAttribute("tiddler"); var initialText = this.wiki.getTiddlerText(tiddler, ""); var initialWikiAst = $tw.wiki.parseText(null, initialText).tree; + // DEBUG: console initialWikiAst + console.log(`initialWikiAst`, initialWikiAst); var doc = wikiAstToProseMirrorAst(initialWikiAst); // DEBUG: console doc console.log(`initial doc`, doc); From a76baed5996861fe8d6b581c2d4cf460661a6ce5 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Wed, 26 Mar 2025 00:52:15 +0800 Subject: [PATCH 96/98] feat: better list input rule --- .../prosemirror/ast/from-prosemirror.js | 4 +-- .../prosemirror/setup/inputrules.js | 33 +++++++++---------- plugins/tiddlywiki/prosemirror/widget.js | 9 ++--- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js b/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js index 3521a2e0c..12d24fbad 100644 --- a/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js +++ b/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js @@ -46,7 +46,7 @@ function list(builder, node, context) { let listItems = []; // Add content from current node to list items - node.content.forEach(item => { + node.content?.forEach?.(item => { listItems.push({ type: "element", tag: "li", @@ -66,7 +66,7 @@ function list(builder, node, context) { const consumedNode = context.nodes.shift(); // Merge its content into current list - consumedNode.content.forEach(item => { + consumedNode.content?.forEach?.(item => { listItems.push({ type: "element", tag: "li", diff --git a/plugins/tiddlywiki/prosemirror/setup/inputrules.js b/plugins/tiddlywiki/prosemirror/setup/inputrules.js index 425af3c51..b1078136a 100644 --- a/plugins/tiddlywiki/prosemirror/setup/inputrules.js +++ b/plugins/tiddlywiki/prosemirror/setup/inputrules.js @@ -8,41 +8,40 @@ module-type: library "use strict"; var { inputRules, wrappingInputRule, textblockTypeInputRule, smartQuotes, emDash, ellipsis } = require("prosemirror-inputrules"); +var { wrappingListInputRule } = require("prosemirror-flat-list"); var { NodeType, Schema } = require("prosemirror-model"); function blockQuoteRule(nodeType) { return wrappingInputRule(/^\s*>\s$/, nodeType); } -function orderedListRule(nodeType) { - return wrappingInputRule( - /^(\d+)\.\s$/, - nodeType, - function(match) { return { order: +match[1] }; }, - function(match, node) { return node.childCount + node.attrs.order == +match[1]; } - ); -} - -function bulletListRule(nodeType) { - return wrappingInputRule(/^\s*([-+*])\s$/, nodeType); -} - function codeBlockRule(nodeType) { return textblockTypeInputRule(/^```$/, nodeType); } function headingRule(nodeType, maxLevel) { - return textblockTypeInputRule(new RegExp("^(#{1," + maxLevel + "})\\s$"), nodeType, function(match) { return { level: match[1].length }; }); + return textblockTypeInputRule(new RegExp("^(\\!{1," + maxLevel + "}|\!{1," + maxLevel + "})\\s$"), nodeType, function(match) { return { level: match[1].length }; }); } function buildInputRules(schema) { var rules = smartQuotes.concat(ellipsis, emDash), type; if (type = schema.nodes.blockquote) rules.push(blockQuoteRule(type)); - if (type = schema.nodes.ordered_list) rules.push(orderedListRule(type)); - if (type = schema.nodes.bullet_list) rules.push(bulletListRule(type)); + if (type = schema.nodes.list) { + rules.push(wrappingListInputRule(/^\s?([*-])\s$/, { + kind: 'bullet', + collapsed: false, + })); + rules.push(wrappingListInputRule(/^\s?(#)\s$|^\s?(\d+)\.\s$/, ({ match }) => { + const order = match[1] === "#" ? 1 : parseInteger(match[1]); + return { + kind: 'ordered', + collapsed: false, + order: order != null && order >= 2 ? order : null, + }; + })); + } if (type = schema.nodes.code_block) rules.push(codeBlockRule(type)); if (type = schema.nodes.heading) rules.push(headingRule(type, 6)); return inputRules({ rules: rules }); } - exports.buildInputRules = buildInputRules; diff --git a/plugins/tiddlywiki/prosemirror/widget.js b/plugins/tiddlywiki/prosemirror/widget.js index 3edd8a560..96eb542ae 100644 --- a/plugins/tiddlywiki/prosemirror/widget.js +++ b/plugins/tiddlywiki/prosemirror/widget.js @@ -19,7 +19,6 @@ var { schema: basicSchema } = require("prosemirror-schema-basic"); var { createListPlugins, createListSpec, - listInputRules, listKeymap } = require("prosemirror-flat-list"); var { exampleSetup } = require("$:/plugins/tiddlywiki/prosemirror/setup/setup.js"); @@ -53,16 +52,15 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { console.log(`initial doc`, doc); var container = $tw.utils.domMaker('div', { - class: 'tc-prosemirror-container', + class: 'tc-prosemirror-container', }); var schema = new Schema({ - nodes: basicSchema.spec.nodes.append({ list: createListSpec() }), - marks: basicSchema.spec.marks, + nodes: basicSchema.spec.nodes.append({ list: createListSpec() }), + marks: basicSchema.spec.marks, }) var listKeymapPlugin = keymap(listKeymap) - var listInputRulePlugin = inputRules({ rules: listInputRules }) var listPlugins = createListPlugins({ schema }) var self = this; @@ -72,7 +70,6 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { doc: schema.nodeFromJSON(doc), plugins: [ listKeymapPlugin, - listInputRulePlugin, ...listPlugins, ...exampleSetup({ schema }), ], From 3f53da9b590dd4e8b63312cd637ebfad00400337 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Wed, 26 Mar 2025 01:05:17 +0800 Subject: [PATCH 97/98] feat: save lock to prevent focus lost --- plugins/tiddlywiki/prosemirror/widget.js | 29 +++++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/plugins/tiddlywiki/prosemirror/widget.js b/plugins/tiddlywiki/prosemirror/widget.js index 96eb542ae..de4ce31f9 100644 --- a/plugins/tiddlywiki/prosemirror/widget.js +++ b/plugins/tiddlywiki/prosemirror/widget.js @@ -27,6 +27,8 @@ var { inputRules } = require("prosemirror-inputrules"); var ProsemirrorWidget = function(parseTreeNode,options) { this.initialise(parseTreeNode,options); + // indicate the change is triggered by the widget itself + this.saveLock = false; }; /* @@ -87,13 +89,17 @@ ProsemirrorWidget.prototype.render = function(parent,nextSibling) { ProsemirrorWidget.prototype.saveEditorContent = function() { var content = this.view.state.doc.toJSON(); - console.log(`ProseMirror: ${JSON.stringify(content)}`, content); var wikiast = wikiAstFromProseMirrorAst(content); - console.log(`WikiAST: ${JSON.stringify(wikiast)}`, wikiast); var wikiText = $tw.utils.serializeParseTree(wikiast); - console.log(`WikiText: ${wikiText}`); var tiddler = this.getAttribute("tiddler"); - this.wiki.setText(tiddler, "text", undefined, wikiText); + var currentText = this.wiki.getTiddlerText(tiddler, ""); + if (currentText !== wikiText) { + console.log(`ProseMirror: ${JSON.stringify(content)}`, content); + console.log(`WikiAST: ${JSON.stringify(wikiast)}`, wikiast); + console.log(`WikiText: ${wikiText}`); + this.saveLock = true; + this.wiki.setText(tiddler, "text", undefined, wikiText); + } } // Debounced save function for performance @@ -111,12 +117,23 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of */ ProsemirrorWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); + // DEBUG: console this.saveLock + console.log(`this.saveLock`, this.saveLock); if(changedAttributes.text) { this.refreshSelf(); return true; - } else { - return false; + } else if (changedTiddlers[this.getAttribute("tiddler")]) { + if (this.saveLock) { + // Skip refresh if the change is triggered by the widget itself + this.saveLock = false; + return false; + } + // Not Re-render the widget, which will cause focus lost. + // We manually update the editor content. + this.refreshSelf(); + return true; } + return false; }; exports.prosemirror = ProsemirrorWidget; From 2d8885959d885fb6f21fbb7fff5f8491300d93e0 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Wed, 26 Mar 2025 01:40:21 +0800 Subject: [PATCH 98/98] feat: support text marks --- .../prosemirror/ast/from-prosemirror.js | 46 +++++++++++++++- .../prosemirror/ast/to-prosemirror.js | 52 ++++++++++++++++++- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js b/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js index 12d24fbad..38fbb7272 100644 --- a/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js +++ b/plugins/tiddlywiki/prosemirror/ast/from-prosemirror.js @@ -20,11 +20,55 @@ function paragraph(builder, node) { }; } +// Map ProseMirror mark types to HTML tags +const markTypeMap = { + strong: "strong", + em: "em", +}; +const markRuleMap = { + em: "italic", + strong: "bold", +}; +// Define mark priority (inner to outer) +const markPriority = ["code", "strong", "bold", "em", "italic", "underline", "strike", "strikethrough", "superscript", "subscript"]; function text(builder, node) { + if (!node.text) { + return { + type: "text", + text: "" + }; + } + if (node.marks && node.marks.length > 0) { + // Create base text node + let textNode = { + type: "text", + text: node.text + }; + const sortedMarks = [...node.marks].sort((a, b) => { + const indexA = markPriority.indexOf(a.type); + const indexB = markPriority.indexOf(b.type); + // Place unknown mark types at the end + if (indexA === -1) return 1; + if (indexB === -1) return -1; + return indexA - indexB; + }); + + // Apply marks from inner to outer + return sortedMarks.reduce((wrappedNode, mark) => { + const tag = markTypeMap[mark.type]; + const rule = markRuleMap[mark.type]; + return { + type: "element", + tag: tag, + rule, + children: [wrappedNode] + }; + }, textNode); + } return { type: "text", text: node.text - } + }; } function heading(builder, node) { diff --git a/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js b/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js index 3be1ea5a4..bcd04ed96 100644 --- a/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js +++ b/plugins/tiddlywiki/prosemirror/ast/to-prosemirror.js @@ -102,6 +102,49 @@ function buildListItem(context, node) { return wrapTextNodesInParagraphs(context, processedContent); } +function buildTextWithMark(context, node, markType) { + const content = convertNodes(context, node.children); + return content.map(childNode => { + if (childNode.type === "text") { + // Add the mark to the text node + const marks = childNode.marks || []; + return { + ...childNode, + marks: [...marks, { type: markType }] + }; + } + return childNode; + }); +} + +function buildStrong(context, node) { + return buildTextWithMark(context, node, "strong"); +} + +function buildEm(context, node) { + return buildTextWithMark(context, node, "em"); +} + +function buildCode(context, node) { + return buildTextWithMark(context, node, "code"); +} + +function buildUnderline(context, node) { + return buildTextWithMark(context, node, "underline"); +} + +function buildStrike(context, node) { + return buildTextWithMark(context, node, "strike"); +} + +function buildSup(context, node) { + return buildTextWithMark(context, node, "superscript"); +} + +function buildSub(context, node) { + return buildTextWithMark(context, node, "subscript"); +} + /** * Many node shares same type `element` in wikiAst, we need to distinguish them by tag. */ @@ -115,7 +158,14 @@ const elementBuilders = { h6: (context, node) => buildHeading(context, node, 6), ul: buildUnorderedList, ol: buildOrderedList, - li: buildListItem + li: buildListItem, + strong: buildStrong, + em: buildEm, + code: buildCode, + u: buildUnderline, + strike: buildStrike, + sup: buildSup, + sub: buildSub }; function element(context, node) {