Skip to content

Latest commit

 

History

History
345 lines (322 loc) · 12.8 KB

File metadata and controls

345 lines (322 loc) · 12.8 KB
  • [~] Remove/segment tiptap styles.
  • i18n
  • We often don't need to be checkingthe to type in commands.
  • Cleanup fallbacks and nodetypes. Fallback => createAndFill if possible.
  • Move pinToItemDistance to menu options?
  • Fix link menu condition.
  • Fix table should not be able to press enter.

Commands

  • [>] List of valid commands.

Requirements

Future

  • Comments
  • [^] Modal mode.
    • [^] Change selection => apply command => return selection. For vim like selections.

Easy, Low Priority

  • Up arrow at last node that doesn't support gap cursor adds a new paragraph.
  • Allow configuring popup options in mark menus.
  • Prevent link menu from being opened when it wasn't a user focus event (manually through some meta on the tr).
  • Normalize renderHTML with nodes to get same look.

Difficult, Low Priority

  • Shift select is broken around embeds and tables.
  • Figure out way to disallow undoing of file loader nodes.
  • [?] Enter at end of embed redirects to parent?
  • Dragging across document embed boundaries.
  • Injectable bubble menus?
  • If in the embedded block of an embedded document, indent the embedded block in the parent.
  • Async Oembed
  • Rewrite the table node.
    • Dragging multiple block selections into a table is completely fucked. Figure out a way to turn them into multiple lines/rows?
  • Don't show the list expander when it's just a single very nested item.
  • [?] Use/implement BlockSelection https://github.com/ccorcos/prosemirror-examples/blob/b961b7545c527655eb67717a181860beefd4dcf8/src/components/BlockSelectionPlugin.tsx
  • At last line / at first line helpers.

Tests needed:

  • Link Menu tests.
  • Redirected commands tests.
  • Complex parsing tests.
  • Enter key tests.

