@kedataindo/docflow-plugins 0.0.83 → 0.0.84

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.
package/dist/index.cjs CHANGED
@@ -625,6 +625,13 @@ var footnotePlugin = (0, import_docflow_core12.definePlugin)({
625
625
  // src/toc.ts
626
626
  var import_core4 = require("@tiptap/core");
627
627
  var import_docflow_core13 = require("@kedataindo/docflow-core");
628
+ var TOC_EXCLUDED_HEADING_NORMS = ["DAFTAR ISI"];
629
+ function normHeadingText(text) {
630
+ return text.toUpperCase().replace(/[—–]/g, "-").replace(/[^A-Z0-9]+/g, " ").trim();
631
+ }
632
+ function withoutExcludedHeadings(headings) {
633
+ return headings.filter((h) => !TOC_EXCLUDED_HEADING_NORMS.includes(normHeadingText(h.text)));
634
+ }
628
635
  function collectHeadingsFromDoc(doc) {
629
636
  const headings = [];
630
637
  doc.descendants((node, pos) => {
@@ -641,6 +648,9 @@ function collectHeadingsFromDoc(doc) {
641
648
  function collectHeadings(editor) {
642
649
  return collectHeadingsFromDoc(editor.state.doc);
643
650
  }
651
+ function collectTocHeadings(doc) {
652
+ return withoutExcludedHeadings(collectHeadingsFromDoc(doc));
653
+ }
644
654
  function createPageResolver(editor) {
645
655
  let breakers = [];
646
656
  try {
@@ -681,7 +691,7 @@ function buildTocEntryNodes(schema, headings, pageFor) {
681
691
  });
682
692
  }
683
693
  function buildTocContentJSON(editor) {
684
- const headings = collectHeadings(editor);
694
+ const headings = collectTocHeadings(editor.state.doc);
685
695
  if (headings.length === 0) {
686
696
  return [{ type: "tocEntry", attrs: { level: 1, pos: 0 } }];
687
697
  }
@@ -710,7 +720,7 @@ function applyTocRegeneration(editor, tr) {
710
720
  return true;
711
721
  });
712
722
  if (targets.length === 0) return false;
713
- const entries = buildTocEntryNodes(editor.schema, collectHeadingsFromDoc(tr.doc), createPageResolver(editor));
723
+ const entries = buildTocEntryNodes(editor.schema, collectTocHeadings(tr.doc), createPageResolver(editor));
714
724
  for (const target of targets.reverse()) {
715
725
  tr.replaceWith(target.pos, target.pos + target.nodeSize, tocType.create(null, entries));
716
726
  }
@@ -855,10 +865,21 @@ var TocNode = import_core4.Node.create({
855
865
  var tocPlugin = (0, import_docflow_core13.definePlugin)({
856
866
  id: "toc",
857
867
  tiptapExtensions: [TocPageNumNode, TocEntryNode, TocNode, TocCommandsExtension],
868
+ // `menu: 'insert'` puts it in the toolbar's "+" (Sisipkan) dropdown: the
869
+ // action is plugin-own (not one of the built-in insert actions), so it has to
870
+ // opt in explicitly. `generateToc` = regenerate, else insert → idempotent.
871
+ toolbar: [
872
+ { id: "insert-toc", label: "Generate Daftar Isi", action: "generateToc", iconComponent: "List", menu: "insert" }
873
+ ],
858
874
  slashCommands: [{ name: "Table of contents", description: "Daftar isi", command: "insertToc" }],
859
875
  commands: {
860
876
  insertToc: (editor) => editor.commands.insertToc(),
861
- refreshToc: (editor) => regenerateToc(editor)
877
+ refreshToc: (editor) => regenerateToc(editor),
878
+ // Toolbar-facing "Generate Daftar Isi": regenerate every existing toc, or
879
+ // insert a prefilled one when the document has none. Implemented as a
880
+ // plugin action (like refreshToc) so the manual `refreshToc` dispatch
881
+ // doesn't nest inside a tiptap command transaction.
882
+ generateToc: (editor) => regenerateToc(editor) || editor.commands.insertToc()
862
883
  }
863
884
  });
864
885
 
package/dist/index.js CHANGED
@@ -532,6 +532,13 @@ var footnotePlugin = definePlugin12({
532
532
  // src/toc.ts
533
533
  import { Extension, Node as Node4, mergeAttributes as mergeAttributes4 } from "@tiptap/core";
534
534
  import { definePlugin as definePlugin13 } from "@kedataindo/docflow-core";
535
+ var TOC_EXCLUDED_HEADING_NORMS = ["DAFTAR ISI"];
536
+ function normHeadingText(text) {
537
+ return text.toUpperCase().replace(/[—–]/g, "-").replace(/[^A-Z0-9]+/g, " ").trim();
538
+ }
539
+ function withoutExcludedHeadings(headings) {
540
+ return headings.filter((h) => !TOC_EXCLUDED_HEADING_NORMS.includes(normHeadingText(h.text)));
541
+ }
535
542
  function collectHeadingsFromDoc(doc) {
536
543
  const headings = [];
537
544
  doc.descendants((node, pos) => {
@@ -548,6 +555,9 @@ function collectHeadingsFromDoc(doc) {
548
555
  function collectHeadings(editor) {
549
556
  return collectHeadingsFromDoc(editor.state.doc);
550
557
  }
558
+ function collectTocHeadings(doc) {
559
+ return withoutExcludedHeadings(collectHeadingsFromDoc(doc));
560
+ }
551
561
  function createPageResolver(editor) {
552
562
  let breakers = [];
553
563
  try {
@@ -588,7 +598,7 @@ function buildTocEntryNodes(schema, headings, pageFor) {
588
598
  });
589
599
  }
590
600
  function buildTocContentJSON(editor) {
591
- const headings = collectHeadings(editor);
601
+ const headings = collectTocHeadings(editor.state.doc);
592
602
  if (headings.length === 0) {
593
603
  return [{ type: "tocEntry", attrs: { level: 1, pos: 0 } }];
594
604
  }
@@ -617,7 +627,7 @@ function applyTocRegeneration(editor, tr) {
617
627
  return true;
618
628
  });
619
629
  if (targets.length === 0) return false;
620
- const entries = buildTocEntryNodes(editor.schema, collectHeadingsFromDoc(tr.doc), createPageResolver(editor));
630
+ const entries = buildTocEntryNodes(editor.schema, collectTocHeadings(tr.doc), createPageResolver(editor));
621
631
  for (const target of targets.reverse()) {
622
632
  tr.replaceWith(target.pos, target.pos + target.nodeSize, tocType.create(null, entries));
623
633
  }
@@ -762,10 +772,21 @@ var TocNode = Node4.create({
762
772
  var tocPlugin = definePlugin13({
763
773
  id: "toc",
764
774
  tiptapExtensions: [TocPageNumNode, TocEntryNode, TocNode, TocCommandsExtension],
775
+ // `menu: 'insert'` puts it in the toolbar's "+" (Sisipkan) dropdown: the
776
+ // action is plugin-own (not one of the built-in insert actions), so it has to
777
+ // opt in explicitly. `generateToc` = regenerate, else insert → idempotent.
778
+ toolbar: [
779
+ { id: "insert-toc", label: "Generate Daftar Isi", action: "generateToc", iconComponent: "List", menu: "insert" }
780
+ ],
765
781
  slashCommands: [{ name: "Table of contents", description: "Daftar isi", command: "insertToc" }],
766
782
  commands: {
767
783
  insertToc: (editor) => editor.commands.insertToc(),
768
- refreshToc: (editor) => regenerateToc(editor)
784
+ refreshToc: (editor) => regenerateToc(editor),
785
+ // Toolbar-facing "Generate Daftar Isi": regenerate every existing toc, or
786
+ // insert a prefilled one when the document has none. Implemented as a
787
+ // plugin action (like refreshToc) so the manual `refreshToc` dispatch
788
+ // doesn't nest inside a tiptap command transaction.
789
+ generateToc: (editor) => regenerateToc(editor) || editor.commands.insertToc()
769
790
  }
770
791
  });
771
792
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kedataindo/docflow-plugins",
3
3
  "license": "UNLICENSED",
4
- "version": "0.0.83",
4
+ "version": "0.0.84",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
@@ -31,7 +31,7 @@
31
31
  "@tiptap/pm": "^2.11.0",
32
32
  "citeproc": "^2.4.63",
33
33
  "tiptap-markdown": "0.8.10",
34
- "@kedataindo/docflow-core": "0.0.81"
34
+ "@kedataindo/docflow-core": "0.0.82"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@tiptap/core": "^2.11.0",