@witchcraft/editor 0.0.6 → 0.0.8

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 (59) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/CodeBlockThemePicker.vue +0 -1
  3. package/dist/runtime/components/Commands.vue +1 -1
  4. package/dist/runtime/components/Editor.vue +1 -2
  5. package/dist/runtime/composables/useEditor.d.ts +1 -1
  6. package/dist/runtime/demo/App.vue +0 -1
  7. package/dist/runtime/pm/features/Blockquote/Blockquote.d.ts +1 -1
  8. package/dist/runtime/pm/features/Blocks/components/DragTreeHandle.d.vue.ts +26 -0
  9. package/dist/runtime/pm/features/Blocks/components/DragTreeHandle.vue +7 -0
  10. package/dist/runtime/pm/features/Blocks/components/DragTreeHandle.vue.d.ts +26 -0
  11. package/dist/runtime/pm/features/Blocks/components/ItemMenu.vue +1 -2
  12. package/dist/runtime/pm/features/Blocks/components/ItemNodeView.vue +0 -1
  13. package/dist/runtime/pm/features/Blocks/components/defaultItemMenu.d.ts +2 -2
  14. package/dist/runtime/pm/features/Blocks/composables/useNodeStates.d.ts +2 -2
  15. package/dist/runtime/pm/features/CodeBlock/CodeBlock.d.ts +1 -1
  16. package/dist/runtime/pm/features/CodeBlock/components/CodeBlockView.vue +0 -1
  17. package/dist/runtime/pm/features/CodeBlock/composables/useHighlightJsTheme.d.ts +3 -3
  18. package/dist/runtime/pm/features/CommandsMenus/components/CommandBar.vue +1 -1
  19. package/dist/runtime/pm/features/CommandsMenus/components/CommandBarItem.vue +1 -1
  20. package/dist/runtime/pm/features/CommandsMenus/components/CommandMenuGroup.vue +0 -1
  21. package/dist/runtime/pm/features/CommandsMenus/icons/HighlightIcon.vue +1 -1
  22. package/dist/runtime/pm/features/EmbeddedDocument/components/EmbeddedDocumentPicker.vue +0 -1
  23. package/dist/runtime/pm/features/EmbeddedDocument/components/EmbeddedNodeView.vue +0 -1
  24. package/dist/runtime/pm/features/FileLoader/components/FileLoaderNodeView.vue +0 -1
  25. package/dist/runtime/pm/features/HardBreak/HardBreak.d.ts +1 -1
  26. package/dist/runtime/pm/features/Link/components/BubbleMenuExternalLink.vue +1 -1
  27. package/dist/runtime/pm/features/Link/components/BubbleMenuInternalLink.vue +1 -1
  28. package/dist/runtime/pm/features/Link/components/BubbleMenuLink.vue +1 -1
  29. package/dist/runtime/pm/features/Menus/components/MarkMenuManager.vue +1 -1
  30. package/dist/runtime/pm/features/Tables/index.d.ts +5 -5
  31. package/dist/runtime/pm/generator.d.ts +82 -0
  32. package/dist/runtime/pm/generator.js +205 -0
  33. package/dist/runtime/pm/testSchema.d.ts +1 -1
  34. package/dist/runtime/pm/utils/generateRandomDoc.d.ts +23 -0
  35. package/dist/runtime/pm/utils/generateRandomDoc.js +83 -0
  36. package/dist/runtime/pm/utils/generateRandomTree.d.ts +50 -0
  37. package/dist/runtime/pm/utils/generateRandomTree.js +38 -0
  38. package/package.json +7 -5
  39. package/src/module.ts +1 -0
  40. package/src/runtime/components/CodeBlockThemePicker.vue +0 -1
  41. package/src/runtime/components/Editor.vue +0 -1
  42. package/src/runtime/demo/App.vue +0 -1
  43. package/src/runtime/pm/commands/changeAttrs.ts +1 -1
  44. package/src/runtime/pm/features/Blocks/Item.ts +1 -1
  45. package/src/runtime/pm/features/Blocks/commands/moveItem.ts +1 -1
  46. package/src/runtime/pm/features/Blocks/components/DragTreeHandle.vue +18 -14
  47. package/src/runtime/pm/features/Blocks/components/ItemMenu.vue +0 -1
  48. package/src/runtime/pm/features/Blocks/components/ItemNodeView.vue +0 -1
  49. package/src/runtime/pm/features/CodeBlock/components/CodeBlockView.vue +0 -1
  50. package/src/runtime/pm/features/CommandsMenus/components/CommandMenuGroup.vue +0 -1
  51. package/src/runtime/pm/features/EmbeddedDocument/Embedded.ts +1 -1
  52. package/src/runtime/pm/features/EmbeddedDocument/components/EmbeddedDocumentPicker.vue +0 -1
  53. package/src/runtime/pm/features/EmbeddedDocument/components/EmbeddedNodeView.vue +0 -1
  54. package/src/runtime/pm/features/FileLoader/components/FileLoaderNodeView.vue +0 -1
  55. package/src/runtime/pm/features/FileLoader/types.ts +2 -2
  56. package/src/runtime/pm/generator.ts +266 -0
  57. package/src/runtime/pm/schema.ts +1 -0
  58. package/src/runtime/pm/utils/generateRandomDoc.ts +140 -0
  59. package/src/runtime/pm/utils/generateRandomTree.ts +100 -0
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "witchcraftEditor",
3
3
  "configKey": "witchcraftEditor",
