From 91a987838d6d71ee3394c660ccf949116e50286d Mon Sep 17 00:00:00 2001 From: Gabriel Chittolina Date: Fri, 17 Apr 2026 14:39:49 -0300 Subject: [PATCH 1/4] feat: implement 2 extra types of bullet lists (square, circle) --- .../components/toolbar/BulletStyleButtons.vue | 136 ++++++++++++++++++ .../v1/components/toolbar/defaultItems.js | 25 +++- .../v1/components/toolbar/super-toolbar.js | 10 ++ .../v1/components/toolbar/toolbarIcons.js | 5 + .../editors/v1/core/commands/toggleList.js | 18 ++- .../v1/core/helpers/list-numbering-helpers.js | 14 +- .../parts/adapters/numbering-transforms.ts | 31 +++- .../v1/extensions/paragraph/paragraph.js | 12 ++ .../v1/extensions/types/paragraph-commands.ts | 3 + .../create-headless-toolbar.test.ts | 6 +- .../src/headless-toolbar/helpers/paragraph.ts | 5 + .../headless-toolbar/toolbar-registry.test.ts | 1 + .../src/headless-toolbar/toolbar-registry.ts | 2 +- shared/common/icons/list-circle-solid.svg | 1 + shared/common/icons/list-square-solid.svg | 1 + 15 files changed, 256 insertions(+), 14 deletions(-) create mode 100644 packages/super-editor/src/editors/v1/components/toolbar/BulletStyleButtons.vue create mode 100644 shared/common/icons/list-circle-solid.svg create mode 100644 shared/common/icons/list-square-solid.svg diff --git a/packages/super-editor/src/editors/v1/components/toolbar/BulletStyleButtons.vue b/packages/super-editor/src/editors/v1/components/toolbar/BulletStyleButtons.vue new file mode 100644 index 0000000000..e9dc1e5e9b --- /dev/null +++ b/packages/super-editor/src/editors/v1/components/toolbar/BulletStyleButtons.vue @@ -0,0 +1,136 @@ + + + + + diff --git a/packages/super-editor/src/editors/v1/components/toolbar/defaultItems.js b/packages/super-editor/src/editors/v1/components/toolbar/defaultItems.js index a16e4b00dc..f9c6206b8a 100644 --- a/packages/super-editor/src/editors/v1/components/toolbar/defaultItems.js +++ b/packages/super-editor/src/editors/v1/components/toolbar/defaultItems.js @@ -4,6 +4,7 @@ import { sanitizeNumber } from './helpers'; import { useToolbarItem } from './use-toolbar-item'; import AIWriter from './AIWriter.vue'; import AlignmentButtons from './AlignmentButtons.vue'; +import BulletStyleButtons from './BulletStyleButtons.vue'; import DocumentMode from './DocumentMode.vue'; import LinkedStyle from './LinkedStyle.vue'; import LinkInput from './LinkInput.vue'; @@ -630,16 +631,34 @@ export const makeDefaultItems = ({ // bullet list const bulletedList = useToolbarItem({ - type: 'button', + type: 'dropdown', name: 'list', - command: 'toggleBulletList', + command: 'toggleBulletListStyle', icon: toolbarIcons.bulletList, - active: false, + hasCaret: true, tooltip: toolbarTexts.bulletList, restoreEditorFocus: true, + suppressActiveHighlight: true, attributes: { ariaLabel: 'Bullet list', }, + options: [ + { + type: 'render', + key: 'bullet-style-buttons', + render: () => { + const handleSelect = (style) => { + closeDropdown(bulletedList); + const item = { ...bulletedList, command: 'toggleBulletListStyle' }; + superToolbar.emitCommand({ item, argument: style }); + }; + return h(BulletStyleButtons, { + selectedStyle: bulletedList.selectedValue.value, + onSelect: handleSelect, + }); + }, + }, + ], }); // number list diff --git a/packages/super-editor/src/editors/v1/components/toolbar/super-toolbar.js b/packages/super-editor/src/editors/v1/components/toolbar/super-toolbar.js index c290c31ad7..9a98bd28de 100644 --- a/packages/super-editor/src/editors/v1/components/toolbar/super-toolbar.js +++ b/packages/super-editor/src/editors/v1/components/toolbar/super-toolbar.js @@ -622,6 +622,16 @@ export class SuperToolbar extends EventEmitter { if (commandState?.value != null) item.activate({ styleId: commandState.value }); else item.label.value = this.config.texts?.formatText || 'Format text'; }, + list: () => { + const markerToStyle = { '•': 'disc', '◦': 'circle', '▪': 'square' }; + if (commandState?.active) { + item.activate(); + item.selectedValue.value = markerToStyle[commandState.value] ?? null; + } else { + item.deactivate(); + item.selectedValue.value = null; + } + }, default: () => { if (commandState?.active) item.activate(); else item.deactivate(); diff --git a/packages/super-editor/src/editors/v1/components/toolbar/toolbarIcons.js b/packages/super-editor/src/editors/v1/components/toolbar/toolbarIcons.js index 70f62342f4..8b8caf0f08 100644 --- a/packages/super-editor/src/editors/v1/components/toolbar/toolbarIcons.js +++ b/packages/super-editor/src/editors/v1/components/toolbar/toolbarIcons.js @@ -2,6 +2,8 @@ import boldIconSvg from '@superdoc/common/icons/bold-solid.svg?raw'; import italicIconSvg from '@superdoc/common/icons/italic-solid.svg?raw'; import underlineIconSvg from '@superdoc/common/icons/underline-solid.svg?raw'; import listIconSvg from '@superdoc/common/icons/list-solid.svg?raw'; +import listCircleIconSvg from '@superdoc/common/icons/list-circle-solid.svg?raw'; +import listSquareIconSvg from '@superdoc/common/icons/list-square-solid.svg?raw'; import listOlIconSvg from '@superdoc/common/icons/list-ol-solid.svg?raw'; import imageIconSvg from '@superdoc/common/icons/image-solid.svg?raw'; import linkIconSvg from '@superdoc/common/icons/link-solid.svg?raw'; @@ -64,6 +66,9 @@ export const toolbarIcons = { alignCenter: alignCenterIconSvg, alignJustify: alignJustifyIconSvg, bulletList: listIconSvg, + bulletListDisc: listIconSvg, + bulletListCircle: listCircleIconSvg, + bulletListSquare: listSquareIconSvg, numberedList: listOlIconSvg, indentLeft: outdentIconSvg, indentRight: indentIconSvg, diff --git a/packages/super-editor/src/editors/v1/core/commands/toggleList.js b/packages/super-editor/src/editors/v1/core/commands/toggleList.js index 048bd03ec0..0c689911d9 100644 --- a/packages/super-editor/src/editors/v1/core/commands/toggleList.js +++ b/packages/super-editor/src/editors/v1/core/commands/toggleList.js @@ -26,10 +26,18 @@ function getParagraphListKind(node, editor) { return numFmtIsBullet(fmt) ? 'bullet' : 'ordered'; } -function paragraphMatchesToggleListType(node, editor, listType) { +/** @type {Record} */ +const MARKER_TEXT_TO_STYLE = { '•': 'disc', '◦': 'circle', '▪': 'square' }; + +function paragraphMatchesToggleListType(node, editor, listType, bulletStyle) { const kind = getParagraphListKind(node, editor); if (!kind) return false; - if (listType === 'bulletList') return kind === 'bullet'; + if (listType === 'bulletList') { + if (kind !== 'bullet') return false; + if (!bulletStyle) return true; + const markerText = node.attrs.listRendering?.markerText; + return MARKER_TEXT_TO_STYLE[markerText] === bulletStyle; + } if (listType === 'orderedList') return kind === 'ordered'; return false; } @@ -60,13 +68,13 @@ function getPrecedingParagraphForListReuse(doc, from, paragraphsInSelection) { } export const toggleList = - (listType) => + (listType, bulletStyle) => ({ editor, state, tr, dispatch }) => { if (listType !== 'orderedList' && listType !== 'bulletList') { return false; } - const predicate = (n) => paragraphMatchesToggleListType(n, editor, listType); + const predicate = (n) => paragraphMatchesToggleListType(n, editor, listType, bulletStyle); const { selection } = state; const { from, to } = selection; let firstListNode = null; @@ -127,7 +135,7 @@ export const toggleList = if (mode === 'create') { const numId = ListHelpers.getNewListId(editor); - ListHelpers.generateNewListDefinition({ numId: Number(numId), listType, editor }); + ListHelpers.generateNewListDefinition({ numId: Number(numId), listType, editor, bulletStyle }); sharedNumberingProperties = { numId: Number(numId), ilvl: 0, diff --git a/packages/super-editor/src/editors/v1/core/helpers/list-numbering-helpers.js b/packages/super-editor/src/editors/v1/core/helpers/list-numbering-helpers.js index 016e536f55..b571958183 100644 --- a/packages/super-editor/src/editors/v1/core/helpers/list-numbering-helpers.js +++ b/packages/super-editor/src/editors/v1/core/helpers/list-numbering-helpers.js @@ -39,10 +39,21 @@ import { mutateNumbering } from '@core/parts/adapters/numbering-mutation'; * @param {string} [param0.text] * @param {string} [param0.fmt] * @param {string} [param0.markerFontFamily] + * @param {'disc'|'circle'|'square'} [param0.bulletStyle] * @param {import('../Editor').Editor} param0.editor * @returns {Object} The new abstract and num definitions. */ -export const generateNewListDefinition = ({ numId, listType, level, start, text, fmt, editor, markerFontFamily }) => { +export const generateNewListDefinition = ({ + numId, + listType, + level, + start, + text, + fmt, + editor, + markerFontFamily, + bulletStyle, +}) => { /** @type {{ abstractDef: any, numDef: any }} */ let resultDefs; @@ -55,6 +66,7 @@ export const generateNewListDefinition = ({ numId, listType, level, start, text, text, fmt, markerFontFamily, + bulletStyle, }); resultDefs = { abstractDef: result.abstractDef, numDef: result.numDef }; }); diff --git a/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-transforms.ts b/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-transforms.ts index 84d16a318f..9dfa065e42 100644 --- a/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-transforms.ts +++ b/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-transforms.ts @@ -30,8 +30,15 @@ interface GenerateOptions { text?: string | null; fmt?: string | null; markerFontFamily?: string | null; + bulletStyle?: 'disc' | 'circle' | 'square' | null; } +const BULLET_STYLE_CHARS: Record = { + disc: { char: '\uf0b7', font: 'Symbol' }, + circle: { char: 'o', font: 'Courier New' }, + square: { char: '\uf0a7', font: 'Wingdings' }, +}; + interface GenerateResult { numId: number; abstractId: number; @@ -72,7 +79,7 @@ function buildNumDef(numId: number, abstractId: number): any { */ export function generateNewListDefinition(numbering: NumberingModel, options: GenerateOptions): GenerateResult { let { listType } = options; - const { numId, level, start, text, fmt, markerFontFamily } = options; + const { numId, level, start, text, fmt, markerFontFamily, bulletStyle } = options; if (typeof listType !== 'string') listType = (listType as any).name; const definition = listType === 'orderedList' ? baseOrderedListDef : baseBulletList; @@ -86,6 +93,28 @@ export function generateNewListDefinition(numbering: NumberingModel, options: Ge }), ); + if (bulletStyle && listType !== 'orderedList') { + const styleChars = BULLET_STYLE_CHARS[bulletStyle]; + if (styleChars) { + const lvl0 = newAbstractDef.elements.find((el: any) => el.name === 'w:lvl' && el.attributes['w:ilvl'] === '0'); + if (lvl0) { + const lvlText = lvl0.elements.find((el: any) => el.name === 'w:lvlText'); + if (lvlText) lvlText.attributes['w:val'] = styleChars.char; + let rPr = lvl0.elements.find((el: any) => el.name === 'w:rPr'); + if (!rPr) { + rPr = { type: 'element', name: 'w:rPr', elements: [] }; + lvl0.elements.push(rPr); + } + rPr.elements = rPr.elements.filter((el: any) => el.name !== 'w:rFonts'); + rPr.elements.push({ + type: 'element', + name: 'w:rFonts', + attributes: { 'w:ascii': styleChars.font, 'w:hAnsi': styleChars.font, 'w:hint': 'default' }, + }); + } + } + } + if (level != null && start != null && text != null && fmt != null) { if (numbering.definitions[numId]) { const abstractId = numbering.definitions[numId]?.elements[0]?.attributes['w:val']; diff --git a/packages/super-editor/src/editors/v1/extensions/paragraph/paragraph.js b/packages/super-editor/src/editors/v1/extensions/paragraph/paragraph.js index 62525501c8..0d51b7e617 100644 --- a/packages/super-editor/src/editors/v1/extensions/paragraph/paragraph.js +++ b/packages/super-editor/src/editors/v1/extensions/paragraph/paragraph.js @@ -173,6 +173,7 @@ export const Paragraph = OxmlNode.create({ listRendering: { keepOnSplit: false, renderDOM: ({ listRendering }) => { + console.log('listRendering', listRendering); return { 'data-marker-type': listRendering?.markerText, 'data-list-level': listRendering?.path ? JSON.stringify(listRendering.path) : null, @@ -323,6 +324,17 @@ export const Paragraph = OxmlNode.create({ return toggleList('bulletList')(params); }, + /** + * Toggle a bullet list with a specific bullet style at the current selection + * @category Command + * @example + * editor.commands.toggleBulletListStyle('disc') + * @note Style can be 'disc' (•), 'circle' (◦), or 'square' (▪) + */ + toggleBulletListStyle: (style) => (params) => { + return toggleList('bulletList', style)(params); + }, + /** * Restart numbering for the current list * @category Command diff --git a/packages/super-editor/src/editors/v1/extensions/types/paragraph-commands.ts b/packages/super-editor/src/editors/v1/extensions/types/paragraph-commands.ts index a8f68ec827..06681a3037 100644 --- a/packages/super-editor/src/editors/v1/extensions/types/paragraph-commands.ts +++ b/packages/super-editor/src/editors/v1/extensions/types/paragraph-commands.ts @@ -15,6 +15,9 @@ export interface ParagraphCommands { /** Toggle bullet list formatting on the current selection */ toggleBulletList: () => boolean; + /** Toggle a bullet list with a specific style ('disc' | 'circle' | 'square') */ + toggleBulletListStyle: (style: 'disc' | 'circle' | 'square') => boolean; + /** Restart numbering for the current list item */ restartNumbering: () => boolean; diff --git a/packages/super-editor/src/headless-toolbar/create-headless-toolbar.test.ts b/packages/super-editor/src/headless-toolbar/create-headless-toolbar.test.ts index 53019dbe9d..41a057582c 100644 --- a/packages/super-editor/src/headless-toolbar/create-headless-toolbar.test.ts +++ b/packages/super-editor/src/headless-toolbar/create-headless-toolbar.test.ts @@ -473,10 +473,10 @@ describe('createHeadlessToolbar', () => { }); it('executes bullet-list through the registry direct command path', () => { - const toggleBulletList = vi.fn(() => true); + const toggleBulletListStyle = vi.fn(() => true); const superdoc = createActiveEditorHost({ commands: { - toggleBulletList, + toggleBulletListStyle, }, state: createSelectionState({ empty: true, @@ -495,7 +495,7 @@ describe('createHeadlessToolbar', () => { }); expect(controller.execute?.('bullet-list')).toBe(true); - expect(toggleBulletList).toHaveBeenCalledTimes(1); + expect(toggleBulletListStyle).toHaveBeenCalledTimes(1); controller.destroy(); }); diff --git a/packages/super-editor/src/headless-toolbar/helpers/paragraph.ts b/packages/super-editor/src/headless-toolbar/helpers/paragraph.ts index 9327cb71fd..8ff4b0598c 100644 --- a/packages/super-editor/src/headless-toolbar/helpers/paragraph.ts +++ b/packages/super-editor/src/headless-toolbar/helpers/paragraph.ts @@ -117,6 +117,11 @@ export const createListStateDeriver = ? activeNumberingType === 'bullet' : activeNumberingType != null && activeNumberingType !== 'bullet'; + if (numberingType === 'bullet') { + const markerText = isActive ? (paragraphNode?.attrs?.listRendering?.markerText ?? null) : null; + return { active: isActive, disabled: false, value: markerText }; + } + return { active: isActive, disabled: false, diff --git a/packages/super-editor/src/headless-toolbar/toolbar-registry.test.ts b/packages/super-editor/src/headless-toolbar/toolbar-registry.test.ts index a0a75f3510..9d705a752f 100644 --- a/packages/super-editor/src/headless-toolbar/toolbar-registry.test.ts +++ b/packages/super-editor/src/headless-toolbar/toolbar-registry.test.ts @@ -542,6 +542,7 @@ describe('createToolbarRegistry', () => { expect(state).toEqual({ active: true, disabled: false, + value: null, }); }); diff --git a/packages/super-editor/src/headless-toolbar/toolbar-registry.ts b/packages/super-editor/src/headless-toolbar/toolbar-registry.ts index a06a49ef71..a4026e9422 100644 --- a/packages/super-editor/src/headless-toolbar/toolbar-registry.ts +++ b/packages/super-editor/src/headless-toolbar/toolbar-registry.ts @@ -119,7 +119,7 @@ export const createToolbarRegistry = (): Partial diff --git a/shared/common/icons/list-square-solid.svg b/shared/common/icons/list-square-solid.svg new file mode 100644 index 0000000000..dd35473232 --- /dev/null +++ b/shared/common/icons/list-square-solid.svg @@ -0,0 +1 @@ + From 8137744afbcf0b0dec668fc7c2eadac5abbf871c Mon Sep 17 00:00:00 2001 From: Gabriel Chittolina Date: Fri, 17 Apr 2026 14:50:30 -0300 Subject: [PATCH 2/4] refactor: code reuse --- .../editors/v1/components/toolbar/super-toolbar.js | 4 ++-- .../src/editors/v1/core/commands/toggleList.js | 7 ++----- .../editors/v1/core/helpers/list-numbering-helpers.js | 11 +++++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/super-editor/src/editors/v1/components/toolbar/super-toolbar.js b/packages/super-editor/src/editors/v1/components/toolbar/super-toolbar.js index 9a98bd28de..28db7b3885 100644 --- a/packages/super-editor/src/editors/v1/components/toolbar/super-toolbar.js +++ b/packages/super-editor/src/editors/v1/components/toolbar/super-toolbar.js @@ -20,6 +20,7 @@ import { useToolbarItem } from '@components/toolbar/use-toolbar-item'; import { calculateResolvedParagraphProperties } from '@extensions/paragraph/resolvedPropertiesCache.js'; import { parseSizeUnit } from '@core/utilities'; import { findElementBySelector, getParagraphFontFamilyFromProperties } from './helpers/general.js'; +import { markerTextToBulletStyle } from '@helpers/list-numbering-helpers.js'; /** * @typedef {function(CommandItem): void} CommandCallback @@ -623,10 +624,9 @@ export class SuperToolbar extends EventEmitter { else item.label.value = this.config.texts?.formatText || 'Format text'; }, list: () => { - const markerToStyle = { '•': 'disc', '◦': 'circle', '▪': 'square' }; if (commandState?.active) { item.activate(); - item.selectedValue.value = markerToStyle[commandState.value] ?? null; + item.selectedValue.value = markerTextToBulletStyle(commandState.value); } else { item.deactivate(); item.selectedValue.value = null; diff --git a/packages/super-editor/src/editors/v1/core/commands/toggleList.js b/packages/super-editor/src/editors/v1/core/commands/toggleList.js index 0c689911d9..7aebd43a76 100644 --- a/packages/super-editor/src/editors/v1/core/commands/toggleList.js +++ b/packages/super-editor/src/editors/v1/core/commands/toggleList.js @@ -1,6 +1,6 @@ // @ts-check import { updateNumberingProperties } from './changeListLevel.js'; -import { ListHelpers } from '@helpers/list-numbering-helpers.js'; +import { ListHelpers, markerTextToBulletStyle } from '@helpers/list-numbering-helpers.js'; import { getResolvedParagraphProperties } from '@extensions/paragraph/resolvedPropertiesCache.js'; import { isVisuallyEmptyParagraph } from './removeNumberingProperties.js'; import { Selection, TextSelection } from 'prosemirror-state'; @@ -26,9 +26,6 @@ function getParagraphListKind(node, editor) { return numFmtIsBullet(fmt) ? 'bullet' : 'ordered'; } -/** @type {Record} */ -const MARKER_TEXT_TO_STYLE = { '•': 'disc', '◦': 'circle', '▪': 'square' }; - function paragraphMatchesToggleListType(node, editor, listType, bulletStyle) { const kind = getParagraphListKind(node, editor); if (!kind) return false; @@ -36,7 +33,7 @@ function paragraphMatchesToggleListType(node, editor, listType, bulletStyle) { if (kind !== 'bullet') return false; if (!bulletStyle) return true; const markerText = node.attrs.listRendering?.markerText; - return MARKER_TEXT_TO_STYLE[markerText] === bulletStyle; + return markerTextToBulletStyle(markerText) === bulletStyle; } if (listType === 'orderedList') return kind === 'ordered'; return false; diff --git a/packages/super-editor/src/editors/v1/core/helpers/list-numbering-helpers.js b/packages/super-editor/src/editors/v1/core/helpers/list-numbering-helpers.js index b571958183..3c584f2b70 100644 --- a/packages/super-editor/src/editors/v1/core/helpers/list-numbering-helpers.js +++ b/packages/super-editor/src/editors/v1/core/helpers/list-numbering-helpers.js @@ -29,6 +29,17 @@ import { mutateNumbering } from '@core/parts/adapters/numbering-mutation'; // Shims will be removed as callers migrate in Phases 1b–1d. // --------------------------------------------------------------------------- +/** + * Maps a bullet marker character (from `listRendering.markerText`) to its named bullet style. + * Returns null for unrecognized markers. + * @param {string|null|undefined} markerText + * @returns {'disc'|'circle'|'square'|null} + */ +export function markerTextToBulletStyle(markerText) { + const map = { '•': 'disc', '◦': 'circle', '▪': 'square' }; + return map[markerText] ?? null; +} + /** * Generate a new list definition for the given list type. * @param {Object} param0 From 778c18e51af1ee3cf382473bcd062273bfd7be86 Mon Sep 17 00:00:00 2001 From: Gabriel Chittolina Date: Fri, 17 Apr 2026 15:14:03 -0300 Subject: [PATCH 3/4] refactor: simplified code removing font override --- .../parts/adapters/numbering-transforms.ts | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-transforms.ts b/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-transforms.ts index 9dfa065e42..2d5280df17 100644 --- a/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-transforms.ts +++ b/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-transforms.ts @@ -33,10 +33,10 @@ interface GenerateOptions { bulletStyle?: 'disc' | 'circle' | 'square' | null; } -const BULLET_STYLE_CHARS: Record = { - disc: { char: '\uf0b7', font: 'Symbol' }, - circle: { char: 'o', font: 'Courier New' }, - square: { char: '\uf0a7', font: 'Wingdings' }, +const BULLET_STYLE_CHARS: Record = { + disc: '•', + circle: '◦', + square: '▪', }; interface GenerateResult { @@ -93,24 +93,19 @@ export function generateNewListDefinition(numbering: NumberingModel, options: Ge }), ); - if (bulletStyle && listType !== 'orderedList') { - const styleChars = BULLET_STYLE_CHARS[bulletStyle]; - if (styleChars) { + // Override the bullet style for the new list if a bullet style is provided + const shouldOverrideBulletStyle = bulletStyle && listType !== 'orderedList'; + if (shouldOverrideBulletStyle) { + const char = BULLET_STYLE_CHARS[bulletStyle]; + if (char) { const lvl0 = newAbstractDef.elements.find((el: any) => el.name === 'w:lvl' && el.attributes['w:ilvl'] === '0'); if (lvl0) { const lvlText = lvl0.elements.find((el: any) => el.name === 'w:lvlText'); - if (lvlText) lvlText.attributes['w:val'] = styleChars.char; - let rPr = lvl0.elements.find((el: any) => el.name === 'w:rPr'); - if (!rPr) { - rPr = { type: 'element', name: 'w:rPr', elements: [] }; - lvl0.elements.push(rPr); - } - rPr.elements = rPr.elements.filter((el: any) => el.name !== 'w:rFonts'); - rPr.elements.push({ - type: 'element', - name: 'w:rFonts', - attributes: { 'w:ascii': styleChars.font, 'w:hAnsi': styleChars.font, 'w:hint': 'default' }, - }); + if (lvlText) lvlText.attributes['w:val'] = char; + + // Remove any inherited font so the Unicode char renders in the document's default font + const rPr = lvl0.elements.find((el: any) => el.name === 'w:rPr'); + if (rPr) rPr.elements = rPr.elements.filter((el: any) => el.name !== 'w:rFonts'); } } } From ce505e4c06582fb38bf7171a16048b4b5be26d01 Mon Sep 17 00:00:00 2001 From: Gabriel Chittolina Date: Fri, 17 Apr 2026 15:17:56 -0300 Subject: [PATCH 4/4] chore: small code tweaks --- .../src/editors/v1/core/parts/adapters/numbering-transforms.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-transforms.ts b/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-transforms.ts index 2d5280df17..487a80a99e 100644 --- a/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-transforms.ts +++ b/packages/super-editor/src/editors/v1/core/parts/adapters/numbering-transforms.ts @@ -97,8 +97,10 @@ export function generateNewListDefinition(numbering: NumberingModel, options: Ge const shouldOverrideBulletStyle = bulletStyle && listType !== 'orderedList'; if (shouldOverrideBulletStyle) { const char = BULLET_STYLE_CHARS[bulletStyle]; + if (char) { const lvl0 = newAbstractDef.elements.find((el: any) => el.name === 'w:lvl' && el.attributes['w:ilvl'] === '0'); + if (lvl0) { const lvlText = lvl0.elements.find((el: any) => el.name === 'w:lvlText'); if (lvlText) lvlText.attributes['w:val'] = char;