@openleaf-editor/core 0.1.0-beta.2 → 0.1.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +115 -0
  2. package/dist/autolink.d.ts.map +1 -1
  3. package/dist/autolink.js +45 -7
  4. package/dist/autolink.js.map +1 -1
  5. package/dist/command-helpers.d.ts +8 -0
  6. package/dist/command-helpers.d.ts.map +1 -0
  7. package/dist/command-helpers.js +36 -0
  8. package/dist/command-helpers.js.map +1 -0
  9. package/dist/commands.d.ts +15 -61
  10. package/dist/commands.d.ts.map +1 -1
  11. package/dist/commands.js +295 -343
  12. package/dist/commands.js.map +1 -1
  13. package/dist/css.d.ts +1 -175
  14. package/dist/css.d.ts.map +1 -1
  15. package/dist/css.js +1 -516
  16. package/dist/css.js.map +1 -1
  17. package/dist/disclosure.d.ts +21 -0
  18. package/dist/disclosure.d.ts.map +1 -0
  19. package/dist/disclosure.js +144 -0
  20. package/dist/disclosure.js.map +1 -0
  21. package/dist/elements.d.ts +2 -0
  22. package/dist/elements.d.ts.map +1 -0
  23. package/dist/elements.js +2 -0
  24. package/dist/elements.js.map +1 -0
  25. package/dist/embed.d.ts +1 -51
  26. package/dist/embed.d.ts.map +1 -1
  27. package/dist/embed.js +1 -115
  28. package/dist/embed.js.map +1 -1
  29. package/dist/errors.d.ts +38 -0
  30. package/dist/errors.d.ts.map +1 -0
  31. package/dist/errors.js +40 -0
  32. package/dist/errors.js.map +1 -0
  33. package/dist/extensions.d.ts +46 -5
  34. package/dist/extensions.d.ts.map +1 -1
  35. package/dist/extensions.js +272 -52
  36. package/dist/extensions.js.map +1 -1
  37. package/dist/formats.d.ts.map +1 -1
  38. package/dist/formats.js +19 -7
  39. package/dist/formats.js.map +1 -1
  40. package/dist/html.d.ts +32 -2
  41. package/dist/html.d.ts.map +1 -1
  42. package/dist/html.js +185 -31
  43. package/dist/html.js.map +1 -1
  44. package/dist/index.d.ts +21 -6
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +32 -6
  47. package/dist/index.js.map +1 -1
  48. package/dist/insert-commands.d.ts +172 -0
  49. package/dist/insert-commands.d.ts.map +1 -0
  50. package/dist/insert-commands.js +560 -0
  51. package/dist/insert-commands.js.map +1 -0
  52. package/dist/isolating-selection.d.ts +41 -0
  53. package/dist/isolating-selection.d.ts.map +1 -0
  54. package/dist/isolating-selection.js +162 -0
  55. package/dist/isolating-selection.js.map +1 -0
  56. package/dist/noneditable.d.ts.map +1 -1
  57. package/dist/noneditable.js +18 -4
  58. package/dist/noneditable.js.map +1 -1
  59. package/dist/plugins.d.ts +20 -2
  60. package/dist/plugins.d.ts.map +1 -1
  61. package/dist/plugins.js +27 -2
  62. package/dist/plugins.js.map +1 -1
  63. package/dist/preserve.d.ts +48 -17
  64. package/dist/preserve.d.ts.map +1 -1
  65. package/dist/preserve.js +214 -43
  66. package/dist/preserve.js.map +1 -1
  67. package/dist/schema.d.ts +15 -0
  68. package/dist/schema.d.ts.map +1 -1
  69. package/dist/schema.js +157 -28
  70. package/dist/schema.js.map +1 -1
  71. package/dist/structure.d.ts +32 -0
  72. package/dist/structure.d.ts.map +1 -1
  73. package/dist/structure.js +53 -10
  74. package/dist/structure.js.map +1 -1
  75. package/dist/tables.d.ts +47 -1
  76. package/dist/tables.d.ts.map +1 -1
  77. package/dist/tables.js +417 -40
  78. package/dist/tables.js.map +1 -1
  79. package/dist/testing.d.ts +3 -0
  80. package/dist/testing.d.ts.map +1 -0
  81. package/dist/testing.js +3 -0
  82. package/dist/testing.js.map +1 -0
  83. package/dist/tokens.d.ts +8 -0
  84. package/dist/tokens.d.ts.map +1 -1
  85. package/dist/tokens.js +54 -6
  86. package/dist/tokens.js.map +1 -1
  87. package/dist/url.d.ts +1 -25
  88. package/dist/url.d.ts.map +1 -1
  89. package/dist/url.js +1 -77
  90. package/dist/url.js.map +1 -1
  91. package/dist/visual-aids.d.ts +11 -1
  92. package/dist/visual-aids.d.ts.map +1 -1
  93. package/dist/visual-aids.js +124 -36
  94. package/dist/visual-aids.js.map +1 -1
  95. package/package.json +15 -1
