@milkdown/preset-commonmark
Advanced tools
Comparing version 4.9.6 to 4.10.0
@@ -0,1 +1,2 @@ | ||
import { css } from '@emotion/css'; | ||
import { createCmd, createCmdKey } from '@milkdown/core'; | ||
@@ -7,30 +8,43 @@ import { createMark, createShortcut, markRule } from '@milkdown/utils'; | ||
export const ToggleInlineCode = createCmdKey(); | ||
export const codeInline = createMark((_, utils) => ({ | ||
id, | ||
schema: { | ||
excludes: '_', | ||
parseDOM: [{ tag: 'code' }], | ||
toDOM: (mark) => ['code', { class: utils.getClassName(mark.attrs, 'code-inline') }], | ||
}, | ||
parser: { | ||
match: (node) => node.type === 'inlineCode', | ||
runner: (state, node, markType) => { | ||
state.openMark(markType); | ||
state.addText(node.value); | ||
state.closeMark(markType); | ||
export const codeInline = createMark((options, utils) => { | ||
const { palette } = utils.themeTool; | ||
const style = (options === null || options === void 0 ? void 0 : options.headless) | ||
? null | ||
: css ` | ||
background-color: ${palette('neutral')}; | ||
color: ${palette('background')}; | ||
border-radius: ${utils.themeTool.size.radius}; | ||
font-weight: 500; | ||
font-family: ${utils.themeTool.font.fontCode}; | ||
padding: 0 0.2rem; | ||
`; | ||
return { | ||
id, | ||
schema: { | ||
excludes: '_', | ||
parseDOM: [{ tag: 'code' }], | ||
toDOM: (mark) => ['code', { class: utils.getClassName(mark.attrs, 'code-inline', style) }], | ||
}, | ||
}, | ||
serializer: { | ||
match: (mark) => mark.type.name === id, | ||
runner: (state, _, node) => { | ||
state.addNode('inlineCode', undefined, node.text || ''); | ||
return true; | ||
parser: { | ||
match: (node) => node.type === 'inlineCode', | ||
runner: (state, node, markType) => { | ||
state.openMark(markType); | ||
state.addText(node.value); | ||
state.closeMark(markType); | ||
}, | ||
}, | ||
}, | ||
inputRules: (markType) => [markRule(/(?:^|[^`])(`([^`]+)`)$/, markType)], | ||
commands: (markType) => [createCmd(ToggleInlineCode, () => toggleMark(markType))], | ||
shortcuts: { | ||
[SupportedKeys.CodeInline]: createShortcut(ToggleInlineCode, 'Mod-e'), | ||
}, | ||
})); | ||
serializer: { | ||
match: (mark) => mark.type.name === id, | ||
runner: (state, _, node) => { | ||
state.addNode('inlineCode', undefined, node.text || ''); | ||
return true; | ||
}, | ||
}, | ||
inputRules: (markType) => [markRule(/(?:^|[^`])(`([^`]+)`)$/, markType)], | ||
commands: (markType) => [createCmd(ToggleInlineCode, () => toggleMark(markType))], | ||
shortcuts: { | ||
[SupportedKeys.CodeInline]: createShortcut(ToggleInlineCode, 'Mod-e'), | ||
}, | ||
}; | ||
}); | ||
//# sourceMappingURL=code-inline.js.map |
@@ -6,90 +6,106 @@ import { createCmd, createCmdKey } from '@milkdown/core'; | ||
import { TextSelection } from 'prosemirror-state'; | ||
import { css } from '@emotion/css'; | ||
export const ToggleLink = createCmdKey(); | ||
export const ModifyLink = createCmdKey(); | ||
const id = 'link'; | ||
export const link = createMark((_, utils) => ({ | ||
id, | ||
schema: { | ||
attrs: { | ||
href: {}, | ||
title: { default: null }, | ||
export const link = createMark((options, utils) => { | ||
const lineColor = utils.themeTool.palette('line'); | ||
const style = (options === null || options === void 0 ? void 0 : options.headless) | ||
? null | ||
: css ` | ||
color: ${utils.themeTool.palette('secondary')}; | ||
cursor: pointer; | ||
transition: all 0.4s ease-in-out; | ||
font-weight: 500; | ||
&:hover { | ||
background-color: ${lineColor}; | ||
box-shadow: 0 0.2rem ${lineColor}, 0 -0.2rem ${lineColor}; | ||
} | ||
`; | ||
return { | ||
id, | ||
schema: { | ||
attrs: { | ||
href: {}, | ||
title: { default: null }, | ||
}, | ||
inclusive: false, | ||
parseDOM: [ | ||
{ | ||
tag: 'a[href]', | ||
getAttrs: (dom) => { | ||
if (!(dom instanceof HTMLElement)) { | ||
throw new Error(); | ||
} | ||
return { href: dom.getAttribute('href'), title: dom.getAttribute('title') }; | ||
}, | ||
}, | ||
], | ||
toDOM: (mark) => ['a', Object.assign(Object.assign({}, mark.attrs), { class: utils.getClassName(mark.attrs, id, style) })], | ||
}, | ||
inclusive: false, | ||
parseDOM: [ | ||
{ | ||
tag: 'a[href]', | ||
getAttrs: (dom) => { | ||
if (!(dom instanceof HTMLElement)) { | ||
throw new Error(); | ||
} | ||
return { href: dom.getAttribute('href'), title: dom.getAttribute('title') }; | ||
}, | ||
parser: { | ||
match: (node) => node.type === 'link', | ||
runner: (state, node, markType) => { | ||
const url = node.url; | ||
const title = node.title; | ||
state.openMark(markType, { href: url, title }); | ||
state.next(node.children); | ||
state.closeMark(markType); | ||
}, | ||
], | ||
toDOM: (mark) => ['a', Object.assign(Object.assign({}, mark.attrs), { class: utils.getClassName(mark.attrs, id) })], | ||
}, | ||
parser: { | ||
match: (node) => node.type === 'link', | ||
runner: (state, node, markType) => { | ||
const url = node.url; | ||
const title = node.title; | ||
state.openMark(markType, { href: url, title }); | ||
state.next(node.children); | ||
state.closeMark(markType); | ||
}, | ||
}, | ||
serializer: { | ||
match: (mark) => mark.type.name === id, | ||
runner: (state, mark) => { | ||
state.withMark(mark, 'link', undefined, { | ||
title: mark.attrs.title, | ||
url: mark.attrs.href, | ||
}); | ||
serializer: { | ||
match: (mark) => mark.type.name === id, | ||
runner: (state, mark) => { | ||
state.withMark(mark, 'link', undefined, { | ||
title: mark.attrs.title, | ||
url: mark.attrs.href, | ||
}); | ||
}, | ||
}, | ||
}, | ||
commands: (markType) => [ | ||
createCmd(ToggleLink, (href = '') => toggleMark(markType, { href })), | ||
createCmd(ModifyLink, (href = '') => (state, dispatch) => { | ||
if (!dispatch) | ||
return false; | ||
const { marks } = state.schema; | ||
let node; | ||
let pos = -1; | ||
const { selection } = state; | ||
state.doc.nodesBetween(selection.from, selection.to, (n, p) => { | ||
if (marks.link.isInSet(n.marks)) { | ||
node = n; | ||
pos = p; | ||
commands: (markType) => [ | ||
createCmd(ToggleLink, (href = '') => toggleMark(markType, { href })), | ||
createCmd(ModifyLink, (href = '') => (state, dispatch) => { | ||
if (!dispatch) | ||
return false; | ||
const { marks } = state.schema; | ||
let node; | ||
let pos = -1; | ||
const { selection } = state; | ||
state.doc.nodesBetween(selection.from, selection.to, (n, p) => { | ||
if (marks.link.isInSet(n.marks)) { | ||
node = n; | ||
pos = p; | ||
return false; | ||
} | ||
return; | ||
}); | ||
if (!node) | ||
return false; | ||
const mark = node.marks.find(({ type }) => type === markType); | ||
if (!mark) | ||
return false; | ||
const start = pos; | ||
const end = pos + node.nodeSize; | ||
const { tr } = state; | ||
const linkMark = marks.link.create(Object.assign(Object.assign({}, mark.attrs), { href })); | ||
dispatch(tr | ||
.removeMark(start, end, mark) | ||
.addMark(start, end, linkMark) | ||
.setSelection(new TextSelection(tr.selection.$anchor)) | ||
.scrollIntoView()); | ||
return true; | ||
}), | ||
], | ||
inputRules: (markType, schema) => [ | ||
new InputRule(/\[(?<text>.+?)]\((?<href>.*?)(?=“|\))"?(?<title>[^"]+)?"?\)/, (state, match, start, end) => { | ||
const [okay, text = '', href, title] = match; | ||
const { tr } = state; | ||
if (okay) { | ||
tr.replaceWith(start, end, schema.text(text)).addMark(start, text.length + start, markType.create({ title, href })); | ||
} | ||
return; | ||
}); | ||
if (!node) | ||
return false; | ||
const mark = node.marks.find(({ type }) => type === markType); | ||
if (!mark) | ||
return false; | ||
const start = pos; | ||
const end = pos + node.nodeSize; | ||
const { tr } = state; | ||
const linkMark = marks.link.create(Object.assign(Object.assign({}, mark.attrs), { href })); | ||
dispatch(tr | ||
.removeMark(start, end, mark) | ||
.addMark(start, end, linkMark) | ||
.setSelection(new TextSelection(tr.selection.$anchor)) | ||
.scrollIntoView()); | ||
return true; | ||
}), | ||
], | ||
inputRules: (markType, schema) => [ | ||
new InputRule(/\[(?<text>.+?)]\((?<href>.*?)(?=“|\))"?(?<title>[^"]+)?"?\)/, (state, match, start, end) => { | ||
const [okay, text = '', href, title] = match; | ||
const { tr } = state; | ||
if (okay) { | ||
tr.replaceWith(start, end, schema.text(text)).addMark(start, text.length + start, markType.create({ title, href })); | ||
} | ||
return tr; | ||
}), | ||
], | ||
})); | ||
return tr; | ||
}), | ||
], | ||
}; | ||
}); | ||
//# sourceMappingURL=link.js.map |
@@ -0,1 +1,2 @@ | ||
import { css } from '@emotion/css'; | ||
import { createCmdKey, createCmd } from '@milkdown/core'; | ||
@@ -8,35 +9,42 @@ import { createMark, markRule } from '@milkdown/utils'; | ||
export const ToggleBold = createCmdKey(); | ||
export const strong = createMark((_, utils) => ({ | ||
id, | ||
schema: { | ||
parseDOM: [ | ||
{ tag: 'b' }, | ||
{ tag: 'strong' }, | ||
{ style: 'font-style', getAttrs: (value) => (value === 'bold') }, | ||
export const strong = createMark((options, utils) => { | ||
const style = (options === null || options === void 0 ? void 0 : options.headless) | ||
? null | ||
: css ` | ||
font-weight: 600; | ||
`; | ||
return { | ||
id, | ||
schema: { | ||
parseDOM: [ | ||
{ tag: 'b' }, | ||
{ tag: 'strong' }, | ||
{ style: 'font-style', getAttrs: (value) => (value === 'bold') }, | ||
], | ||
toDOM: (mark) => ['strong', { class: utils.getClassName(mark.attrs, id, style) }], | ||
}, | ||
parser: { | ||
match: (node) => node.type === 'strong', | ||
runner: (state, node, markType) => { | ||
state.openMark(markType); | ||
state.next(node.children); | ||
state.closeMark(markType); | ||
}, | ||
}, | ||
serializer: { | ||
match: (mark) => mark.type.name === id, | ||
runner: (state, mark) => { | ||
state.withMark(mark, 'strong'); | ||
}, | ||
}, | ||
inputRules: (markType) => [ | ||
markRule(/(?:__)([^_]+)(?:__)$/, markType), | ||
markRule(/(?:\*\*)([^*]+)(?:\*\*)$/, markType), | ||
], | ||
toDOM: (mark) => ['strong', { class: utils.getClassName(mark.attrs, id) }], | ||
}, | ||
parser: { | ||
match: (node) => node.type === 'strong', | ||
runner: (state, node, markType) => { | ||
state.openMark(markType); | ||
state.next(node.children); | ||
state.closeMark(markType); | ||
commands: (markType) => [createCmd(ToggleBold, () => toggleMark(markType))], | ||
shortcuts: { | ||
[SupportedKeys.Bold]: createShortcut(ToggleBold, 'Mod-b'), | ||
}, | ||
}, | ||
serializer: { | ||
match: (mark) => mark.type.name === id, | ||
runner: (state, mark) => { | ||
state.withMark(mark, 'strong'); | ||
}, | ||
}, | ||
inputRules: (markType) => [ | ||
markRule(/(?:__)([^_]+)(?:__)$/, markType), | ||
markRule(/(?:\*\*)([^*]+)(?:\*\*)$/, markType), | ||
], | ||
commands: (markType) => [createCmd(ToggleBold, () => toggleMark(markType))], | ||
shortcuts: { | ||
[SupportedKeys.Bold]: createShortcut(ToggleBold, 'Mod-b'), | ||
}, | ||
})); | ||
}; | ||
}); | ||
//# sourceMappingURL=strong.js.map |
@@ -0,1 +1,2 @@ | ||
import { css } from '@emotion/css'; | ||
import { createCmdKey, createCmd } from '@milkdown/core'; | ||
@@ -9,29 +10,42 @@ import { createNode } from '@milkdown/utils'; | ||
export const WrapInBlockquote = createCmdKey(); | ||
export const blockquote = createNode((_, utils) => ({ | ||
id, | ||
schema: { | ||
content: 'block+', | ||
group: 'block', | ||
defining: true, | ||
parseDOM: [{ tag: 'blockquote' }], | ||
toDOM: (node) => ['blockquote', { class: utils.getClassName(node.attrs, id) }, 0], | ||
}, | ||
parser: { | ||
match: ({ type }) => type === id, | ||
runner: (state, node, type) => { | ||
state.openNode(type).next(node.children).closeNode(); | ||
export const blockquote = createNode((options, utils) => { | ||
const style = (options === null || options === void 0 ? void 0 : options.headless) | ||
? null | ||
: css ` | ||
padding-left: 1.875rem; | ||
line-height: 1.75rem; | ||
border-left: 4px solid ${utils.themeTool.palette('primary')}; | ||
* { | ||
font-size: 1rem; | ||
line-height: 1.5rem; | ||
} | ||
`; | ||
return { | ||
id, | ||
schema: { | ||
content: 'block+', | ||
group: 'block', | ||
defining: true, | ||
parseDOM: [{ tag: 'blockquote' }], | ||
toDOM: (node) => ['blockquote', { class: utils.getClassName(node.attrs, id, style) }, 0], | ||
}, | ||
}, | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state, node) => { | ||
state.openNode('blockquote').next(node.content).closeNode(); | ||
parser: { | ||
match: ({ type }) => type === id, | ||
runner: (state, node, type) => { | ||
state.openNode(type).next(node.children).closeNode(); | ||
}, | ||
}, | ||
}, | ||
inputRules: (nodeType) => [wrappingInputRule(/^\s*>\s$/, nodeType)], | ||
commands: (nodeType) => [createCmd(WrapInBlockquote, () => wrapIn(nodeType))], | ||
shortcuts: { | ||
[SupportedKeys.Blockquote]: createShortcut(WrapInBlockquote, 'Mod-Shift-b'), | ||
}, | ||
})); | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state, node) => { | ||
state.openNode('blockquote').next(node.content).closeNode(); | ||
}, | ||
}, | ||
inputRules: (nodeType) => [wrappingInputRule(/^\s*>\s$/, nodeType)], | ||
commands: (nodeType) => [createCmd(WrapInBlockquote, () => wrapIn(nodeType))], | ||
shortcuts: { | ||
[SupportedKeys.Blockquote]: createShortcut(WrapInBlockquote, 'Mod-Shift-b'), | ||
}, | ||
}; | ||
}); | ||
//# sourceMappingURL=blockquote.js.map |
@@ -9,30 +9,32 @@ import { createCmdKey, createCmd } from '@milkdown/core'; | ||
const id = 'bullet_list'; | ||
export const bulletList = createNode((_, utils) => ({ | ||
id, | ||
schema: { | ||
content: 'listItem+', | ||
group: 'block', | ||
parseDOM: [{ tag: 'ul' }], | ||
toDOM: (node) => { | ||
return ['ul', { class: utils.getClassName(node.attrs, 'bullet-list') }, 0]; | ||
export const bulletList = createNode((_, utils) => { | ||
return { | ||
id, | ||
schema: { | ||
content: 'listItem+', | ||
group: 'block', | ||
parseDOM: [{ tag: 'ul' }], | ||
toDOM: (node) => { | ||
return ['ul', { class: utils.getClassName(node.attrs, 'bullet-list') }, 0]; | ||
}, | ||
}, | ||
}, | ||
parser: { | ||
match: ({ type, ordered }) => type === 'list' && !ordered, | ||
runner: (state, node, type) => { | ||
state.openNode(type).next(node.children).closeNode(); | ||
parser: { | ||
match: ({ type, ordered }) => type === 'list' && !ordered, | ||
runner: (state, node, type) => { | ||
state.openNode(type).next(node.children).closeNode(); | ||
}, | ||
}, | ||
}, | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state, node) => { | ||
state.openNode('list', undefined, { ordered: false }).next(node.content).closeNode(); | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state, node) => { | ||
state.openNode('list', undefined, { ordered: false }).next(node.content).closeNode(); | ||
}, | ||
}, | ||
}, | ||
inputRules: (nodeType) => [wrappingInputRule(/^\s*([-+*])\s$/, nodeType)], | ||
commands: (nodeType) => [createCmd(WrapInBulletList, () => wrapIn(nodeType))], | ||
shortcuts: { | ||
[SupportedKeys.BulletList]: createShortcut(WrapInBulletList, 'Mod-Shift-8'), | ||
}, | ||
})); | ||
inputRules: (nodeType) => [wrappingInputRule(/^\s*([-+*])\s$/, nodeType)], | ||
commands: (nodeType) => [createCmd(WrapInBulletList, () => wrapIn(nodeType))], | ||
shortcuts: { | ||
[SupportedKeys.BulletList]: createShortcut(WrapInBulletList, 'Mod-Shift-8'), | ||
}, | ||
}; | ||
}); | ||
//# sourceMappingURL=bullet-list.js.map |
@@ -0,1 +1,2 @@ | ||
import { css } from '@emotion/css'; | ||
import { createCmdKey, createCmd } from '@milkdown/core'; | ||
@@ -28,154 +29,265 @@ import { createNode } from '@milkdown/utils'; | ||
const id = 'fence'; | ||
export const codeFence = createNode((options, utils) => ({ | ||
id, | ||
schema: { | ||
content: 'text*', | ||
group: 'block', | ||
marks: '', | ||
defining: true, | ||
code: true, | ||
attrs: { | ||
language: { | ||
default: '', | ||
export const codeFence = createNode((options, utils) => { | ||
const { palette } = utils.themeTool; | ||
const { shadow, icon, scrollbar, border } = utils.themeTool.widget; | ||
const { lineWidth } = utils.themeTool.size; | ||
const style = (options === null || options === void 0 ? void 0 : options.headless) | ||
? null | ||
: css ` | ||
background-color: ${palette('background')}; | ||
color: ${palette('neutral')}; | ||
font-size: 0.85rem; | ||
padding: 1.2rem 0.4rem 1.4rem; | ||
border-radius: ${utils.themeTool.size.radius}; | ||
font-family: ${utils.themeTool.font.font}; | ||
* { | ||
margin: 0; | ||
} | ||
.code-fence_select-wrapper { | ||
position: relative; | ||
} | ||
.code-fence_value { | ||
width: 10.25rem; | ||
box-sizing: border-box; | ||
border-radius: ${utils.themeTool.size.radius}; | ||
margin: 0 1.2rem 1.2rem; | ||
${border === null || border === void 0 ? void 0 : border()}; | ||
${shadow === null || shadow === void 0 ? void 0 : shadow()}; | ||
cursor: pointer; | ||
background-color: ${palette('surface')}; | ||
position: relative; | ||
display: flex; | ||
color: ${palette('neutral', 0.87)}; | ||
letter-spacing: 0.5px; | ||
height: 2.625rem; | ||
align-items: center; | ||
&::after { | ||
${icon === null || icon === void 0 ? void 0 : icon('expand_more')}; | ||
width: 2.625rem; | ||
height: 100%; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
color: ${palette('solid', 0.87)}; | ||
border-left: ${lineWidth} solid ${palette('line')}; | ||
text-align: center; | ||
transition: all 0.4s ease-in-out; | ||
} | ||
&:hover::after { | ||
background: ${palette('background')}; | ||
color: ${palette('primary')}; | ||
} | ||
> span:first-child { | ||
padding-left: 1rem; | ||
flex: 1; | ||
font-weight: 500; | ||
} | ||
} | ||
.code-fence_select-option { | ||
list-style: none; | ||
line-height: 2rem; | ||
padding-left: 1rem; | ||
cursor: pointer; | ||
:hover { | ||
background: ${palette('secondary', 0.12)}; | ||
color: ${palette('primary')}; | ||
} | ||
} | ||
.code-fence_select { | ||
&[data-fold='true'] { | ||
display: none; | ||
} | ||
font-weight: 500; | ||
position: absolute; | ||
z-index: 1; | ||
top: 2.625rem; | ||
box-sizing: border-box; | ||
left: 1.2rem; | ||
padding: 0.5rem 0; | ||
max-height: 16.75rem; | ||
width: 10.25rem; | ||
${border === null || border === void 0 ? void 0 : border()}; | ||
${shadow === null || shadow === void 0 ? void 0 : shadow()}; | ||
background-color: ${palette('surface')}; | ||
border-top: none; | ||
overflow-y: auto; | ||
display: flex; | ||
flex-direction: column; | ||
${scrollbar === null || scrollbar === void 0 ? void 0 : scrollbar('y')} | ||
} | ||
code { | ||
line-height: 1.5; | ||
} | ||
pre { | ||
font-family: var(--font-code); | ||
margin: 0 1.2rem !important; | ||
overflow-x: scroll; | ||
white-space: pre !important; | ||
padding-bottom: 1.4rem; | ||
${scrollbar === null || scrollbar === void 0 ? void 0 : scrollbar('x')} | ||
} | ||
`; | ||
return { | ||
id, | ||
schema: { | ||
content: 'text*', | ||
group: 'block', | ||
marks: '', | ||
defining: true, | ||
code: true, | ||
attrs: { | ||
language: { | ||
default: '', | ||
}, | ||
fold: { | ||
default: true, | ||
}, | ||
}, | ||
fold: { | ||
default: true, | ||
parseDOM: [ | ||
{ | ||
tag: 'pre', | ||
preserveWhitespace: 'full', | ||
getAttrs: (dom) => { | ||
if (!(dom instanceof HTMLElement)) { | ||
throw new Error('Parse DOM error.'); | ||
} | ||
return { language: dom.dataset.language }; | ||
}, | ||
}, | ||
], | ||
toDOM: (node) => { | ||
return [ | ||
'div', | ||
{ | ||
'data-language': node.attrs.language, | ||
class: utils.getClassName(node.attrs, 'code-fence', style), | ||
}, | ||
['pre', ['code', { spellCheck: 'false' }, 0]], | ||
]; | ||
}, | ||
}, | ||
parseDOM: [ | ||
{ | ||
tag: 'pre', | ||
preserveWhitespace: 'full', | ||
getAttrs: (dom) => { | ||
if (!(dom instanceof HTMLElement)) { | ||
throw new Error('Parse DOM error.'); | ||
} | ||
return { language: dom.dataset.language }; | ||
}, | ||
parser: { | ||
match: ({ type }) => type === 'code', | ||
runner: (state, node, type) => { | ||
const language = node.lang; | ||
const value = node.value; | ||
state.openNode(type, { language }); | ||
state.addText(value); | ||
state.closeNode(); | ||
}, | ||
}, | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state, node) => { | ||
var _a; | ||
state.addNode('code', undefined, ((_a = node.content.firstChild) === null || _a === void 0 ? void 0 : _a.text) || '', { lang: node.attrs.language }); | ||
}, | ||
}, | ||
inputRules: (nodeType) => [ | ||
textblockTypeInputRule(inputRegex, nodeType, ([ok, language]) => { | ||
if (!ok) | ||
return; | ||
return { language }; | ||
}), | ||
], | ||
toDOM: (node) => { | ||
return [ | ||
'div', | ||
{ | ||
'data-language': node.attrs.language, | ||
class: utils.getClassName(node.attrs, 'code-fence'), | ||
commands: (nodeType) => [createCmd(TurnIntoCodeFence, () => setBlockType(nodeType))], | ||
shortcuts: { | ||
[SupportedKeys.CodeFence]: createShortcut(TurnIntoCodeFence, 'Mod-Alt-c'), | ||
}, | ||
view: (editor, nodeType, node, view, getPos, decorations) => { | ||
if (options === null || options === void 0 ? void 0 : options.view) { | ||
return options.view(editor, nodeType, node, view, getPos, decorations); | ||
} | ||
const container = document.createElement('div'); | ||
const selectWrapper = document.createElement('div'); | ||
const select = document.createElement('ul'); | ||
const pre = document.createElement('pre'); | ||
const code = document.createElement('code'); | ||
const valueWrapper = document.createElement('div'); | ||
valueWrapper.className = 'code-fence_value'; | ||
const value = document.createElement('span'); | ||
valueWrapper.appendChild(value); | ||
select.className = 'code-fence_select'; | ||
select.addEventListener('mousedown', (e) => { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
if (!view.editable) | ||
return; | ||
const el = e.target; | ||
if (!(el instanceof HTMLLIElement)) | ||
return; | ||
const { tr } = view.state; | ||
view.dispatch(tr.setNodeMarkup(getPos(), undefined, { | ||
fold: true, | ||
language: el.dataset.value, | ||
})); | ||
}); | ||
valueWrapper.addEventListener('mousedown', (e) => { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
if (!view.editable) | ||
return; | ||
const { tr } = view.state; | ||
view.dispatch(tr.setNodeMarkup(getPos(), undefined, { | ||
fold: false, | ||
language: container.dataset.language, | ||
})); | ||
}); | ||
document.addEventListener('mousedown', () => { | ||
if (!view.editable || select.dataset.fold === 'true') | ||
return; | ||
const { tr } = view.state; | ||
view.dispatch(tr.setNodeMarkup(getPos(), undefined, { | ||
fold: true, | ||
language: container.dataset.language, | ||
})); | ||
}); | ||
languageOptions.concat((options === null || options === void 0 ? void 0 : options.languageList) || []).forEach((lang) => { | ||
const option = document.createElement('li'); | ||
option.className = 'code-fence_select-option'; | ||
option.innerText = lang || '--'; | ||
select.appendChild(option); | ||
option.setAttribute('data-value', lang); | ||
}); | ||
code.spellcheck = false; | ||
selectWrapper.className = 'code-fence_select-wrapper'; | ||
selectWrapper.contentEditable = 'false'; | ||
selectWrapper.append(valueWrapper); | ||
selectWrapper.append(select); | ||
pre.append(code); | ||
container.append(selectWrapper, pre); | ||
container.setAttribute('class', utils.getClassName(node.attrs, 'code-fence', style)); | ||
container.setAttribute('data-language', node.attrs.language); | ||
value.innerText = node.attrs.language || '--'; | ||
select.setAttribute('data-fold', node.attrs.fold ? 'true' : 'false'); | ||
return { | ||
dom: container, | ||
contentDOM: code, | ||
update: (updatedNode) => { | ||
if (updatedNode.type.name !== id) | ||
return false; | ||
const lang = updatedNode.attrs.language; | ||
container.dataset.language = lang; | ||
value.innerText = lang || '--'; | ||
select.setAttribute('data-fold', updatedNode.attrs.fold ? 'true' : 'false'); | ||
return true; | ||
}, | ||
['pre', ['code', { spellCheck: 'false' }, 0]], | ||
]; | ||
}; | ||
}, | ||
}, | ||
parser: { | ||
match: ({ type }) => type === 'code', | ||
runner: (state, node, type) => { | ||
const language = node.lang; | ||
const value = node.value; | ||
state.openNode(type, { language }); | ||
state.addText(value); | ||
state.closeNode(); | ||
}, | ||
}, | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state, node) => { | ||
var _a; | ||
state.addNode('code', undefined, ((_a = node.content.firstChild) === null || _a === void 0 ? void 0 : _a.text) || '', { lang: node.attrs.language }); | ||
}, | ||
}, | ||
inputRules: (nodeType) => [ | ||
textblockTypeInputRule(inputRegex, nodeType, ([ok, language]) => { | ||
if (!ok) | ||
return; | ||
return { language }; | ||
}), | ||
], | ||
commands: (nodeType) => [createCmd(TurnIntoCodeFence, () => setBlockType(nodeType))], | ||
shortcuts: { | ||
[SupportedKeys.CodeFence]: createShortcut(TurnIntoCodeFence, 'Mod-Alt-c'), | ||
}, | ||
view: (editor, nodeType, node, view, getPos, decorations) => { | ||
if (options === null || options === void 0 ? void 0 : options.view) { | ||
return options.view(editor, nodeType, node, view, getPos, decorations); | ||
} | ||
const container = document.createElement('div'); | ||
const selectWrapper = document.createElement('div'); | ||
const select = document.createElement('ul'); | ||
const pre = document.createElement('pre'); | ||
const code = document.createElement('code'); | ||
const valueWrapper = document.createElement('div'); | ||
valueWrapper.className = 'code-fence_value'; | ||
const value = document.createElement('span'); | ||
const button = document.createElement('span'); | ||
button.className = 'icon material-icons material-icons-outlined'; | ||
button.textContent = 'expand_more'; | ||
valueWrapper.appendChild(value); | ||
valueWrapper.appendChild(button); | ||
select.className = 'code-fence_select'; | ||
select.addEventListener('mousedown', (e) => { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
if (!view.editable) | ||
return; | ||
const el = e.target; | ||
if (!(el instanceof HTMLLIElement)) | ||
return; | ||
const { tr } = view.state; | ||
view.dispatch(tr.setNodeMarkup(getPos(), undefined, { | ||
fold: true, | ||
language: el.dataset.value, | ||
})); | ||
}); | ||
valueWrapper.addEventListener('mousedown', (e) => { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
if (!view.editable) | ||
return; | ||
const { tr } = view.state; | ||
view.dispatch(tr.setNodeMarkup(getPos(), undefined, { | ||
fold: false, | ||
language: container.dataset.language, | ||
})); | ||
}); | ||
document.addEventListener('mousedown', () => { | ||
if (!view.editable || select.dataset.fold === 'true') | ||
return; | ||
const { tr } = view.state; | ||
view.dispatch(tr.setNodeMarkup(getPos(), undefined, { | ||
fold: true, | ||
language: container.dataset.language, | ||
})); | ||
}); | ||
languageOptions.concat((options === null || options === void 0 ? void 0 : options.languageList) || []).forEach((lang) => { | ||
const option = document.createElement('li'); | ||
option.className = 'code-fence_select-option'; | ||
option.innerText = lang || '--'; | ||
select.appendChild(option); | ||
option.setAttribute('data-value', lang); | ||
}); | ||
code.spellcheck = false; | ||
selectWrapper.className = 'code-fence_select-wrapper'; | ||
selectWrapper.contentEditable = 'false'; | ||
selectWrapper.append(valueWrapper); | ||
selectWrapper.append(select); | ||
pre.append(code); | ||
container.append(selectWrapper, pre); | ||
container.setAttribute('class', utils.getClassName(node.attrs, 'code-fence')); | ||
container.setAttribute('data-language', node.attrs.language); | ||
value.innerText = node.attrs.language || '--'; | ||
select.setAttribute('data-fold', node.attrs.fold ? 'true' : 'false'); | ||
return { | ||
dom: container, | ||
contentDOM: code, | ||
update: (updatedNode) => { | ||
if (updatedNode.type.name !== id) | ||
return false; | ||
const lang = updatedNode.attrs.language; | ||
container.dataset.language = lang; | ||
value.innerText = lang || '--'; | ||
select.setAttribute('data-fold', updatedNode.attrs.fold ? 'true' : 'false'); | ||
return true; | ||
}, | ||
}; | ||
}, | ||
})); | ||
}; | ||
}); | ||
//# sourceMappingURL=code-fence.js.map |
@@ -7,2 +7,3 @@ import { createNode } from '@milkdown/utils'; | ||
import { createShortcut } from '@milkdown/utils'; | ||
import { css } from '@emotion/css'; | ||
const headingIndex = Array(5) | ||
@@ -13,49 +14,72 @@ .fill(0) | ||
export const TurnIntoHeading = createCmdKey(); | ||
export const heading = createNode((_, utils) => ({ | ||
id, | ||
schema: { | ||
content: 'inline*', | ||
group: 'block', | ||
attrs: { | ||
level: { | ||
default: 1, | ||
export const heading = createNode((options, utils) => { | ||
const headingMap = { | ||
1: css ` | ||
font-size: 3rem; | ||
line-height: 3.5rem; | ||
`, | ||
2: css ` | ||
font-size: 2.125rem; | ||
line-height: 2.25rem; | ||
`, | ||
3: css ` | ||
font-size: 1.5rem; | ||
line-height: 1.5rem; | ||
`, | ||
}; | ||
const style = (level) => (options === null || options === void 0 ? void 0 : options.headless) | ||
? null | ||
: css ` | ||
${headingMap[level] || ''} | ||
margin: 2.5rem 0 !important; | ||
font-weight: 400; | ||
`; | ||
return { | ||
id, | ||
schema: { | ||
content: 'inline*', | ||
group: 'block', | ||
attrs: { | ||
level: { | ||
default: 1, | ||
}, | ||
}, | ||
parseDOM: headingIndex.map((x) => ({ tag: `h${x}`, attrs: { level: x } })), | ||
toDOM: (node) => [ | ||
`h${node.attrs.level}`, | ||
{ class: utils.getClassName(node.attrs, `heading h${node.attrs.level}`, style(node.attrs.level)) }, | ||
0, | ||
], | ||
}, | ||
parseDOM: headingIndex.map((x) => ({ tag: `h${x}`, attrs: { level: x } })), | ||
toDOM: (node) => [ | ||
`h${node.attrs.level}`, | ||
{ class: utils.getClassName(node.attrs, `heading h${node.attrs.level}`) }, | ||
0, | ||
], | ||
}, | ||
parser: { | ||
match: ({ type }) => type === id, | ||
runner: (state, node, type) => { | ||
const depth = node.depth; | ||
state.openNode(type, { level: depth }); | ||
state.next(node.children); | ||
state.closeNode(); | ||
parser: { | ||
match: ({ type }) => type === id, | ||
runner: (state, node, type) => { | ||
const depth = node.depth; | ||
state.openNode(type, { level: depth }); | ||
state.next(node.children); | ||
state.closeNode(); | ||
}, | ||
}, | ||
}, | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state, node) => { | ||
state.openNode('heading', undefined, { depth: node.attrs.level }); | ||
state.next(node.content); | ||
state.closeNode(); | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state, node) => { | ||
state.openNode('heading', undefined, { depth: node.attrs.level }); | ||
state.next(node.content); | ||
state.closeNode(); | ||
}, | ||
}, | ||
}, | ||
inputRules: (nodeType) => headingIndex.map((x) => textblockTypeInputRule(new RegExp(`^(#{1,${x}})\\s$`), nodeType, () => ({ | ||
level: x, | ||
}))), | ||
commands: (nodeType) => [createCmd(TurnIntoHeading, (level = 1) => setBlockType(nodeType, { level }))], | ||
shortcuts: { | ||
[SupportedKeys.H1]: createShortcut(TurnIntoHeading, 'Mod-Alt-1', 1), | ||
[SupportedKeys.H2]: createShortcut(TurnIntoHeading, 'Mod-Alt-2', 2), | ||
[SupportedKeys.H3]: createShortcut(TurnIntoHeading, 'Mod-Alt-3', 3), | ||
[SupportedKeys.H4]: createShortcut(TurnIntoHeading, 'Mod-Alt-4', 4), | ||
[SupportedKeys.H5]: createShortcut(TurnIntoHeading, 'Mod-Alt-5', 5), | ||
[SupportedKeys.H6]: createShortcut(TurnIntoHeading, 'Mod-Alt-6', 6), | ||
}, | ||
})); | ||
inputRules: (nodeType) => headingIndex.map((x) => textblockTypeInputRule(new RegExp(`^(#{1,${x}})\\s$`), nodeType, () => ({ | ||
level: x, | ||
}))), | ||
commands: (nodeType) => [createCmd(TurnIntoHeading, (level = 1) => setBlockType(nodeType, { level }))], | ||
shortcuts: { | ||
[SupportedKeys.H1]: createShortcut(TurnIntoHeading, 'Mod-Alt-1', 1), | ||
[SupportedKeys.H2]: createShortcut(TurnIntoHeading, 'Mod-Alt-2', 2), | ||
[SupportedKeys.H3]: createShortcut(TurnIntoHeading, 'Mod-Alt-3', 3), | ||
[SupportedKeys.H4]: createShortcut(TurnIntoHeading, 'Mod-Alt-4', 4), | ||
[SupportedKeys.H5]: createShortcut(TurnIntoHeading, 'Mod-Alt-5', 5), | ||
[SupportedKeys.H6]: createShortcut(TurnIntoHeading, 'Mod-Alt-6', 6), | ||
}, | ||
}; | ||
}); | ||
//# sourceMappingURL=heading.js.map |
@@ -0,1 +1,2 @@ | ||
import { css } from '@emotion/css'; | ||
import { createCmd, createCmdKey } from '@milkdown/core'; | ||
@@ -7,50 +8,59 @@ import { createNode } from '@milkdown/utils'; | ||
export const InsertHr = createCmdKey(); | ||
export const hr = createNode((_, utils) => ({ | ||
id, | ||
schema: { | ||
group: 'block', | ||
parseDOM: [{ tag: 'hr' }], | ||
toDOM: (node) => ['hr', { class: utils.getClassName(node.attrs, id) }], | ||
}, | ||
parser: { | ||
match: ({ type }) => type === 'thematicBreak', | ||
runner: (state, _, type) => { | ||
state.addNode(type); | ||
export const hr = createNode((options, utils) => { | ||
const style = (options === null || options === void 0 ? void 0 : options.headless) | ||
? null | ||
: css ` | ||
height: ${utils.themeTool.size.lineWidth}; | ||
background-color: ${utils.themeTool.palette('line')}; | ||
border-width: 0; | ||
`; | ||
return { | ||
id, | ||
schema: { | ||
group: 'block', | ||
parseDOM: [{ tag: 'hr' }], | ||
toDOM: (node) => ['hr', { class: utils.getClassName(node.attrs, id, style) }], | ||
}, | ||
}, | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state) => { | ||
state.addNode('thematicBreak'); | ||
parser: { | ||
match: ({ type }) => type === 'thematicBreak', | ||
runner: (state, _, type) => { | ||
state.addNode(type); | ||
}, | ||
}, | ||
}, | ||
inputRules: (nodeType) => [ | ||
new InputRule(/^(?:---|___\s|\*\*\*\s)$/, (state, match, start, end) => { | ||
const { tr } = state; | ||
if (match[0]) { | ||
tr.replaceWith(start, end, nodeType.create({})); | ||
} | ||
return tr; | ||
}), | ||
], | ||
commands: (nodeType, schema) => [ | ||
createCmd(InsertHr, () => (state, dispatch) => { | ||
if (!dispatch) | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state) => { | ||
state.addNode('thematicBreak'); | ||
}, | ||
}, | ||
inputRules: (nodeType) => [ | ||
new InputRule(/^(?:---|___\s|\*\*\*\s)$/, (state, match, start, end) => { | ||
const { tr } = state; | ||
if (match[0]) { | ||
tr.replaceWith(start, end, nodeType.create({})); | ||
} | ||
return tr; | ||
}), | ||
], | ||
commands: (nodeType, schema) => [ | ||
createCmd(InsertHr, () => (state, dispatch) => { | ||
if (!dispatch) | ||
return true; | ||
const { tr, selection } = state; | ||
const from = selection.from; | ||
const node = nodeType.create(); | ||
if (!node) { | ||
return true; | ||
} | ||
const _tr = tr.replaceSelectionWith(node).insert(from, schema.node('paragraph')); | ||
const sel = Selection.findFrom(_tr.doc.resolve(from), 1, true); | ||
if (!sel) { | ||
return true; | ||
} | ||
dispatch(_tr.setSelection(sel).scrollIntoView()); | ||
return true; | ||
const { tr, selection } = state; | ||
const from = selection.from; | ||
const node = nodeType.create(); | ||
if (!node) { | ||
return true; | ||
} | ||
const _tr = tr.replaceSelectionWith(node).insert(from, schema.node('paragraph')); | ||
const sel = Selection.findFrom(_tr.doc.resolve(from), 1, true); | ||
if (!sel) { | ||
return true; | ||
} | ||
dispatch(_tr.setSelection(sel).scrollIntoView()); | ||
return true; | ||
}), | ||
], | ||
})); | ||
}), | ||
], | ||
}; | ||
}); | ||
//# sourceMappingURL=hr.js.map |
@@ -0,1 +1,2 @@ | ||
import { css } from '@emotion/css'; | ||
import { createCmd, createCmdKey } from '@milkdown/core'; | ||
@@ -8,103 +9,150 @@ import { createNode, findSelectedNodeOfType } from '@milkdown/utils'; | ||
const id = 'image'; | ||
export const image = createNode((_, utils) => ({ | ||
id, | ||
schema: { | ||
inline: true, | ||
group: 'inline', | ||
draggable: true, | ||
selectable: true, | ||
marks: '', | ||
attrs: { | ||
src: { default: '' }, | ||
alt: { default: null }, | ||
title: { default: null }, | ||
}, | ||
parseDOM: [ | ||
{ | ||
tag: 'img[src]', | ||
getAttrs: (dom) => { | ||
if (!(dom instanceof HTMLElement)) { | ||
throw new Error(); | ||
} | ||
return { | ||
src: dom.getAttribute('src') || '', | ||
alt: dom.getAttribute('alt'), | ||
title: dom.getAttribute('title'), | ||
}; | ||
export const image = createNode((options, utils) => { | ||
var _a, _b; | ||
const style = (options === null || options === void 0 ? void 0 : options.headless) | ||
? null | ||
: css ` | ||
display: inline-block; | ||
margin: 0 auto; | ||
object-fit: contain; | ||
width: 100%; | ||
position: relative; | ||
height: auto; | ||
text-align: center; | ||
&.empty { | ||
box-sizing: border-box; | ||
height: 3rem; | ||
background-color: ${utils.themeTool.palette('background')}; | ||
border-radius: ${utils.themeTool.size.radius}; | ||
display: inline-flex; | ||
gap: 2rem; | ||
justify-content: flex-start; | ||
align-items: center; | ||
.icon { | ||
width: 1.5rem; | ||
height: 1.5rem; | ||
margin: 0; | ||
margin-left: 1rem; | ||
position: relative; | ||
&::before { | ||
${(_b = (_a = utils.themeTool.widget).icon) === null || _b === void 0 ? void 0 : _b.call(_a, 'image')} | ||
position: absolute; | ||
top: 0; | ||
bottom: 0; | ||
left: 0; | ||
right: 0; | ||
} | ||
} | ||
.placeholder { | ||
margin: 0; | ||
&:before { | ||
content: 'Add an image'; | ||
font-size: 0.875rem; | ||
color: ${utils.themeTool.palette('neutral', 0.6)}; | ||
} | ||
} | ||
} | ||
`; | ||
return { | ||
id, | ||
schema: { | ||
inline: true, | ||
group: 'inline', | ||
draggable: true, | ||
selectable: true, | ||
marks: '', | ||
attrs: { | ||
src: { default: '' }, | ||
alt: { default: null }, | ||
title: { default: null }, | ||
}, | ||
parseDOM: [ | ||
{ | ||
tag: 'img[src]', | ||
getAttrs: (dom) => { | ||
if (!(dom instanceof HTMLElement)) { | ||
throw new Error(); | ||
} | ||
return { | ||
src: dom.getAttribute('src') || '', | ||
alt: dom.getAttribute('alt'), | ||
title: dom.getAttribute('title'), | ||
}; | ||
}, | ||
}, | ||
], | ||
toDOM: (node) => { | ||
var _a; | ||
if (((_a = node.attrs.src) === null || _a === void 0 ? void 0 : _a.length) > 0) { | ||
return ['img', Object.assign(Object.assign({}, node.attrs), { class: utils.getClassName(node.attrs, id, style) })]; | ||
} | ||
return [ | ||
'div', | ||
Object.assign(Object.assign({}, node.attrs), { class: utils.getClassName(node.attrs, 'image', 'empty', style) }), | ||
['span', { contentEditable: 'false', class: 'icon' }], | ||
['span', { contentEditable: 'false', class: 'placeholder' }], | ||
]; | ||
}, | ||
], | ||
toDOM: (node) => { | ||
var _a; | ||
if (((_a = node.attrs.src) === null || _a === void 0 ? void 0 : _a.length) > 0) { | ||
return ['img', Object.assign(Object.assign({}, node.attrs), { class: utils.getClassName(node.attrs, id) })]; | ||
} | ||
return [ | ||
'div', | ||
Object.assign(Object.assign({}, node.attrs), { class: utils.getClassName(node.attrs, 'image empty') }), | ||
['span', { contentEditable: 'false', class: 'icon' }], | ||
['span', { contentEditable: 'false', class: 'placeholder' }], | ||
]; | ||
}, | ||
}, | ||
parser: { | ||
match: ({ type }) => type === id, | ||
runner: (state, node, type) => { | ||
const url = node.url; | ||
const alt = node.alt; | ||
const title = node.title; | ||
state.addNode(type, { | ||
src: url, | ||
alt, | ||
title, | ||
}); | ||
parser: { | ||
match: ({ type }) => type === id, | ||
runner: (state, node, type) => { | ||
const url = node.url; | ||
const alt = node.alt; | ||
const title = node.title; | ||
state.addNode(type, { | ||
src: url, | ||
alt, | ||
title, | ||
}); | ||
}, | ||
}, | ||
}, | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state, node) => { | ||
state.addNode('image', undefined, undefined, { | ||
title: node.attrs.title, | ||
url: node.attrs.src, | ||
alt: node.attrs.alt, | ||
}); | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state, node) => { | ||
state.addNode('image', undefined, undefined, { | ||
title: node.attrs.title, | ||
url: node.attrs.src, | ||
alt: node.attrs.alt, | ||
}); | ||
}, | ||
}, | ||
}, | ||
commands: (nodeType, schema) => [ | ||
createCmd(InsertImage, (src = '') => (state, dispatch) => { | ||
if (!dispatch) | ||
commands: (nodeType, schema) => [ | ||
createCmd(InsertImage, (src = '') => (state, dispatch) => { | ||
if (!dispatch) | ||
return true; | ||
const { tr } = state; | ||
const node = nodeType.create({ src }); | ||
if (!node) { | ||
return true; | ||
} | ||
const _tr = tr.replaceSelectionWith(node); | ||
const { $from } = _tr.selection; | ||
const start = $from.start(); | ||
const __tr = _tr.replaceSelectionWith(schema.node('paragraph')); | ||
const sel = NodeSelection.create(__tr.doc, start); | ||
dispatch(__tr.setSelection(sel)); | ||
return true; | ||
const { tr } = state; | ||
const node = nodeType.create({ src }); | ||
if (!node) { | ||
}), | ||
createCmd(ModifyImage, (src = '') => (state, dispatch) => { | ||
const node = findSelectedNodeOfType(state.selection, nodeType); | ||
if (!node) | ||
return false; | ||
const { tr } = state; | ||
dispatch === null || dispatch === void 0 ? void 0 : dispatch(tr.setNodeMarkup(node.pos, undefined, Object.assign(Object.assign({}, node.node.attrs), { src })).scrollIntoView()); | ||
return true; | ||
} | ||
const _tr = tr.replaceSelectionWith(node); | ||
const { $from } = _tr.selection; | ||
const start = $from.start(); | ||
const __tr = _tr.replaceSelectionWith(schema.node('paragraph')); | ||
const sel = NodeSelection.create(__tr.doc, start); | ||
dispatch(__tr.setSelection(sel)); | ||
return true; | ||
}), | ||
createCmd(ModifyImage, (src = '') => (state, dispatch) => { | ||
const node = findSelectedNodeOfType(state.selection, nodeType); | ||
if (!node) | ||
return false; | ||
const { tr } = state; | ||
dispatch === null || dispatch === void 0 ? void 0 : dispatch(tr.setNodeMarkup(node.pos, undefined, Object.assign(Object.assign({}, node.node.attrs), { src })).scrollIntoView()); | ||
return true; | ||
}), | ||
], | ||
inputRules: (nodeType) => [ | ||
new InputRule(/!\[(?<alt>.*?)]\((?<filename>.*?)(?=“|\))"?(?<title>[^"]+)?"?\)/, (state, match, start, end) => { | ||
const [okay, alt, src = '', title] = match; | ||
const { tr } = state; | ||
if (okay) { | ||
tr.replaceWith(start, end, nodeType.create({ src, alt, title })); | ||
} | ||
return tr; | ||
}), | ||
], | ||
})); | ||
}), | ||
], | ||
inputRules: (nodeType) => [ | ||
new InputRule(/!\[(?<alt>.*?)]\((?<filename>.*?)(?=“|\))"?(?<title>[^"]+)?"?\)/, (state, match, start, end) => { | ||
const [okay, alt, src = '', title] = match; | ||
const { tr } = state; | ||
if (okay) { | ||
tr.replaceWith(start, end, nodeType.create({ src, alt, title })); | ||
} | ||
return tr; | ||
}), | ||
], | ||
}; | ||
}); | ||
//# sourceMappingURL=image.js.map |
@@ -7,2 +7,3 @@ import { createNode } from '@milkdown/utils'; | ||
import { createShortcut } from '@milkdown/utils'; | ||
import { css } from '@emotion/css'; | ||
const id = 'list_item'; | ||
@@ -12,39 +13,56 @@ export const SplitListItem = createCmdKey(); | ||
export const LiftListItem = createCmdKey(); | ||
export const listItem = createNode((_, utils) => ({ | ||
id, | ||
schema: { | ||
group: 'listItem', | ||
content: 'paragraph block*', | ||
defining: true, | ||
parseDOM: [{ tag: 'li' }], | ||
toDOM: (node) => ['li', { class: utils.getClassName(node.attrs, 'list-item') }, 0], | ||
}, | ||
parser: { | ||
match: ({ type, checked }) => type === 'listItem' && checked === null, | ||
runner: (state, node, type) => { | ||
state.openNode(type); | ||
state.next(node.children); | ||
state.closeNode(); | ||
export const listItem = createNode((options, utils) => { | ||
const style = (options === null || options === void 0 ? void 0 : options.headless) | ||
? null | ||
: css ` | ||
&, | ||
& > * { | ||
margin: 0.5rem 0; | ||
} | ||
&, | ||
li { | ||
&::marker { | ||
color: ${utils.themeTool.palette('primary')}; | ||
} | ||
} | ||
`; | ||
return { | ||
id, | ||
schema: { | ||
group: 'listItem', | ||
content: 'paragraph block*', | ||
defining: true, | ||
parseDOM: [{ tag: 'li' }], | ||
toDOM: (node) => ['li', { class: utils.getClassName(node.attrs, 'list-item', style) }, 0], | ||
}, | ||
}, | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state, node) => { | ||
state.openNode('listItem'); | ||
state.next(node.content); | ||
state.closeNode(); | ||
parser: { | ||
match: ({ type, checked }) => type === 'listItem' && checked === null, | ||
runner: (state, node, type) => { | ||
state.openNode(type); | ||
state.next(node.children); | ||
state.closeNode(); | ||
}, | ||
}, | ||
}, | ||
inputRules: (nodeType) => [wrappingInputRule(/^\s*([-+*])\s$/, nodeType)], | ||
commands: (nodeType) => [ | ||
createCmd(SplitListItem, () => splitListItem(nodeType)), | ||
createCmd(SinkListItem, () => sinkListItem(nodeType)), | ||
createCmd(LiftListItem, () => liftListItem(nodeType)), | ||
], | ||
shortcuts: { | ||
[SupportedKeys.NextListItem]: createShortcut(SplitListItem, 'Enter'), | ||
[SupportedKeys.SinkListItem]: createShortcut(SinkListItem, 'Mod-]'), | ||
[SupportedKeys.LiftListItem]: createShortcut(LiftListItem, 'Mod-['), | ||
}, | ||
})); | ||
serializer: { | ||
match: (node) => node.type.name === id, | ||
runner: (state, node) => { | ||
state.openNode('listItem'); | ||
state.next(node.content); | ||
state.closeNode(); | ||
}, | ||
}, | ||
inputRules: (nodeType) => [wrappingInputRule(/^\s*([-+*])\s$/, nodeType)], | ||
commands: (nodeType) => [ | ||
createCmd(SplitListItem, () => splitListItem(nodeType)), | ||
createCmd(SinkListItem, () => sinkListItem(nodeType)), | ||
createCmd(LiftListItem, () => liftListItem(nodeType)), | ||
], | ||
shortcuts: { | ||
[SupportedKeys.NextListItem]: createShortcut(SplitListItem, 'Enter'), | ||
[SupportedKeys.SinkListItem]: createShortcut(SinkListItem, 'Mod-]'), | ||
[SupportedKeys.LiftListItem]: createShortcut(LiftListItem, 'Mod-['), | ||
}, | ||
}; | ||
}); | ||
//# sourceMappingURL=list-item.js.map |
@@ -0,1 +1,2 @@ | ||
import { css } from '@emotion/css'; | ||
import { createCmdKey, createCmd } from '@milkdown/core'; | ||
@@ -8,36 +9,45 @@ import { createNode } from '@milkdown/utils'; | ||
const id = 'paragraph'; | ||
export const paragraph = createNode((_, utils) => ({ | ||
id, | ||
schema: { | ||
content: 'inline*', | ||
group: 'block', | ||
parseDOM: [{ tag: 'p' }], | ||
toDOM: (node) => ['p', { class: utils.getClassName(node.attrs, id) }, 0], | ||
}, | ||
parser: { | ||
match: (node) => node.type === 'paragraph', | ||
runner: (state, node, type) => { | ||
state.openNode(type); | ||
if (node.children) { | ||
state.next(node.children); | ||
} | ||
else { | ||
state.addText(node.value); | ||
} | ||
state.closeNode(); | ||
export const paragraph = createNode((options, utils) => { | ||
const style = (options === null || options === void 0 ? void 0 : options.headless) | ||
? null | ||
: css ` | ||
font-size: 1rem; | ||
line-height: 1.5; | ||
letter-spacing: 0.5px; | ||
`; | ||
return { | ||
id, | ||
schema: { | ||
content: 'inline*', | ||
group: 'block', | ||
parseDOM: [{ tag: 'p' }], | ||
toDOM: (node) => ['p', { class: utils.getClassName(node.attrs, id, style) }, 0], | ||
}, | ||
}, | ||
serializer: { | ||
match: (node) => node.type.name === 'paragraph', | ||
runner: (state, node) => { | ||
state.openNode('paragraph'); | ||
state.next(node.content); | ||
state.closeNode(); | ||
parser: { | ||
match: (node) => node.type === 'paragraph', | ||
runner: (state, node, type) => { | ||
state.openNode(type); | ||
if (node.children) { | ||
state.next(node.children); | ||
} | ||
else { | ||
state.addText(node.value); | ||
} | ||
state.closeNode(); | ||
}, | ||
}, | ||
}, | ||
commands: (nodeType) => [createCmd(TurnIntoText, () => setBlockType(nodeType))], | ||
shortcuts: { | ||
[SupportedKeys.Text]: createShortcut(TurnIntoText, 'Mod-Alt-0'), | ||
}, | ||
})); | ||
serializer: { | ||
match: (node) => node.type.name === 'paragraph', | ||
runner: (state, node) => { | ||
state.openNode('paragraph'); | ||
state.next(node.content); | ||
state.closeNode(); | ||
}, | ||
}, | ||
commands: (nodeType) => [createCmd(TurnIntoText, () => setBlockType(nodeType))], | ||
shortcuts: { | ||
[SupportedKeys.Text]: createShortcut(TurnIntoText, 'Mod-Alt-0'), | ||
}, | ||
}; | ||
}); | ||
//# sourceMappingURL=paragraph.js.map |
{ | ||
"name": "@milkdown/preset-commonmark", | ||
"version": "4.9.6", | ||
"version": "4.10.0", | ||
"main": "lib/index.js", | ||
@@ -21,2 +21,3 @@ "module": "lib/index.js", | ||
"dependencies": { | ||
"@emotion/css": "^11.1.3", | ||
"@milkdown/utils": " *", | ||
@@ -33,9 +34,7 @@ "@types/prosemirror-schema-list": "^1.0.3", | ||
"start": "vite", | ||
"watch": "concurrently -n ts,css \"tsc -w\" \"postcss style/style.css --watch --verbose -o lib/style.css\"", | ||
"watch:css": "postcss style/style.css --watch --verbose -o lib/style.css", | ||
"watch": "tsc -w", | ||
"test": "jest", | ||
"tsc": "tsc --noEmit", | ||
"build": "tsc && postcss style/style.css --verbose -o lib/style.css", | ||
"build:css": "postcss style/style.css --verbose -o lib/style.css" | ||
"build": "tsc" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
107318
7
87
1374
+ Added@emotion/css@^11.1.3
+ Added@babel/code-frame@7.26.2(transitive)
+ Added@babel/generator@7.26.9(transitive)
+ Added@babel/helper-module-imports@7.25.9(transitive)
+ Added@babel/helper-string-parser@7.25.9(transitive)
+ Added@babel/helper-validator-identifier@7.25.9(transitive)
+ Added@babel/parser@7.26.9(transitive)
+ Added@babel/runtime@7.26.9(transitive)
+ Added@babel/template@7.26.9(transitive)
+ Added@babel/traverse@7.26.9(transitive)
+ Added@babel/types@7.26.9(transitive)
+ Added@emotion/babel-plugin@11.13.5(transitive)
+ Added@emotion/cache@11.14.0(transitive)
+ Added@emotion/css@11.13.5(transitive)
+ Added@emotion/hash@0.9.2(transitive)
+ Added@emotion/memoize@0.9.0(transitive)
+ Added@emotion/serialize@1.3.3(transitive)
+ Added@emotion/sheet@1.4.0(transitive)
+ Added@emotion/unitless@0.10.0(transitive)
+ Added@emotion/utils@1.4.2(transitive)
+ Added@emotion/weak-memoize@0.4.0(transitive)
+ Added@jridgewell/gen-mapping@0.3.8(transitive)
+ Added@jridgewell/resolve-uri@3.1.2(transitive)
+ Added@jridgewell/set-array@1.2.1(transitive)
+ Added@jridgewell/sourcemap-codec@1.5.0(transitive)
+ Added@jridgewell/trace-mapping@0.3.25(transitive)
+ Added@types/parse-json@4.0.2(transitive)
+ Addedbabel-plugin-macros@3.1.0(transitive)
+ Addedcallsites@3.1.0(transitive)
+ Addedconvert-source-map@1.9.0(transitive)
+ Addedcosmiconfig@7.1.0(transitive)
+ Addedcsstype@3.1.3(transitive)
+ Addederror-ex@1.3.2(transitive)
+ Addedescape-string-regexp@4.0.0(transitive)
+ Addedfind-root@1.1.0(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedglobals@11.12.0(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedimport-fresh@3.3.1(transitive)
+ Addedis-arrayish@0.2.1(transitive)
+ Addedis-core-module@2.16.1(transitive)
+ Addedjs-tokens@4.0.0(transitive)
+ Addedjsesc@3.1.0(transitive)
+ Addedjson-parse-even-better-errors@2.3.1(transitive)
+ Addedlines-and-columns@1.2.4(transitive)
+ Addedparent-module@1.0.1(transitive)
+ Addedparse-json@5.2.0(transitive)
+ Addedpath-parse@1.0.7(transitive)
+ Addedpath-type@4.0.0(transitive)
+ Addedpicocolors@1.1.1(transitive)
+ Addedregenerator-runtime@0.14.1(transitive)
+ Addedresolve@1.22.10(transitive)
+ Addedresolve-from@4.0.0(transitive)
+ Addedsource-map@0.5.7(transitive)
+ Addedstylis@4.2.0(transitive)
+ Addedsupports-preserve-symlinks-flag@1.0.0(transitive)
+ Addedyaml@1.10.2(transitive)