@milkdown/prose
Advanced tools
Comparing version 6.5.2 to 6.5.3
@@ -55,5 +55,5 @@ import { InputRule } from 'prosemirror-inputrules'; | ||
declare type Point = [top: number, left: number]; | ||
type Point = [top: number, left: number]; | ||
declare const calculateNodePosition: (view: EditorView, target: HTMLElement, handler: (selectedRect: DOMRect, targetRect: DOMRect, parentRect: DOMRect) => Point) => void; | ||
declare type Rect = { | ||
interface Rect { | ||
left: number; | ||
@@ -63,3 +63,3 @@ right: number; | ||
bottom: number; | ||
}; | ||
} | ||
declare const calculateTextPosition: (view: EditorView, target: HTMLElement, handler: (start: Rect, end: Rect, targetRect: DOMRect, parentRect: DOMRect) => Point) => void; | ||
@@ -70,8 +70,8 @@ | ||
declare type Predicate = (node: Node) => boolean; | ||
type Predicate = (node: Node) => boolean; | ||
declare type NodeWithPos = { | ||
interface NodeWithPos { | ||
pos: number; | ||
node: Node; | ||
}; | ||
} | ||
declare const flatten: (node: Node, descend?: boolean) => NodeWithPos[]; | ||
@@ -84,3 +84,3 @@ declare const findChildren: (predicate: Predicate) => (node: Node, descend?: boolean) => NodeWithPos[]; | ||
declare type ContentNodeWithPos = { | ||
interface ContentNodeWithPos { | ||
pos: number; | ||
@@ -90,3 +90,3 @@ start: number; | ||
node: Node; | ||
}; | ||
} | ||
declare const findParentNodeClosestToPos: (predicate: Predicate) => ($pos: ResolvedPos) => ContentNodeWithPos | undefined; | ||
@@ -93,0 +93,0 @@ declare const findParentNode: (predicate: Predicate) => (selection: Selection) => ContentNodeWithPos | undefined; |
@@ -26,15 +26,15 @@ import { PluginKey, Plugin, NodeSelection } from 'prosemirror-state'; | ||
var browser = /*#__PURE__*/Object.freeze({ | ||
__proto__: null, | ||
ie: ie, | ||
ie_version: ie_version, | ||
gecko: gecko, | ||
gecko_version: gecko_version, | ||
chrome: chrome, | ||
chrome_version: chrome_version, | ||
safari: safari, | ||
ios: ios, | ||
mac: mac, | ||
android: android, | ||
webkit: webkit, | ||
webkit_version: webkit_version | ||
__proto__: null, | ||
ie: ie, | ||
ie_version: ie_version, | ||
gecko: gecko, | ||
gecko_version: gecko_version, | ||
chrome: chrome, | ||
chrome_version: chrome_version, | ||
safari: safari, | ||
ios: ios, | ||
mac: mac, | ||
android: android, | ||
webkit: webkit, | ||
webkit_version: webkit_version | ||
}); | ||
@@ -45,3 +45,4 @@ | ||
return false; | ||
const state = view.state, $from = state.doc.resolve(from); | ||
const state = view.state; | ||
const $from = state.doc.resolve(from); | ||
if ($from.parent.type.spec.code) | ||
@@ -118,11 +119,8 @@ return false; | ||
const excludedMarks = getMarksBetween(start, end, state).filter((item) => item.mark.type.excludes(markType)).filter((item) => item.end > matchStart); | ||
if (excludedMarks.length) { | ||
if (excludedMarks.length) | ||
return null; | ||
} | ||
if (textEnd < matchEnd) { | ||
if (textEnd < matchEnd) | ||
tr.delete(textEnd, matchEnd); | ||
} | ||
if (textStart > matchStart) { | ||
if (textStart > matchStart) | ||
tr.delete(matchStart, textStart); | ||
} | ||
markStart = matchStart; | ||
@@ -156,15 +154,13 @@ markEnd = markStart + last.length; | ||
const element = node instanceof Text ? node.parentElement : node; | ||
if (!(element instanceof HTMLElement)) { | ||
if (!(element instanceof HTMLElement)) | ||
throw expectDomTypeError(element); | ||
} | ||
const selectedNodeRect = element.getBoundingClientRect(); | ||
const targetNodeRect = target.getBoundingClientRect(); | ||
const parent = target.parentElement; | ||
if (!parent) { | ||
if (!parent) | ||
throw expectDomTypeError(parent); | ||
} | ||
const parentNodeRect = parent.getBoundingClientRect(); | ||
const [top, left] = handler(selectedNodeRect, targetNodeRect, parentNodeRect); | ||
target.style.top = top + "px"; | ||
target.style.left = left + "px"; | ||
target.style.top = `${top}px`; | ||
target.style.left = `${left}px`; | ||
}; | ||
@@ -178,9 +174,8 @@ const calculateTextPosition = (view, target, handler) => { | ||
const parent = target.parentElement; | ||
if (!parent) { | ||
if (!parent) | ||
throw missingRootElement(); | ||
} | ||
const parentNodeRect = parent.getBoundingClientRect(); | ||
const [top, left] = handler(start, end, targetNodeRect, parentNodeRect); | ||
target.style.top = top + "px"; | ||
target.style.left = left + "px"; | ||
target.style.top = `${top}px`; | ||
target.style.left = `${left}px`; | ||
}; | ||
@@ -192,3 +187,3 @@ | ||
const equalNodeType = (nodeType, node) => { | ||
return Array.isArray(nodeType) && nodeType.indexOf(node.type) > -1 || node.type === nodeType; | ||
return Array.isArray(nodeType) && nodeType.includes(node.type) || node.type === nodeType; | ||
}; | ||
@@ -200,5 +195,4 @@ | ||
result.push({ node: child, pos }); | ||
if (!descend) { | ||
if (!descend) | ||
return false; | ||
} | ||
return void 0; | ||
@@ -213,5 +207,4 @@ }); | ||
const target = schema.nodes[type]; | ||
if (!target) { | ||
if (!target) | ||
throw getAtomFromSchemaFail("node", type); | ||
} | ||
return target; | ||
@@ -221,5 +214,4 @@ }; | ||
const target = schema.marks[type]; | ||
if (!target) { | ||
if (!target) | ||
throw getAtomFromSchemaFail("mark", type); | ||
} | ||
return target; | ||
@@ -240,3 +232,3 @@ }; | ||
} | ||
return; | ||
return void 0; | ||
}; | ||
@@ -247,9 +239,7 @@ const findParentNode = (predicate) => (selection) => { | ||
const findSelectedNodeOfType = (selection, nodeType) => { | ||
if (!(selection instanceof NodeSelection)) { | ||
if (!(selection instanceof NodeSelection)) | ||
return; | ||
} | ||
const { node, $from } = selection; | ||
if (equalNodeType(nodeType, node)) { | ||
if (equalNodeType(nodeType, node)) | ||
return { node, pos: $from.pos, start: $from.start($from.depth), depth: $from.depth }; | ||
} | ||
return void 0; | ||
@@ -256,0 +246,0 @@ }; |
{ | ||
"name": "@milkdown/prose", | ||
"version": "6.5.2", | ||
"type": "module", | ||
"main": "./lib/index.js", | ||
"types": "./lib/index.d.ts", | ||
"version": "6.5.3", | ||
"license": "MIT", | ||
"sideEffects": false, | ||
"exports": { | ||
".": { | ||
"import": "./lib/index.js", | ||
"types": "./lib/index.d.ts" | ||
"types": "./lib/index.d.ts", | ||
"import": "./lib/index.js" | ||
}, | ||
"./commands": { | ||
"import": "./lib/commands.js", | ||
"types": "./lib/commands.d.ts" | ||
"types": "./lib/commands.d.ts", | ||
"import": "./lib/commands.js" | ||
}, | ||
"./dropcursor": { | ||
"import": "./lib/dropcursor.js", | ||
"types": "./lib/dropcursor.d.ts" | ||
"types": "./lib/dropcursor.d.ts", | ||
"import": "./lib/dropcursor.js" | ||
}, | ||
"./gapcursor": { | ||
"import": "./lib/gapcursor.js", | ||
"types": "./lib/gapcursor.d.ts" | ||
"types": "./lib/gapcursor.d.ts", | ||
"import": "./lib/gapcursor.js" | ||
}, | ||
"./history": { | ||
"import": "./lib/history.js", | ||
"types": "./lib/history.d.ts" | ||
"types": "./lib/history.d.ts", | ||
"import": "./lib/history.js" | ||
}, | ||
"./inputrules": { | ||
"import": "./lib/inputrules.js", | ||
"types": "./lib/inputrules.d.ts" | ||
"types": "./lib/inputrules.d.ts", | ||
"import": "./lib/inputrules.js" | ||
}, | ||
"./keymap": { | ||
"import": "./lib/keymap.js", | ||
"types": "./lib/keymap.d.ts" | ||
"types": "./lib/keymap.d.ts", | ||
"import": "./lib/keymap.js" | ||
}, | ||
"./model": { | ||
"import": "./lib/model.js", | ||
"types": "./lib/model.d.ts" | ||
"types": "./lib/model.d.ts", | ||
"import": "./lib/model.js" | ||
}, | ||
"./schema-list": { | ||
"import": "./lib/schema-list.js", | ||
"types": "./lib/schema-list.d.ts" | ||
"types": "./lib/schema-list.d.ts", | ||
"import": "./lib/schema-list.js" | ||
}, | ||
"./state": { | ||
"import": "./lib/state.js", | ||
"types": "./lib/state.d.ts" | ||
"types": "./lib/state.d.ts", | ||
"import": "./lib/state.js" | ||
}, | ||
"./transform": { | ||
"import": "./lib/transform.js", | ||
"types": "./lib/transform.d.ts" | ||
"types": "./lib/transform.d.ts", | ||
"import": "./lib/transform.js" | ||
}, | ||
"./view": { | ||
"import": "./lib/view.js", | ||
"types": "./lib/view.d.ts" | ||
"types": "./lib/view.d.ts", | ||
"import": "./lib/view.js" | ||
} | ||
}, | ||
"main": "./lib/index.js", | ||
"types": "./lib/index.d.ts", | ||
"typesVersions": { | ||
@@ -94,4 +96,2 @@ "*": { | ||
}, | ||
"sideEffects": false, | ||
"license": "MIT", | ||
"files": [ | ||
@@ -102,3 +102,2 @@ "lib", | ||
"dependencies": { | ||
"@milkdown/exception": "6.5.2", | ||
"prosemirror-commands": "^1.3.1", | ||
@@ -115,3 +114,4 @@ "prosemirror-dropcursor": "^1.5.0", | ||
"prosemirror-view": "^1.28.0", | ||
"tslib": "^2.4.0" | ||
"tslib": "^2.4.0", | ||
"@milkdown/exception": "6.5.3" | ||
}, | ||
@@ -118,0 +118,0 @@ "nx": { |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from 'prosemirror-commands'; | ||
export * from 'prosemirror-commands' |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from 'prosemirror-dropcursor'; | ||
export * from 'prosemirror-dropcursor' |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from 'prosemirror-gapcursor'; | ||
export * from 'prosemirror-gapcursor' |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from 'prosemirror-history'; | ||
export * from 'prosemirror-history' |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from './toolkit'; | ||
export * from './toolkit' |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from 'prosemirror-inputrules'; | ||
export * from 'prosemirror-inputrules' |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from 'prosemirror-keymap'; | ||
export * from 'prosemirror-keymap' |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from 'prosemirror-model'; | ||
export * from 'prosemirror-model' |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from 'prosemirror-schema-list'; | ||
export * from 'prosemirror-schema-list' |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from 'prosemirror-state'; | ||
export * from 'prosemirror-state' |
@@ -8,31 +8,30 @@ /* Copyright 2021, Milkdown by Mirone. */ | ||
/* eslint-disable @typescript-eslint/no-non-null-assertion */ | ||
const nav = typeof navigator != 'undefined' ? navigator : null; | ||
const doc = typeof document != 'undefined' ? document : null; | ||
const agent = (nav && nav.userAgent) || ''; | ||
const nav = typeof navigator != 'undefined' ? navigator : null | ||
const doc = typeof document != 'undefined' ? document : null | ||
const agent = (nav && nav.userAgent) || '' | ||
const ie_edge = /Edge\/(\d+)/.exec(agent); | ||
const ie_upto10 = /MSIE \d/.exec(agent); | ||
const ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(agent); | ||
const ie_edge = /Edge\/(\d+)/.exec(agent) | ||
const ie_upto10 = /MSIE \d/.exec(agent) | ||
const ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(agent) | ||
export const ie = !!(ie_upto10 || ie_11up || ie_edge); | ||
export const ie = !!(ie_upto10 || ie_11up || ie_edge) | ||
export const ie_version = ie_upto10 | ||
? (document as typeof document & { documentMode: unknown }).documentMode | ||
: ie_11up | ||
? (document as typeof document & { documentMode: unknown }).documentMode | ||
: ie_11up | ||
? +ie_11up![1]! | ||
: ie_edge | ||
? +ie_edge![1]! | ||
: 0; | ||
export const gecko = !ie && /gecko\/(\d+)/i.test(agent); | ||
export const gecko_version = gecko && +(/Firefox\/(\d+)/.exec(agent) || [0, 0])![1]!; | ||
? +ie_edge![1]! | ||
: 0 | ||
export const gecko = !ie && /gecko\/(\d+)/i.test(agent) | ||
export const gecko_version = gecko && +(/Firefox\/(\d+)/.exec(agent) || [0, 0])![1]! | ||
const _chrome = !ie && /Chrome\/(\d+)/.exec(agent); | ||
export const chrome = !!_chrome; | ||
export const chrome_version = _chrome ? +_chrome[1]! : 0; | ||
export const safari = !ie && !!nav && /Apple Computer/.test(nav.vendor); | ||
const _chrome = !ie && /Chrome\/(\d+)/.exec(agent) | ||
export const chrome = !!_chrome | ||
export const chrome_version = _chrome ? +_chrome[1]! : 0 | ||
export const safari = !ie && !!nav && /Apple Computer/.test(nav.vendor) | ||
// Is true for both iOS and iPadOS for convenience | ||
export const ios = safari && (/Mobile\/\w+/.test(agent) || (!!nav && nav.maxTouchPoints > 2)); | ||
export const mac = ios || (nav ? /Mac/.test(nav.platform) : false); | ||
export const android = /Android \d/.test(agent); | ||
export const webkit = !!doc && 'webkitFontSmoothing' in doc.documentElement.style; | ||
export const webkit_version = webkit ? +(/\bAppleWebKit\/(\d+)/.exec(navigator.userAgent) || [0, 0])![1]! : 0; | ||
export const ios = safari && (/Mobile\/\w+/.test(agent) || (!!nav && nav.maxTouchPoints > 2)) | ||
export const mac = ios || (nav ? /Mac/.test(nav.platform) : false) | ||
export const android = /Android \d/.test(agent) | ||
export const webkit = !!doc && 'webkitFontSmoothing' in doc.documentElement.style | ||
export const webkit_version = webkit ? +(/\bAppleWebKit\/(\d+)/.exec(navigator.userAgent) || [0, 0])![1]! : 0 |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * as browser from './browser'; | ||
export * from './input-rules'; | ||
export * from './position'; | ||
export * from './prose'; | ||
export * as browser from './browser' | ||
export * from './input-rules' | ||
export * from './position' | ||
export * from './prose' |
/* Copyright 2021, Milkdown by Mirone. */ | ||
import type { InputRule } from '../../inputrules'; | ||
import { EditorState, Plugin, PluginKey, TextSelection, Transaction } from '../../state'; | ||
import type { EditorView } from '../../view'; | ||
import type { InputRule } from '../../inputrules' | ||
import type { EditorState, TextSelection, Transaction } from '../../state' | ||
import { Plugin, PluginKey } from '../../state' | ||
import type { EditorView } from '../../view' | ||
function run(view: EditorView, from: number, to: number, text: string, rules: InputRule[], plugin: Plugin) { | ||
if (view.composing) return false; | ||
const state = view.state, | ||
$from = state.doc.resolve(from); | ||
if ($from.parent.type.spec.code) return false; | ||
const textBefore = | ||
$from.parent.textBetween(Math.max(0, $from.parentOffset - 500), $from.parentOffset, undefined, '\ufffc') + text; | ||
for (let i = 0; i < rules.length; i++) { | ||
const match = (rules[i] as { match: RegExp }).match.exec(textBefore); | ||
const tr = | ||
match && | ||
match[0] && | ||
( | ||
rules[i] as { handler: (state: EditorState, match: string[], from: number, to: number) => Transaction } | ||
).handler(state, match, from - (match[0].length - text.length), to); | ||
if (!tr) continue; | ||
view.dispatch(tr.setMeta(plugin, { transform: tr, from, to, text })); | ||
return true; | ||
} | ||
return false; | ||
if (view.composing) | ||
return false | ||
const state = view.state | ||
const $from = state.doc.resolve(from) | ||
if ($from.parent.type.spec.code) | ||
return false | ||
const textBefore | ||
= $from.parent.textBetween(Math.max(0, $from.parentOffset - 500), $from.parentOffset, undefined, '\uFFFC') + text | ||
for (let i = 0; i < rules.length; i++) { | ||
const match = (rules[i] as { match: RegExp }).match.exec(textBefore) | ||
const tr | ||
= match | ||
&& match[0] | ||
&& ( | ||
rules[i] as { handler: (state: EditorState, match: string[], from: number, to: number) => Transaction } | ||
).handler(state, match, from - (match[0].length - text.length), to) | ||
if (!tr) | ||
continue | ||
view.dispatch(tr.setMeta(plugin, { transform: tr, from, to, text })) | ||
return true | ||
} | ||
return false | ||
} | ||
export const customInputRulesKey = new PluginKey('MILKDOWN_CUSTOM_INPUTRULES'); | ||
export const customInputRulesKey = new PluginKey('MILKDOWN_CUSTOM_INPUTRULES') | ||
export const customInputRules = ({ rules }: { rules: InputRule[] }): Plugin => { | ||
const plugin: Plugin = new Plugin({ | ||
key: customInputRulesKey, | ||
isInputRules: true, | ||
const plugin: Plugin = new Plugin({ | ||
key: customInputRulesKey, | ||
isInputRules: true, | ||
state: { | ||
init() { | ||
return null; | ||
}, | ||
apply(this: typeof plugin, tr, prev) { | ||
const stored = tr.getMeta(this); | ||
if (stored) return stored; | ||
return tr.selectionSet || tr.docChanged ? null : prev; | ||
}, | ||
state: { | ||
init() { | ||
return null | ||
}, | ||
apply(this: typeof plugin, tr, prev) { | ||
const stored = tr.getMeta(this) | ||
if (stored) | ||
return stored | ||
return tr.selectionSet || tr.docChanged ? null : prev | ||
}, | ||
}, | ||
props: { | ||
handleTextInput(view, from, to, text) { | ||
return run(view, from, to, text, rules, plugin) | ||
}, | ||
handleDOMEvents: { | ||
compositionend: (view) => { | ||
setTimeout(() => { | ||
const { $cursor } = view.state.selection as TextSelection | ||
if ($cursor) | ||
run(view, $cursor.pos, $cursor.pos, '', rules, plugin) | ||
}) | ||
return false | ||
}, | ||
props: { | ||
handleTextInput(view, from, to, text) { | ||
return run(view, from, to, text, rules, plugin); | ||
}, | ||
handleDOMEvents: { | ||
compositionend: (view) => { | ||
setTimeout(() => { | ||
const { $cursor } = view.state.selection as TextSelection; | ||
if ($cursor) run(view, $cursor.pos, $cursor.pos, '', rules, plugin); | ||
}); | ||
return false; | ||
}, | ||
}, | ||
handleKeyDown(view, event) { | ||
if (event.key !== 'Enter') return false; | ||
const { $cursor } = view.state.selection as TextSelection; | ||
if ($cursor) return run(view, $cursor.pos, $cursor.pos, '\n', rules, plugin); | ||
return false; | ||
}, | ||
}, | ||
}); | ||
return plugin; | ||
}; | ||
}, | ||
handleKeyDown(view, event) { | ||
if (event.key !== 'Enter') | ||
return false | ||
const { $cursor } = view.state.selection as TextSelection | ||
if ($cursor) | ||
return run(view, $cursor.pos, $cursor.pos, '\n', rules, plugin) | ||
return false | ||
}, | ||
}, | ||
}) | ||
return plugin | ||
} |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from './custom-input-rules'; | ||
export * from './mark-rule'; | ||
export * from './custom-input-rules' | ||
export * from './mark-rule' |
/* Copyright 2021, Milkdown by Mirone. */ | ||
import { InputRule } from '../../inputrules'; | ||
import { Mark, MarkType } from '../../model'; | ||
import { EditorState } from '../../state'; | ||
import { InputRule } from '../../inputrules' | ||
import type { Mark, MarkType } from '../../model' | ||
import type { EditorState } from '../../state' | ||
export function markRule(regexp: RegExp, markType: MarkType): InputRule { | ||
return new InputRule(regexp, (state, match, start, end) => { | ||
const { tr } = state; | ||
const matchLength = match.length; | ||
return new InputRule(regexp, (state, match, start, end) => { | ||
const { tr } = state | ||
const matchLength = match.length | ||
let markStart = start; | ||
let markEnd = end; | ||
let markStart = start | ||
let markEnd = end | ||
if (match[matchLength - 1]) { | ||
const first = match[0] as string; | ||
const last = match[matchLength - 1] as string; | ||
const last1 = match[matchLength - 2] as string; | ||
if (match[matchLength - 1]) { | ||
const first = match[0] as string | ||
const last = match[matchLength - 1] as string | ||
const last1 = match[matchLength - 2] as string | ||
const matchStart = start + first.indexOf(last1); | ||
const matchEnd = matchStart + last1.length - 1; | ||
const textStart = matchStart + last1.lastIndexOf(last); | ||
const textEnd = textStart + last.length; | ||
const matchStart = start + first.indexOf(last1) | ||
const matchEnd = matchStart + last1.length - 1 | ||
const textStart = matchStart + last1.lastIndexOf(last) | ||
const textEnd = textStart + last.length | ||
const excludedMarks = getMarksBetween(start, end, state) | ||
.filter((item) => item.mark.type.excludes(markType)) | ||
.filter((item) => item.end > matchStart); | ||
const excludedMarks = getMarksBetween(start, end, state) | ||
.filter(item => item.mark.type.excludes(markType)) | ||
.filter(item => item.end > matchStart) | ||
if (excludedMarks.length) { | ||
return null; | ||
} | ||
if (excludedMarks.length) | ||
return null | ||
if (textEnd < matchEnd) { | ||
tr.delete(textEnd, matchEnd); | ||
} | ||
if (textStart > matchStart) { | ||
tr.delete(matchStart, textStart); | ||
} | ||
markStart = matchStart; | ||
markEnd = markStart + last.length; | ||
} | ||
tr.addMark(markStart, markEnd, markType.create()); | ||
tr.removeStoredMark(markType); | ||
return tr; | ||
}); | ||
if (textEnd < matchEnd) | ||
tr.delete(textEnd, matchEnd) | ||
if (textStart > matchStart) | ||
tr.delete(matchStart, textStart) | ||
markStart = matchStart | ||
markEnd = markStart + last.length | ||
} | ||
tr.addMark(markStart, markEnd, markType.create()) | ||
tr.removeStoredMark(markType) | ||
return tr | ||
}) | ||
} | ||
function getMarksBetween(start: number, end: number, state: EditorState) { | ||
let marks: { start: number; end: number; mark: Mark }[] = []; | ||
let marks: { start: number; end: number; mark: Mark }[] = [] | ||
state.doc.nodesBetween(start, end, (node, pos) => { | ||
marks = [ | ||
...marks, | ||
...node.marks.map((mark) => ({ | ||
start: pos, | ||
end: pos + node.nodeSize, | ||
mark, | ||
})), | ||
]; | ||
}); | ||
state.doc.nodesBetween(start, end, (node, pos) => { | ||
marks = [ | ||
...marks, | ||
...node.marks.map(mark => ({ | ||
start: pos, | ||
end: pos + node.nodeSize, | ||
mark, | ||
})), | ||
] | ||
}) | ||
return marks; | ||
return marks | ||
} |
/* Copyright 2021, Milkdown by Mirone. */ | ||
import { expectDomTypeError, missingRootElement } from '@milkdown/exception'; | ||
import { expectDomTypeError, missingRootElement } from '@milkdown/exception' | ||
import type { EditorView } from '../../view'; | ||
import type { EditorView } from '../../view' | ||
type Point = [top: number, left: number]; | ||
type Point = [top: number, left: number] | ||
export const calculateNodePosition = ( | ||
view: EditorView, | ||
target: HTMLElement, | ||
handler: (selectedRect: DOMRect, targetRect: DOMRect, parentRect: DOMRect) => Point, | ||
view: EditorView, | ||
target: HTMLElement, | ||
handler: (selectedRect: DOMRect, targetRect: DOMRect, parentRect: DOMRect) => Point, | ||
) => { | ||
const state = view.state; | ||
const { from } = state.selection; | ||
const state = view.state | ||
const { from } = state.selection | ||
const { node } = view.domAtPos(from); | ||
const element = node instanceof Text ? node.parentElement : node; | ||
if (!(element instanceof HTMLElement)) { | ||
throw expectDomTypeError(element); | ||
} | ||
const { node } = view.domAtPos(from) | ||
const element = node instanceof Text ? node.parentElement : node | ||
if (!(element instanceof HTMLElement)) | ||
throw expectDomTypeError(element) | ||
const selectedNodeRect = element.getBoundingClientRect(); | ||
const targetNodeRect = target.getBoundingClientRect(); | ||
const parent = target.parentElement; | ||
if (!parent) { | ||
throw expectDomTypeError(parent); | ||
} | ||
const parentNodeRect = parent.getBoundingClientRect(); | ||
const selectedNodeRect = element.getBoundingClientRect() | ||
const targetNodeRect = target.getBoundingClientRect() | ||
const parent = target.parentElement | ||
if (!parent) | ||
throw expectDomTypeError(parent) | ||
const [top, left] = handler(selectedNodeRect, targetNodeRect, parentNodeRect); | ||
const parentNodeRect = parent.getBoundingClientRect() | ||
target.style.top = top + 'px'; | ||
target.style.left = left + 'px'; | ||
}; | ||
const [top, left] = handler(selectedNodeRect, targetNodeRect, parentNodeRect) | ||
type Rect = { | ||
left: number; | ||
right: number; | ||
top: number; | ||
bottom: number; | ||
}; | ||
target.style.top = `${top}px` | ||
target.style.left = `${left}px` | ||
} | ||
interface Rect { | ||
left: number | ||
right: number | ||
top: number | ||
bottom: number | ||
} | ||
export const calculateTextPosition = ( | ||
view: EditorView, | ||
target: HTMLElement, | ||
handler: (start: Rect, end: Rect, targetRect: DOMRect, parentRect: DOMRect) => Point, | ||
view: EditorView, | ||
target: HTMLElement, | ||
handler: (start: Rect, end: Rect, targetRect: DOMRect, parentRect: DOMRect) => Point, | ||
) => { | ||
const state = view.state; | ||
const { from, to } = state.selection; | ||
const start = view.coordsAtPos(from); | ||
const end = view.coordsAtPos(to); | ||
const state = view.state | ||
const { from, to } = state.selection | ||
const start = view.coordsAtPos(from) | ||
const end = view.coordsAtPos(to) | ||
const targetNodeRect = target.getBoundingClientRect(); | ||
const parent = target.parentElement; | ||
if (!parent) { | ||
throw missingRootElement(); | ||
} | ||
const parentNodeRect = parent.getBoundingClientRect(); | ||
const targetNodeRect = target.getBoundingClientRect() | ||
const parent = target.parentElement | ||
if (!parent) | ||
throw missingRootElement() | ||
const [top, left] = handler(start, end, targetNodeRect, parentNodeRect); | ||
const parentNodeRect = parent.getBoundingClientRect() | ||
target.style.top = top + 'px'; | ||
target.style.left = left + 'px'; | ||
}; | ||
const [top, left] = handler(start, end, targetNodeRect, parentNodeRect) | ||
target.style.top = `${top}px` | ||
target.style.left = `${left}px` | ||
} |
/* Copyright 2021, Milkdown by Mirone. */ | ||
import type { Node as ProseNode, NodeType } from '../../model'; | ||
import type { Transaction } from '../../state'; | ||
import type { NodeType, Node as ProseNode } from '../../model' | ||
import type { Transaction } from '../../state' | ||
export const cloneTr = (tr: Transaction): Transaction => { | ||
return Object.assign(Object.create(tr), tr).setTime(Date.now()); | ||
}; | ||
return Object.assign(Object.create(tr), tr).setTime(Date.now()) | ||
} | ||
export const equalNodeType = (nodeType: NodeType | NodeType[], node: ProseNode) => { | ||
return (Array.isArray(nodeType) && nodeType.indexOf(node.type) > -1) || node.type === nodeType; | ||
}; | ||
return (Array.isArray(nodeType) && nodeType.includes(node.type)) || node.type === nodeType | ||
} |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from './helper'; | ||
export * from './node'; | ||
export * from './schema'; | ||
export * from './selection'; | ||
export * from './helper' | ||
export * from './node' | ||
export * from './schema' | ||
export * from './selection' |
/* Copyright 2021, Milkdown by Mirone. */ | ||
import type { MarkType, Node as ProseNode } from '../../model'; | ||
import type { Predicate } from './types'; | ||
import type { MarkType, Node as ProseNode } from '../../model' | ||
import type { Predicate } from './types' | ||
export type NodeWithPos = { pos: number; node: ProseNode }; | ||
export interface NodeWithPos { pos: number; node: ProseNode } | ||
export const flatten = (node: ProseNode, descend = true): NodeWithPos[] => { | ||
const result: NodeWithPos[] = []; | ||
node.descendants((child, pos) => { | ||
result.push({ node: child, pos }); | ||
if (!descend) { | ||
return false; | ||
} | ||
return undefined; | ||
}); | ||
return result; | ||
}; | ||
const result: NodeWithPos[] = [] | ||
node.descendants((child, pos) => { | ||
result.push({ node: child, pos }) | ||
if (!descend) | ||
return false | ||
export const findChildren = | ||
(predicate: Predicate) => | ||
(node: ProseNode, descend?: boolean): NodeWithPos[] => | ||
flatten(node, descend).filter((child) => predicate(child.node)); | ||
return undefined | ||
}) | ||
return result | ||
} | ||
export const findChildren | ||
= (predicate: Predicate) => | ||
(node: ProseNode, descend?: boolean): NodeWithPos[] => | ||
flatten(node, descend).filter(child => predicate(child.node)) | ||
export const findChildrenByMark = (node: ProseNode, markType: MarkType, descend?: boolean): NodeWithPos[] => | ||
findChildren((child) => Boolean(markType.isInSet(child.marks)))(node, descend); | ||
findChildren(child => Boolean(markType.isInSet(child.marks)))(node, descend) |
/* Copyright 2021, Milkdown by Mirone. */ | ||
import { getAtomFromSchemaFail } from '@milkdown/exception'; | ||
import { getAtomFromSchemaFail } from '@milkdown/exception' | ||
import type { MarkType, NodeType, Schema } from '../../model'; | ||
import type { MarkType, NodeType, Schema } from '../../model' | ||
export const getNodeFromSchema = (type: string, schema: Schema): NodeType => { | ||
const target = schema.nodes[type]; | ||
const target = schema.nodes[type] | ||
if (!target) { | ||
throw getAtomFromSchemaFail('node', type); | ||
} | ||
if (!target) | ||
throw getAtomFromSchemaFail('node', type) | ||
return target; | ||
}; | ||
return target | ||
} | ||
export const getMarkFromSchema = (type: string, schema: Schema): MarkType => { | ||
const target = schema.marks[type]; | ||
const target = schema.marks[type] | ||
if (!target) { | ||
throw getAtomFromSchemaFail('mark', type); | ||
} | ||
if (!target) | ||
throw getAtomFromSchemaFail('mark', type) | ||
return target; | ||
}; | ||
return target | ||
} |
/* Copyright 2021, Milkdown by Mirone. */ | ||
import type { Node as ProseNode, NodeType, ResolvedPos } from '../../model'; | ||
import { NodeSelection, Selection } from '../../state'; | ||
import { equalNodeType } from './helper'; | ||
import type { Predicate } from './types'; | ||
import type { NodeType, Node as ProseNode, ResolvedPos } from '../../model' | ||
import type { Selection } from '../../state' | ||
import { NodeSelection } from '../../state' | ||
import { equalNodeType } from './helper' | ||
import type { Predicate } from './types' | ||
export type ContentNodeWithPos = { pos: number; start: number; depth: number; node: ProseNode }; | ||
export interface ContentNodeWithPos { pos: number; start: number; depth: number; node: ProseNode } | ||
export const findParentNodeClosestToPos = | ||
(predicate: Predicate) => | ||
($pos: ResolvedPos): ContentNodeWithPos | undefined => { | ||
export const findParentNodeClosestToPos | ||
= (predicate: Predicate) => | ||
($pos: ResolvedPos): ContentNodeWithPos | undefined => { | ||
for (let i = $pos.depth; i > 0; i--) { | ||
const node = $pos.node(i); | ||
if (predicate(node)) { | ||
return { | ||
pos: i > 0 ? $pos.before(i) : 0, | ||
start: $pos.start(i), | ||
depth: i, | ||
node, | ||
}; | ||
const node = $pos.node(i) | ||
if (predicate(node)) { | ||
return { | ||
pos: i > 0 ? $pos.before(i) : 0, | ||
start: $pos.start(i), | ||
depth: i, | ||
node, | ||
} | ||
} | ||
} | ||
return; | ||
}; | ||
export const findParentNode = | ||
(predicate: Predicate) => | ||
(selection: Selection): ContentNodeWithPos | undefined => { | ||
return findParentNodeClosestToPos(predicate)(selection.$from); | ||
}; | ||
return undefined | ||
} | ||
export const findParentNode | ||
= (predicate: Predicate) => | ||
(selection: Selection): ContentNodeWithPos | undefined => { | ||
return findParentNodeClosestToPos(predicate)(selection.$from) | ||
} | ||
export const findSelectedNodeOfType = (selection: Selection, nodeType: NodeType): ContentNodeWithPos | undefined => { | ||
if (!(selection instanceof NodeSelection)) { | ||
return; | ||
} | ||
const { node, $from } = selection; | ||
if (equalNodeType(nodeType, node)) { | ||
return { node, pos: $from.pos, start: $from.start($from.depth), depth: $from.depth }; | ||
} | ||
return undefined; | ||
}; | ||
if (!(selection instanceof NodeSelection)) | ||
return | ||
const { node, $from } = selection | ||
if (equalNodeType(nodeType, node)) | ||
return { node, pos: $from.pos, start: $from.start($from.depth), depth: $from.depth } | ||
return undefined | ||
} |
/* Copyright 2021, Milkdown by Mirone. */ | ||
import type { Node as ProseNode } from '../../model'; | ||
import type { Node as ProseNode } from '../../model' | ||
export type Predicate = (node: ProseNode) => boolean; | ||
export type Predicate = (node: ProseNode) => boolean |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from 'prosemirror-transform'; | ||
export * from 'prosemirror-transform' |
/* Copyright 2021, Milkdown by Mirone. */ | ||
export * from 'prosemirror-view'; | ||
export * from 'prosemirror-view' |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
54313
675
+ Added@milkdown/exception@6.5.3(transitive)
- Removed@milkdown/exception@6.5.2(transitive)
Updated@milkdown/exception@6.5.3