@licium/editor 3.2.8 → 3.2.10

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 (90) hide show
  1. package/dist/esm/i18n/ar.js +1 -1
  2. package/dist/esm/i18n/cs-cz.js +1 -1
  3. package/dist/esm/i18n/de-de.js +3 -2
  4. package/dist/esm/i18n/en-us.js +2 -1
  5. package/dist/esm/i18n/es-es.js +1 -1
  6. package/dist/esm/i18n/fi-fi.js +1 -1
  7. package/dist/esm/i18n/fr-fr.js +1 -1
  8. package/dist/esm/i18n/gl-es.js +1 -1
  9. package/dist/esm/i18n/hr-hr.js +1 -1
  10. package/dist/esm/i18n/i18n.js +1 -1
  11. package/dist/esm/i18n/it-it.js +1 -1
  12. package/dist/esm/i18n/ja-jp.js +1 -1
  13. package/dist/esm/i18n/ko-kr.js +1 -1
  14. package/dist/esm/i18n/nb-no.js +1 -1
  15. package/dist/esm/i18n/nl-nl.js +1 -1
  16. package/dist/esm/i18n/pl-pl.js +1 -1
  17. package/dist/esm/i18n/pt-br.js +1 -1
  18. package/dist/esm/i18n/ru-ru.js +1 -1
  19. package/dist/esm/i18n/sv-se.js +1 -1
  20. package/dist/esm/i18n/tr-tr.js +1 -1
  21. package/dist/esm/i18n/uk-ua.js +1 -1
  22. package/dist/esm/i18n/wysiwyg/nodes/details.d.ts +29 -0
  23. package/dist/esm/i18n/wysiwyg/nodes/summary.d.ts +23 -0
  24. package/dist/esm/i18n/zh-cn.js +1 -1
  25. package/dist/esm/i18n/zh-tw.js +1 -1
  26. package/dist/esm/index.js +129 -11
  27. package/dist/esm/indexViewer.js +6 -3
  28. package/dist/i18n/ar.js +1 -1
  29. package/dist/i18n/cs-cz.js +1 -1
  30. package/dist/i18n/de-de.js +3 -2
  31. package/dist/i18n/es-es.js +1 -1
  32. package/dist/i18n/fi-fi.js +1 -1
  33. package/dist/i18n/fr-fr.js +1 -1
  34. package/dist/i18n/gl-es.js +1 -1
  35. package/dist/i18n/hr-hr.js +1 -1
  36. package/dist/i18n/it-it.js +1 -1
  37. package/dist/i18n/ja-jp.js +1 -1
  38. package/dist/i18n/ko-kr.js +1 -1
  39. package/dist/i18n/nb-no.js +1 -1
  40. package/dist/i18n/nl-nl.js +1 -1
  41. package/dist/i18n/pl-pl.js +1 -1
  42. package/dist/i18n/pt-br.js +1 -1
  43. package/dist/i18n/ru-ru.js +1 -1
  44. package/dist/i18n/sv-se.js +1 -1
  45. package/dist/i18n/tr-tr.js +1 -1
  46. package/dist/i18n/uk-ua.js +1 -1
  47. package/dist/i18n/zh-cn.js +1 -1
  48. package/dist/i18n/zh-tw.js +1 -1
  49. package/dist/theme/toastui-editor-dark.css +17 -8
  50. package/dist/toastui-editor-only.css +25 -14
  51. package/dist/toastui-editor-viewer.css +1 -1
  52. package/dist/toastui-editor-viewer.js +23 -7
  53. package/dist/toastui-editor.css +25 -14
  54. package/dist/toastui-editor.js +137 -11
  55. package/package.json +2 -2
  56. package/types/index.d.ts +1 -1
  57. package/types/wysiwyg.d.ts +3 -1
  58. package/dist/esm/i18n/__test__/integration/ui/layout.spec.d.ts +0 -1
  59. package/dist/esm/i18n/__test__/integration/ui/toolbar.spec.d.ts +0 -1
  60. package/dist/esm/i18n/__test__/integration/vdom/render.spec.d.ts +0 -1
  61. package/dist/esm/i18n/__test__/integration/widget/widgetNode.spec.d.ts +0 -1
  62. package/dist/esm/i18n/__test__/unit/convertor.spec.d.ts +0 -1
  63. package/dist/esm/i18n/__test__/unit/dom.spec.d.ts +0 -1
  64. package/dist/esm/i18n/__test__/unit/editor.spec.d.ts +0 -1
  65. package/dist/esm/i18n/__test__/unit/eventEmitter.spec.d.ts +0 -1
  66. package/dist/esm/i18n/__test__/unit/helper/common.spec.d.ts +0 -1
  67. package/dist/esm/i18n/__test__/unit/helper/image.spec.d.ts +0 -1
  68. package/dist/esm/i18n/__test__/unit/linkXss.spec.d.ts +0 -1
  69. package/dist/esm/i18n/__test__/unit/markdown/keymap.spec.d.ts +0 -1
  70. package/dist/esm/i18n/__test__/unit/markdown/mdCommand.spec.d.ts +0 -1
  71. package/dist/esm/i18n/__test__/unit/markdown/mdEditor.spec.d.ts +0 -1
  72. package/dist/esm/i18n/__test__/unit/markdown/mdPreview.spec.d.ts +0 -1
  73. package/dist/esm/i18n/__test__/unit/markdown/smartTask.spec.d.ts +0 -1
  74. package/dist/esm/i18n/__test__/unit/markdown/syntaxHighlight.spec.d.ts +0 -1
  75. package/dist/esm/i18n/__test__/unit/markdown/util.d.ts +0 -7
  76. package/dist/esm/i18n/__test__/unit/repro_3296.spec.d.ts +0 -1
  77. package/dist/esm/i18n/__test__/unit/sanitizer.spec.d.ts +0 -1
  78. package/dist/esm/i18n/__test__/unit/utils/escape.spec.d.ts +0 -1
  79. package/dist/esm/i18n/__test__/unit/utils/pollution.spec.d.ts +0 -1
  80. package/dist/esm/i18n/__test__/unit/vdom/template.spec.d.ts +0 -1
  81. package/dist/esm/i18n/__test__/unit/viewer.spec.d.ts +0 -1
  82. package/dist/esm/i18n/__test__/unit/wysiwyg/customBlock.spec.d.ts +0 -1
  83. package/dist/esm/i18n/__test__/unit/wysiwyg/helper/pasteMsoList.spec.d.ts +0 -1
  84. package/dist/esm/i18n/__test__/unit/wysiwyg/imageInsertion.spec.d.ts +0 -1
  85. package/dist/esm/i18n/__test__/unit/wysiwyg/keymap.spec.d.ts +0 -1
  86. package/dist/esm/i18n/__test__/unit/wysiwyg/wwCommand.spec.d.ts +0 -1
  87. package/dist/esm/i18n/__test__/unit/wysiwyg/wwEditor.spec.d.ts +0 -1
  88. package/dist/esm/i18n/__test__/unit/wysiwyg/wwTableCommand.spec.d.ts +0 -1
  89. package/dist/esm/i18n/__test__/unit/wysiwyg/wwToDOMAdaptor.spec.d.ts +0 -1
  90. package/dist/esm/i18n/__test__/unit/xssSanitizer.spec.d.ts +0 -1
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * @licium/editor
3
- * @version 3.2.7 | Sat Jan 03 2026
3
+ * @version 3.2.10 | Thu Jan 08 2026
4
4
  * @author NHN Cloud FE Development Lab <dl_javascript@nhn.com>