package/dist/tokens.d.ts CHANGED
@@ -25,4 +25,12 @@ export declare const IMAGE_ALIGN_CLASS: Readonly<Record<ImageAlign, string>>;
25
25
  /** The modelled alignment class in this list, if any. */
26
26
  export declare function imageAlignFromClass(value: string | null | undefined): ImageAlign | null;
27
27
  export declare const IMAGE_ALIGN_CLASSES: ReadonlySet<string>;
28
+ /**
29
+ * True for a name that can be written back with `setAttribute` anywhere.
30
+ *
31
+ * Used where unmodelled attributes are picked up to be carried through the
32
+ * round trip: an attribute that cannot be written is not content, and refusing
33
+ * it there is what keeps `serializeHtml(parseHtml(x))` from throwing.
34
+ */
35
+ export declare function isWritableAttributeName(name: string): boolean;
28
36
  //# sourceMappingURL=tokens.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,8CAA8C;AAC9C,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAKtE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,OAAO,GAAE,WAAW,CAAC,MAAM,CAAa,GACvC,MAAM,GAAG,IAAI,CAWf;AAED,kFAAkF;AAClF,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEpD,eAAO,MAAM,gBAAgB,EAAE,SAAS,UAAU,EAAgC,CAAA;AAElF,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAIlE,CAAA;AASD,yDAAyD;AACzD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,UAAU,GAAG,IAAI,CAOvF;AAED,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAA6C,CAAA"}
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAgBH,8CAA8C;AAC9C,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAKtE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,OAAO,GAAE,WAAW,CAAC,MAAM,CAAa,GACvC,MAAM,GAAG,IAAI,CAWf;AAED,kFAAkF;AAClF,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEpD,eAAO,MAAM,gBAAgB,EAAE,SAAS,UAAU,EAAgC,CAAA;AAElF,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAIlE,CAAA;AASD,yDAAyD;AACzD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,UAAU,GAAG,IAAI,CAOvF;AAED,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAA6C,CAAA;AAiCjG;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D"}
package/dist/tokens.js CHANGED
@@ -8,16 +8,25 @@
8
8
  * Which class names a deployment offers in a pick list is an integrator
9
9
  * decision; which characters may appear in one is not.
10
10
  */
11
- /** HTML5 ids: no spaces, not empty. */
12
- const ID = /^[^\s]+$/;
13
- /** A single class token. */
14
- const CLASS_TOKEN = /^-?[_a-zA-Z]+[_a-zA-Z0-9-]*$/;
11
+ /**
12
+ * HTML5 ids and class tokens: a non-empty run of non-whitespace.
13
+ *
14
+ * Class names are not CSS identifiers. Tailwind (`md:w-1/2`, `p-[10px]`),
15
+ * leading digits (`2col`), and non-ASCII (`größe-mittel`) are legal in HTML
16
+ * and in CSS (with escaping at selector time, which is the site's problem).
17
+ * Restricting tokens to ASCII identifiers silently deleted half of a mixed
18
+ * `class` whenever another token survived the filter -- the modelled write
19
+ * then overrode the residue that would have carried the original string.
20
+ * Policy about *which* classes a deployment stores belongs in sanitize, not
21
+ * here.
22
+ */
23
+ const HTML_TOKEN = /^[^\s]+$/;
15
24
  /** An `id` the schema will store, or null. */
16
25
  export function safeId(value) {
17
26
  if (value === null || value === undefined)
18
27
  return null;
19
28
  const candidate = value.trim();
20
- if (candidate === '' || !ID.test(candidate))
29
+ if (candidate === '' || !HTML_TOKEN.test(candidate))
21
30
  return null;
22
31
  return candidate;
23
32
  }
