@prosekit/extensions
Advanced tools
Comparing version 0.0.0-next-20240427200701 to 0.0.0-next-20240427202431
@@ -422,2 +422,4 @@ import { Attrs } from '@prosekit/pm/model'; | ||
export declare function defineLinkMarkRule(): Extension<ExtensionTyping<string, string, CommandArgs>>; | ||
export declare function defineLinkSpec(): Extension< { | ||
@@ -424,0 +426,0 @@ MARKS: "link"; |
@@ -5,3 +5,4 @@ export { defineLinkSpec } from './_tsup-dts-rollup'; | ||
export { defineLinkEnterRule } from './_tsup-dts-rollup'; | ||
export { defineLinkMarkRule } from './_tsup-dts-rollup'; | ||
export { defineLink } from './_tsup-dts-rollup'; | ||
export { LinkAttrs } from './_tsup-dts-rollup'; |
import { | ||
defineMarkRule | ||
} from "./chunk-TXF4SPMB.js"; | ||
import { | ||
defineEnterRule | ||
@@ -88,2 +91,9 @@ } from "./chunk-ASTUC4KT.js"; | ||
} | ||
function defineLinkMarkRule() { | ||
return defineMarkRule({ | ||
regex: LINK_RE, | ||
type: "link", | ||
attrs: (match) => ({ href: match[1] }) | ||
}); | ||
} | ||
function defineLink() { | ||
@@ -102,3 +112,4 @@ return union([ | ||
defineLinkInputRule, | ||
defineLinkMarkRule, | ||
defineLinkSpec | ||
}; |
@@ -1,184 +0,6 @@ | ||
// src/mark-rule/index.ts | ||
import { Facet, pluginFacet } from "@prosekit/core"; | ||
import { ProseMirrorPlugin } from "@prosekit/pm/state"; | ||
// src/mark-rule/apply.ts | ||
import { OBJECT_REPLACEMENT_CHARACTER, getMarkType } from "@prosekit/core"; | ||
import "@prosekit/pm/model"; | ||
import "@prosekit/pm/state"; | ||
// src/mark-rule/range.ts | ||
import "@prosekit/pm/state"; | ||
function getSpanTextRanges($from, $to) { | ||
const nodeRange = $from.blockRange($to); | ||
if (!nodeRange) { | ||
return []; | ||
} | ||
const stack = []; | ||
let start = nodeRange.start; | ||
for (let i = nodeRange.startIndex; i < nodeRange.endIndex; i++) { | ||
const child = nodeRange.parent.child(i); | ||
stack.push([start, child]); | ||
start += child.nodeSize; | ||
} | ||
const ranges = []; | ||
while (stack.length > 0) { | ||
const [start2, node] = stack.pop(); | ||
if (node.type.spec.code) { | ||
continue; | ||
} | ||
if (node.type.isTextblock) { | ||
ranges.push([start2 + 1, start2 + 1 + node.content.size]); | ||
continue; | ||
} | ||
node.forEach((child, offset) => { | ||
stack.push([start2 + offset + 1, child]); | ||
}); | ||
} | ||
return ranges; | ||
} | ||
function getInlineTextRange($from, $to) { | ||
return [$from.start(), $to.end()]; | ||
} | ||
function getTextRanges(doc, from, to) { | ||
const $from = doc.resolve(from); | ||
const $to = doc.resolve(to); | ||
if ($from.sameParent($to) && $from.parent.isTextblock) { | ||
return [getInlineTextRange($from, $to)]; | ||
} else { | ||
const nodeRange = $from.blockRange($to); | ||
if (!nodeRange) { | ||
return []; | ||
} | ||
return getSpanTextRanges($from, $to); | ||
} | ||
} | ||
function getMapRange(transactions, oldState, newState) { | ||
let lo = oldState.selection.from; | ||
let hi = oldState.selection.to; | ||
for (const tr of transactions) { | ||
for (const map of tr.mapping.maps) { | ||
lo = map.map(lo); | ||
hi = map.map(hi); | ||
map.forEach((_oldStart, _oldEnd, newStart, newEnd) => { | ||
lo = Math.min(lo, hi, newStart); | ||
hi = Math.max(hi, hi, newEnd); | ||
}); | ||
} | ||
} | ||
lo = Math.min(lo, hi, newState.selection.from); | ||
hi = Math.min(lo, hi, newState.selection.to); | ||
return [lo, hi]; | ||
} | ||
function getCheckRanges(transactions, oldState, newState) { | ||
const [from, to] = getMapRange(transactions, oldState, newState); | ||
return getTextRanges(newState.doc, from, to); | ||
} | ||
// src/mark-rule/apply.ts | ||
function getExpectedMarkings(rules, doc, from, to) { | ||
const text = doc.textBetween(from, to, OBJECT_REPLACEMENT_CHARACTER); | ||
const result = []; | ||
for (const rule of rules) { | ||
rule.regex.lastIndex = 0; | ||
const matches = text.matchAll(rule.regex); | ||
const markType = getMarkType(doc.type.schema, rule.type); | ||
for (const match of matches) { | ||
const index = match.index; | ||
if (index == null) | ||
continue; | ||
const attrs = rule.getAttrs(match); | ||
const mark = markType.create(attrs); | ||
result.push([mark, from + index, from + index + match[0].length]); | ||
} | ||
} | ||
return result; | ||
} | ||
function getReceivedMarkings(rules, doc, from, to) { | ||
const result = []; | ||
const schema = doc.type.schema; | ||
const markTypes = rules.map((rule) => getMarkType(schema, rule.type)); | ||
doc.nodesBetween(from, to, (node, pos) => { | ||
if (!node.isInline) { | ||
return; | ||
} | ||
for (const markType of markTypes) { | ||
const mark = node.marks.find((mark2) => mark2.type === markType); | ||
if (mark) { | ||
result.push([mark, pos, pos + node.nodeSize]); | ||
} | ||
} | ||
}); | ||
return result; | ||
} | ||
function markingEquals(a, b) { | ||
return a[1] === b[1] && a[2] === b[2] && a[0].eq(b[0]); | ||
} | ||
function markingDiffs(a, b) { | ||
return a.filter((x) => !b.some((y) => markingEquals(x, y))); | ||
} | ||
function applyMarkRules(rules, transactions, oldState, newState) { | ||
if (transactions.length === 0 || transactions.every((tr2) => !tr2.docChanged)) { | ||
return null; | ||
} | ||
const ranges = getCheckRanges(transactions, oldState, newState); | ||
const toRemove = []; | ||
const toCreate = []; | ||
for (const [from, to] of ranges) { | ||
const expected = getExpectedMarkings(rules, newState.doc, from, to); | ||
const received = getReceivedMarkings(rules, newState.doc, from, to); | ||
toRemove.push(...markingDiffs(received, expected)); | ||
toCreate.push(...markingDiffs(expected, received)); | ||
} | ||
if (toCreate.length === 0 && toRemove.length === 0) { | ||
return null; | ||
} | ||
const tr = newState.tr; | ||
for (const [mark, from, to] of toRemove) { | ||
tr.removeMark(from, to, mark); | ||
} | ||
for (const [mark, from, to] of toCreate) { | ||
tr.addMark(from, to, mark); | ||
} | ||
return tr; | ||
} | ||
// src/mark-rule/rule.ts | ||
import "@prosekit/pm/model"; | ||
var MarkRule = class { | ||
constructor({ regex, type, attrs = null }) { | ||
this.regex = regex; | ||
this.type = type; | ||
this.getAttrs = typeof attrs === "function" ? attrs : () => attrs; | ||
} | ||
}; | ||
// src/mark-rule/index.ts | ||
function defineMarkRule(options) { | ||
return markRuleFacet.extension([new MarkRule(options)]); | ||
} | ||
var markRuleFacet = Facet.define({ | ||
converter: () => { | ||
let rules = []; | ||
const plugin = new ProseMirrorPlugin({ | ||
appendTransaction: (transactions, oldState, newState) => { | ||
return applyMarkRules(rules, transactions, oldState, newState); | ||
} | ||
}); | ||
const pluginFunc = () => [plugin]; | ||
return { | ||
create: (inputs) => { | ||
rules = inputs; | ||
return pluginFunc; | ||
}, | ||
update: (inputs) => { | ||
rules = inputs; | ||
return null; | ||
} | ||
}; | ||
}, | ||
next: pluginFacet | ||
}); | ||
import { | ||
defineMarkRule | ||
} from "./chunk-TXF4SPMB.js"; | ||
export { | ||
defineMarkRule | ||
}; |
{ | ||
"name": "@prosekit/extensions", | ||
"type": "module", | ||
"version": "0.0.0-next-20240427200701", | ||
"version": "0.0.0-next-20240427202431", | ||
"private": false, | ||
@@ -155,4 +155,4 @@ "author": { | ||
"dependencies": { | ||
"@prosekit/core": "0.0.0-next-20240427200701", | ||
"@prosekit/pm": "0.0.0-next-20240427200701", | ||
"@prosekit/core": "0.0.0-next-20240427202431", | ||
"@prosekit/pm": "0.0.0-next-20240427202431", | ||
"prosemirror-dropcursor": "^1.8.1", | ||
@@ -159,0 +159,0 @@ "prosemirror-flat-list": "^0.5.0", |
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
95478
56
2808
+ Added@prosekit/core@0.0.0-next-20240427202431(transitive)
+ Added@prosekit/pm@0.0.0-next-20240427202431(transitive)
- Removed@prosekit/core@0.0.0-next-20240427200701(transitive)
- Removed@prosekit/pm@0.0.0-next-20240427200701(transitive)