@portabletext/editor 1.19.0 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/_chunks-cjs/behavior.core.cjs.map +1 -1
- package/lib/_chunks-cjs/selector.is-selection-collapsed.cjs.map +1 -1
- package/lib/_chunks-es/behavior.core.js.map +1 -1
- package/lib/_chunks-es/selector.is-selection-collapsed.js.map +1 -1
- package/lib/behaviors/index.cjs.map +1 -1
- package/lib/behaviors/index.d.cts +2 -2
- package/lib/behaviors/index.d.ts +2 -2
- package/lib/behaviors/index.js.map +1 -1
- package/lib/index.cjs +44 -172
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +245 -27
- package/lib/index.d.ts +245 -27
- package/lib/index.js +44 -173
- package/lib/index.js.map +1 -1
- package/lib/selectors/index.cjs.map +1 -1
- package/package.json +5 -7
- package/src/behaviors/behavior.types.ts +2 -2
- package/src/editor/components/Element.tsx +17 -23
- package/src/editor/create-editor.ts +17 -0
- package/src/editor/editor-machine.ts +30 -4
- package/src/editor/nodes/DefaultObject.tsx +2 -2
- package/src/editor/nodes/index.ts +0 -189
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../src/selectors/selector.get-active-list-item.ts","../../src/selectors/selector.get-active-style.ts","../../src/selectors/selector.get-selected-spans.ts","../../src/selectors/selector.is-active-annotation.ts","../../src/selectors/selector.is-selection-expanded.ts","../../src/selectors/selector.is-active-decorator.ts","../../src/selectors/selector.is-active-list-item.ts","../../src/selectors/selector.is-active-style.ts"],"sourcesContent":["import type {PortableTextListBlock} from '@sanity/types'\nimport {createGuards} from '../behavior-actions/behavior.guards'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getSelectedBlocks} from './selectors'\n\n/**\n * @public\n */\nexport const getActiveListItem: EditorSelector<\n PortableTextListBlock['listItem'] | undefined\n> = ({context}) => {\n if (!context.selection) {\n return undefined\n }\n\n const guards = createGuards(context)\n const selectedBlocks = getSelectedBlocks({context}).map((block) => block.node)\n const selectedTextBlocks = selectedBlocks.filter(guards.isTextBlock)\n\n const firstTextBlock = selectedTextBlocks.at(0)\n\n if (!firstTextBlock) {\n return undefined\n }\n\n const firstListItem = firstTextBlock.listItem\n\n if (!firstListItem) {\n return undefined\n }\n\n if (selectedTextBlocks.every((block) => block.listItem === firstListItem)) {\n return firstListItem\n }\n\n return undefined\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport {createGuards} from '../behavior-actions/behavior.guards'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getSelectedBlocks} from './selectors'\n\n/**\n * @public\n */\nexport const getActiveStyle: EditorSelector<PortableTextTextBlock['style']> = ({\n context,\n}) => {\n if (!context.selection) {\n return undefined\n }\n\n const guards = createGuards(context)\n const selectedBlocks = getSelectedBlocks({context}).map((block) => block.node)\n const selectedTextBlocks = selectedBlocks.filter(guards.isTextBlock)\n\n const firstTextBlock = selectedTextBlocks.at(0)\n\n if (!firstTextBlock) {\n return undefined\n }\n\n const firstStyle = firstTextBlock.style\n\n if (!firstStyle) {\n return undefined\n }\n\n if (selectedTextBlocks.every((block) => block.style === firstStyle)) {\n return firstStyle\n }\n\n return undefined\n}\n","import {\n isKeySegment,\n isPortableTextSpan,\n isPortableTextTextBlock,\n type KeyedSegment,\n type PortableTextSpan,\n} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\n\n/**\n * @public\n */\nexport const getSelectedSpans: EditorSelector<\n Array<{\n node: PortableTextSpan\n path: [KeyedSegment, 'children', KeyedSegment]\n }>\n> = ({context}) => {\n if (!context.selection) {\n return []\n }\n\n const selectedSpans: Array<{\n node: PortableTextSpan\n path: [KeyedSegment, 'children', KeyedSegment]\n }> = []\n\n const startPoint = context.selection.backward\n ? context.selection.focus\n : context.selection.anchor\n const endPoint = context.selection.backward\n ? context.selection.anchor\n : context.selection.focus\n\n const startBlockKey = isKeySegment(startPoint.path[0])\n ? startPoint.path[0]._key\n : undefined\n const endBlockKey = isKeySegment(endPoint.path[0])\n ? endPoint.path[0]._key\n : undefined\n\n if (!startBlockKey || !endBlockKey) {\n return selectedSpans\n }\n\n const startSpanKey = isKeySegment(startPoint.path[2])\n ? startPoint.path[2]._key\n : undefined\n const endSpanKey = isKeySegment(endPoint.path[2])\n ? endPoint.path[2]._key\n : undefined\n\n for (const block of context.value) {\n if (!isPortableTextTextBlock(block)) {\n continue\n }\n\n if (block._key === startBlockKey) {\n for (const child of block.children) {\n if (!isPortableTextSpan(child)) {\n continue\n }\n\n if (startSpanKey && child._key === startSpanKey) {\n selectedSpans.push({\n node: child,\n path: [{_key: block._key}, 'children', {_key: child._key}],\n })\n\n if (startSpanKey === endSpanKey) {\n break\n }\n\n continue\n }\n\n if (endSpanKey && child._key === endSpanKey) {\n selectedSpans.push({\n node: child,\n path: [{_key: block._key}, 'children', {_key: child._key}],\n })\n break\n }\n\n if (selectedSpans.length > 0) {\n selectedSpans.push({\n node: child,\n path: [{_key: block._key}, 'children', {_key: child._key}],\n })\n }\n }\n\n if (startBlockKey === endBlockKey) {\n break\n }\n\n continue\n }\n\n if (block._key === endBlockKey) {\n for (const child of block.children) {\n if (!isPortableTextSpan(child)) {\n continue\n }\n\n if (endSpanKey && child._key === endSpanKey) {\n selectedSpans.push({\n node: child,\n path: [{_key: block._key}, 'children', {_key: child._key}],\n })\n break\n }\n\n selectedSpans.push({\n node: child,\n path: [{_key: block._key}, 'children', {_key: child._key}],\n })\n }\n\n break\n }\n\n if (selectedSpans.length > 0) {\n for (const child of block.children) {\n if (!isPortableTextSpan(child)) {\n continue\n }\n\n selectedSpans.push({\n node: child,\n path: [{_key: block._key}, 'children', {_key: child._key}],\n })\n }\n }\n }\n\n return selectedSpans\n}\n","import {isPortableTextTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getSelectedSpans} from './selector.get-selected-spans'\nimport {getSelectedBlocks} from './selectors'\n\n/**\n * @public\n */\nexport function isActiveAnnotation(\n annotation: string,\n): EditorSelector<boolean> {\n return (snapshot) => {\n if (!snapshot.context.selection) {\n return false\n }\n\n const selectedBlocks = getSelectedBlocks(snapshot)\n const selectedSpans = getSelectedSpans(snapshot)\n\n if (selectedSpans.length === 0) {\n return false\n }\n\n if (\n selectedSpans.some(\n (span) => !span.node.marks || span.node.marks?.length === 0,\n )\n ) {\n return false\n }\n\n const selectionMarkDefs = selectedBlocks.flatMap((block) =>\n isPortableTextTextBlock(block.node) ? (block.node.markDefs ?? []) : [],\n )\n\n return selectedSpans.every((span) => {\n const spanMarkDefs =\n span.node.marks?.flatMap((mark) => {\n const markDef = selectionMarkDefs.find(\n (markDef) => markDef._key === mark,\n )\n\n return markDef ? [markDef._type] : []\n }) ?? []\n\n return spanMarkDefs.includes(annotation)\n })\n }\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport {isSelectionCollapsed} from './selector.is-selection-collapsed'\n\n/**\n * @public\n */\nexport const isSelectionExpanded: EditorSelector<boolean> = ({context}) => {\n return !isSelectionCollapsed({context})\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport {getSelectedSpans} from './selector.get-selected-spans'\nimport {isSelectionExpanded} from './selector.is-selection-expanded'\n\n/**\n * @public\n */\nexport function isActiveDecorator(decorator: string): EditorSelector<boolean> {\n return (snapshot) => {\n if (isSelectionExpanded(snapshot)) {\n const selectedSpans = getSelectedSpans(snapshot)\n\n return (\n selectedSpans.length > 0 &&\n selectedSpans.every((span) => span.node.marks?.includes(decorator))\n )\n }\n\n return snapshot.context.activeDecorators.includes(decorator)\n }\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport {getActiveListItem} from './selector.get-active-list-item'\n\n/**\n * @public\n */\nexport function isActiveListItem(listItem: string): EditorSelector<boolean> {\n return (snapshot) => {\n const activeListItem = getActiveListItem(snapshot)\n\n return activeListItem === listItem\n }\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport {getActiveStyle} from './selector.get-active-style'\n\n/**\n * @public\n */\nexport function isActiveStyle(style: string): EditorSelector<boolean> {\n return (snapshot) => {\n const activeStyle = getActiveStyle(snapshot)\n\n return activeStyle === style\n }\n}\n"],"names":["getActiveListItem","context","selection","guards","createGuards","selectedTextBlocks","getSelectedBlocks","map","block","node","filter","isTextBlock","firstTextBlock","at","firstListItem","listItem","every","getActiveStyle","firstStyle","style","getSelectedSpans","selectedSpans","startPoint","backward","focus","anchor","endPoint","startBlockKey","isKeySegment","path","_key","undefined","endBlockKey","startSpanKey","endSpanKey","value","isPortableTextTextBlock","child","children","isPortableTextSpan","push","length","isActiveAnnotation","annotation","snapshot","selectedBlocks","some","span","marks","selectionMarkDefs","flatMap","markDefs","mark","markDef","find","_type","includes","isSelectionExpanded","isSelectionCollapsed","isActiveDecorator","decorator","activeDecorators","isActiveListItem","isActiveStyle"],"mappings":";;;AAQO,MAAMA,oBAETA,CAAC;AAAA,EAACC;AAAO,MAAM;AACjB,MAAI,CAACA,QAAQC;AACX;AAGF,QAAMC,SAASC,8BAAAA,aAAaH,OAAO,GAE7BI,qBADiBC,8BAAAA,kBAAkB;AAAA,IAACL;AAAAA,EAAQ,CAAA,EAAEM,IAAKC,CAAAA,UAAUA,MAAMC,IAAI,EACnCC,OAAOP,OAAOQ,WAAW,GAE7DC,iBAAiBP,mBAAmBQ,GAAG,CAAC;AAE9C,MAAI,CAACD;AACH;AAGF,QAAME,gBAAgBF,eAAeG;AAErC,MAAKD,iBAIDT,mBAAmBW,MAAOR,CAAUA,UAAAA,MAAMO,aAAaD,aAAa;AAC/DA,WAAAA;AAIX,GC5BaG,iBAAiEA,CAAC;AAAA,EAC7EhB;AACF,MAAM;AACJ,MAAI,CAACA,QAAQC;AACX;AAGF,QAAMC,SAASC,8BAAAA,aAAaH,OAAO,GAE7BI,qBADiBC,8BAAAA,kBAAkB;AAAA,IAACL;AAAAA,EAAQ,CAAA,EAAEM,IAAKC,CAAAA,UAAUA,MAAMC,IAAI,EACnCC,OAAOP,OAAOQ,WAAW,GAE7DC,iBAAiBP,mBAAmBQ,GAAG,CAAC;AAE9C,MAAI,CAACD;AACH;AAGF,QAAMM,aAAaN,eAAeO;AAElC,MAAKD,cAIDb,mBAAmBW,MAAOR,CAAUA,UAAAA,MAAMW,UAAUD,UAAU;AACzDA,WAAAA;AAIX,GCxBaE,mBAKTA,CAAC;AAAA,EAACnB;AAAO,MAAM;AACjB,MAAI,CAACA,QAAQC;AACX,WAAO,CAAE;AAGLmB,QAAAA,gBAGD,IAECC,aAAarB,QAAQC,UAAUqB,WACjCtB,QAAQC,UAAUsB,QAClBvB,QAAQC,UAAUuB,QAChBC,WAAWzB,QAAQC,UAAUqB,WAC/BtB,QAAQC,UAAUuB,SAClBxB,QAAQC,UAAUsB,OAEhBG,gBAAgBC,MAAAA,aAAaN,WAAWO,KAAK,CAAC,CAAC,IACjDP,WAAWO,KAAK,CAAC,EAAEC,OACnBC,QACEC,cAAcJ,MAAAA,aAAaF,SAASG,KAAK,CAAC,CAAC,IAC7CH,SAASG,KAAK,CAAC,EAAEC,OACjBC;AAEA,MAAA,CAACJ,iBAAiB,CAACK;AACdX,WAAAA;AAGHY,QAAAA,eAAeL,MAAAA,aAAaN,WAAWO,KAAK,CAAC,CAAC,IAChDP,WAAWO,KAAK,CAAC,EAAEC,OACnBC,QACEG,aAAaN,MAAAA,aAAaF,SAASG,KAAK,CAAC,CAAC,IAC5CH,SAASG,KAAK,CAAC,EAAEC,OACjBC;AAEJ,aAAWvB,SAASP,QAAQkC;AACrBC,QAAAA,MAAAA,wBAAwB5B,KAAK,GAIlC;AAAIA,UAAAA,MAAMsB,SAASH,eAAe;AAChC,mBAAWU,SAAS7B,MAAM8B;AACnBC,cAAAA,MAAAA,mBAAmBF,KAAK,GAI7B;AAAIJ,gBAAAA,gBAAgBI,MAAMP,SAASG,cAAc;AAM/C,kBALAZ,cAAcmB,KAAK;AAAA,gBACjB/B,MAAM4B;AAAAA,gBACNR,MAAM,CAAC;AAAA,kBAACC,MAAMtB,MAAMsB;AAAAA,mBAAO,YAAY;AAAA,kBAACA,MAAMO,MAAMP;AAAAA,gBAAK,CAAA;AAAA,cAAA,CAC1D,GAEGG,iBAAiBC;AACnB;AAGF;AAAA,YAAA;AAGEA,gBAAAA,cAAcG,MAAMP,SAASI,YAAY;AAC3Cb,4BAAcmB,KAAK;AAAA,gBACjB/B,MAAM4B;AAAAA,gBACNR,MAAM,CAAC;AAAA,kBAACC,MAAMtB,MAAMsB;AAAAA,mBAAO,YAAY;AAAA,kBAACA,MAAMO,MAAMP;AAAAA,gBAAK,CAAA;AAAA,cAAA,CAC1D;AACD;AAAA,YAAA;AAGET,0BAAcoB,SAAS,KACzBpB,cAAcmB,KAAK;AAAA,cACjB/B,MAAM4B;AAAAA,cACNR,MAAM,CAAC;AAAA,gBAACC,MAAMtB,MAAMsB;AAAAA,iBAAO,YAAY;AAAA,gBAACA,MAAMO,MAAMP;AAAAA,cAAK,CAAA;AAAA,YAAA,CAC1D;AAAA,UAAA;AAIL,YAAIH,kBAAkBK;AACpB;AAGF;AAAA,MAAA;AAGExB,UAAAA,MAAMsB,SAASE,aAAa;AAC9B,mBAAWK,SAAS7B,MAAM8B;AACnBC,cAAAA,MAAAA,mBAAmBF,KAAK,GAI7B;AAAIH,gBAAAA,cAAcG,MAAMP,SAASI,YAAY;AAC3Cb,4BAAcmB,KAAK;AAAA,gBACjB/B,MAAM4B;AAAAA,gBACNR,MAAM,CAAC;AAAA,kBAACC,MAAMtB,MAAMsB;AAAAA,mBAAO,YAAY;AAAA,kBAACA,MAAMO,MAAMP;AAAAA,gBAAK,CAAA;AAAA,cAAA,CAC1D;AACD;AAAA,YAAA;AAGFT,0BAAcmB,KAAK;AAAA,cACjB/B,MAAM4B;AAAAA,cACNR,MAAM,CAAC;AAAA,gBAACC,MAAMtB,MAAMsB;AAAAA,iBAAO,YAAY;AAAA,gBAACA,MAAMO,MAAMP;AAAAA,cAAK,CAAA;AAAA,YAAA,CAC1D;AAAA,UAAA;AAGH;AAAA,MAAA;AAGF,UAAIT,cAAcoB,SAAS;AACzB,mBAAWJ,SAAS7B,MAAM8B;AACnBC,gBAAAA,mBAAmBF,KAAK,KAI7BhB,cAAcmB,KAAK;AAAA,YACjB/B,MAAM4B;AAAAA,YACNR,MAAM,CAAC;AAAA,cAACC,MAAMtB,MAAMsB;AAAAA,eAAO,YAAY;AAAA,cAACA,MAAMO,MAAMP;AAAAA,YAAK,CAAA;AAAA,UAAA,CAC1D;AAAA,IAAA;AAKAT,SAAAA;AACT;ACjIO,SAASqB,mBACdC,YACyB;AACzB,SAAQC,CAAa,aAAA;AACf,QAAA,CAACA,SAAS3C,QAAQC;AACb,aAAA;AAGT,UAAM2C,iBAAiBvC,8BAAAA,kBAAkBsC,QAAQ,GAC3CvB,gBAAgBD,iBAAiBwB,QAAQ;AAM/C,QAJIvB,cAAcoB,WAAW,KAK3BpB,cAAcyB,KACXC,CAAS,SAAA,CAACA,KAAKtC,KAAKuC,SAASD,KAAKtC,KAAKuC,OAAOP,WAAW,CAC5D;AAEO,aAAA;AAGT,UAAMQ,oBAAoBJ,eAAeK,QAAS1C,CAAAA,UAChD4B,MAAAA,wBAAwB5B,MAAMC,IAAI,IAAKD,MAAMC,KAAK0C,YAAY,CAAA,IAAM,CAAA,CACtE;AAEA,WAAO9B,cAAcL,MAAO+B,CAAAA,UAExBA,KAAKtC,KAAKuC,OAAOE,QAASE,CAAS,SAAA;AACjC,YAAMC,UAAUJ,kBAAkBK,KAC/BD,CAAAA,aAAYA,SAAQvB,SAASsB,IAChC;AAEA,aAAOC,UAAU,CAACA,QAAQE,KAAK,IAAI,CAAE;AAAA,IACtC,CAAA,KAAK,CAEYC,GAAAA,SAASb,UAAU,CACxC;AAAA,EACH;AACF;AC1CO,MAAMc,sBAA+CA,CAAC;AAAA,EAACxD;AAAO,MAC5D,CAACyD,8BAAAA,qBAAqB;AAAA,EAACzD;AAAO,CAAC;ACAjC,SAAS0D,kBAAkBC,WAA4C;AAC5E,SAAQhB,CAAa,aAAA;AACfa,QAAAA,oBAAoBb,QAAQ,GAAG;AAC3BvB,YAAAA,gBAAgBD,iBAAiBwB,QAAQ;AAG7CvB,aAAAA,cAAcoB,SAAS,KACvBpB,cAAcL,MAAO+B,CAASA,SAAAA,KAAKtC,KAAKuC,OAAOQ,SAASI,SAAS,CAAC;AAAA,IAAA;AAItE,WAAOhB,SAAS3C,QAAQ4D,iBAAiBL,SAASI,SAAS;AAAA,EAC7D;AACF;ACdO,SAASE,iBAAiB/C,UAA2C;AAClE6B,SAAAA,CAAAA,aACiB5C,kBAAkB4C,QAAQ,MAEvB7B;AAE9B;ACNO,SAASgD,cAAc5C,OAAwC;AAC5DyB,SAAAA,CAAAA,aACc3B,eAAe2B,QAAQ,MAEpBzB;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/selectors/selector.get-active-list-item.ts","../../src/selectors/selector.get-active-style.ts","../../src/selectors/selector.get-selected-spans.ts","../../src/selectors/selector.is-active-annotation.ts","../../src/selectors/selector.is-selection-expanded.ts","../../src/selectors/selector.is-active-decorator.ts","../../src/selectors/selector.is-active-list-item.ts","../../src/selectors/selector.is-active-style.ts"],"sourcesContent":["import type {PortableTextListBlock} from '@sanity/types'\nimport {createGuards} from '../behavior-actions/behavior.guards'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getSelectedBlocks} from './selectors'\n\n/**\n * @public\n */\nexport const getActiveListItem: EditorSelector<\n PortableTextListBlock['listItem'] | undefined\n> = ({context}) => {\n if (!context.selection) {\n return undefined\n }\n\n const guards = createGuards(context)\n const selectedBlocks = getSelectedBlocks({context}).map((block) => block.node)\n const selectedTextBlocks = selectedBlocks.filter(guards.isTextBlock)\n\n const firstTextBlock = selectedTextBlocks.at(0)\n\n if (!firstTextBlock) {\n return undefined\n }\n\n const firstListItem = firstTextBlock.listItem\n\n if (!firstListItem) {\n return undefined\n }\n\n if (selectedTextBlocks.every((block) => block.listItem === firstListItem)) {\n return firstListItem\n }\n\n return undefined\n}\n","import type {PortableTextTextBlock} from '@sanity/types'\nimport {createGuards} from '../behavior-actions/behavior.guards'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getSelectedBlocks} from './selectors'\n\n/**\n * @public\n */\nexport const getActiveStyle: EditorSelector<PortableTextTextBlock['style']> = ({\n context,\n}) => {\n if (!context.selection) {\n return undefined\n }\n\n const guards = createGuards(context)\n const selectedBlocks = getSelectedBlocks({context}).map((block) => block.node)\n const selectedTextBlocks = selectedBlocks.filter(guards.isTextBlock)\n\n const firstTextBlock = selectedTextBlocks.at(0)\n\n if (!firstTextBlock) {\n return undefined\n }\n\n const firstStyle = firstTextBlock.style\n\n if (!firstStyle) {\n return undefined\n }\n\n if (selectedTextBlocks.every((block) => block.style === firstStyle)) {\n return firstStyle\n }\n\n return undefined\n}\n","import {\n isKeySegment,\n isPortableTextSpan,\n isPortableTextTextBlock,\n type KeyedSegment,\n type PortableTextSpan,\n} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\n\n/**\n * @public\n */\nexport const getSelectedSpans: EditorSelector<\n Array<{\n node: PortableTextSpan\n path: [KeyedSegment, 'children', KeyedSegment]\n }>\n> = ({context}) => {\n if (!context.selection) {\n return []\n }\n\n const selectedSpans: Array<{\n node: PortableTextSpan\n path: [KeyedSegment, 'children', KeyedSegment]\n }> = []\n\n const startPoint = context.selection.backward\n ? context.selection.focus\n : context.selection.anchor\n const endPoint = context.selection.backward\n ? context.selection.anchor\n : context.selection.focus\n\n const startBlockKey = isKeySegment(startPoint.path[0])\n ? startPoint.path[0]._key\n : undefined\n const endBlockKey = isKeySegment(endPoint.path[0])\n ? endPoint.path[0]._key\n : undefined\n\n if (!startBlockKey || !endBlockKey) {\n return selectedSpans\n }\n\n const startSpanKey = isKeySegment(startPoint.path[2])\n ? startPoint.path[2]._key\n : undefined\n const endSpanKey = isKeySegment(endPoint.path[2])\n ? endPoint.path[2]._key\n : undefined\n\n for (const block of context.value) {\n if (!isPortableTextTextBlock(block)) {\n continue\n }\n\n if (block._key === startBlockKey) {\n for (const child of block.children) {\n if (!isPortableTextSpan(child)) {\n continue\n }\n\n if (startSpanKey && child._key === startSpanKey) {\n selectedSpans.push({\n node: child,\n path: [{_key: block._key}, 'children', {_key: child._key}],\n })\n\n if (startSpanKey === endSpanKey) {\n break\n }\n\n continue\n }\n\n if (endSpanKey && child._key === endSpanKey) {\n selectedSpans.push({\n node: child,\n path: [{_key: block._key}, 'children', {_key: child._key}],\n })\n break\n }\n\n if (selectedSpans.length > 0) {\n selectedSpans.push({\n node: child,\n path: [{_key: block._key}, 'children', {_key: child._key}],\n })\n }\n }\n\n if (startBlockKey === endBlockKey) {\n break\n }\n\n continue\n }\n\n if (block._key === endBlockKey) {\n for (const child of block.children) {\n if (!isPortableTextSpan(child)) {\n continue\n }\n\n if (endSpanKey && child._key === endSpanKey) {\n selectedSpans.push({\n node: child,\n path: [{_key: block._key}, 'children', {_key: child._key}],\n })\n break\n }\n\n selectedSpans.push({\n node: child,\n path: [{_key: block._key}, 'children', {_key: child._key}],\n })\n }\n\n break\n }\n\n if (selectedSpans.length > 0) {\n for (const child of block.children) {\n if (!isPortableTextSpan(child)) {\n continue\n }\n\n selectedSpans.push({\n node: child,\n path: [{_key: block._key}, 'children', {_key: child._key}],\n })\n }\n }\n }\n\n return selectedSpans\n}\n","import {isPortableTextTextBlock} from '@sanity/types'\nimport type {EditorSelector} from '../editor/editor-selector'\nimport {getSelectedSpans} from './selector.get-selected-spans'\nimport {getSelectedBlocks} from './selectors'\n\n/**\n * @public\n */\nexport function isActiveAnnotation(\n annotation: string,\n): EditorSelector<boolean> {\n return (snapshot) => {\n if (!snapshot.context.selection) {\n return false\n }\n\n const selectedBlocks = getSelectedBlocks(snapshot)\n const selectedSpans = getSelectedSpans(snapshot)\n\n if (selectedSpans.length === 0) {\n return false\n }\n\n if (\n selectedSpans.some(\n (span) => !span.node.marks || span.node.marks?.length === 0,\n )\n ) {\n return false\n }\n\n const selectionMarkDefs = selectedBlocks.flatMap((block) =>\n isPortableTextTextBlock(block.node) ? (block.node.markDefs ?? []) : [],\n )\n\n return selectedSpans.every((span) => {\n const spanMarkDefs =\n span.node.marks?.flatMap((mark) => {\n const markDef = selectionMarkDefs.find(\n (markDef) => markDef._key === mark,\n )\n\n return markDef ? [markDef._type] : []\n }) ?? []\n\n return spanMarkDefs.includes(annotation)\n })\n }\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport {isSelectionCollapsed} from './selector.is-selection-collapsed'\n\n/**\n * @public\n */\nexport const isSelectionExpanded: EditorSelector<boolean> = ({context}) => {\n return !isSelectionCollapsed({context})\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport {getSelectedSpans} from './selector.get-selected-spans'\nimport {isSelectionExpanded} from './selector.is-selection-expanded'\n\n/**\n * @public\n */\nexport function isActiveDecorator(decorator: string): EditorSelector<boolean> {\n return (snapshot) => {\n if (isSelectionExpanded(snapshot)) {\n const selectedSpans = getSelectedSpans(snapshot)\n\n return (\n selectedSpans.length > 0 &&\n selectedSpans.every((span) => span.node.marks?.includes(decorator))\n )\n }\n\n return snapshot.context.activeDecorators.includes(decorator)\n }\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport {getActiveListItem} from './selector.get-active-list-item'\n\n/**\n * @public\n */\nexport function isActiveListItem(listItem: string): EditorSelector<boolean> {\n return (snapshot) => {\n const activeListItem = getActiveListItem(snapshot)\n\n return activeListItem === listItem\n }\n}\n","import type {EditorSelector} from '../editor/editor-selector'\nimport {getActiveStyle} from './selector.get-active-style'\n\n/**\n * @public\n */\nexport function isActiveStyle(style: string): EditorSelector<boolean> {\n return (snapshot) => {\n const activeStyle = getActiveStyle(snapshot)\n\n return activeStyle === style\n }\n}\n"],"names":["getActiveListItem","context","selection","guards","createGuards","selectedTextBlocks","getSelectedBlocks","map","block","node","filter","isTextBlock","firstTextBlock","at","firstListItem","listItem","every","getActiveStyle","firstStyle","style","getSelectedSpans","selectedSpans","startPoint","backward","focus","anchor","endPoint","startBlockKey","isKeySegment","path","_key","undefined","endBlockKey","startSpanKey","endSpanKey","value","isPortableTextTextBlock","child","children","isPortableTextSpan","push","length","isActiveAnnotation","annotation","snapshot","selectedBlocks","some","span","marks","selectionMarkDefs","flatMap","markDefs","mark","markDef","find","_type","includes","isSelectionExpanded","isSelectionCollapsed","isActiveDecorator","decorator","activeDecorators","isActiveListItem","isActiveStyle"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.0",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@portabletext/toolkit": "^2.0.16",
|
|
73
73
|
"@sanity/block-tools": "^3.68.3",
|
|
74
74
|
"@sanity/diff-match-patch": "^3.1.2",
|
|
75
|
-
"@sanity/pkg-utils": "^6.
|
|
75
|
+
"@sanity/pkg-utils": "^6.13.1",
|
|
76
76
|
"@sanity/schema": "^3.68.3",
|
|
77
77
|
"@sanity/types": "^3.68.3",
|
|
78
78
|
"@testing-library/jest-dom": "^6.6.3",
|
|
@@ -87,15 +87,14 @@
|
|
|
87
87
|
"@vitejs/plugin-react": "^4.3.4",
|
|
88
88
|
"@vitest/browser": "^2.1.8",
|
|
89
89
|
"@vitest/coverage-istanbul": "^2.1.8",
|
|
90
|
-
"babel-plugin-react-compiler": "19.0.0-beta-
|
|
90
|
+
"babel-plugin-react-compiler": "19.0.0-beta-63e3235-20250105",
|
|
91
91
|
"eslint": "8.57.1",
|
|
92
|
-
"eslint-plugin-react-compiler": "19.0.0-beta-
|
|
92
|
+
"eslint-plugin-react-compiler": "19.0.0-beta-63e3235-20250105",
|
|
93
93
|
"eslint-plugin-react-hooks": "^5.1.0",
|
|
94
94
|
"jsdom": "^25.0.1",
|
|
95
95
|
"react": "^19.0.0",
|
|
96
96
|
"react-dom": "^19.0.0",
|
|
97
97
|
"rxjs": "^7.8.1",
|
|
98
|
-
"styled-components": "^6.1.13",
|
|
99
98
|
"typescript": "5.7.2",
|
|
100
99
|
"vite": "^6.0.4",
|
|
101
100
|
"vitest": "^2.1.8",
|
|
@@ -107,8 +106,7 @@
|
|
|
107
106
|
"@sanity/schema": "^3.68.3",
|
|
108
107
|
"@sanity/types": "^3.68.3",
|
|
109
108
|
"react": "^16.9 || ^17 || ^18 || ^19",
|
|
110
|
-
"rxjs": "^7.8.1"
|
|
111
|
-
"styled-components": "^6.1.13"
|
|
109
|
+
"rxjs": "^7.8.1"
|
|
112
110
|
},
|
|
113
111
|
"engines": {
|
|
114
112
|
"node": ">=18"
|
|
@@ -296,9 +296,9 @@ export type BehaviorActionIntendSet<
|
|
|
296
296
|
* @beta
|
|
297
297
|
*/
|
|
298
298
|
export function defineBehavior<
|
|
299
|
-
|
|
299
|
+
TBehaviorEventType extends BehaviorEvent['type'],
|
|
300
300
|
TGuardResponse = true,
|
|
301
|
-
>(behavior: Behavior<
|
|
301
|
+
>(behavior: Behavior<TBehaviorEventType, TGuardResponse>): Behavior {
|
|
302
302
|
return behavior as unknown as Behavior
|
|
303
303
|
}
|
|
304
304
|
|
|
@@ -30,11 +30,6 @@ import {debugWithName} from '../../utils/debug'
|
|
|
30
30
|
import {fromSlateValue} from '../../utils/values'
|
|
31
31
|
import {KEY_TO_VALUE_ELEMENT} from '../../utils/weakMaps'
|
|
32
32
|
import ObjectNode from '../nodes/DefaultObject'
|
|
33
|
-
import {
|
|
34
|
-
DefaultBlockObject,
|
|
35
|
-
DefaultListItem,
|
|
36
|
-
DefaultListItemInner,
|
|
37
|
-
} from '../nodes/index'
|
|
38
33
|
import {DraggableBlock} from './DraggableBlock'
|
|
39
34
|
|
|
40
35
|
const debug = debugWithName('components:Element')
|
|
@@ -185,12 +180,14 @@ export const Element: FunctionComponent<ElementProps> = ({
|
|
|
185
180
|
})
|
|
186
181
|
}
|
|
187
182
|
let level: number | undefined
|
|
183
|
+
|
|
188
184
|
if (isListItem) {
|
|
189
185
|
if (typeof element.level === 'number') {
|
|
190
186
|
level = element.level
|
|
191
187
|
}
|
|
192
188
|
className += ` pt-list-item pt-list-item-${element.listItem} pt-list-item-level-${level || 1}`
|
|
193
189
|
}
|
|
190
|
+
|
|
194
191
|
if (editor.isListBlock(value) && isListItem && element.listItem) {
|
|
195
192
|
const listType = schemaTypes.lists.find(
|
|
196
193
|
(item) => item.value === element.listItem,
|
|
@@ -207,17 +204,9 @@ export const Element: FunctionComponent<ElementProps> = ({
|
|
|
207
204
|
level: value.level || 1,
|
|
208
205
|
editorElementRef: blockRef,
|
|
209
206
|
})
|
|
210
|
-
} else {
|
|
211
|
-
renderedBlock = (
|
|
212
|
-
<DefaultListItem
|
|
213
|
-
listStyle={value.listItem || schemaTypes.lists[0].value}
|
|
214
|
-
listLevel={value.level || 1}
|
|
215
|
-
>
|
|
216
|
-
<DefaultListItemInner>{renderedBlock}</DefaultListItemInner>
|
|
217
|
-
</DefaultListItem>
|
|
218
|
-
)
|
|
219
207
|
}
|
|
220
208
|
}
|
|
209
|
+
|
|
221
210
|
const renderProps: Omit<BlockRenderProps, 'type'> = Object.defineProperty(
|
|
222
211
|
{
|
|
223
212
|
children: renderedBlock,
|
|
@@ -263,24 +252,31 @@ export const Element: FunctionComponent<ElementProps> = ({
|
|
|
263
252
|
</div>
|
|
264
253
|
)
|
|
265
254
|
}
|
|
255
|
+
|
|
266
256
|
const schemaType = schemaTypes.blockObjects.find(
|
|
267
257
|
(_type) => _type.name === element._type,
|
|
268
258
|
)
|
|
259
|
+
|
|
269
260
|
if (!schemaType) {
|
|
270
261
|
throw new Error(
|
|
271
262
|
`Could not find schema type for block element of _type ${element._type}`,
|
|
272
263
|
)
|
|
273
264
|
}
|
|
265
|
+
|
|
274
266
|
if (debugRenders) {
|
|
275
267
|
debug(`Render ${element._key} (object block)`)
|
|
276
268
|
}
|
|
269
|
+
|
|
277
270
|
className = 'pt-block pt-object-block'
|
|
271
|
+
|
|
278
272
|
const block = fromSlateValue(
|
|
279
273
|
[element],
|
|
280
274
|
schemaTypes.block.name,
|
|
281
275
|
KEY_TO_VALUE_ELEMENT.get(editor),
|
|
282
276
|
)[0]
|
|
277
|
+
|
|
283
278
|
let renderedBlockFromProps: JSX.Element | undefined
|
|
279
|
+
|
|
284
280
|
if (renderBlock) {
|
|
285
281
|
const _props: Omit<BlockRenderProps, 'type'> = Object.defineProperty(
|
|
286
282
|
{
|
|
@@ -305,20 +301,18 @@ export const Element: FunctionComponent<ElementProps> = ({
|
|
|
305
301
|
)
|
|
306
302
|
renderedBlockFromProps = renderBlock(_props as BlockRenderProps)
|
|
307
303
|
}
|
|
304
|
+
|
|
308
305
|
return (
|
|
309
306
|
<div key={element._key} {...attributes} className={className}>
|
|
310
307
|
{children}
|
|
311
308
|
<DraggableBlock element={element} readOnly={readOnly} blockRef={blockRef}>
|
|
312
|
-
{
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
)}
|
|
317
|
-
{!renderedBlockFromProps && (
|
|
318
|
-
<DefaultBlockObject selected={selected}>
|
|
309
|
+
<div ref={blockRef} contentEditable={false}>
|
|
310
|
+
{renderedBlockFromProps ? (
|
|
311
|
+
renderedBlockFromProps
|
|
312
|
+
) : (
|
|
319
313
|
<ObjectNode value={value} />
|
|
320
|
-
|
|
321
|
-
|
|
314
|
+
)}
|
|
315
|
+
</div>
|
|
322
316
|
</DraggableBlock>
|
|
323
317
|
</div>
|
|
324
318
|
)
|
|
@@ -82,6 +82,10 @@ export type EditorEvent = PickFromUnion<
|
|
|
82
82
|
*/
|
|
83
83
|
export type Editor = {
|
|
84
84
|
getSnapshot: () => EditorSnapshot
|
|
85
|
+
/**
|
|
86
|
+
* @beta
|
|
87
|
+
*/
|
|
88
|
+
registerBehavior: (config: {behavior: Behavior}) => () => void
|
|
85
89
|
send: (event: EditorEvent) => void
|
|
86
90
|
on: ActorRef<Snapshot<unknown>, EventObject, EditorEmittedEvent>['on']
|
|
87
91
|
_internal: {
|
|
@@ -135,6 +139,19 @@ function createEditorFromActor(editorActor: EditorActor): Editor {
|
|
|
135
139
|
editorActorSnapshot: editorActor.getSnapshot(),
|
|
136
140
|
slateEditorInstance: slateEditor.instance,
|
|
137
141
|
}),
|
|
142
|
+
registerBehavior: (config) => {
|
|
143
|
+
editorActor.send({
|
|
144
|
+
type: 'add behavior',
|
|
145
|
+
behavior: config.behavior,
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
return () => {
|
|
149
|
+
editorActor.send({
|
|
150
|
+
type: 'remove behavior',
|
|
151
|
+
behavior: config.behavior,
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
},
|
|
138
155
|
send: (event) => {
|
|
139
156
|
editorActor.send(event)
|
|
140
157
|
},
|
|
@@ -79,6 +79,14 @@ export type InternalEditorEvent =
|
|
|
79
79
|
editor: PortableTextSlateEditor
|
|
80
80
|
nativeEvent?: {preventDefault: () => void}
|
|
81
81
|
}
|
|
82
|
+
| {
|
|
83
|
+
type: 'add behavior'
|
|
84
|
+
behavior: Behavior
|
|
85
|
+
}
|
|
86
|
+
| {
|
|
87
|
+
type: 'remove behavior'
|
|
88
|
+
behavior: Behavior
|
|
89
|
+
}
|
|
82
90
|
| {
|
|
83
91
|
type: 'update readOnly'
|
|
84
92
|
readOnly: boolean
|
|
@@ -181,7 +189,7 @@ export type InternalEditorEmittedEvent =
|
|
|
181
189
|
export const editorMachine = setup({
|
|
182
190
|
types: {
|
|
183
191
|
context: {} as {
|
|
184
|
-
behaviors:
|
|
192
|
+
behaviors: Set<Behavior>
|
|
185
193
|
keyGenerator: () => string
|
|
186
194
|
pendingEvents: Array<PatchEvent | MutationEvent>
|
|
187
195
|
schema: EditorSchema
|
|
@@ -202,10 +210,26 @@ export const editorMachine = setup({
|
|
|
202
210
|
},
|
|
203
211
|
},
|
|
204
212
|
actions: {
|
|
213
|
+
'add behavior to context': assign({
|
|
214
|
+
behaviors: ({context, event}) => {
|
|
215
|
+
assertEvent(event, 'add behavior')
|
|
216
|
+
|
|
217
|
+
return new Set([...context.behaviors, event.behavior])
|
|
218
|
+
},
|
|
219
|
+
}),
|
|
220
|
+
'remove behavior from context': assign({
|
|
221
|
+
behaviors: ({context, event}) => {
|
|
222
|
+
assertEvent(event, 'remove behavior')
|
|
223
|
+
|
|
224
|
+
context.behaviors.delete(event.behavior)
|
|
225
|
+
|
|
226
|
+
return new Set([...context.behaviors])
|
|
227
|
+
},
|
|
228
|
+
}),
|
|
205
229
|
'assign behaviors': assign({
|
|
206
230
|
behaviors: ({event}) => {
|
|
207
231
|
assertEvent(event, 'update behaviors')
|
|
208
|
-
return event.behaviors
|
|
232
|
+
return new Set(event.behaviors)
|
|
209
233
|
},
|
|
210
234
|
}),
|
|
211
235
|
'assign schema': assign({
|
|
@@ -253,7 +277,7 @@ export const editorMachine = setup({
|
|
|
253
277
|
editor: event.editor,
|
|
254
278
|
} satisfies BehaviorAction)
|
|
255
279
|
|
|
256
|
-
const eventBehaviors = context.behaviors.filter(
|
|
280
|
+
const eventBehaviors = [...context.behaviors.values()].filter(
|
|
257
281
|
(behavior) => behavior.on === event.behaviorEvent.type,
|
|
258
282
|
)
|
|
259
283
|
|
|
@@ -375,7 +399,7 @@ export const editorMachine = setup({
|
|
|
375
399
|
}).createMachine({
|
|
376
400
|
id: 'editor',
|
|
377
401
|
context: ({input}) => ({
|
|
378
|
-
behaviors: input.behaviors ?? coreBehaviors,
|
|
402
|
+
behaviors: new Set(input.behaviors ?? coreBehaviors),
|
|
379
403
|
keyGenerator: input.keyGenerator,
|
|
380
404
|
pendingEvents: [],
|
|
381
405
|
schema: input.schema,
|
|
@@ -385,6 +409,8 @@ export const editorMachine = setup({
|
|
|
385
409
|
value: input.value,
|
|
386
410
|
}),
|
|
387
411
|
on: {
|
|
412
|
+
'add behavior': {actions: 'add behavior to context'},
|
|
413
|
+
'remove behavior': {actions: 'remove behavior from context'},
|
|
388
414
|
'unset': {actions: emit(({event}) => event)},
|
|
389
415
|
'value changed': {actions: emit(({event}) => event)},
|
|
390
416
|
'invalid value': {actions: emit(({event}) => event)},
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import {styled} from 'styled-components'
|
|
2
|
-
|
|
3
|
-
export const DefaultBlockObject = styled.div<{selected: boolean}>`
|
|
4
|
-
user-select: none;
|
|
5
|
-
border: ${(props) => {
|
|
6
|
-
if (props.selected) {
|
|
7
|
-
return '1px solid blue'
|
|
8
|
-
}
|
|
9
|
-
return '1px solid transparent'
|
|
10
|
-
}};
|
|
11
|
-
`
|
|
12
|
-
|
|
13
|
-
export const DefaultInlineObject = styled.span<{selected: boolean}>`
|
|
14
|
-
background: #999;
|
|
15
|
-
border: ${(props) => {
|
|
16
|
-
if (props.selected) {
|
|
17
|
-
return '1px solid blue'
|
|
18
|
-
}
|
|
19
|
-
return '1px solid transparent'
|
|
20
|
-
}};
|
|
21
|
-
`
|
|
22
|
-
|
|
23
|
-
type ListItemProps = {listLevel: number; listStyle: string}
|
|
24
|
-
|
|
25
|
-
export const DefaultListItem = styled.div<ListItemProps>`
|
|
26
|
-
&.pt-list-item {
|
|
27
|
-
width: fit-content;
|
|
28
|
-
position: relative;
|
|
29
|
-
display: block;
|
|
30
|
-
|
|
31
|
-
/* Important 'transform' in order to force refresh the ::before and ::after rules
|
|
32
|
-
in Webkit: https://stackoverflow.com/a/21947628/831480
|
|
33
|
-
*/
|
|
34
|
-
transform: translateZ(0);
|
|
35
|
-
margin-left: ${(props: ListItemProps) => getLeftPositionForListLevel(props.listLevel)};
|
|
36
|
-
}
|
|
37
|
-
&.pt-list-item > .pt-list-item-inner {
|
|
38
|
-
display: flex;
|
|
39
|
-
margin: 0;
|
|
40
|
-
padding: 0;
|
|
41
|
-
&:before {
|
|
42
|
-
justify-content: flex-start;
|
|
43
|
-
vertical-align: top;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
&.pt-list-item-bullet > .pt-list-item-inner:before {
|
|
47
|
-
content: '${(props: ListItemProps) =>
|
|
48
|
-
getContentForListLevelAndStyle(props.listLevel, props.listStyle)}';
|
|
49
|
-
font-size: 0.4375rem; /* 7px */
|
|
50
|
-
line-height: 1.5rem; /* Same as body text */
|
|
51
|
-
/* Optical alignment */
|
|
52
|
-
position: relative;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
&.pt-list-item-bullet > .pt-list-item-inner {
|
|
56
|
-
&:before {
|
|
57
|
-
min-width: 1.5rem; /* Make sure space between bullet and text never shrinks */
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
&.pt-list-item-number {
|
|
61
|
-
counter-increment: ${(props: {listLevel: number}) =>
|
|
62
|
-
getCounterIncrementForListLevel(props.listLevel)};
|
|
63
|
-
counter-reset: ${(props: {listLevel: number}) => getCounterResetForListLevel(props.listLevel)};
|
|
64
|
-
}
|
|
65
|
-
& + :not(.pt-list-item-number) {
|
|
66
|
-
counter-reset: listItemNumber;
|
|
67
|
-
}
|
|
68
|
-
&.pt-list-item-number > .pt-list-item-inner:before {
|
|
69
|
-
content: ${(props) => getCounterContentForListLevel(props.listLevel)};
|
|
70
|
-
min-width: 1.5rem; /* Make sure space between number and text never shrinks */
|
|
71
|
-
/* Optical alignment */
|
|
72
|
-
position: relative;
|
|
73
|
-
top: 1px;
|
|
74
|
-
}
|
|
75
|
-
`
|
|
76
|
-
|
|
77
|
-
export const DefaultListItemInner = styled.div``
|
|
78
|
-
|
|
79
|
-
function getLeftPositionForListLevel(level: number) {
|
|
80
|
-
switch (Number(level)) {
|
|
81
|
-
case 1:
|
|
82
|
-
return '1.5em'
|
|
83
|
-
case 2:
|
|
84
|
-
return '3em'
|
|
85
|
-
case 3:
|
|
86
|
-
return '4.5em'
|
|
87
|
-
case 4:
|
|
88
|
-
return '6em'
|
|
89
|
-
case 5:
|
|
90
|
-
return '7.5em'
|
|
91
|
-
case 6:
|
|
92
|
-
return '9em'
|
|
93
|
-
case 7:
|
|
94
|
-
return '10.5em'
|
|
95
|
-
case 8:
|
|
96
|
-
return '12em'
|
|
97
|
-
case 9:
|
|
98
|
-
return '13.5em'
|
|
99
|
-
case 10:
|
|
100
|
-
return '15em'
|
|
101
|
-
default:
|
|
102
|
-
return '0em'
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const bullets = ['●', '○', '■']
|
|
107
|
-
|
|
108
|
-
function getContentForListLevelAndStyle(level: number, style: string) {
|
|
109
|
-
const normalizedLevel = (level - 1) % 3
|
|
110
|
-
if (style === 'bullet') {
|
|
111
|
-
return bullets[normalizedLevel]
|
|
112
|
-
}
|
|
113
|
-
return '*'
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function getCounterIncrementForListLevel(level: number) {
|
|
117
|
-
switch (level) {
|
|
118
|
-
case 1:
|
|
119
|
-
return 'listItemNumber'
|
|
120
|
-
case 2:
|
|
121
|
-
return 'listItemAlpha'
|
|
122
|
-
case 3:
|
|
123
|
-
return 'listItemRoman'
|
|
124
|
-
case 4:
|
|
125
|
-
return 'listItemNumberNext'
|
|
126
|
-
case 5:
|
|
127
|
-
return 'listItemLetterNext'
|
|
128
|
-
case 6:
|
|
129
|
-
return 'listItemRomanNext'
|
|
130
|
-
case 7:
|
|
131
|
-
return 'listItemNumberNextNext'
|
|
132
|
-
case 8:
|
|
133
|
-
return 'listItemAlphaNextNext'
|
|
134
|
-
case 9:
|
|
135
|
-
return 'listItemRomanNextNext'
|
|
136
|
-
default:
|
|
137
|
-
return 'listItemNumberNextNextNext'
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function getCounterResetForListLevel(level: number) {
|
|
142
|
-
switch (level) {
|
|
143
|
-
case 1:
|
|
144
|
-
return 'listItemAlpha'
|
|
145
|
-
case 2:
|
|
146
|
-
return 'listItemRoman'
|
|
147
|
-
case 3:
|
|
148
|
-
return 'listItemNumberNext'
|
|
149
|
-
case 4:
|
|
150
|
-
return 'listItemLetterNext'
|
|
151
|
-
case 5:
|
|
152
|
-
return 'listItemRomanNext'
|
|
153
|
-
case 6:
|
|
154
|
-
return 'listItemNumberNextNext'
|
|
155
|
-
case 7:
|
|
156
|
-
return 'listItemAlphaNextNext'
|
|
157
|
-
case 8:
|
|
158
|
-
return 'listItemRomanNextNext'
|
|
159
|
-
case 9:
|
|
160
|
-
return 'listItemNumberNextNextNext'
|
|
161
|
-
default:
|
|
162
|
-
return 'listItemNumberNextNextNext'
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function getCounterContentForListLevel(level: number) {
|
|
167
|
-
switch (level) {
|
|
168
|
-
case 1:
|
|
169
|
-
return `counter(listItemNumber) '. '`
|
|
170
|
-
case 2:
|
|
171
|
-
return `counter(listItemAlpha, lower-alpha) '. '`
|
|
172
|
-
case 3:
|
|
173
|
-
return `counter(listItemRoman, lower-roman) '. '`
|
|
174
|
-
case 4:
|
|
175
|
-
return `counter(listItemNumberNext) '. '`
|
|
176
|
-
case 5:
|
|
177
|
-
return `counter(listItemLetterNext, lower-alpha) '. '`
|
|
178
|
-
case 6:
|
|
179
|
-
return `counter(listItemRomanNext, lower-roman) '. '`
|
|
180
|
-
case 7:
|
|
181
|
-
return `counter(listItemNumberNextNext) '. '`
|
|
182
|
-
case 8:
|
|
183
|
-
return `counter(listItemAlphaNextNext, lower-alpha) '. '`
|
|
184
|
-
case 9:
|
|
185
|
-
return `counter(listItemRomanNextNext, lower-roman) '. '`
|
|
186
|
-
default:
|
|
187
|
-
return `counter(listItemNumberNextNextNext) '. '`
|
|
188
|
-
}
|
|
189
|
-
}
|