diff --git a/README.md b/README.md index 15e58564..e90a5d40 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ var editor = EditorJS({ |--------------|----------|----------------------------------------------------------------| | defaultStyle | `string` | default list style: `ordered`, `unordered` or `checklist`, default is `unordered` | | maxLevel | `number` | maximum level of the list nesting, could be set to `1` to disable nesting, unlimited by default | +| counterTypes | `string[]` | specifies which counter types should be shown in the ordered list style, could be set to `['numeric','upper-roman']`, default is `undefined` which shows all counter types | ## Output data @@ -97,6 +98,35 @@ Object `ItemMeta` for Ordered list Object `ItemMeta` for Unordered list would be empty. +## Localisation +If you want to use your language for toolbox items, you can pass i18n dictionary to the editorjs instance below the tools `block`: +```javascript +i18n: { + messages: { + "toolNames": { + "Ordered List": "Nummerierte Liste", + "Unordered List": "Unnummeriert Liste", + "Checklist": "Checkliste", + }, + "tools": { + "List": { + 'Unordered': 'Unnummeriert', + 'Ordered': 'Nummerierte', + 'Checklist': 'Checkliste', + } + }, + }, +}, +``` + +### Other supported keys for `tools.List` +- `Start with` +- `Counter type` +- `Numeric` +- `Lower Roman` +- `Upper Roman` +- `Lower Alpha` +- `Upper Alpha` ## Example of the content for `Unordered List` ```json diff --git a/package.json b/package.json index 59465f85..bc04c630 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "@editorjs/list", - "version": "2.0.2", + "name": "@editorjs/list", + "version": "2.0.8", "keywords": [ "codex editor", "list", diff --git a/playground/index.html b/playground/index.html index c33e7015..799a9f09 100644 --- a/playground/index.html +++ b/playground/index.html @@ -104,6 +104,25 @@ } }, }, + /** + * Example of the lacalisation dictionary + */ + i18n: { + messages: { + "toolNames": { + "Ordered List": "Nummerierte Liste", + "Unordered List": "Unnummeriert Liste", + "Checklist": "Checkliste", + }, + "tools": { + "List": { + 'Unordered': 'Unnummeriert', + 'Ordered': 'Nummerierte', + 'Checklist': 'Checkliste', + } + }, + }, + }, /** * This Tool will be used as default diff --git a/src/ListTabulator/index.ts b/src/ListTabulator/index.ts index 277b018e..3721e71c 100644 --- a/src/ListTabulator/index.ts +++ b/src/ListTabulator/index.ts @@ -167,7 +167,9 @@ export default class ListTabulator { (event) => { switch (event.key) { case 'Enter': - this.enterPressed(event); + if (!event.shiftKey) { + this.enterPressed(event); + } break; case 'Backspace': this.backspace(event); @@ -533,6 +535,13 @@ export default class ListTabulator { return; } + /** + * If backspace is pressed with selection, it should be handled as usual + */ + if (window.getSelection()?.isCollapsed === false) { + return; + } + /** * Prevent Editor.js backspace handling */ diff --git a/src/index.ts b/src/index.ts index 4cb763d7..96435b35 100644 --- a/src/index.ts +++ b/src/index.ts @@ -171,6 +171,11 @@ export default class EditorjsList { */ private defaultListStyle?: ListConfig['defaultStyle']; + /** + * Default Counter type of the ordered list + */ + private defaultCounterTypes: OlCounterType[]; + /** * Tool's data */ @@ -210,6 +215,11 @@ export default class EditorjsList { */ this.defaultListStyle = this.config?.defaultStyle || 'unordered'; + /** + * Set the default counter types for the ordered list + */ + this.defaultCounterTypes = (this.config as ListConfig).counterTypes || Array.from(OlCounterTypesMap.values()) as OlCounterType[]; + const initialData = { style: this.defaultListStyle, meta: {}, @@ -342,9 +352,15 @@ export default class EditorjsList { * For each counter type in OlCounterType create toolbox item */ OlCounterTypesMap.forEach((_, counterType: string) => { + const counterTypeValue = OlCounterTypesMap.get(counterType)! as OlCounterType; + + if (!this.defaultCounterTypes.includes(counterTypeValue)) { + return; + } + orderedListCountersTunes.children.items!.push({ title: this.api.i18n.t(counterType), - icon: OlCounterIconsMap.get(OlCounterTypesMap.get(counterType)!), + icon: OlCounterIconsMap.get(counterTypeValue), isActive: (this.data.meta as OrderedListItemMeta).counterType === OlCounterTypesMap.get(counterType), closeOnActivate: true, onActivate: () => { @@ -352,8 +368,16 @@ export default class EditorjsList { }, }); }); + + /** + * Dont show Counter type tune if there is no valid counter types + */ + if (orderedListCountersTunes.children.items!.length > 1) { + orderedListTunes.push(orderedListCountersTunes); + } + // @ts-expect-error ts(2820) can not use PopoverItem enum from editor.js types - defaultTunes.push({ type: 'separator' }, ...orderedListTunes, orderedListCountersTunes); + defaultTunes.push({ type: 'separator' }, ...orderedListTunes); } return defaultTunes; diff --git a/src/types/ListParams.ts b/src/types/ListParams.ts index e377b15f..b57d50a3 100644 --- a/src/types/ListParams.ts +++ b/src/types/ListParams.ts @@ -1,4 +1,5 @@ import type { ItemMeta } from './ItemMeta'; +import type { OlCounterType } from './OlCounterType'; /** * list style to make list as ordered or unordered @@ -29,6 +30,11 @@ export interface OldListData { items: string[]; } +/** + * Type that represents data of the List tool + */ +export type OldNestedListData = Omit; + /** * Interface that represents old checklist data format */ @@ -87,4 +93,10 @@ export interface ListConfig { * If nesting is not needed, it could be set to 1 */ maxLevel?: number; + /** + * Specifies which counter types should be shown in the ordered list style selector. + * @example ['numeric', 'upper-roman'] // Shows selector with these two options + * @default undefined // All counter types are available when not specified + */ + counterTypes?: OlCounterType[]; } diff --git a/src/utils/normalizeData.ts b/src/utils/normalizeData.ts index 91221eff..e9d83c96 100644 --- a/src/utils/normalizeData.ts +++ b/src/utils/normalizeData.ts @@ -1,20 +1,29 @@ -import type { OldListData, ListData, ListItem, OldChecklistData } from '../types/ListParams'; +import type { OldListData, ListData, ListItem, OldChecklistData, OldNestedListData } from '../types/ListParams'; /** * Method that checks if data is result of the Old list tool save mtehod - * @param data - data of the OldList, Checklist or Editorjs List tool + * @param data - data of the OldList, Checklist, OldNestedList or Editorjs List tool * @returns true if data related to the List tool, false otherwise */ -function instanceOfOldListData(data: ListData | OldListData | OldChecklistData): data is OldListData { +function instanceOfOldListData(data: ListData | OldListData | OldChecklistData | OldNestedListData): data is OldListData { return (typeof data.items[0] === 'string'); } +/** + * Method that checks if data is result of the Old nested list tool save method + * @param data - data of the OldList, Checklist, OldNestedList or Editorjs List tool + * @returns true if data is related to the Nested List tool, false otherwise + */ +function instanceOfOldNestedListData(data: ListData | OldListData | OldChecklistData | OldNestedListData): data is OldNestedListData { + return !('meta' in data); +} + /** * Method that checks if data is result of the Old checklist tool save method - * @param data - data of the Checklist, OldList or Editorjs List tool + * @param data - data of the Checklist, OldList, OldNestedList or Editorjs List tool * @returns true if data is related to the Checklist tool, false otherwise */ -function instanceOfChecklistData(data: ListData | OldListData | OldChecklistData): data is OldChecklistData { +function instanceOfChecklistData(data: ListData | OldListData | OldChecklistData | OldNestedListData): data is OldChecklistData { return ( typeof data.items[0] !== 'string' && 'text' in data.items[0] @@ -62,7 +71,13 @@ export default function normalizeData(data: ListData | OldListData | OldChecklis meta: {}, items: normalizedDataItems, }; + } else if (instanceOfOldNestedListData(data)) { + return { + style: data.style, + meta: {}, + items: data.items, + }; } else { - return data; + return structuredClone(data); } };