4
- "version": "0.0.6",
4
+ "version": "0.0.8",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -40,7 +40,6 @@ const codeBlocksTheme = defineModel("codeBlocksTheme", { type: String, ...{ requ
40
40
  gap-2
41
41
  "
42
42
  >
43
- <!-- @vue-expect-error -->
44
43
  <ComboboxInput
45
44
  class="
46
45
  bg-inherit
@@ -46,7 +46,7 @@ import { pretty } from "@alanscodelog/utils";
46
46
  import WButton from "@witchcraft/ui/components/LibButton";
47
47
  import { twMerge } from "tailwind-merge";
48
48
  const props = defineProps({
49
- editor: { type: null, required: true },
49
+ editor: { type: Object, required: true },
50
50
  commands: { type: Array, required: true }
51
51
  });
52
52
  function handlePointerDown($event, command, args) {
@@ -27,7 +27,6 @@
27
27
  v-bind="$attrs"
28
28
  >
29
29
  <!-- The class `is-embedded-block` is not needed internally, but is added for consistency in case it might be useful. -->
30
- <!-- @vue-expect-error -->
31
30
  <editor-content
32
31
  :editor="editor"
33
32
  spellcheck="false"
@@ -80,7 +79,7 @@ import MarkMenuManager from "../pm/features/Menus/components/MarkMenuManager.vue
80
79
  import { extensions } from "../pm/schema.js";
81
80
  import { menusInjectionKey } from "../types/index.js";
82
81
  const props = defineProps({
83
- content: { type: null, required: false, default: void 0 },
82
+ content: { type: [String, Object, Array, null], required: false, default: void 0 },
84
83
  docId: { type: String, required: false, default: void 0 },
85
84
  documentApi: { type: null, required: false, default: void 0 },
86
85
  linkOptions: { type: Object, required: false, default: void 0 },
@@ -4,6 +4,6 @@ import { Editor } from "@tiptap/vue-3";
4
4
  * Unline tiptap's useEditor, this does not auto-mount the editor. Instead the returned `recreate` function must be called manually. This was built with the use of {@link useContentEditor} in mind.
5
5
  */
6
6
  export declare const useEditor: (options?: Partial<EditorOptions>) => {
7
- editor: import("@vue/reactivity").ShallowRef<Editor | undefined, Editor | undefined>;
7
+ editor: import("vue").ShallowRef<Editor | undefined, Editor | undefined>;
8
8
  recreate: (modifyOptions?: (options: Partial<EditorOptions>) => Partial<EditorOptions>) => void;
9
9
  };
@@ -1,6 +1,5 @@
1
1
  <template>
2
2
  <WRoot class="items-center py-4">
3
- <!-- @vue-expect-error use unhead in a real app -->
4
3
  <style>
5
4
  {{ codeBlocksThemeCss.join("\n") }}
6
5
  </style>
@@ -1,5 +1,5 @@
1
1
  import { Node } from "@tiptap/core";
2
- export declare const Blockquote: Node<import("@tiptap/extension-blockquote", { with: { "resolution-mode": "require" } }).BlockquoteOptions, any>;
2
+ export declare const Blockquote: Node<import("@tiptap/extension-blockquote").BlockquoteOptions, any>;
3
3
  export type NodeBlockquoteName = "blockquote";
4
4
  export declare const Cite: Node<any, any>;
5
5
  export type NodeCiteName = "cite";
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Multipurpose drag handle + collapse indicator.
3
+ *
4
+ * This is incredibly useful for making a compact draggable tree view.
5
+ *
6
+ * The collapse indicator has a default height, but it should be set manually. For example `[&>.collapse-indicator]:h-[...]`
7
+ *
8
+ * The component only emits a few events, it does not handle the dragging itself or what actually happens on any clicks/input.
9
+ */
10
+ interface Props {
11
+ hasChildren: boolean;
12
+ passedDragThreshold: boolean;
13
+ hideChildren: boolean;
14
+ }
15
+ declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
16
+ collapseIndicatorClick: (event: MouseEvent) => any;
17
+ grabHandlePassiveTouchStart: (event: TouchEvent) => any;
18
+ grabHandlePointerDown: (event: PointerEvent) => any;
19
+ grabHandleContextMenu: (event: PointerEvent) => any;
20
+ }, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
21
+ onCollapseIndicatorClick?: ((event: MouseEvent) => any) | undefined;
22
+ onGrabHandlePassiveTouchStart?: ((event: TouchEvent) => any) | undefined;
23
+ onGrabHandlePointerDown?: ((event: PointerEvent) => any) | undefined;
24
+ onGrabHandleContextMenu?: ((event: PointerEvent) => any) | undefined;
25
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
26
+ export default _default;
@@ -99,9 +99,16 @@
99
99
  </div>
100
100
  </template>
101
101
 
102
+ <script>
103
+
104
+ </script>
105
+
102
106
  <script setup>
103
107
  import { twMerge } from "@witchcraft/ui/utils/twMerge";
104
108
  import { onMounted, onUnmounted, ref, useAttrs } from "vue";
109
+ defineOptions({
110
+ name: "DragTreeHandle"
111
+ });
105
112
  const $attrs = useAttrs();
106
113
  defineProps({
107
114
  hasChildren: { type: Boolean, required: true },
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Multipurpose drag handle + collapse indicator.
3
+ *
4
+ * This is incredibly useful for making a compact draggable tree view.
5
+ *
6
+ * The collapse indicator has a default height, but it should be set manually. For example `[&>.collapse-indicator]:h-[...]`
7
+ *
8
+ * The component only emits a few events, it does not handle the dragging itself or what actually happens on any clicks/input.
9
+ */
10
+ interface Props {
11
+ hasChildren: boolean;
12
+ passedDragThreshold: boolean;
13
+ hideChildren: boolean;
14
+ }
15
+ declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
16
+ collapseIndicatorClick: (event: MouseEvent) => any;
17
+ grabHandlePassiveTouchStart: (event: TouchEvent) => any;
18
+ grabHandlePointerDown: (event: PointerEvent) => any;
19
+ grabHandleContextMenu: (event: PointerEvent) => any;
20
+ }, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
21
+ onCollapseIndicatorClick?: ((event: MouseEvent) => any) | undefined;
22
+ onGrabHandlePassiveTouchStart?: ((event: TouchEvent) => any) | undefined;
23
+ onGrabHandlePointerDown?: ((event: PointerEvent) => any) | undefined;
24
+ onGrabHandleContextMenu?: ((event: PointerEvent) => any) | undefined;
25
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
26
+ export default _default;
@@ -1,5 +1,4 @@
1
1
  <template>
2
- <!-- @vue-expect-error -->
3
2
  <WPopup
4
3
  :model-value="menu.opened"
5
4
  :preferred-horizontal="['left-most']"
@@ -33,7 +32,7 @@ import { popupVerticalPositioner } from "../../CommandsMenus/utils/popupVertical
33
32
  import { itemMenuPluginKey } from "../types.js";
34
33
  import { createItemMenuCommandExecuter } from "../utils/createItemMenuCommandExecuter.js";
35
34
  const props = defineProps({
36
- editor: { type: null, required: true }
35
+ editor: { type: Object, required: true }
37
36
  });
38
37
  const menu = ref({ opened: false, id: void 0 });
39
38
  const popup = ref();
@@ -7,7 +7,6 @@
7
7
  --pmNodeTypeMargin
8
8
  --pmDragDropIndicatorHeight
9
9
  -->
10
- <!-- @vue-expect-error role is a valid attribute -->
11
10
  <node-view-wrapper
12
11
  :class="twMerge(
13
12
  `
@@ -1,5 +1,5 @@
1
- export declare const defaultItemMenu: (import("../types.ts").ItemMenuCommand | {
1
+ export declare const defaultItemMenu: (import("../types.js").ItemMenuCommand | {
2
2
  type: "group";
3
3
  title: string;
4
- variations: import("../types.ts").ItemMenuCommand[];
4
+ variations: import("../types.js").ItemMenuCommand[];
5
5
  })[];
@@ -2,6 +2,6 @@ import type { Node } from "@tiptap/pm/model";
2
2
  export declare function useNodeStates(props: {
3
3
  node: Node;
4
4
  }): {
5
- counterStyle: import("@vue/reactivity").ComputedRef<string>;
6
- nodeState: import("@vue/reactivity").ComputedRef<import("../types.js").StatefulNodeStateEntry<string> | undefined>;
5
+ counterStyle: import("vue").ComputedRef<string>;
6
+ nodeState: import("vue").ComputedRef<import("../types.js").StatefulNodeStateEntry<string> | undefined>;
7
7
  };
@@ -12,5 +12,5 @@ export declare const lowlightInstance: {
12
12
  };
13
13
  registered: (aliasOrName: string) => boolean;
14
14
  };
15
- export declare const CodeBlock: import("@tiptap/core").Node<import("@tiptap/extension-code-block-lowlight", { with: { "resolution-mode": "require" } }).CodeBlockLowlightOptions, any>;
15
+ export declare const CodeBlock: import("@tiptap/core").Node<import("@tiptap/extension-code-block-lowlight").CodeBlockLowlightOptions, any>;
16
16
  export type NodeCodeBlockName = "codeBlock";
@@ -38,7 +38,6 @@
38
38
  />
39
39
  </div>
40
40
 
41
- <!-- @vue-expect-error -->
42
41
  <node-view-content
43
42
  :class="twMerge(
44
43
  `
@@ -30,8 +30,8 @@ export declare function useHighlightJsTheme({ defaultTheme, darkLightBgs, additi
30
30
  theme: Ref<string, string>;
31
31
  knownThemes: Ref<string[], string[]>;
32
32
  loadTheme: (themeName: string) => Promise<undefined | Error>;
33
- isDark: import("@vue/reactivity").ComputedRef<boolean>;
34
- backgroundColor: import("@vue/reactivity").ComputedRef<string>;
35
- themeCss: import("@vue/reactivity").ComputedRef<string[]>;
33
+ isDark: import("vue").ComputedRef<boolean>;
34
+ backgroundColor: import("vue").ComputedRef<string>;
35
+ themeCss: import("vue").ComputedRef<string[]>;
36
36
  rawThemeCss: Ref<string, string>;
37
37
  };
@@ -52,7 +52,7 @@
52
52
  <script setup>
53
53
  import CommandBarItem from "./CommandBarItem.vue";
54
54
  defineProps({
55
- editor: { type: null, required: true },
55
+ editor: { type: Object, required: true },
56
56
  commands: { type: Array, required: true }
57
57
  });
58
58
  </script>
@@ -29,7 +29,7 @@ import { commandExecuterInjectionKey } from "../types.js";
29
29
  import { defaultCommandExecuter } from "../utils/defaultCommandExecutor";
30
30
  const props = defineProps({
31
31
  item: { type: null, required: true },
32
- editor: { type: null, required: true }
32
+ editor: { type: Object, required: true }
33
33
  });
34
34
  const emit = defineEmits(["close"]);
35
35
  const executer = inject(commandExecuterInjectionKey, defaultCommandExecuter);
@@ -10,7 +10,6 @@
10
10
  :item="item"
11
11
  v-extract-root-el="(_) => el = _"
12
12
  />
13
- <!-- @vue-expect-error -->
14
13
  <WPopup
15
14
  :model-value="showSubMenu"
16
15
  :preferred-horizontal="['right-most']"
@@ -32,7 +32,7 @@ import { computed } from "vue";
32
32
  import FaSolidHighlighter from "~icons/lucide/highlighter";
33
33
  import { highlightPluginKey } from "../../Highlight/types.js";
34
34
  const props = defineProps({
35
- editor: { type: null, required: true },
35
+ editor: { type: Object, required: true },
36
36
  colorSlot: { type: null, required: false }
37
37
  });
38
38
  const color = computed(() => {
@@ -84,7 +84,6 @@
84
84
  @pointerdown.prevent
85
85
  @pointerup.prevent="pickBlockId"
86
86
  >
87
- <!-- @vue-expect-error -->
88
87
  <Editor
89
88
  :is-embedded="true"
90
89
  :doc-id="newEmbedId.docId"
@@ -1,5 +1,4 @@
1
1
  <template>
2
- <!-- @vue-expect-error -->
3
2
  <node-view-wrapper
4
3
  :class="`
5
4
  group/embedded-doc
@@ -1,5 +1,4 @@
1
1
  <template>
2
- <!-- @vue-expect-error contenteditable exists -->
3
2
  <node-view-wrapper
4
3
  :class="twMerge(
5
4
  `
@@ -2,4 +2,4 @@
2
2
  * Extends the tiptap hard break extension to set the linebreakReplacement option (which tiptap does not expose).
3
3
  * This option tells prosemirror that when converting between blocks that can/can't show whitespace, it should use this node type to represent line breaks in node types that don't display them.
4
4
  */
5
- export declare const HardBreak: import("@tiptap/core").Node<import("@tiptap/extension-hard-break", { with: { "resolution-mode": "require" } }).HardBreakOptions, any>;
5
+ export declare const HardBreak: import("@tiptap/core").Node<import("@tiptap/extension-hard-break").HardBreakOptions, any>;
@@ -83,7 +83,7 @@ import iFaSolidExternalLinkAlt from "~icons/fa-solid/external-link-alt";
83
83
  import iIcRoundLink from "~icons/ic/round-link";
84
84
  import iIcRoundShortText from "~icons/ic/round-short-text";
85
85
  const props = defineProps({
86
- editor: { type: null, required: true },
86
+ editor: { type: Object, required: true },
87
87
  linkSuggestions: { type: Array, required: false },
88
88
  linkMark: { type: null, required: true },
89
89
  isChanged: { type: Boolean, required: true }
@@ -56,7 +56,7 @@ import { ref, watch } from "vue";
56
56
  import BubbleMenuLinkActions from "./BubbleMenuLinkActions.vue";
57
57
  import iIcRoundLink from "~icons/ic/round-link";
58
58
  const props = defineProps({
59
- editor: { type: null, required: true },
59
+ editor: { type: Object, required: true },
60
60
  linkSuggestions: { type: Array, required: false },
61
61
  linkMark: { type: null, required: true },
62
62
  isChanged: { type: Boolean, required: true },
@@ -53,7 +53,7 @@ import { getMarkPosition } from "../../../utils/getMarkPosition.js";
53
53
  import { getMarksInSelection } from "../../../utils/getMarksInSelection.js";
54
54
  import { linkMenuPluginKey } from "../types.js";
55
55
  const props = defineProps({
56
- editor: { type: null, required: true },
56
+ editor: { type: Object, required: true },
57
57
  linkSuggestions: { type: Array, required: false },
58
58
  internalLinkSuggestions: { type: Array, required: false },
59
59
  getLinkSuggestions: { type: Function, required: false },
@@ -47,7 +47,7 @@ import {
47
47
  import { findUpwards } from "../../../utils/findUpwards.js";
48
48
  import { menusInjectionKey, menusPluginKey } from "../types.js";
49
49
  const props = defineProps({
50
- editor: { type: null, required: true }
50
+ editor: { type: Object, required: true }
51
51
  });
52
52
  const menus = inject(menusInjectionKey, ref({}));
53
53
  const activeMarkMenu = ref();
@@ -1,8 +1,8 @@
1
- export declare const TableRow: import("@tiptap/core").Node<import("@tiptap/extension-table", { with: { "resolution-mode": "require" } }).TableRowOptions, any>;
2
- export declare const TableCell: import("@tiptap/core").Node<import("@tiptap/extension-table", { with: { "resolution-mode": "require" } }).TableCellOptions, any>;
3
- export declare const TableHeader: import("@tiptap/core").Node<import("@tiptap/extension-table", { with: { "resolution-mode": "require" } }).TableHeaderOptions, any>;
4
- export declare const Table: import("@tiptap/core").Node<import("@tiptap/extension-table", { with: { "resolution-mode": "require" } }).TableOptions, any>;
5
- export declare const TableExtensions: (import("@tiptap/core").Node<import("@tiptap/extension-table", { with: { "resolution-mode": "require" } }).TableRowOptions, any> | import("@tiptap/core").Node<import("@tiptap/extension-table", { with: { "resolution-mode": "require" } }).TableOptions, any>)[];
1
+ export declare const TableRow: import("@tiptap/core").Node<import("@tiptap/extension-table").TableRowOptions, any>;
2
+ export declare const TableCell: import("@tiptap/core").Node<import("@tiptap/extension-table").TableCellOptions, any>;
3
+ export declare const TableHeader: import("@tiptap/core").Node<import("@tiptap/extension-table").TableHeaderOptions, any>;
4
+ export declare const Table: import("@tiptap/core").Node<import("@tiptap/extension-table").TableOptions, any>;
5
+ export declare const TableExtensions: (import("@tiptap/core").Node<import("@tiptap/extension-table").TableRowOptions, any> | import("@tiptap/core").Node<import("@tiptap/extension-table").TableOptions, any>)[];
6
6
  export type NodeTableName = "table";
7
7
  export type NodeTableRowName = "tableRow";
8
8
  export type NodeTableCellName = "tableCell";
@@ -0,0 +1,82 @@
1
+ import type { Mark, Node } from "@tiptap/pm/model";
2
+ export declare const pm: {
3
+ schema: import("@tiptap/pm/model").Schema<"paragraph" | "item" | "codeBlock" | "heading" | "iframe" | "image" | "table" | "text" | "blockquote" | "cite" | "list" | "tableCell" | "doc" | "embeddedDoc" | "tableRow" | "tableHeader", "bold" | "code" | "italic" | "strike" | "subscript" | "superscript" | "underline" | "hardBreak" | "highlight">;
4
+ } & {
5
+ readonly [x: string]: import("prosemirror-test-builder").NodeBuilder;
6
+ readonly paragraph: import("prosemirror-test-builder").NodeBuilder;
7
+ readonly item: import("prosemirror-test-builder").NodeBuilder;
8
+ readonly codeBlock: import("prosemirror-test-builder").NodeBuilder;
9
+ readonly heading: import("prosemirror-test-builder").NodeBuilder;
10
+ readonly iframe: import("prosemirror-test-builder").NodeBuilder;
11
+ readonly image: import("prosemirror-test-builder").NodeBuilder;
12
+ readonly table: import("prosemirror-test-builder").NodeBuilder;
13
+ readonly text: import("prosemirror-test-builder").NodeBuilder;
14
+ readonly blockquote: import("prosemirror-test-builder").NodeBuilder;
15
+ readonly cite: import("prosemirror-test-builder").NodeBuilder;
16
+ readonly list: import("prosemirror-test-builder").NodeBuilder;
17
+ readonly tableCell: import("prosemirror-test-builder").NodeBuilder;
18
+ readonly doc: import("prosemirror-test-builder").NodeBuilder;
19
+ readonly embeddedDoc: import("prosemirror-test-builder").NodeBuilder;
20
+ readonly tableRow: import("prosemirror-test-builder").NodeBuilder;
21
+ readonly tableHeader: import("prosemirror-test-builder").NodeBuilder;
22
+ } & {
23
+ readonly [x: string]: import("prosemirror-test-builder").MarkBuilder;
24
+ readonly bold: import("prosemirror-test-builder").MarkBuilder;
25
+ readonly code: import("prosemirror-test-builder").MarkBuilder;
26
+ readonly italic: import("prosemirror-test-builder").MarkBuilder;
27
+ readonly strike: import("prosemirror-test-builder").MarkBuilder;
28
+ readonly subscript: import("prosemirror-test-builder").MarkBuilder;
29
+ readonly superscript: import("prosemirror-test-builder").MarkBuilder;
30
+ readonly underline: import("prosemirror-test-builder").MarkBuilder;
31
+ readonly hardBreak: import("prosemirror-test-builder").MarkBuilder;
32
+ readonly highlight: import("prosemirror-test-builder").MarkBuilder;
33
+ } & {
34
+ [name: string]: import("prosemirror-test-builder").NodeBuilder | import("prosemirror-test-builder").MarkBuilder;
35
+ };
36
+ export type GeneratorConfigEntry<TChildrenType extends "node" | "text" = "node" | "text", TParentType extends "node" | "text" = "node" | "text", TChildren extends TChildrenType extends "node" ? Node : Mark | string = TChildrenType extends "node" ? Node : Mark | string, TParent extends TParentType extends "node" ? Node : Mark | string = TParentType extends "node" ? Node : Mark | string> = {
37
+ parents: {
38
+ /**
39
+ * The type of the parent (node or "text") where "text" is a string or mark.
40
+ * Determines the call signature of the create function.
41
+ */
42
+ type: TParentType;
43
+ /** Possible parent nodes that can have the given children. The children need not be direct descendants, see `ignoreValidation`. */
44
+ names: string[];
45
+ };
46
+ children: {
47
+ /**
48
+ * The type of children (node or "text") where "text" is a string or mark.
49
+ * Determines the call signature of the create function.
50
+ */
51
+ type: TChildrenType;
52
+ names?: string[];
53
+ };
54
+ /**
55
+ * Set to true to ignore all children mismatches, or set an array of children names to ignore.
56
+ *
57
+ * This is needed for creating "end" nodes that aren't valid names (e.g. `text` is not technically allowed since you can't do `builder.text()`).
58
+ *
59
+ * Or when the children are not direct children of the parent types as there is some in-between wrapper node that needs to be generated.
60
+ */
61
+ ignoreValidation?: boolean | string[];
62
+ isRoot?: boolean;
63
+ /**
64
+ * Creates the node. Can return undefined to "terminate" the branch being created, the node will be filtered out of the nodes passed to it's parent.
65
+ *
66
+ * If not set, a default `builder[parentType]({}, ...children)` will be used.
67
+ *
68
+ * Note also, it is not required to use the children. You can ignore them or use a subset or create a different one if needed (some node types *require* text and if your text not can return "" this can be a problem).
69
+ */
70
+ create?: (parent: string, children: TChildren[]) => TParent | undefined;
71
+ };
72
+ export declare function getTextOrMarkLength(textOrMark: string | Mark): number;
73
+ export declare function createGeneratorConfig<TChildrenType extends "node" | "text" = "node" | "text", TParentType extends "node" | "text" = "node" | "text", TChildren extends TChildrenType extends "node" ? Node : Mark | string = TChildrenType extends "node" ? Node : Mark | string, TParent extends TParentType extends "node" ? Node : Mark | string = TParentType extends "node" ? Node : Mark | string>(config: GeneratorConfigEntry<TChildrenType, TParentType, TChildren, TParent>): GeneratorConfigEntry<TChildrenType, TParentType, TChildren, TParent>;
74
+ export declare const generatorConfig: (GeneratorConfigEntry<"node", "node", Node, Node & {
75
+ tag: {
76
+ [tag: string]: number;
77
+ };
78
+ }> | GeneratorConfigEntry<"text", "node", string | Mark, Node & {
79
+ tag: {
80
+ [tag: string]: number;
81
+ };
82
+ }> | GeneratorConfigEntry<"text", "text", string | Mark, string | Mark>)[];
@@ -0,0 +1,205 @@
1
+ import { faker } from "@faker-js/faker";
2
+ import { nanoid } from "nanoid";
3
+ import { builders } from "prosemirror-test-builder";
4
+ import { schema } from "./schema.js";
5
+ export const pm = builders(schema);
6
+ export function getTextOrMarkLength(textOrMark) {
7
+ if (typeof textOrMark === "string") {
8
+ return textOrMark.length;
9
+ }
10
+ const textNodes = textOrMark.flat.map((_) => "text" in _ ? _.text.length : getTextOrMarkLength(_));
11
+ return textNodes.reduce((a, b) => a + b, 0);
12
+ }
13
+ export function createGeneratorConfig(config) {
14
+ return config;
15
+ }
16
+ function createPsuedoSentence() {
17
+ const sentenceLength = faker.number.int({ min: 0, max: 1e3 });
18
+ const sentence = Array.from(
19
+ { length: sentenceLength },
20
+ () => faker.string.sample({ min: 0, max: 1e3 })
21
+ ).join(" ");
22
+ return sentence;
23
+ }
24
+ export const generatorConfig = [
25
+ createGeneratorConfig({
26
+ isRoot: true,
27
+ parents: { type: "node", names: ["doc"] },
28
+ ignoreValidation: true,
29
+ children: { type: "node", names: ["item"] },
30
+ create: (_parent, children) => {
31
+ if (!children || children.length === 0) {
32
+ return pm.doc(pm.list(pm.item({ blockId: nanoid(10) }, pm.paragraph({}, ""))));
33
+ }
34
+ return pm.doc(pm.list(...children));
35
+ }
36
+ }),
37
+ createGeneratorConfig({
38
+ parents: { type: "node", names: ["list"] },
39
+ children: { type: "node", names: ["item"] },
40
+ create: (_parent, children) => {
41
+ if (!children || children.length === 0) {
42
+ return pm.list(pm.item({ blockId: nanoid(10) }, pm.paragraph("")));
43
+ }
44
+ return pm.list(...children);
45
+ }
46
+ }),
47
+ createGeneratorConfig({
48
+ parents: { type: "node", names: ["item"] },
49
+ children: { type: "node", names: [
50
+ "paragraph",
51
+ "heading",
52
+ "codeBlock",
53
+ "embeddedDoc",
54
+ "iframe",
55
+ "table",
56
+ "image",
57
+ "blockquote"
58
+ ] },
59
+ create: (_parent, children) => {
60
+ if (!children || children.length === 0) {
61
+ return pm.item({ blockId: nanoid(10) }, pm.paragraph(""));
62
+ }
63
+ return pm.item(
64
+ { blockId: nanoid(10) },
65
+ children[0],
66
+ ...children.length > 1 ? [pm.list(
67
+ {},
68
+ ...children.slice(1).map(
69
+ (_) => pm.item({ blockId: nanoid(10) }, _)
70
+ )
71
+ )] : []
72
+ );
73
+ }
74
+ }),
75
+ createGeneratorConfig({
76
+ parents: { type: "node", names: ["blockquote"] },
77
+ children: { type: "node", names: ["paragraph", "cite"] },
78
+ create: (_parent, children) => {
79
+ const parTypes = [];
80
+ const citeTypes = [];
81
+ for (const child of children) {
82
+ if (child.type.name === "cite") {
83
+ citeTypes.push(child);
84
+ } else {
85
+ parTypes.push(child);
86
+ }
87
+ }
88
+ if (parTypes.length === 0) {
89
+ return pm.blockquote({}, pm.paragraph(""));
90
+ } else {
91
+ const someCite = citeTypes.find((_) => _.textContent.length > 0) ?? pm.cite({}, createPsuedoSentence());
92
+ return pm.blockquote({}, ...parTypes, someCite);
93
+ }
94
+ }
95
+ }),
96
+ createGeneratorConfig({
97
+ parents: { type: "node", names: ["table"] },
98
+ children: { type: "node", names: [
99
+ "tableHeader",
100
+ "tableCell"
101
+ ] },
102
+ ignoreValidation: true,
103
+ // we're handling the in-between tableRow nodes
104
+ create: (_parent, children) => {
105
+ const headerType = [];
106
+ const cellType = [];
107
+ for (const child of children) {
108
+ if (child.type.name === "tableHeader") {
109
+ headerType.push(child);
110
+ } else if (child.type.name === "tableCell") {
111
+ cellType.push(child);
112
+ }
113
+ }
114
+ const colNum = headerType.length;
115
+ if (colNum === 0) {
116
+ return pm.table({}, pm.tableRow({}, pm.tableCell(pm.paragraph(""))));
117
+ }
118
+ const rowCount = Math.ceil(cellType.length / colNum);
119
+ const rows = [];
120
+ for (let i = 0; i < rowCount; i++) {
121
+ rows.push(pm.tableRow({}, ...cellType.slice(i * colNum, (i + 1) * colNum)));
122
+ }
123
+ return pm.table({}, pm.tableRow({}, ...headerType), ...rows);
124
+ }
125
+ }),
126
+ createGeneratorConfig({
127
+ parents: { type: "node", names: ["tableHeader", "tableCell"] },
128
+ children: { type: "node", names: ["paragraph"] },
129
+ create: (_parent, children) => {
130
+ if (!children || children.length === 0) {
131
+ return pm.tableCell(pm.paragraph(""));
132
+ }
133
+ return pm.tableCell(...children.slice(0, 1));
134
+ }
135
+ }),
136
+ createGeneratorConfig({
137
+ parents: { type: "node", names: ["paragraph", "heading", "codeBlock", "cite", "heading"] },
138
+ children: { type: "text", names: [
139
+ "bold",
140
+ "italic",
141
+ "underline",
142
+ "strike",
143
+ "subscript",
144
+ "superscript",
145
+ "code",
146
+ "link"
147
+ ] },
148
+ create(parent, children) {
149
+ if (parent === "heading") {
150
+ return pm[parent]({ level: 1 }, ...children);
151
+ }
152
+ if (parent === "cite") {
153
+ return pm[parent]({}, faker.lorem.sentence());
154
+ }
155
+ if (parent === "paragraph") {
156
+ const someIndex = faker.number.int({ min: 0, max: children.length });
157
+ children.splice(someIndex, 0, pm.hardBreak());
158
+ }
159
+ return pm[parent]({}, ...children);
160
+ }
161
+ }),
162
+ createGeneratorConfig({
163
+ parents: {
164
+ type: "text",
165
+ names: [
166
+ "bold",
167
+ "italic",
168
+ "underline",
169
+ "strike",
170
+ "subscript",
171
+ "superscript",
172
+ "link"
173
+ ]
174
+ },
175
+ // note the addition of text
176
+ children: { type: "text", names: [
177
+ "bold",
178
+ "italic",
179
+ "underline",
180
+ "strike",
181
+ "subscript",
182
+ "superscript",
183
+ "link",
184
+ "text"
185
+ ] },
186
+ ignoreValidation: ["text"]
187
+ // text is not a real node
188
+ // create: (parent, children) => {
189
+ // return pm[parent]({}, ...children as any) as any
190
+ // }
191
+ }),
192
+ createGeneratorConfig({
193
+ ignoreValidation: true,
194
+ // text is not a real node
195
+ parents: { type: "text", names: ["code"] },
196
+ children: { type: "text", names: ["text"] }
197
+ }),
198
+ createGeneratorConfig({
199
+ parents: { type: "text", names: ["text"] },
200
+ children: { type: "text" },
201
+ create: (_parent) => {
202
+ return createPsuedoSentence();
203
+ }
204
+ })
205
+ ];
@@ -1,5 +1,5 @@
1
1
  import type { Schema } from "@tiptap/pm/model";
2
2
  import { type NodeFileLoaderName } from "./features/FileLoader/FileLoader.js";
3
3
  import { type schema as baseSchema } from "./schema.js";
4
- export declare const testExtensions: (import("@tiptap/core").AnyExtension | import("@tiptap/core").Node<import("./features/FileLoader/types.ts").FileLoaderExtensionOptions, any>)[];
4
+ export declare const testExtensions: (import("@tiptap/core").AnyExtension | import("@tiptap/core").Node<import("./features/FileLoader/types.js").FileLoaderExtensionOptions, any>)[];
5
5
  export declare const testSchema: typeof baseSchema & Schema<NodeFileLoaderName & "itemNoId">;