@@ -34,7 +43,7 @@ export function safeClassList(value, exclude = new Set()) {
34
43
  const kept = [];
35
44
  const seen = new Set();
36
45
  for (const token of value.trim().split(/\s+/)) {
37
- if (token === '' || exclude.has(token) || !CLASS_TOKEN.test(token))
46
+ if (token === '' || exclude.has(token) || !HTML_TOKEN.test(token))
38
47
  continue;
39
48
  if (seen.has(token))
40
49
  continue;
@@ -65,4 +74,43 @@ export function imageAlignFromClass(value) {
65
74
  return null;
66
75
  }
67
76
  export const IMAGE_ALIGN_CLASSES = new Set(Object.values(IMAGE_ALIGN_CLASS));
77
+ /*
78
+ * Attribute names the schema is willing to write back.
79
+ *
80
+ * The HTML parser accepts names `setAttribute` refuses. `<p ="v">` parses to one
81
+ * attribute literally named `="v"`, and every engine's `setAttribute` throws
82
+ * `InvalidCharacterError` on it -- so a name the parser produced through error
83
+ * recovery was carried in as residue and then detonated on the way out, in the
84
+ * middle of rendering a document. One stray `=` typed in the source box left the
85
+ * editor blank with no way back, and a stored document containing one could not
86
+ * be loaded at all.
87
+ *
88
+ * This is the XML `Name` production, which is what `setAttribute` validates
89
+ * against. Deliberately the spec's rule rather than the host's: browsers are
90
+ * laxer than the spec for HTML documents and jsdom implements it strictly, so
91
+ * asking the current runtime would accept names in a browser session that then
92
+ * throw on a jsdom server -- the cross-environment divergence this project
93
+ * refuses elsewhere. Being stricter than the strictest runtime is the only test
94
+ * that makes stored content portable.
95
+ *
96
+ * Nothing legal is lost. Every name a document could have meant -- including
97
+ * non-ASCII and namespaced ones -- is a `Name`; the names this rejects exist
98
+ * only because a parser recovered from malformed markup.
99
+ */
100
+ const NAME_START = 'A-Za-z_:' +
101
+ '\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF' +
102
+ '\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF' +
103
+ '\\uFDF0-\\uFFFD\\u{10000}-\\u{EFFFF}';
104
+ const NAME_REST = NAME_START + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040';
105
+ const ATTRIBUTE_NAME = new RegExp(`^[${NAME_START}][${NAME_REST}]*$`, 'u');
106
+ /**
107
+ * True for a name that can be written back with `setAttribute` anywhere.
108
+ *
109
+ * Used where unmodelled attributes are picked up to be carried through the
110
+ * round trip: an attribute that cannot be written is not content, and refusing
111
+ * it there is what keeps `serializeHtml(parseHtml(x))` from throwing.
112
+ */
113
+ export function isWritableAttributeName(name) {
114
+ return ATTRIBUTE_NAME.test(name);
115
+ }
68
116
  //# sourceMappingURL=tokens.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,uCAAuC;AACvC,MAAM,EAAE,GAAG,UAAU,CAAA;AAErB,4BAA4B;AAC5B,MAAM,WAAW,GAAG,8BAA8B,CAAA;AAElD,8CAA8C;AAC9C,MAAM,UAAU,MAAM,CAAC,KAAgC;IACrD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IACtD,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IAC9B,IAAI,SAAS,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAA;IACxD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,KAAgC,EAChC,UAA+B,IAAI,GAAG,EAAE;IAExC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IACtD,MAAM,IAAI,GAAa,EAAE,CAAA;IACzB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9C,IAAI,KAAK,KAAK,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,SAAQ;QAC5E,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAQ;QAC7B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACf,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAClB,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AAChD,CAAC;AAKD,MAAM,CAAC,MAAM,gBAAgB,GAA0B,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;AAElF,MAAM,CAAC,MAAM,iBAAiB,GAAyC;IACrE,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,gBAAgB;IACvB,MAAM,EAAE,iBAAiB;CAC1B,CAAA;AAED,MAAM,cAAc,GAAG,IAAI,GAAG,CAC3B,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAiC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;IACxF,IAAI;IACJ,KAAK;CACN,CAAC,CACH,CAAA;AAED,yDAAyD;AACzD,MAAM,UAAU,mBAAmB,CAAC,KAAgC;IAClE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACvC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAA;IACzB,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,GAAG,UAAU,CAAA;AAE7B,8CAA8C;AAC9C,MAAM,UAAU,MAAM,CAAC,KAAgC;IACrD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IACtD,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IAC9B,IAAI,SAAS,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAA;IAChE,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,KAAgC,EAChC,UAA+B,IAAI,GAAG,EAAE;IAExC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IACtD,MAAM,IAAI,GAAa,EAAE,CAAA;IACzB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9C,IAAI,KAAK,KAAK,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,SAAQ;QAC3E,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAQ;QAC7B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACf,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAClB,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AAChD,CAAC;AAKD,MAAM,CAAC,MAAM,gBAAgB,GAA0B,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;AAElF,MAAM,CAAC,MAAM,iBAAiB,GAAyC;IACrE,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,gBAAgB;IACvB,MAAM,EAAE,iBAAiB;CAC1B,CAAA;AAED,MAAM,cAAc,GAAG,IAAI,GAAG,CAC3B,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAiC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;IACxF,IAAI;IACJ,KAAK;CACN,CAAC,CACH,CAAA;AAED,yDAAyD;AACzD,MAAM,UAAU,mBAAmB,CAAC,KAAgC;IAClE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QACvC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAA;IACzB,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAA;AAEjG;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,GACd,UAAU;IACV,6EAA6E;IAC7E,6EAA6E;IAC7E,sCAAsC,CAAA;AACxC,MAAM,SAAS,GAAG,UAAU,GAAG,8CAA8C,CAAA;AAC7E,MAAM,cAAc,GAAG,IAAI,MAAM,CAAC,KAAK,UAAU,KAAK,SAAS,KAAK,EAAE,GAAG,CAAC,CAAA;AAE1E;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAClC,CAAC"}
package/dist/url.d.ts CHANGED
@@ -1,26 +1,2 @@
1
- /**
2
- * URL safety.
3
- *
4
- * A link is the cheapest XSS vector there is: `<a href="javascript:...">` needs
5
- * no injected element, no script tag, and no clever parsing trick -- just a user
6
- * who clicks. OpenLeaf's schema previously accepted any `href` at all.
7
- *
8
- * The checks here are deliberately a small allowlist of schemes rather than a
9
- * blocklist of dangerous ones. A blocklist is a promise to have thought of every
10
- * scheme, including the ones a browser will invent later.
11
- */
12
- /**
13
- * Is this URL safe to put in an `href` or `src`?
14
- *
15
- * Relative URLs, fragments and query-only URLs are allowed: they cannot carry a
16
- * scheme, so they cannot execute. Protocol-relative `//host/path` is allowed
17
- * because it inherits the page's scheme.
18
- */
19
- export declare function isSafeUrl(value: string | null | undefined): boolean;
20
- /** The safe URL, or null when it should be dropped. */
21
- export declare function safeUrlOrNull(value: string | null | undefined): string | null;
22
- /** Attributes whose values are URLs and therefore need checking. */
23
- export declare const URL_ATTRIBUTES: ReadonlySet<string>;
24
- /** True for `onclick`, `onmouseover` and every other inline event handler. */
25
- export declare function isEventHandlerAttribute(name: string): boolean;
1
+ export * from '@openleaf-editor/content-policy/url';
26
2
  //# sourceMappingURL=url.d.ts.map
package/dist/url.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA6BH;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAUnE;AAED,uDAAuD;AACvD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAE7E;AAED,oEAAoE;AACpE,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,CAa7C,CAAA;AAEF,8EAA8E;AAC9E,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D"}
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAA"}
package/dist/url.js CHANGED
@@ -1,78 +1,2 @@
1
- /**
2
- * URL safety.
3
- *
4
- * A link is the cheapest XSS vector there is: `<a href="javascript:...">` needs
5
- * no injected element, no script tag, and no clever parsing trick -- just a user
6
- * who clicks. OpenLeaf's schema previously accepted any `href` at all.
7
- *
8
- * The checks here are deliberately a small allowlist of schemes rather than a
9
- * blocklist of dangerous ones. A blocklist is a promise to have thought of every
10
- * scheme, including the ones a browser will invent later.
11
- */
12
- /**
13
- * Schemes an author may link to.
14
- *
15
- * `data:` is absent on purpose. `data:text/html` is a full XSS vector, and
16
- * distinguishing safe data URLs from dangerous ones by sniffing the media type
17
- * is exactly the kind of parsing that gets defeated. Integrators who genuinely
18
- * need inline images can permit them in their server-side policy, where the
19
- * decision is explicit and reviewable.
20
- */
21
- const SAFE_SCHEMES = new Set(['http', 'https', 'mailto', 'tel', 'ftp', 'ftps']);
22
- /** Matches a leading URL scheme, per RFC 3986. */
23
- const SCHEME = /^([a-z][a-z0-9+.-]*):/i;
24
- /**
25
- * Strip the characters browsers ignore when resolving a scheme.
26
- *
27
- * `java\tscript:alert(1)` and `java\nscript:alert(1)` both navigate. Browsers
28
- * discard ASCII whitespace and control characters while parsing the scheme, so
29
- * any check that does not do the same is trivially bypassed. Attribute values
30
- * arrive already entity-decoded from `getAttribute`, so `&#106;avascript:` is
31
- * covered by the same normalization.
32
- */
33
- function normalize(value) {
34
- return value.replace(/[\u0000-\u0020\u007f-\u00a0]/g, '').toLowerCase();
35
- }
36
- /**
37
- * Is this URL safe to put in an `href` or `src`?
38
- *
39
- * Relative URLs, fragments and query-only URLs are allowed: they cannot carry a
40
- * scheme, so they cannot execute. Protocol-relative `//host/path` is allowed
41
- * because it inherits the page's scheme.
42
- */
43
- export function isSafeUrl(value) {
44
- if (value === null || value === undefined)
45
- return false;
46
- const candidate = normalize(value);
47
- if (candidate === '')
48
- return false;
49
- const match = SCHEME.exec(candidate);
50
- // No scheme means relative, fragment or protocol-relative. All are safe.
51
- if (!match)
52
- return true;
53
- return SAFE_SCHEMES.has(match[1]);
54
- }
55
- /** The safe URL, or null when it should be dropped. */
56
- export function safeUrlOrNull(value) {
57
- return isSafeUrl(value) ? value : null;
58
- }
59
- /** Attributes whose values are URLs and therefore need checking. */
60
- export const URL_ATTRIBUTES = new Set([
61
- 'href',
62
- 'src',
63
- 'action',
64
- 'formaction',
65
- 'data',
66
- 'poster',
67
- 'background',
68
- 'cite',
69
- 'longdesc',
70
- 'srcdoc',
71
- 'xlink:href',
72
- 'ping',
73
- ]);
74
- /** True for `onclick`, `onmouseover` and every other inline event handler. */
75
- export function isEventHandlerAttribute(name) {
76
- return /^on/i.test(name);
77
- }
1
+ export * from '@openleaf-editor/content-policy/url';
78
2
  //# sourceMappingURL=url.js.map
package/dist/url.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"url.js","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;;;;GAQG;AACH,MAAM,YAAY,GAAwB,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;AAEpG,kDAAkD;AAClD,MAAM,MAAM,GAAG,wBAAwB,CAAA;AAEvC;;;;;;;;GAQG;AACH,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO,KAAK,CAAC,OAAO,CAAC,+BAA+B,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;AACzE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,KAAgC;IACxD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAA;IACvD,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;IAClC,IAAI,SAAS,KAAK,EAAE;QAAE,OAAO,KAAK,CAAA;IAElC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACpC,yEAAyE;IACzE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IAEvB,OAAO,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAW,CAAC,CAAA;AAC7C,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,aAAa,CAAC,KAAgC;IAC5D,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,KAAgB,CAAC,CAAC,CAAC,IAAI,CAAA;AACpD,CAAC;AAED,oEAAoE;AACpE,MAAM,CAAC,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC;IACzD,MAAM;IACN,KAAK;IACL,QAAQ;IACR,YAAY;IACZ,MAAM;IACN,QAAQ;IACR,YAAY;IACZ,MAAM;IACN,UAAU;IACV,QAAQ;IACR,YAAY;IACZ,MAAM;CACP,CAAC,CAAA;AAEF,8EAA8E;AAC9E,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC1B,CAAC"}
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAA"}
@@ -4,7 +4,17 @@
4
4
  *
5
5
  * These marks are view-only. They must never reach serialized HTML: an empty
6
6
  * paragraph is still an empty paragraph, and a `&nbsp;` is still a nbsp.
7
+ *
8
+ * The set lives in plugin state rather than being recomputed by the
9
+ * `decorations` prop. That prop is a *pull* prop -- ProseMirror calls it on
10
+ * every `updateState`, so building the set there rebuilt the whole document's
11
+ * decorations on every keystroke, every arrow key and every click. On
12
+ * Word-pasted content, which is mostly non-breaking spaces, that measured 263 ms
13
+ * per keystroke; mapping the existing set through the transaction instead
14
+ * measures under 2 ms. Only the ranges the transaction actually touched are
15
+ * rebuilt.
7
16
  */
8
17
  import { Plugin } from 'prosemirror-state';
9
- export declare function visualAidsPlugin(): Plugin;
18
+ import { DecorationSet } from 'prosemirror-view';
19
+ export declare function visualAidsPlugin(): Plugin<DecorationSet>;
10
20
  //# sourceMappingURL=visual-aids.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"visual-aids.d.ts","sourceRoot":"","sources":["../src/visual-aids.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,MAAM,EAAa,MAAM,mBAAmB,CAAA;AAsBrD,wBAAgB,gBAAgB,IAAI,MAAM,CAqCzC"}
1
+ {"version":3,"file":"visual-aids.d.ts","sourceRoot":"","sources":["../src/visual-aids.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,MAAM,EAAa,MAAM,mBAAmB,CAAA;AAErD,OAAO,EAAc,aAAa,EAAE,MAAM,kBAAkB,CAAA;AA0G5D,wBAAgB,gBAAgB,IAAI,MAAM,CAAC,aAAa,CAAC,CAwBxD"}
@@ -4,56 +4,144 @@
4
4
  *
5
5
  * These marks are view-only. They must never reach serialized HTML: an empty
6
6
  * paragraph is still an empty paragraph, and a `&nbsp;` is still a nbsp.
7
+ *
8
+ * The set lives in plugin state rather than being recomputed by the
9
+ * `decorations` prop. That prop is a *pull* prop -- ProseMirror calls it on
10
+ * every `updateState`, so building the set there rebuilt the whole document's
11
+ * decorations on every keystroke, every arrow key and every click. On
12
+ * Word-pasted content, which is mostly non-breaking spaces, that measured 263 ms
13
+ * per keystroke; mapping the existing set through the transaction instead
14
+ * measures under 2 ms. Only the ranges the transaction actually touched are
15
+ * rebuilt.
7
16
  */
8
17
  import { Plugin, PluginKey } from 'prosemirror-state';
9
18
  import { Decoration, DecorationSet } from 'prosemirror-view';
10
19
  const key = new PluginKey('openleaf-visual-aids');
11
20
  /**
12
- * True when this position is the last character of its text block.
21
+ * Mark every nbsp in one inline container, except a block-final one.
22
+ *
23
+ * ProseMirror renders a document space at the end of a text block as a
24
+ * non-breaking space itself, so the browser does not collapse it. Decorating
25
+ * that position wrapped the rendering artifact in a span, and the editor then
26
+ * read the nbsp back as the author's own character -- so every space typed at
27
+ * the end of a paragraph became a nbsp in the stored HTML, and the next one
28
+ * after it too. A genuinely stored trailing nbsp therefore goes unmarked. That
29
+ * is the price of the aid never changing the document it describes.
13
30
  *
14
- * ProseMirror renders a document space in that position as a non-breaking space
15
- * itself, so the browser does not collapse it. Decorating it wraps that
16
- * rendering artifact in a span, and the editor then reads the nbsp back as the
17
- * author's own character -- so every space typed at the end of a paragraph
18
- * became a nbsp in the stored HTML, and the next one after it too.
31
+ * The block-final test used to be `doc.resolve(at)` per nbsp, and
32
+ * `Fragment.findIndex` inside `resolve` is a linear scan of the parent's
33
+ * children -- O(nbsp x children) over the document. The traversal already knows
34
+ * the parent's `content.size` and the running offset of each child, so the same
35
+ * question is answered by comparing two integers.
36
+ */
37
+ function markNbsp(parent, contentStart, out) {
38
+ const contentSize = parent.content.size;
39
+ let offset = 0;
40
+ parent.forEach((child) => {
41
+ if (child.isText) {
42
+ const text = child.text ?? '';
43
+ for (let i = 0; i < text.length; i += 1) {
44
+ if (text.charCodeAt(i) !== 0xa0)
45
+ continue;
46
+ // `parentOffset + 1 >= parent.content.size` is the block-final test,
47
+ // and `offset + i` is exactly that parent offset.
48
+ if (offset + i + 1 >= contentSize)
49
+ continue;
50
+ // `contentStart + offset + i` already addresses the character itself: a
51
+ // text node has no opening token to step over, unlike a node. Adding one
52
+ // marked the character after each nbsp, and ran off the end of the node
53
+ // when the nbsp was last -- where the decoration disappeared entirely.
54
+ const at = contentStart + offset + i;
55
+ out.push(Decoration.inline(at, at + 1, { class: 'ol-nbsp' }));
56
+ }
57
+ }
58
+ offset += child.nodeSize;
59
+ });
60
+ }
61
+ /** Every aid for the nodes overlapping `[from, to]`. */
62
+ function decorationsIn(doc, from, to) {
63
+ const out = [];
64
+ doc.nodesBetween(from, to, (node, pos) => {
65
+ // Text is scanned from its parent, which is where the offsets are known.
66
+ if (node.isText)
67
+ return false;
68
+ if (node.isTextblock && node.content.size === 0) {
69
+ out.push(Decoration.node(pos, pos + node.nodeSize, { class: 'ol-empty-block' }));
70
+ }
71
+ if (node.type.name === 'unknown_block' || node.type.name === 'unknown_inline') {
72
+ out.push(Decoration.node(pos, pos + node.nodeSize, { class: 'ol-hidden-structure' }));
73
+ }
74
+ if (node.inlineContent && node.content.size > 0)
75
+ markNbsp(node, pos + 1, out);
76
+ return true;
77
+ });
78
+ return out;
79
+ }
80
+ /**
81
+ * The span of `tr.doc` the transaction touched, or null when it touched nothing.
19
82
  *
20
- * A genuinely stored trailing nbsp therefore goes unmarked. That is the price of
21
- * the aid never changing the document it describes.
83
+ * Each step's map reports positions in the document *that step* produced, which
84
+ * for every step but the last is not `tr.doc`. Rather than slicing the mapping
85
+ * per step -- the O(steps^2) shape this plugin exists to avoid -- the accumulated
86
+ * range is carried forward one step at a time, so the whole scan is O(steps).
22
87
  */
23
- function isBlockFinal(doc, at) {
24
- const $at = doc.resolve(at);
25
- return $at.parentOffset + 1 >= $at.parent.content.size;
88
+ function changedRange(maps) {
89
+ let from = -1;
90
+ let to = -1;
91
+ for (const map of maps) {
92
+ if (from > -1) {
93
+ from = map.map(from, -1);
94
+ to = map.map(to, 1);
95
+ }
96
+ map.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
97
+ from = from < 0 ? newStart : Math.min(from, newStart);
98
+ to = to < 0 ? newEnd : Math.max(to, newEnd);
99
+ });
100
+ }
101
+ return from < 0 ? null : { from, to };
102
+ }
103
+ /**
104
+ * Widen a range to whole top-level blocks.
105
+ *
106
+ * Every aid is contained in one top-level block, so widening to that boundary
107
+ * means a node overlapping the rebuilt range is *entirely* inside it. Without
108
+ * that, a decoration on the half of a paragraph outside the range would survive
109
+ * the removal and be added a second time.
110
+ */
111
+ function widen(doc, from, to) {
112
+ const size = doc.content.size;
113
+ const start = Math.max(0, Math.min(from, size));
114
+ const end = Math.max(start, Math.min(to, size));
115
+ const $start = doc.resolve(start);
116
+ const $end = doc.resolve(end);
117
+ return {
118
+ from: $start.depth > 0 ? $start.before(1) : start,
119
+ to: $end.depth > 0 ? $end.after(1) : end,
120
+ };
26
121
  }
27
122
  export function visualAidsPlugin() {
28
123
  return new Plugin({
29
124
  key,
125
+ state: {
126
+ init(_config, state) {
127
+ return DecorationSet.create(state.doc, decorationsIn(state.doc, 0, state.doc.content.size));
128
+ },
129
+ apply(tr, set) {
130
+ if (!tr.docChanged)
131
+ return set;
132
+ const changed = changedRange(tr.mapping.maps);
133
+ const mapped = set.map(tr.mapping, tr.doc);
134
+ if (!changed)
135
+ return mapped;
136
+ const { from, to } = widen(tr.doc, changed.from, changed.to);
137
+ const stale = mapped.find(from, to);
138
+ const kept = stale.length > 0 ? mapped.remove(stale) : mapped;
139
+ return kept.add(tr.doc, decorationsIn(tr.doc, from, to));
140
+ },
141
+ },
30
142
  props: {
31
143
  decorations(state) {
32
- const decorations = [];
33
- state.doc.descendants((node, pos) => {
34
- if (node.isTextblock && node.content.size === 0) {
35
- decorations.push(Decoration.node(pos, pos + node.nodeSize, { class: 'ol-empty-block' }));
36
- }
37
- if (node.type.name === 'unknown_block' || node.type.name === 'unknown_inline') {
38
- decorations.push(Decoration.node(pos, pos + node.nodeSize, { class: 'ol-hidden-structure' }));
39
- }
40
- if (node.isText) {
41
- const text = node.text ?? '';
42
- for (let i = 0; i < text.length; i += 1) {
43
- if (text.charCodeAt(i) !== 0xa0)
44
- continue;
45
- // `pos` already addresses the first character: a text node has no
46
- // opening token to step over, unlike a node. Adding one marked the
47
- // character after each nbsp, and ran off the end of the node when
48
- // the nbsp was last -- where the decoration disappeared entirely.
49
- const at = pos + i;
50
- if (isBlockFinal(state.doc, at))
51
- continue;
52
- decorations.push(Decoration.inline(at, at + 1, { class: 'ol-nbsp' }));
53
- }
54
- }
55
- });
56
- return DecorationSet.create(state.doc, decorations);
144
+ return key.getState(state);
57
145
  },
58
146
  },
59
147
  });
@@ -1 +1 @@
1
- {"version":3,"file":"visual-aids.js","sourceRoot":"","sources":["../src/visual-aids.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAE5D,MAAM,GAAG,GAAG,IAAI,SAAS,CAAC,sBAAsB,CAAC,CAAA;AAEjD;;;;;;;;;;;GAWG;AACH,SAAS,YAAY,CAAC,GAAW,EAAE,EAAU;IAC3C,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAC3B,OAAO,GAAG,CAAC,YAAY,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAA;AACxD,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,IAAI,MAAM,CAAC;QAChB,GAAG;QACH,KAAK,EAAE;YACL,WAAW,CAAC,KAAK;gBACf,MAAM,WAAW,GAAiB,EAAE,CAAA;gBACpC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;oBAClC,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;wBAChD,WAAW,CAAC,IAAI,CACd,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CACvE,CAAA;oBACH,CAAC;oBACD,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;wBAC9E,WAAW,CAAC,IAAI,CACd,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAC5E,CAAA;oBACH,CAAC;oBACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;wBAChB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAA;wBAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;4BACxC,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI;gCAAE,SAAQ;4BACzC,kEAAkE;4BAClE,mEAAmE;4BACnE,kEAAkE;4BAClE,kEAAkE;4BAClE,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC,CAAA;4BAClB,IAAI,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC;gCAAE,SAAQ;4BACzC,WAAW,CAAC,IAAI,CACd,UAAU,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CACpD,CAAA;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC,CAAC,CAAA;gBACF,OAAO,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,WAAW,CAAC,CAAA;YACrD,CAAC;SACF;KACF,CAAC,CAAA;AACJ,CAAC"}
1
+ {"version":3,"file":"visual-aids.js","sourceRoot":"","sources":["../src/visual-aids.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openleaf-editor/core",
3
- "version": "0.1.0-beta.2",
3
+ "version": "0.1.0-beta.3",
4
4
  "description": "OpenLeaf editing core: ProseMirror schema, HTML I/O, and the content-preservation layer. No UI, no framework dependencies.",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
@@ -16,12 +16,19 @@
16
16
  "url": "https://github.com/PeytonNowlin/openleaf/issues"
17
17
  },
18
18
  "type": "module",
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
19
22
  "main": "./dist/index.js",
20
23
  "types": "./dist/index.d.ts",
21
24
  "exports": {
22
25
  ".": {
23
26
  "types": "./dist/index.d.ts",
24
27
  "import": "./dist/index.js"
28
+ },
29
+ "./testing": {
30
+ "types": "./dist/testing.d.ts",
31
+ "import": "./dist/testing.js"
25
32
  }
26
33
  },
27
34
  "files": [
@@ -30,6 +37,9 @@
30
37
  "sideEffects": false,
31
38
  "dependencies": {
32
39
  "orderedmap": "^2.1.1",
40
+ "@openleaf-editor/content-policy": "0.1.0-beta.3"
41
+ },
42
+ "peerDependencies": {
33
43
  "prosemirror-commands": "^1.6.2",
34
44
  "prosemirror-history": "^1.4.1",
35
45
  "prosemirror-model": "^1.24.1",
@@ -38,6 +48,10 @@
38
48
  "prosemirror-transform": "^1.10.2",
39
49
  "prosemirror-view": "^1.37.0"
40
50
  },
51
+ "devDependencies": {
52
+ "prosemirror-tables": "^1.6.4",
53
+ "prosemirror-transform": "^1.10.2"
54
+ },
41
55
  "scripts": {
42
56
  "build": "tsc -p tsconfig.json"
43
57
  }