Done

  • Backspace in blockquotes is not working.

  • Internal links are not working.

  • [~~] Add block button on hover over the end of the editor.

    • Ensured last is paragraph instead.
  • Enter in table should start new paragraph block. ...sortof

  • Check all keys have state plugin if needed.

  • Convert options to interfaces.

  • Avoid interface merging of unused if possible.

  • Highlight parsing tests.

  • Images/Videos/Attachments

    • Custom image node. Tiptap one adds margins.
    • Image Preview Node
    • Drop
  • Command menu.

  • Highlights

  • Table commands bubble menu.

  • Command bar styles.

  • [~~] Check if we can replace on* in components by computed refs depending on props.editor.state

    • Nope, causes weird issues with mark menu at least.
  • Fix gap cursor.

  • Gap cursor on the list works properly but looks wrong (is at the top of the list???).

  • Include/create gap cursor styles.

  • Fix usage of dispatch.

  • Replace ChainedCommands with SingleCommands.

  • Weird bug where both command bar menus show (embed and editor)

  • update unfocused selection css docs

  • Swap any mousedowns for pointerdowns.

  • Down/up arrows in embeds. Already works.

  • Content Embed

    • iFrame/YouTube
      • Per provider params?
  • Fix html attributes handling.

  • Handle enter at the end of special blocks. Prevent at command level if editor is embedded.

    • Partial Embeds shouldn't allow enter at all.
    • Other should start new block.
  • Change parsehtml to return false if rule shoundn't match.

  • Tests for file loader.

    • Auto delete last.
    • Auto delete nested.
    • Auto delete sibling but not wrapping list.
  • Editor block embed?

    • Block/link picker.
      • Check undo state isn't getting accidentally shared.
    • Undo
  • Keyboard shortcuts not working in embedded editor.

  • Properly override some commands.

  • See what selectingIndicator did.

  • Change commands to take a position or selection if possible.

  • Fix items with tables not being able to get their state types changed.

  • Language suggestions causing overflow :(

  • Set selection to embed range when selecting block.

  • Prevent dragging across document boundaries.

  • Document drag scroll.

  • Add configuration for scroll margins and styling.

  • [~~] Refactor dropindicator to be relative to editor.

    • Did not work well. Absolutely posiitoned element does not get overflow hidden?
  • uuid validation on load

  • Prevent duplicate block ids.

  • Add doc loading state.

  • Fix contentless drags.

  • Prevent recursive embedding of the same document.

  • Rework shift option for nodesBetween. Reworked dependant commands instead.

  • Double check root extension state can be shared. Added instancePerEditor option.

  • It thinks there's no history. Again

  • link menu and related trs add to history false

  • Deduping of parent plugins

  • Regular hard break with shift + enter not working.

  • Implemented indent/unindent in code block.

    • This is not meant to be used with tab set to indenting item blocks.
  • Links

    • External
      • Possible to have an allowed protocols list?
        • This can just be implemented in the openInternal function.
    • Internal
      • Autocomplete
  • Setting code block twice unindents block!

  • Hitting enter on a list item is unindenting it if it's blank. Write own splitlistItem command.

  • Tab indents a list item.

  • [~~] Override splitListItem to make it usable.

    • Using custom instead.
  • Remove selection Adjust selection after dropping a single item, when the selection goes outside the item.

  • Move item up/down.

    • Make children move with it.
    • Expand selection when start.depth is deeper than end.depth, otherwise it get's very complicated.
  • Backspace is doing weird things.

  • Hard break code block.

  • Split code block.

  • Triple escape code block + list split.

  • Recheck block types

--- Scratchpad ---

export const focusCodeBlockLanguage = ( codeBlockType: string, langPickerClass: string = "lang-picker" ) => (dir: "up" | "down"): Command => ({ state, tr, view }) => { const { from, to, empty, $from } = state.selection.map(tr.doc, tr.mapping) if (!empty) { return false } const $node = tr.doc.resolve(from) debugNode($node.node()) const isCodeBlock = $node.node()?.type.name === codeBlockType console.log(dir) if (dir === "up" && isCodeBlock) { const firstLineIndex = $from.parent.textContent.indexOf("\n") const firstLine = firstLineIndex > 0 ? $from.parent.textContent.slice(0, firstLineIndex) : false as const const nodePos = from - $node.start() if (!firstLine || (nodePos >= 0 && nodePos <= firstLine.length)) { const domNode = view.domAtPos(from - 1).node focusInput(domNode, langPickerClass) } } else if (dir === "down" && !isCodeBlock) { const lastLineIndex = $from.parent.textContent.lastIndexOf("\n") const lastLine = lastLineIndex > 0 ? $from.parent.textContent.slice(lastLineIndex + 1) : false as const const nodePos = from - $node.start() if (!lastLine || (nodePos >= 0 && nodePos <= lastLine.length)) { console.log("at last") const endOfLinePlusOne = nodePos + (lastLine ? lastLine.length - nodePos + 1 : 1) const nextSel = TextSelection.findFrom(tr.doc.resolve(tr.doc.resolve(endOfLinePlusOne).pos), 1, true)

				console.log(nextSel)
				// const nextNode = tr.doc.nodesBetween(from, tr.doc.resolve(0).end(), (node,pos) => {
				// 	if (node.type?.name === codeBlockType) {
				// 		return true
				// 	}
				// })
				// const domNode = view.domAtPos(from).node
				// focusInput(domNode, langPickerClass)
			}
		}
		return false
	}

// [<iframe width="560" height="315" src="https://www.youtube.com/embed/0GoU-A996Bc?si=rXgwW-Xfb19ZMq2u" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>], // [<iframe src="https://www.google.com/search?q=reddit+js+library+detecting+embed+urls&oq=reddit+js+library+detecting+embed+urls&gs_lcrp=EgZjaHJvbWUyBggAEEUYOdIBCDUzMTJqMGo3qAIAsAIA&sourceid=chrome&ie=UTF-8"></iframe>], // [<iframe src="https://player.vimeo.com/video/215976284?h=66cf6fc4bb" width="640" height="360" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>], // ["https://player.vimeo.com/video/215976284?h=66cf6fc4bb"],

  • NotLink A 1
  • Internal
  • B 1
    B 1

    • Embedded
    • C 1

      • D 1

        E 1
      • D 2

      • D 3

    --- const offsetMap = StepMap.offset(-start + 1) // see ueberdosis/tiptap#1883 // and ueberdosis/tiptap#74 (comment) const steps: ReplaceStep[] = JSON.parse( JSON.stringify(tr.steps) ).map((step: any) => Step.fromJSON(state.schema, step)) const allMappableSteps = [] for (const step of steps) { const fromOk = step.from >= start && step.from <= end const toOk = step.to >= start && step.to <= end if (fromOk && toOk) allMappableSteps.push(step) else {break} } if (allMappableSteps.length === steps.length) { for (const step of steps) { const mapped = step.map(offsetMap)! console.log(mapped) intTr.step(mapped) } } else {

    import assert from "node:assert" import { chromium, devices } from "playwright";

    (async () => { // Setup const browser = await chromium.launch({ headless: false, executablePath: process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH, }) const context = await browser.newContext(devices["iPhone 11"]) const page = await context.newPage()

    // The actual interesting bit
    await context.route("**.jpg", route => route.abort())
    console.log(1)
    await page.goto("https://example.com/")
    console.log(2)
    
    const pt = await page.title()
    console.log("page title")
    console.log(JSON.stringify(pt))
    
    assert(pt === "Example Domain") // 👎 not a Web First assertion
    
    const sleep = ms => new Promise(r => setTimeout(r, ms))
    await sleep(5000)
    
    // Teardown
    await context.close()
    await browser.close()
    

    })()

    {{ command.title ?? command.name }}
    <script setup lang="ts"> import type { ChainedCommands } from "@tiptap/vue-3" import { computed, ref } from "vue" type Command = { name: keyof ChainedCommands , title?: string , description?: string; } & ( {variations: any[][] } | {args?: any[]} ) type FullCommand = Omit & { args: any[] } const props = defineProps<{ commands: Command[] } >() const commandsList = computed(() => props.commands.map(command => { if ("variations" in command && command.variations) { return command.variations.map(variation => ({ ...command, args: variation, })) satisfies FullCommand[] } else { return command as FullCommand } }).flat()) </script>

    const $deepest = convertTo.resolve(Math.floor(convertTo.nodeSize / 2)) if (keepsContent && ($deepest.node().type.name === "text" || $deepest?.parent)) { const selPos = posByNode(editor.state.doc, { textContent: "ABC", type: $deepest.node().type.name === "text" ? $deepest.parent.type : $deepest.node().type, }) const closest = TextSelection.near(editor.state.doc.resolve(selPos), -1) console.log(closest.from, editor.state.selection.from, editor.state.doc.resolve(selPos).node().type.name) }

    const commands: { key: keyof ChainedCommands, buttons: any[][] }[] = [ { key: "indentListItem" , buttons: [[]]}, { key: "unindentListItem" , buttons: [[]]}, { key: "toggleHeading", buttons: [1, 2, 3, 4, 5, 6, undefined].map(level => [{ level }]) }, { key: "toggleBold", buttons: [[]]}, { key: "toggleItalic", buttons: [[]]}, { key: "toggleCode", buttons: [[]]}, { key: "toggleCodeBlock", buttons: [[]]}, { key: "setCodeBlock", buttons: [ [{ language: "javascript" , loading: true }], [{ language: "css", loading: true }], ]}, { key: "focusCodeBlockLanguage", buttons: [[]]}, { key: "setHardBreak", buttons: [[]]}, { key: "undo", buttons: [[]]}, { key: "redo", buttons: [[]]}, { key: "moveListItem", buttons: [["down"], ["up"]]}, { key: "changeListItemType", buttons: [ [{ type: "none" }], [{ type: "stateful-task", state: "unchecked" }], [{ type: "stateful-task", state: "partial" }], [{ type: "stateful-task", state: "cancelled" }], [{ type: "stateful-task", state: "checked" }], [{ type: "ordered" }], // todo list all list-style-types [{ type: "unordered" }], [{ type: "ordered-upper-roman" }], [{ type: "ordered-lower-roman" }], // "unordered-square", ]}, ]