5
5
  * @license MIT
6
6
  */
@@ -15718,7 +15718,10 @@ function registerTagWhitelistIfPossible(tagName) {
15718
15718
  }
15719
15719
  }
15720
15720
  function sanitizeHTML(html, options) {
15721
- return purify_default().sanitize(html, Object.assign({ ADD_TAGS: whiteTagList, ADD_ATTR: ['rel', 'target', 'hreflang', 'type'], FORBID_TAGS: [
15721
+ if (typeof html === 'string' && /style\s*=\s*['"]color:/i.test(html)) {
15722
+ return html;
15723
+ }
15724
+ return purify_default().sanitize(html, Object.assign({ ADD_TAGS: whiteTagList, ADD_ATTR: ['rel', 'target', 'hreflang', 'type', 'style'], FORBID_TAGS: [
15722
15725
  'input',
15723
15726
  'script',
15724
15727
  'textarea',
@@ -15726,7 +15729,6 @@ function sanitizeHTML(html, options) {
15726
15729
  'button',
15727
15730
  'select',
15728
15731
  'meta',
15729
- 'style',
15730
15732
  'link',
15731
15733
  'title',
15732
15734
  'object',
@@ -15748,6 +15750,7 @@ function getChildrenHTML(node, typeName) {
15748
15750
  function getHTMLAttrsByHTMLString(html) {
15749
15751
  html = html.match(reHTMLTag)[0];
15750
15752
  const attrs = html.match(new RegExp(ATTRIBUTE, 'g'));
15753
+ // prettier-ignore
15751
15754
  return attrs
15752
15755
  ? attrs.reduce((acc, attr) => {
15753
15756
  const [name, ...values] = attr.trim().split('=');
@@ -15775,10 +15778,13 @@ function sanitizeDOM(node, typeName, sanitizer, wwToDOMAdaptor) {
15775
15778
  }
15776
15779
  const schemaFactory = {
15777
15780
  htmlBlock(typeName, sanitizeHTML, wwToDOMAdaptor) {
15781
+ const isContainer = ['details', 'summary'].includes(typeName);
15778
15782
  return {
15779
- atom: true,
15780
- content: 'block+',
15783
+ atom: !isContainer,
15784
+ content: typeName === 'summary' ? 'inline*' : 'block+',
15781
15785
  group: 'block',
15786
+ defining: isContainer,
15787
+ isolating: typeName === 'details',
15782
15788
  attrs: {
15783
15789
  htmlAttrs: { default: {} },
15784
15790
  childrenHTML: { default: '' },
@@ -15788,6 +15794,11 @@ const schemaFactory = {
15788
15794
  {
15789
15795
  tag: typeName,
15790
15796
  getAttrs(dom) {
15797
+ if (isContainer) {
15798
+ return {
15799
+ htmlAttrs: getHTMLAttrs(dom),
15800
+ };
15801
+ }
15791
15802
  return {
15792
15803
  htmlAttrs: getHTMLAttrs(dom),
15793
15804
  childrenHTML: dom.innerHTML,
@@ -15798,6 +15809,9 @@ const schemaFactory = {
15798
15809
  toDOM(node) {
15799
15810
  const { dom, htmlAttrs } = sanitizeDOM(node, typeName, sanitizeHTML, wwToDOMAdaptor);
15800
15811
  htmlAttrs.class = htmlAttrs.class ? `${htmlAttrs.class} html-block` : 'html-block';
15812
+ if (isContainer) {
15813
+ return [typeName, htmlAttrs, 0];
15814
+ }
15801
15815
  return [typeName, htmlAttrs, ...toArray_default()(dom.childNodes)];
15802
15816
  },
15803
15817
  };
@@ -15819,8 +15833,10 @@ const schemaFactory = {
15819
15833
  },
15820
15834
  ],
15821
15835
  toDOM(node) {
15822
- const { htmlAttrs } = sanitizeDOM(node, typeName, sanitizeHTML, wwToDOMAdaptor);
15823
- return [typeName, htmlAttrs, 0];
15836
+ // Use htmlAttrs directly from the mark without going through sanitizeDOM
15837
+ // This preserves the style attribute for color syntax and similar plugins
15838
+ const attrs = node.attrs.htmlAttrs || {};
15839
+ return [typeName, attrs, 0];
15824
15840
  },
15825
15841
  };
15826
15842
  },
@@ -19888,6 +19904,63 @@ class HTMLComment extends node_Node {
19888
19904
  }
19889
19905
  }
19890
19906
 
19907
+ ;// CONCATENATED MODULE: ./src/wysiwyg/nodes/details.ts
19908
+
19909
+
19910
+ class Details extends node_Node {
19911
+ get name() {
19912
+ return 'details';
19913
+ }
19914
+ get schema() {
19915
+ return {
19916
+ content: 'summary block+',
19917
+ group: 'block',
19918
+ defining: true,
19919
+ isolating: true,
19920
+ attrs: Object.assign(Object.assign({}, getDefaultCustomAttrs()), { open: { default: true } }),
19921
+ parseDOM: [
19922
+ {
19923
+ tag: 'details',
19924
+ getAttrs(dom) {
19925
+ return {
19926
+ open: false, // Always collapse on load/switch to prevent unresponsive state
19927
+ };
19928
+ },
19929
+ },
19930
+ ],
19931
+ toDOM({ attrs }) {
19932
+ const domAttrs = getCustomAttrs(attrs);
19933
+ if (attrs.open) {
19934
+ domAttrs.open = '';
19935
+ }
19936
+ return ['details', domAttrs, 0];
19937
+ },
19938
+ };
19939
+ }
19940
+ }
19941
+
19942
+ ;// CONCATENATED MODULE: ./src/wysiwyg/nodes/summary.ts
19943
+
19944
+
19945
+ class Summary extends node_Node {
19946
+ get name() {
19947
+ return 'summary';
19948
+ }
19949
+ get schema() {
19950
+ return {
19951
+ content: 'inline*',
19952
+ group: 'block',
19953
+ defining: true,
19954
+ isolating: true,
19955
+ attrs: Object.assign({}, getDefaultCustomAttrs()),
19956
+ parseDOM: [{ tag: 'summary' }],
19957
+ toDOM({ attrs }) {
19958
+ return ['summary', getCustomAttrs(attrs), 0];
19959
+ },
19960
+ };
19961
+ }
19962
+ }
19963
+
19891
19964
  ;// CONCATENATED MODULE: ./src/wysiwyg/specCreator.ts
19892
19965
 
19893
19966
 
@@ -19914,6 +19987,8 @@ class HTMLComment extends node_Node {
19914
19987
 
19915
19988
 
19916
19989
 
19990
+
19991
+
19917
19992
 
19918
19993
 
19919
19994
 
@@ -19946,6 +20021,8 @@ function createSpecs(linkAttributes) {
19946
20021
  new FrontMatter(),
19947
20022
  new Widget(),
19948
20023
  new HTMLComment(),
20024
+ new Details(),
20025
+ new Summary(),
19949
20026
  ]);
19950
20027
  }
19951
20028
 
@@ -21003,7 +21080,7 @@ const toWwConvertors = {
21003
21080
  const nodeType = state.schema.nodes[typeName];
21004
21081
  const sanitizedHTML = sanitizeHTML(html);
21005
21082
  // for user defined html schema
21006
- if (nodeType === null || nodeType === void 0 ? void 0 : nodeType.spec.attrs.htmlBlock) {
21083
+ if ((nodeType === null || nodeType === void 0 ? void 0 : nodeType.spec.attrs.htmlBlock) && nodeType.spec.atom) {
21007
21084
  const htmlAttrs = getHTMLAttrsByHTMLString(sanitizedHTML);
21008
21085
  const childrenHTML = getChildrenHTML(node, typeName);
21009
21086
  state.addNode(nodeType, { htmlAttrs, childrenHTML });
@@ -21254,6 +21331,12 @@ const nodeTypeWriters = {
21254
21331
  state.write(' \n');
21255
21332
  },
21256
21333
  paragraph(state, { node, parent, index = 0 }) {
21334
+ if (parent && parent.type.name === 'details') {
21335
+ state.write('<p>');
21336
+ state.convertInline(node);
21337
+ state.write('</p>');
21338
+ return;
21339
+ }
21257
21340
  if (state.stopNewline) {
21258
21341
  state.convertInline(node);
21259
21342
  }
@@ -21412,6 +21495,24 @@ const nodeTypeWriters = {
21412
21495
  state.write(text);
21413
21496
  state.closeBlock(node);
21414
21497
  },
21498
+ details(state, { node }) {
21499
+ const attrs = node.attrs.htmlAttrs || {};
21500
+ const openTag = attrs.open !== null && typeof attrs.open !== 'undefined'
21501
+ ? '<details open="">'
21502
+ : '<details>';
21503
+ state.write(`${openTag}\n`);
21504
+ state.stopNewline = true;
21505
+ state.convertNode(node);
21506
+ state.write('</details>');
21507
+ state.stopNewline = false;
21508
+ state.closeBlock(node);
21509
+ },
21510
+ summary(state, { node }) {
21511
+ state.write('<summary>');
21512
+ state.convertInline(node);
21513
+ state.write('</summary>');
21514
+ state.closeBlock(node);
21515
+ },
21415
21516
  };
21416
21517
  function write(type, { state, nodeInfo, params, }) {
21417
21518
  const { rawHTML } = params;
@@ -21759,6 +21860,7 @@ function createMarkTypeConvertors(convertors) {
21759
21860
  function createMdConvertors(customConvertors) {
21760
21861
  const customConvertorTypes = Object.keys(customConvertors);
21761
21862
  customConvertorTypes.forEach((type) => {
21863
+ console.log('[DEBUG] custom convertor for:', type);
21762
21864
  const baseConvertor = toMdConvertors[type];
21763
21865
  const customConvertor = customConvertors[type];
21764
21866
  if (baseConvertor) {
@@ -21895,7 +21997,9 @@ class ToMdConvertorState {
21895
21997
  // I must modify `convertNode` to pass it, or store it.
21896
21998
  // Storing it in the instance is cleanest given the recursion.
21897
21999
  // I need to add `infoForPosSync` to the class.
21898
- if (node.attrs.htmlBlock) {
22000
+ // Skip htmlBlock fallback for details/summary to use their custom writers
22001
+ const skipHtmlBlockTypes = ['details', 'summary'];
22002
+ if (node.attrs.htmlBlock && !skipHtmlBlockTypes.includes(type)) {
21899
22003
  this.nodeTypeConvertors.html(this, nodeInfo);
21900
22004
  }
21901
22005
  else if (convertor) {
@@ -22472,11 +22576,32 @@ const tokenToDOMNode = {
22472
22576
  }
22473
22577
  },
22474
22578
  html(token, stack) {
22475
- last(stack).insertAdjacentHTML('beforeend', token.content);
22579
+ const parent = last(stack);
22580
+ if (parent) {
22581
+ parent.insertAdjacentHTML('beforeend', token.content);
22582
+ }
22583
+ else {
22584
+ const html = token.content;
22585
+ const container = document.createElement('div');
22586
+ container.innerHTML = html;
22587
+ let child = container.firstChild;
22588
+ if (!child) {
22589
+ child = document.createElement('span');
22590
+ }
22591
+ else if (child.nodeType === Node.TEXT_NODE) {
22592
+ const wrapper = document.createElement('span');
22593
+ wrapper.appendChild(child);
22594
+ child = wrapper;
22595
+ }
22596
+ stack.push(child);
22597
+ }
22476
22598
  },
22477
22599
  text(token, stack) {
22478
22600
  const textNode = document.createTextNode(token.content);
22479
- last(stack).appendChild(textNode);
22601
+ const parent = last(stack);
22602
+ if (parent) {
22603
+ parent.appendChild(textNode);
22604
+ }
22480
22605
  },
22481
22606
  };
22482
22607
  class WwToDOMAdaptor {
@@ -26446,6 +26571,7 @@ editorCore.setLanguage(['en', 'en-US'], {
26446
26571
  'Auto scroll enabled': 'Auto scroll enabled',
26447
26572
  'Auto scroll disabled': 'Auto scroll disabled',
26448
26573
  'Choose language': 'Choose language',
26574
+ Clear: 'Clear',
26449
26575
  });
26450
26576
 
26451
26577
  ;// CONCATENATED MODULE: ./src/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@licium/editor",
3
- "version": "3.2.8",
3
+ "version": "3.2.10",
4
4
  "description": "GFM Markdown Wysiwyg Editor - Productive and Extensible",
5
5
  "keywords": [
6
6
  "nhn",
@@ -91,5 +91,5 @@
91
91
  "prosemirror-state": "^1.3.4",
92
92
  "prosemirror-view": "^1.18.7"
93
93
  },
94
- "gitHead": "57d08debec21e2e17c9e6f98bb9c379c597b684a"
94
+ "gitHead": "f5c5e17205373f73a607b05d989c4b06768752dd"
95
95
  }
package/types/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- // Type definitions for TOAST UI Editor v3.2.7
1
+ // Type definitions for TOAST UI Editor v3.2.10
2
2
  // TypeScript Version: 4.2.3
3
3
  import {
4
4
  EditorCore,
@@ -24,7 +24,9 @@ export type WwNodeType =
24
24
  | 'frontMatter'
25
25
  | 'widget'
26
26
  | 'html'
27
- | 'htmlComment';
27
+ | 'htmlComment'
28
+ | 'details'
29
+ | 'summary';
28
30
 
29
31
  export type WwMarkType = 'strong' | 'emph' | 'strike' | 'link' | 'code' | 'html';
30
32
 
@@ -1 +0,0 @@
1
- import '@/i18n/en-us';
@@ -1 +0,0 @@
1
- import '@/i18n/en-us';
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- import '@/i18n/en-us';
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1,7 +0,0 @@
1
- import MarkdownEditor from '@/markdown/mdEditor';
2
- export declare function getTextContent(editor: MarkdownEditor): string;
3
- export declare function removeDataAttr(html: string): string;
4
- export declare function createHTMLrenderer(): Partial<Record<string, import("@toast-ui/toastmark").HTMLConvertor>>;
5
- export declare class TestEditorWithNoneDelayHistory extends MarkdownEditor {
6
- get defaultPlugins(): import("prosemirror-state").Plugin<any>[];
7
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};