roosterjs-content-model-core 0.21.0 → 0.21.2

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.
@@ -102,6 +102,9 @@ var EntityPlugin = /** @class */ (function () {
102
102
  if (operation == 'newEntity') {
103
103
  entity.entityFormat.id = _this.ensureUniqueId(entityType, id !== null && id !== void 0 ? id : '', wrapper);
104
104
  wrapper.className = (0, roosterjs_content_model_dom_1.generateEntityClassNames)(entity.entityFormat);
105
+ if (entity.entityFormat.isReadonly) {
106
+ wrapper.contentEditable = 'false';
107
+ }
105
108
  var eventResult = _this.triggerEvent(editor, wrapper, operation, rawEvent);
106
109
  _this.state.entityMap[entity.entityFormat.id] = {
107
110
  element: wrapper,
@@ -1 +1 @@
1
- {"version":3,"file":"EntityPlugin.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/corePlugin/EntityPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { findAllEntities } from './utils/findAllEntities';\nimport {\n createEntity,\n generateEntityClassNames,\n getAllEntityWrappers,\n getObjectKeys,\n isEntityElement,\n parseEntityClassName,\n} from 'roosterjs-content-model-dom';\nimport {\n ColorTransformDirection,\n EntityOperation as LegacyEntityOperation,\n PluginEventType,\n} from 'roosterjs-editor-types';\nimport type {\n ChangedEntity,\n ContentModelContentChangedEvent,\n ContentModelEntityFormat,\n EntityOperation,\n EntityPluginState,\n IStandaloneEditor,\n} from 'roosterjs-content-model-types';\nimport type {\n ContentChangedEvent,\n IEditor,\n PluginEvent,\n PluginMouseUpEvent,\n PluginWithState,\n} from 'roosterjs-editor-types';\n\nconst ENTITY_ID_REGEX = /_(\\d{1,8})$/;\n\n// This is only used for compatibility with old editor\n// TODO: Remove this map once we have standalone editor\nconst EntityOperationMap: Record<EntityOperation, LegacyEntityOperation> = {\n newEntity: LegacyEntityOperation.NewEntity,\n overwrite: LegacyEntityOperation.Overwrite,\n removeFromEnd: LegacyEntityOperation.RemoveFromEnd,\n removeFromStart: LegacyEntityOperation.RemoveFromStart,\n replaceTemporaryContent: LegacyEntityOperation.ReplaceTemporaryContent,\n updateEntityState: LegacyEntityOperation.UpdateEntityState,\n click: LegacyEntityOperation.Click,\n};\n\n/**\n * Entity Plugin helps handle all operations related to an entity and generate entity specified events\n */\nclass EntityPlugin implements PluginWithState<EntityPluginState> {\n private editor: (IEditor & IStandaloneEditor) | null = null;\n private state: EntityPluginState;\n\n /**\n * Construct a new instance of EntityPlugin\n */\n constructor() {\n this.state = {\n entityMap: {},\n };\n }\n\n /**\n * Get a friendly name of this plugin\n */\n getName() {\n return 'Entity';\n }\n\n /**\n * Initialize this plugin. This should only be called from Editor\n * @param editor Editor instance\n */\n initialize(editor: IEditor) {\n this.editor = editor as IStandaloneEditor & IEditor;\n }\n\n /**\n * Dispose this plugin\n */\n dispose() {\n this.editor = null;\n this.state.entityMap = {};\n }\n\n /**\n * Get plugin state object\n */\n getState() {\n return this.state;\n }\n\n /**\n * Handle events triggered from editor\n * @param event PluginEvent object\n */\n onPluginEvent(event: PluginEvent) {\n if (this.editor) {\n switch (event.eventType) {\n case PluginEventType.MouseUp:\n this.handleMouseUpEvent(this.editor, event);\n break;\n case PluginEventType.ContentChanged:\n this.handleContentChangedEvent(this.editor, event);\n break;\n\n case PluginEventType.EditorReady:\n this.handleContentChangedEvent(this.editor);\n break;\n case PluginEventType.ExtractContentWithDom:\n this.handleExtractContentWithDomEvent(this.editor, event.clonedRoot);\n break;\n }\n }\n }\n\n private handleMouseUpEvent(editor: IEditor & IStandaloneEditor, event: PluginMouseUpEvent) {\n const { rawEvent, isClicking } = event;\n let node: Node | null = rawEvent.target as Node;\n\n if (isClicking && this.editor) {\n while (node && this.editor.contains(node)) {\n if (isEntityElement(node)) {\n this.triggerEvent(editor, node as HTMLElement, 'click', rawEvent);\n break;\n } else {\n node = node.parentNode;\n }\n }\n }\n }\n\n private handleContentChangedEvent(\n editor: IStandaloneEditor & IEditor,\n event?: ContentChangedEvent\n ) {\n const modifiedEntities: ChangedEntity[] =\n (event as ContentModelContentChangedEvent)?.changedEntities ??\n this.getChangedEntities(editor);\n\n modifiedEntities.forEach(entry => {\n const { entity, operation, rawEvent } = entry;\n const {\n entityFormat: { id, entityType, isFakeEntity },\n wrapper,\n } = entity;\n\n if (entityType && !isFakeEntity) {\n if (operation == 'newEntity') {\n entity.entityFormat.id = this.ensureUniqueId(entityType, id ?? '', wrapper);\n wrapper.className = generateEntityClassNames(entity.entityFormat);\n\n const eventResult = this.triggerEvent(editor, wrapper, operation, rawEvent);\n\n this.state.entityMap[entity.entityFormat.id] = {\n element: wrapper,\n canPersist: eventResult?.shouldPersist,\n };\n\n if (editor.isDarkMode()) {\n editor.transformToDarkColor(wrapper, ColorTransformDirection.LightToDark);\n }\n } else if (id) {\n const mapEntry = this.state.entityMap[id];\n\n if (mapEntry) {\n mapEntry.isDeleted = true;\n }\n\n this.triggerEvent(editor, wrapper, operation, rawEvent);\n }\n }\n });\n }\n\n private getChangedEntities(editor: IStandaloneEditor): ChangedEntity[] {\n const result: ChangedEntity[] = [];\n\n findAllEntities(editor.createContentModel(), result);\n\n getObjectKeys(this.state.entityMap).forEach(id => {\n const entry = this.state.entityMap[id];\n\n if (!entry.isDeleted) {\n const index = result.findIndex(\n x =>\n x.operation == 'newEntity' &&\n x.entity.entityFormat.id == id &&\n x.entity.wrapper == entry.element\n );\n\n if (index >= 0) {\n // Found matched entity in editor, so there is no change to this entity,\n // we can safely remove it from the new entity array\n result.splice(index, 1);\n } else {\n // Entity is not in editor, which means it is deleted, use a temporary entity here to represent this entity\n const tempEntity = createEntity(entry.element);\n let isEntity = false;\n\n entry.element.classList.forEach(name => {\n isEntity = parseEntityClassName(name, tempEntity.entityFormat) || isEntity;\n });\n\n if (isEntity) {\n result.push({\n entity: tempEntity,\n operation: 'overwrite',\n });\n }\n }\n }\n });\n\n return result;\n }\n\n private handleExtractContentWithDomEvent(\n editor: IEditor & IStandaloneEditor,\n root: HTMLElement\n ) {\n getAllEntityWrappers(root).forEach(element => {\n element.removeAttribute('contentEditable');\n\n this.triggerEvent(editor, element, 'replaceTemporaryContent');\n });\n }\n\n private triggerEvent(\n editor: IEditor & IStandaloneEditor,\n wrapper: HTMLElement,\n operation: EntityOperation,\n rawEvent?: Event\n ) {\n const format: ContentModelEntityFormat = {};\n wrapper.classList.forEach(name => {\n parseEntityClassName(name, format);\n });\n\n return format.id && format.entityType && !format.isFakeEntity\n ? editor.triggerPluginEvent(PluginEventType.EntityOperation, {\n operation: EntityOperationMap[operation],\n rawEvent,\n entity: {\n id: format.id,\n type: format.entityType,\n isReadonly: !!format.isReadonly,\n wrapper,\n },\n })\n : null;\n }\n\n private ensureUniqueId(type: string, id: string, wrapper: HTMLElement): string {\n const match = ENTITY_ID_REGEX.exec(id);\n const baseId = (match ? id.substr(0, id.length - match[0].length) : id) || type;\n\n // Make sure entity id is unique\n let newId = '';\n\n for (let num = (match && parseInt(match[1])) || 0; ; num++) {\n newId = num > 0 ? `${baseId}_${num}` : baseId;\n\n const item = this.state.entityMap[newId];\n\n if (!item || item.element == wrapper) {\n break;\n }\n }\n\n return newId;\n }\n}\n\n/**\n * @internal\n * Create a new instance of EntityPlugin.\n */\nexport function createEntityPlugin(): PluginWithState<EntityPluginState> {\n return new EntityPlugin();\n}\n"]}
1
+ {"version":3,"file":"EntityPlugin.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/corePlugin/EntityPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { findAllEntities } from './utils/findAllEntities';\nimport {\n createEntity,\n generateEntityClassNames,\n getAllEntityWrappers,\n getObjectKeys,\n isEntityElement,\n parseEntityClassName,\n} from 'roosterjs-content-model-dom';\nimport {\n ColorTransformDirection,\n EntityOperation as LegacyEntityOperation,\n PluginEventType,\n} from 'roosterjs-editor-types';\nimport type {\n ChangedEntity,\n ContentModelContentChangedEvent,\n ContentModelEntityFormat,\n EntityOperation,\n EntityPluginState,\n IStandaloneEditor,\n} from 'roosterjs-content-model-types';\nimport type {\n ContentChangedEvent,\n IEditor,\n PluginEvent,\n PluginMouseUpEvent,\n PluginWithState,\n} from 'roosterjs-editor-types';\n\nconst ENTITY_ID_REGEX = /_(\\d{1,8})$/;\n\n// This is only used for compatibility with old editor\n// TODO: Remove this map once we have standalone editor\nconst EntityOperationMap: Record<EntityOperation, LegacyEntityOperation> = {\n newEntity: LegacyEntityOperation.NewEntity,\n overwrite: LegacyEntityOperation.Overwrite,\n removeFromEnd: LegacyEntityOperation.RemoveFromEnd,\n removeFromStart: LegacyEntityOperation.RemoveFromStart,\n replaceTemporaryContent: LegacyEntityOperation.ReplaceTemporaryContent,\n updateEntityState: LegacyEntityOperation.UpdateEntityState,\n click: LegacyEntityOperation.Click,\n};\n\n/**\n * Entity Plugin helps handle all operations related to an entity and generate entity specified events\n */\nclass EntityPlugin implements PluginWithState<EntityPluginState> {\n private editor: (IEditor & IStandaloneEditor) | null = null;\n private state: EntityPluginState;\n\n /**\n * Construct a new instance of EntityPlugin\n */\n constructor() {\n this.state = {\n entityMap: {},\n };\n }\n\n /**\n * Get a friendly name of this plugin\n */\n getName() {\n return 'Entity';\n }\n\n /**\n * Initialize this plugin. This should only be called from Editor\n * @param editor Editor instance\n */\n initialize(editor: IEditor) {\n this.editor = editor as IStandaloneEditor & IEditor;\n }\n\n /**\n * Dispose this plugin\n */\n dispose() {\n this.editor = null;\n this.state.entityMap = {};\n }\n\n /**\n * Get plugin state object\n */\n getState() {\n return this.state;\n }\n\n /**\n * Handle events triggered from editor\n * @param event PluginEvent object\n */\n onPluginEvent(event: PluginEvent) {\n if (this.editor) {\n switch (event.eventType) {\n case PluginEventType.MouseUp:\n this.handleMouseUpEvent(this.editor, event);\n break;\n case PluginEventType.ContentChanged:\n this.handleContentChangedEvent(this.editor, event);\n break;\n\n case PluginEventType.EditorReady:\n this.handleContentChangedEvent(this.editor);\n break;\n case PluginEventType.ExtractContentWithDom:\n this.handleExtractContentWithDomEvent(this.editor, event.clonedRoot);\n break;\n }\n }\n }\n\n private handleMouseUpEvent(editor: IEditor & IStandaloneEditor, event: PluginMouseUpEvent) {\n const { rawEvent, isClicking } = event;\n let node: Node | null = rawEvent.target as Node;\n\n if (isClicking && this.editor) {\n while (node && this.editor.contains(node)) {\n if (isEntityElement(node)) {\n this.triggerEvent(editor, node as HTMLElement, 'click', rawEvent);\n break;\n } else {\n node = node.parentNode;\n }\n }\n }\n }\n\n private handleContentChangedEvent(\n editor: IStandaloneEditor & IEditor,\n event?: ContentChangedEvent\n ) {\n const modifiedEntities: ChangedEntity[] =\n (event as ContentModelContentChangedEvent)?.changedEntities ??\n this.getChangedEntities(editor);\n\n modifiedEntities.forEach(entry => {\n const { entity, operation, rawEvent } = entry;\n const {\n entityFormat: { id, entityType, isFakeEntity },\n wrapper,\n } = entity;\n\n if (entityType && !isFakeEntity) {\n if (operation == 'newEntity') {\n entity.entityFormat.id = this.ensureUniqueId(entityType, id ?? '', wrapper);\n wrapper.className = generateEntityClassNames(entity.entityFormat);\n\n if (entity.entityFormat.isReadonly) {\n wrapper.contentEditable = 'false';\n }\n\n const eventResult = this.triggerEvent(editor, wrapper, operation, rawEvent);\n\n this.state.entityMap[entity.entityFormat.id] = {\n element: wrapper,\n canPersist: eventResult?.shouldPersist,\n };\n\n if (editor.isDarkMode()) {\n editor.transformToDarkColor(wrapper, ColorTransformDirection.LightToDark);\n }\n } else if (id) {\n const mapEntry = this.state.entityMap[id];\n\n if (mapEntry) {\n mapEntry.isDeleted = true;\n }\n\n this.triggerEvent(editor, wrapper, operation, rawEvent);\n }\n }\n });\n }\n\n private getChangedEntities(editor: IStandaloneEditor): ChangedEntity[] {\n const result: ChangedEntity[] = [];\n\n findAllEntities(editor.createContentModel(), result);\n\n getObjectKeys(this.state.entityMap).forEach(id => {\n const entry = this.state.entityMap[id];\n\n if (!entry.isDeleted) {\n const index = result.findIndex(\n x =>\n x.operation == 'newEntity' &&\n x.entity.entityFormat.id == id &&\n x.entity.wrapper == entry.element\n );\n\n if (index >= 0) {\n // Found matched entity in editor, so there is no change to this entity,\n // we can safely remove it from the new entity array\n result.splice(index, 1);\n } else {\n // Entity is not in editor, which means it is deleted, use a temporary entity here to represent this entity\n const tempEntity = createEntity(entry.element);\n let isEntity = false;\n\n entry.element.classList.forEach(name => {\n isEntity = parseEntityClassName(name, tempEntity.entityFormat) || isEntity;\n });\n\n if (isEntity) {\n result.push({\n entity: tempEntity,\n operation: 'overwrite',\n });\n }\n }\n }\n });\n\n return result;\n }\n\n private handleExtractContentWithDomEvent(\n editor: IEditor & IStandaloneEditor,\n root: HTMLElement\n ) {\n getAllEntityWrappers(root).forEach(element => {\n element.removeAttribute('contentEditable');\n\n this.triggerEvent(editor, element, 'replaceTemporaryContent');\n });\n }\n\n private triggerEvent(\n editor: IEditor & IStandaloneEditor,\n wrapper: HTMLElement,\n operation: EntityOperation,\n rawEvent?: Event\n ) {\n const format: ContentModelEntityFormat = {};\n wrapper.classList.forEach(name => {\n parseEntityClassName(name, format);\n });\n\n return format.id && format.entityType && !format.isFakeEntity\n ? editor.triggerPluginEvent(PluginEventType.EntityOperation, {\n operation: EntityOperationMap[operation],\n rawEvent,\n entity: {\n id: format.id,\n type: format.entityType,\n isReadonly: !!format.isReadonly,\n wrapper,\n },\n })\n : null;\n }\n\n private ensureUniqueId(type: string, id: string, wrapper: HTMLElement): string {\n const match = ENTITY_ID_REGEX.exec(id);\n const baseId = (match ? id.substr(0, id.length - match[0].length) : id) || type;\n\n // Make sure entity id is unique\n let newId = '';\n\n for (let num = (match && parseInt(match[1])) || 0; ; num++) {\n newId = num > 0 ? `${baseId}_${num}` : baseId;\n\n const item = this.state.entityMap[newId];\n\n if (!item || item.element == wrapper) {\n break;\n }\n }\n\n return newId;\n }\n}\n\n/**\n * @internal\n * Create a new instance of EntityPlugin.\n */\nexport function createEntityPlugin(): PluginWithState<EntityPluginState> {\n return new EntityPlugin();\n}\n"]}
@@ -4,9 +4,9 @@ import type { ColorKeyAndValue, DarkColorHandler, ModeIndependentColor } from 'r
4
4
  */
5
5
  export declare class DarkColorHandlerImpl implements DarkColorHandler {
6
6
  private contentDiv;
7
+ private getDarkColor;
7
8
  private knownColors;
8
- readonly baseLightness: number;
9
- constructor(contentDiv: HTMLElement, baseDarkColor?: string);
9
+ constructor(contentDiv: HTMLElement, getDarkColor: (color: string) => string);
10
10
  /**
11
11
  * Get a copy of known colors
12
12
  * @returns
@@ -2,9 +2,7 @@
2
2
  var _a, _b;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.DarkColorHandlerImpl = void 0;
5
- var Color = require("color");
6
5
  var roosterjs_editor_dom_1 = require("roosterjs-editor-dom");
7
- var DefaultLightness = 21.25; // Lightness for #333333
8
6
  var VARIABLE_REGEX = /^\s*var\(\s*(\-\-[a-zA-Z0-9\-_]+)\s*(?:,\s*(.*))?\)\s*$/;
9
7
  var VARIABLE_PREFIX = 'var(';
10
8
  var COLOR_VAR_PREFIX = 'darkColor';
@@ -27,10 +25,10 @@ var ColorAttributeName = [
27
25
  * @internal
28
26
  */
29
27
  var DarkColorHandlerImpl = /** @class */ (function () {
30
- function DarkColorHandlerImpl(contentDiv, baseDarkColor) {
28
+ function DarkColorHandlerImpl(contentDiv, getDarkColor) {
31
29
  this.contentDiv = contentDiv;
30
+ this.getDarkColor = getDarkColor;
32
31
  this.knownColors = {};
33
- this.baseLightness = getLightness(baseDarkColor);
34
32
  }
35
33
  /**
36
34
  * Get a copy of known colors
@@ -58,7 +56,7 @@ var DarkColorHandlerImpl = /** @class */ (function () {
58
56
  colorKey =
59
57
  colorKey || "--" + COLOR_VAR_PREFIX + "_" + lightModeColor.replace(/[^\d\w]/g, '_');
60
58
  if (!this.knownColors[colorKey]) {
61
- darkModeColor = darkModeColor || getDarkColor(lightModeColor, this.baseLightness);
59
+ darkModeColor = darkModeColor || this.getDarkColor(lightModeColor);
62
60
  this.knownColors[colorKey] = { lightModeColor: lightModeColor, darkModeColor: darkModeColor };
63
61
  this.contentDiv.style.setProperty(colorKey, darkModeColor);
64
62
  }
@@ -157,28 +155,4 @@ var DarkColorHandlerImpl = /** @class */ (function () {
157
155
  return DarkColorHandlerImpl;
158
156
  }());
159
157
  exports.DarkColorHandlerImpl = DarkColorHandlerImpl;
160
- function getDarkColor(color, baseLightness) {
161
- try {
162
- var computedColor = Color(color || undefined);
163
- var colorLab = computedColor.lab().array();
164
- var newLValue = (100 - colorLab[0]) * ((100 - baseLightness) / 100) + baseLightness;
165
- color = Color.lab(newLValue, colorLab[1], colorLab[2])
166
- .rgb()
167
- .alpha(computedColor.alpha())
168
- .toString();
169
- }
170
- catch (_a) { }
171
- return color;
172
- }
173
- function getLightness(color) {
174
- var result = DefaultLightness;
175
- if (color) {
176
- try {
177
- var computedColor = Color(color || undefined);
178
- result = computedColor.lab().array()[0];
179
- }
180
- catch (_a) { }
181
- }
182
- return result;
183
- }
184
158
  //# sourceMappingURL=DarkColorHandlerImpl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DarkColorHandlerImpl.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/editor/DarkColorHandlerImpl.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Color from 'color';\nimport { getObjectKeys, parseColor, setColor } from 'roosterjs-editor-dom';\nimport type {\n ColorKeyAndValue,\n DarkColorHandler,\n ModeIndependentColor,\n} from 'roosterjs-editor-types';\n\nconst DefaultLightness = 21.25; // Lightness for #333333\nconst VARIABLE_REGEX = /^\\s*var\\(\\s*(\\-\\-[a-zA-Z0-9\\-_]+)\\s*(?:,\\s*(.*))?\\)\\s*$/;\nconst VARIABLE_PREFIX = 'var(';\nconst COLOR_VAR_PREFIX = 'darkColor';\nconst enum ColorAttributeEnum {\n CssColor = 0,\n HtmlColor = 1,\n}\nconst ColorAttributeName: { [key in ColorAttributeEnum]: string }[] = [\n {\n [ColorAttributeEnum.CssColor]: 'color',\n [ColorAttributeEnum.HtmlColor]: 'color',\n },\n {\n [ColorAttributeEnum.CssColor]: 'background-color',\n [ColorAttributeEnum.HtmlColor]: 'bgcolor',\n },\n];\n\n/**\n * @internal\n */\nexport class DarkColorHandlerImpl implements DarkColorHandler {\n private knownColors: Record<string, Readonly<ModeIndependentColor>> = {};\n readonly baseLightness: number;\n\n constructor(private contentDiv: HTMLElement, baseDarkColor?: string) {\n this.baseLightness = getLightness(baseDarkColor);\n }\n\n /**\n * Get a copy of known colors\n * @returns\n */\n getKnownColorsCopy() {\n return Object.values(this.knownColors);\n }\n\n /**\n * Given a light mode color value and an optional dark mode color value, register this color\n * so that editor can handle it, then return the CSS color value for current color mode.\n * @param lightModeColor Light mode color value\n * @param isDarkMode Whether current color mode is dark mode\n * @param darkModeColor Optional dark mode color value. If not passed, we will calculate one.\n */\n registerColor(lightModeColor: string, isDarkMode: boolean, darkModeColor?: string): string {\n const parsedColor = this.parseColorValue(lightModeColor);\n let colorKey: string | undefined;\n\n if (parsedColor) {\n lightModeColor = parsedColor.lightModeColor;\n darkModeColor = parsedColor.darkModeColor || darkModeColor;\n colorKey = parsedColor.key;\n }\n\n if (isDarkMode && lightModeColor) {\n colorKey =\n colorKey || `--${COLOR_VAR_PREFIX}_${lightModeColor.replace(/[^\\d\\w]/g, '_')}`;\n\n if (!this.knownColors[colorKey]) {\n darkModeColor = darkModeColor || getDarkColor(lightModeColor, this.baseLightness);\n\n this.knownColors[colorKey] = { lightModeColor, darkModeColor };\n this.contentDiv.style.setProperty(colorKey, darkModeColor);\n }\n\n return `var(${colorKey}, ${lightModeColor})`;\n } else {\n return lightModeColor;\n }\n }\n\n /**\n * Reset known color record, clean up registered color variables.\n */\n reset(): void {\n getObjectKeys(this.knownColors).forEach(key => this.contentDiv.style.removeProperty(key));\n this.knownColors = {};\n }\n\n /**\n * Parse an existing color value, if it is in variable-based color format, extract color key,\n * light color and query related dark color if any\n * @param color The color string to parse\n * @param isInDarkMode Whether current content is in dark mode. When set to true, if the color value is not in dark var format,\n * we will treat is as a dark mode color and try to find a matched dark mode color.\n */\n parseColorValue(color: string | undefined | null, isInDarkMode?: boolean): ColorKeyAndValue {\n let key: string | undefined;\n let lightModeColor = '';\n let darkModeColor: string | undefined;\n\n if (color) {\n const match = color.startsWith(VARIABLE_PREFIX) ? VARIABLE_REGEX.exec(color) : null;\n\n if (match) {\n if (match[2]) {\n key = match[1];\n lightModeColor = match[2];\n darkModeColor = this.knownColors[key]?.darkModeColor;\n } else {\n lightModeColor = '';\n }\n } else if (isInDarkMode) {\n // If editor is in dark mode but the color is not in dark color format, it is possible the color was inserted from external code\n // without any light color info. So we first try to see if there is a known dark color can match this color, and use its related\n // light color as light mode color. Otherwise we need to drop this color to avoid show \"white on white\" content.\n lightModeColor = this.findLightColorFromDarkColor(color) || '';\n\n if (lightModeColor) {\n darkModeColor = color;\n }\n } else {\n lightModeColor = color;\n }\n }\n\n return { key, lightModeColor, darkModeColor };\n }\n\n /**\n * Find related light mode color from dark mode color.\n * @param darkColor The existing dark color\n */\n findLightColorFromDarkColor(darkColor: string): string | null {\n const rgbSearch = parseColor(darkColor);\n\n if (rgbSearch) {\n const key = getObjectKeys(this.knownColors).find(key => {\n const rgbCurrent = parseColor(this.knownColors[key].darkModeColor);\n\n return (\n rgbCurrent &&\n rgbCurrent[0] == rgbSearch[0] &&\n rgbCurrent[1] == rgbSearch[1] &&\n rgbCurrent[2] == rgbSearch[2]\n );\n });\n\n if (key) {\n return this.knownColors[key].lightModeColor;\n }\n }\n\n return null;\n }\n\n /**\n * Transform element color, from dark to light or from light to dark\n * @param element The element to transform color\n * @param fromDarkMode Whether this is transforming color from dark mode\n * @param toDarkMode Whether this is transforming color to dark mode\n */\n transformElementColor(element: HTMLElement, fromDarkMode: boolean, toDarkMode: boolean): void {\n ColorAttributeName.forEach((names, i) => {\n const color = this.parseColorValue(\n element.style.getPropertyValue(names[ColorAttributeEnum.CssColor]) ||\n element.getAttribute(names[ColorAttributeEnum.HtmlColor]),\n !!fromDarkMode\n ).lightModeColor;\n\n element.style.setProperty(names[ColorAttributeEnum.CssColor], null);\n element.removeAttribute(names[ColorAttributeEnum.HtmlColor]);\n\n if (color && color != 'inherit') {\n setColor(element, color, i != 0, toDarkMode, false /*shouldAdaptFontColor*/, this);\n }\n });\n }\n}\n\nfunction getDarkColor(color: string, baseLightness: number): string {\n try {\n const computedColor = Color(color || undefined);\n const colorLab = computedColor.lab().array();\n const newLValue = (100 - colorLab[0]) * ((100 - baseLightness) / 100) + baseLightness;\n color = Color.lab(newLValue, colorLab[1], colorLab[2])\n .rgb()\n .alpha(computedColor.alpha())\n .toString();\n } catch {}\n\n return color;\n}\n\nfunction getLightness(color?: string): number {\n let result = DefaultLightness;\n\n if (color) {\n try {\n const computedColor = Color(color || undefined);\n result = computedColor.lab().array()[0];\n } catch {}\n }\n\n return result;\n}\n"]}
1
+ {"version":3,"file":"DarkColorHandlerImpl.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/editor/DarkColorHandlerImpl.ts"],"names":[],"mappings":";;;;AAAA,6DAA2E;AAO3E,IAAM,cAAc,GAAG,yDAAyD,CAAC;AACjF,IAAM,eAAe,GAAG,MAAM,CAAC;AAC/B,IAAM,gBAAgB,GAAG,WAAW,CAAC;AACrC,IAAW,kBAGV;AAHD,WAAW,kBAAkB;IACzB,mEAAY,CAAA;IACZ,qEAAa,CAAA;AACjB,CAAC,EAHU,kBAAkB,KAAlB,kBAAkB,QAG5B;AACD,IAAM,kBAAkB,GAA8C;;QAE9D,uBAA+B,OAAO;QACtC,wBAAgC,OAAO;;;QAGvC,uBAA+B,kBAAkB;QACjD,wBAAgC,SAAS;;CAEhD,CAAC;AAEF;;GAEG;AACH;IAGI,8BAAoB,UAAuB,EAAU,YAAuC;QAAxE,eAAU,GAAV,UAAU,CAAa;QAAU,iBAAY,GAAZ,YAAY,CAA2B;QAFpF,gBAAW,GAAmD,EAAE,CAAC;IAEsB,CAAC;IAEhG;;;OAGG;IACH,iDAAkB,GAAlB;QACI,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;OAMG;IACH,4CAAa,GAAb,UAAc,cAAsB,EAAE,UAAmB,EAAE,aAAsB;QAC7E,IAAM,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;QACzD,IAAI,QAA4B,CAAC;QAEjC,IAAI,WAAW,EAAE;YACb,cAAc,GAAG,WAAW,CAAC,cAAc,CAAC;YAC5C,aAAa,GAAG,WAAW,CAAC,aAAa,IAAI,aAAa,CAAC;YAC3D,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC;SAC9B;QAED,IAAI,UAAU,IAAI,cAAc,EAAE;YAC9B,QAAQ;gBACJ,QAAQ,IAAI,OAAK,gBAAgB,SAAI,cAAc,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAG,CAAC;YAEnF,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE;gBAC7B,aAAa,GAAG,aAAa,IAAI,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;gBAEnE,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,EAAE,cAAc,gBAAA,EAAE,aAAa,eAAA,EAAE,CAAC;gBAC/D,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;aAC9D;YAED,OAAO,SAAO,QAAQ,UAAK,cAAc,MAAG,CAAC;SAChD;aAAM;YACH,OAAO,cAAc,CAAC;SACzB;IACL,CAAC;IAED;;OAEG;IACH,oCAAK,GAAL;QAAA,iBAGC;QAFG,IAAA,oCAAa,EAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,UAAA,GAAG,IAAI,OAAA,KAAI,CAAC,UAAU,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,EAAzC,CAAyC,CAAC,CAAC;QAC1F,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;IAC1B,CAAC;IAED;;;;;;OAMG;IACH,8CAAe,GAAf,UAAgB,KAAgC,EAAE,YAAsB;;QACpE,IAAI,GAAuB,CAAC;QAC5B,IAAI,cAAc,GAAG,EAAE,CAAC;QACxB,IAAI,aAAiC,CAAC;QAEtC,IAAI,KAAK,EAAE;YACP,IAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAEpF,IAAI,KAAK,EAAE;gBACP,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE;oBACV,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;oBACf,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;oBAC1B,aAAa,GAAG,MAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,0CAAE,aAAa,CAAC;iBACxD;qBAAM;oBACH,cAAc,GAAG,EAAE,CAAC;iBACvB;aACJ;iBAAM,IAAI,YAAY,EAAE;gBACrB,gIAAgI;gBAChI,gIAAgI;gBAChI,gHAAgH;gBAChH,cAAc,GAAG,IAAI,CAAC,2BAA2B,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;gBAE/D,IAAI,cAAc,EAAE;oBAChB,aAAa,GAAG,KAAK,CAAC;iBACzB;aACJ;iBAAM;gBACH,cAAc,GAAG,KAAK,CAAC;aAC1B;SACJ;QAED,OAAO,EAAE,GAAG,KAAA,EAAE,cAAc,gBAAA,EAAE,aAAa,eAAA,EAAE,CAAC;IAClD,CAAC;IAED;;;OAGG;IACH,0DAA2B,GAA3B,UAA4B,SAAiB;QAA7C,iBAqBC;QApBG,IAAM,SAAS,GAAG,IAAA,iCAAU,EAAC,SAAS,CAAC,CAAC;QAExC,IAAI,SAAS,EAAE;YACX,IAAM,GAAG,GAAG,IAAA,oCAAa,EAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,UAAA,GAAG;gBAChD,IAAM,UAAU,GAAG,IAAA,iCAAU,EAAC,KAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC;gBAEnE,OAAO,CACH,UAAU;oBACV,UAAU,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC;oBAC7B,UAAU,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC;oBAC7B,UAAU,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAChC,CAAC;YACN,CAAC,CAAC,CAAC;YAEH,IAAI,GAAG,EAAE;gBACL,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC;aAC/C;SACJ;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACH,oDAAqB,GAArB,UAAsB,OAAoB,EAAE,YAAqB,EAAE,UAAmB;QAAtF,iBAeC;QAdG,kBAAkB,CAAC,OAAO,CAAC,UAAC,KAAK,EAAE,CAAC;YAChC,IAAM,KAAK,GAAG,KAAI,CAAC,eAAe,CAC9B,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,KAAK,kBAA6B,CAAC;gBAC9D,OAAO,CAAC,YAAY,CAAC,KAAK,mBAA8B,CAAC,EAC7D,CAAC,CAAC,YAAY,CACjB,CAAC,cAAc,CAAC;YAEjB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,kBAA6B,EAAE,IAAI,CAAC,CAAC;YACpE,OAAO,CAAC,eAAe,CAAC,KAAK,mBAA8B,CAAC,CAAC;YAE7D,IAAI,KAAK,IAAI,KAAK,IAAI,SAAS,EAAE;gBAC7B,IAAA,+BAAQ,EAAC,OAAO,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,wBAAwB,EAAE,KAAI,CAAC,CAAC;aACtF;QACL,CAAC,CAAC,CAAC;IACP,CAAC;IACL,2BAAC;AAAD,CAAC,AAhJD,IAgJC;AAhJY,oDAAoB","sourcesContent":["import { getObjectKeys, parseColor, setColor } from 'roosterjs-editor-dom';\nimport type {\n ColorKeyAndValue,\n DarkColorHandler,\n ModeIndependentColor,\n} from 'roosterjs-editor-types';\n\nconst VARIABLE_REGEX = /^\\s*var\\(\\s*(\\-\\-[a-zA-Z0-9\\-_]+)\\s*(?:,\\s*(.*))?\\)\\s*$/;\nconst VARIABLE_PREFIX = 'var(';\nconst COLOR_VAR_PREFIX = 'darkColor';\nconst enum ColorAttributeEnum {\n CssColor = 0,\n HtmlColor = 1,\n}\nconst ColorAttributeName: { [key in ColorAttributeEnum]: string }[] = [\n {\n [ColorAttributeEnum.CssColor]: 'color',\n [ColorAttributeEnum.HtmlColor]: 'color',\n },\n {\n [ColorAttributeEnum.CssColor]: 'background-color',\n [ColorAttributeEnum.HtmlColor]: 'bgcolor',\n },\n];\n\n/**\n * @internal\n */\nexport class DarkColorHandlerImpl implements DarkColorHandler {\n private knownColors: Record<string, Readonly<ModeIndependentColor>> = {};\n\n constructor(private contentDiv: HTMLElement, private getDarkColor: (color: string) => string) {}\n\n /**\n * Get a copy of known colors\n * @returns\n */\n getKnownColorsCopy() {\n return Object.values(this.knownColors);\n }\n\n /**\n * Given a light mode color value and an optional dark mode color value, register this color\n * so that editor can handle it, then return the CSS color value for current color mode.\n * @param lightModeColor Light mode color value\n * @param isDarkMode Whether current color mode is dark mode\n * @param darkModeColor Optional dark mode color value. If not passed, we will calculate one.\n */\n registerColor(lightModeColor: string, isDarkMode: boolean, darkModeColor?: string): string {\n const parsedColor = this.parseColorValue(lightModeColor);\n let colorKey: string | undefined;\n\n if (parsedColor) {\n lightModeColor = parsedColor.lightModeColor;\n darkModeColor = parsedColor.darkModeColor || darkModeColor;\n colorKey = parsedColor.key;\n }\n\n if (isDarkMode && lightModeColor) {\n colorKey =\n colorKey || `--${COLOR_VAR_PREFIX}_${lightModeColor.replace(/[^\\d\\w]/g, '_')}`;\n\n if (!this.knownColors[colorKey]) {\n darkModeColor = darkModeColor || this.getDarkColor(lightModeColor);\n\n this.knownColors[colorKey] = { lightModeColor, darkModeColor };\n this.contentDiv.style.setProperty(colorKey, darkModeColor);\n }\n\n return `var(${colorKey}, ${lightModeColor})`;\n } else {\n return lightModeColor;\n }\n }\n\n /**\n * Reset known color record, clean up registered color variables.\n */\n reset(): void {\n getObjectKeys(this.knownColors).forEach(key => this.contentDiv.style.removeProperty(key));\n this.knownColors = {};\n }\n\n /**\n * Parse an existing color value, if it is in variable-based color format, extract color key,\n * light color and query related dark color if any\n * @param color The color string to parse\n * @param isInDarkMode Whether current content is in dark mode. When set to true, if the color value is not in dark var format,\n * we will treat is as a dark mode color and try to find a matched dark mode color.\n */\n parseColorValue(color: string | undefined | null, isInDarkMode?: boolean): ColorKeyAndValue {\n let key: string | undefined;\n let lightModeColor = '';\n let darkModeColor: string | undefined;\n\n if (color) {\n const match = color.startsWith(VARIABLE_PREFIX) ? VARIABLE_REGEX.exec(color) : null;\n\n if (match) {\n if (match[2]) {\n key = match[1];\n lightModeColor = match[2];\n darkModeColor = this.knownColors[key]?.darkModeColor;\n } else {\n lightModeColor = '';\n }\n } else if (isInDarkMode) {\n // If editor is in dark mode but the color is not in dark color format, it is possible the color was inserted from external code\n // without any light color info. So we first try to see if there is a known dark color can match this color, and use its related\n // light color as light mode color. Otherwise we need to drop this color to avoid show \"white on white\" content.\n lightModeColor = this.findLightColorFromDarkColor(color) || '';\n\n if (lightModeColor) {\n darkModeColor = color;\n }\n } else {\n lightModeColor = color;\n }\n }\n\n return { key, lightModeColor, darkModeColor };\n }\n\n /**\n * Find related light mode color from dark mode color.\n * @param darkColor The existing dark color\n */\n findLightColorFromDarkColor(darkColor: string): string | null {\n const rgbSearch = parseColor(darkColor);\n\n if (rgbSearch) {\n const key = getObjectKeys(this.knownColors).find(key => {\n const rgbCurrent = parseColor(this.knownColors[key].darkModeColor);\n\n return (\n rgbCurrent &&\n rgbCurrent[0] == rgbSearch[0] &&\n rgbCurrent[1] == rgbSearch[1] &&\n rgbCurrent[2] == rgbSearch[2]\n );\n });\n\n if (key) {\n return this.knownColors[key].lightModeColor;\n }\n }\n\n return null;\n }\n\n /**\n * Transform element color, from dark to light or from light to dark\n * @param element The element to transform color\n * @param fromDarkMode Whether this is transforming color from dark mode\n * @param toDarkMode Whether this is transforming color to dark mode\n */\n transformElementColor(element: HTMLElement, fromDarkMode: boolean, toDarkMode: boolean): void {\n ColorAttributeName.forEach((names, i) => {\n const color = this.parseColorValue(\n element.style.getPropertyValue(names[ColorAttributeEnum.CssColor]) ||\n element.getAttribute(names[ColorAttributeEnum.HtmlColor]),\n !!fromDarkMode\n ).lightModeColor;\n\n element.style.setProperty(names[ColorAttributeEnum.CssColor], null);\n element.removeAttribute(names[ColorAttributeEnum.HtmlColor]);\n\n if (color && color != 'inherit') {\n setColor(element, color, i != 0, toDarkMode, false /*shouldAdaptFontColor*/, this);\n }\n });\n }\n}\n"]}
@@ -12,6 +12,7 @@ var standaloneCoreApiMap_1 = require("./standaloneCoreApiMap");
12
12
  * @param options Editor options
13
13
  */
14
14
  function createStandaloneEditorCore(contentDiv, options, unportedCoreApiMap, unportedCorePluginState, tempPlugins) {
15
+ var _a;
15
16
  var corePlugins = (0, createStandaloneEditorCorePlugins_1.createStandaloneEditorCorePlugins)(options, contentDiv);
16
17
  return (0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)({ contentDiv: contentDiv, api: (0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)({}, standaloneCoreApiMap_1.standaloneCoreApiMap), unportedCoreApiMap), options.coreApiOverride), originalApi: (0, tslib_1.__assign)((0, tslib_1.__assign)({}, standaloneCoreApiMap_1.standaloneCoreApiMap), unportedCoreApiMap), plugins: (0, tslib_1.__spreadArray)((0, tslib_1.__spreadArray)([
17
18
  corePlugins.cache,
@@ -22,7 +23,7 @@ function createStandaloneEditorCore(contentDiv, options, unportedCoreApiMap, unp
22
23
  corePlugins.entity
23
24
  ], (0, tslib_1.__read)(tempPlugins), false), [
24
25
  corePlugins.lifecycle,
25
- ], false), environment: createEditorEnvironment(), darkColorHandler: new DarkColorHandlerImpl_1.DarkColorHandlerImpl(contentDiv, options.baseDarkColor), trustedHTMLHandler: options.trustedHTMLHandler || defaultTrustHtmlHandler }, (0, createStandaloneEditorDefaultSettings_1.createStandaloneEditorDefaultSettings)(options)), getPluginState(corePlugins)), unportedCorePluginState);
26
+ ], false), environment: createEditorEnvironment(), darkColorHandler: new DarkColorHandlerImpl_1.DarkColorHandlerImpl(contentDiv, (_a = options.getDarkColor) !== null && _a !== void 0 ? _a : getDarkColorFallback), trustedHTMLHandler: options.trustedHTMLHandler || defaultTrustHtmlHandler }, (0, createStandaloneEditorDefaultSettings_1.createStandaloneEditorDefaultSettings)(options)), getPluginState(corePlugins)), unportedCorePluginState);
26
27
  }
27
28
  exports.createStandaloneEditorCore = createStandaloneEditorCore;
28
29
  function createEditorEnvironment() {
@@ -54,4 +55,8 @@ function getPluginState(corePlugins) {
54
55
  selection: corePlugins.selection.getState(),
55
56
  };
56
57
  }
58
+ // A fallback function, always return original color
59
+ function getDarkColorFallback(color) {
60
+ return color;
61
+ }
57
62
  //# sourceMappingURL=createStandaloneEditorCore.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"createStandaloneEditorCore.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/editor/createStandaloneEditorCore.ts"],"names":[],"mappings":";;;;AAAA,qGAAoG;AACpG,iGAAgG;AAChG,+DAA8D;AAC9D,+DAA8D;AAY9D;;;;GAIG;AACH,SAAgB,0BAA0B,CACtC,UAA0B,EAC1B,OAAgC,EAChC,kBAAsC,EACtC,uBAAgD,EAChD,WAA2B;IAE3B,IAAM,WAAW,GAAG,IAAA,qEAAiC,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAE3E,2EACI,UAAU,YAAA,EACV,GAAG,wEAAO,2CAAoB,GAAK,kBAAkB,GAAK,OAAO,CAAC,eAAe,GACjF,WAAW,kDAAO,2CAAoB,GAAK,kBAAkB,GAC7D,OAAO;YACH,WAAW,CAAC,KAAK;YACjB,WAAW,CAAC,MAAM;YAClB,WAAW,CAAC,SAAS;YACrB,WAAW,CAAC,QAAQ;YACpB,WAAW,CAAC,SAAS;YACrB,WAAW,CAAC,MAAM;+BACf,WAAW;YACd,WAAW,CAAC,SAAS;mBAEzB,WAAW,EAAE,uBAAuB,EAAE,EACtC,gBAAgB,EAAE,IAAI,2CAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,EAC7E,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,uBAAuB,IACtE,IAAA,6EAAqC,EAAC,OAAO,CAAC,GAC9C,cAAc,CAAC,WAAW,CAAC,GAC3B,uBAAuB,EAC5B;AACN,CAAC;AA9BD,gEA8BC;AAED,SAAS,uBAAuB;IAC5B,oHAAoH;IACpH,IAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;IAE7C,OAAO;QACH,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvD,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;QACrC,QAAQ,EACJ,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;YAChC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;YAC/B,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC;KACvC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,SAAgB,uBAAuB,CAAC,IAAY;IAChD,OAAO,IAAI,CAAC;AAChB,CAAC;AAFD,0DAEC;AAED,SAAS,cAAc,CAAC,WAAwC;IAC5D,OAAO;QACH,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC,QAAQ,EAAE;QACzC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;QAC3C,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE;QACnC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE;QACrC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;QAC3C,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE;QACrC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;KAC9C,CAAC;AACN,CAAC","sourcesContent":["import { createStandaloneEditorCorePlugins } from '../corePlugin/createStandaloneEditorCorePlugins';\nimport { createStandaloneEditorDefaultSettings } from './createStandaloneEditorDefaultSettings';\nimport { DarkColorHandlerImpl } from './DarkColorHandlerImpl';\nimport { standaloneCoreApiMap } from './standaloneCoreApiMap';\nimport type { EditorPlugin } from 'roosterjs-editor-types';\nimport type {\n EditorEnvironment,\n StandaloneEditorCore,\n StandaloneEditorCorePluginState,\n StandaloneEditorCorePlugins,\n StandaloneEditorOptions,\n UnportedCoreApiMap,\n UnportedCorePluginState,\n} from 'roosterjs-content-model-types';\n\n/**\n * A temporary function to create Standalone Editor core\n * @param contentDiv Editor content DIV\n * @param options Editor options\n */\nexport function createStandaloneEditorCore(\n contentDiv: HTMLDivElement,\n options: StandaloneEditorOptions,\n unportedCoreApiMap: UnportedCoreApiMap,\n unportedCorePluginState: UnportedCorePluginState,\n tempPlugins: EditorPlugin[]\n): StandaloneEditorCore {\n const corePlugins = createStandaloneEditorCorePlugins(options, contentDiv);\n\n return {\n contentDiv,\n api: { ...standaloneCoreApiMap, ...unportedCoreApiMap, ...options.coreApiOverride },\n originalApi: { ...standaloneCoreApiMap, ...unportedCoreApiMap },\n plugins: [\n corePlugins.cache,\n corePlugins.format,\n corePlugins.copyPaste,\n corePlugins.domEvent,\n corePlugins.selection,\n corePlugins.entity,\n ...tempPlugins,\n corePlugins.lifecycle,\n ],\n environment: createEditorEnvironment(),\n darkColorHandler: new DarkColorHandlerImpl(contentDiv, options.baseDarkColor),\n trustedHTMLHandler: options.trustedHTMLHandler || defaultTrustHtmlHandler,\n ...createStandaloneEditorDefaultSettings(options),\n ...getPluginState(corePlugins),\n ...unportedCorePluginState,\n };\n}\n\nfunction createEditorEnvironment(): EditorEnvironment {\n // It is ok to use global window here since the environment should always be the same for all windows in one session\n const userAgent = window.navigator.userAgent;\n\n return {\n isMac: window.navigator.appVersion.indexOf('Mac') != -1,\n isAndroid: /android/i.test(userAgent),\n isSafari:\n userAgent.indexOf('Safari') >= 0 &&\n userAgent.indexOf('Chrome') < 0 &&\n userAgent.indexOf('Android') < 0,\n };\n}\n\n/**\n * @internal export for test only\n */\nexport function defaultTrustHtmlHandler(html: string) {\n return html;\n}\n\nfunction getPluginState(corePlugins: StandaloneEditorCorePlugins): StandaloneEditorCorePluginState {\n return {\n domEvent: corePlugins.domEvent.getState(),\n copyPaste: corePlugins.copyPaste.getState(),\n cache: corePlugins.cache.getState(),\n format: corePlugins.format.getState(),\n lifecycle: corePlugins.lifecycle.getState(),\n entity: corePlugins.entity.getState(),\n selection: corePlugins.selection.getState(),\n };\n}\n"]}
1
+ {"version":3,"file":"createStandaloneEditorCore.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/editor/createStandaloneEditorCore.ts"],"names":[],"mappings":";;;;AAAA,qGAAoG;AACpG,iGAAgG;AAChG,+DAA8D;AAC9D,+DAA8D;AAY9D;;;;GAIG;AACH,SAAgB,0BAA0B,CACtC,UAA0B,EAC1B,OAAgC,EAChC,kBAAsC,EACtC,uBAAgD,EAChD,WAA2B;;IAE3B,IAAM,WAAW,GAAG,IAAA,qEAAiC,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAE3E,2EACI,UAAU,YAAA,EACV,GAAG,wEAAO,2CAAoB,GAAK,kBAAkB,GAAK,OAAO,CAAC,eAAe,GACjF,WAAW,kDAAO,2CAAoB,GAAK,kBAAkB,GAC7D,OAAO;YACH,WAAW,CAAC,KAAK;YACjB,WAAW,CAAC,MAAM;YAClB,WAAW,CAAC,SAAS;YACrB,WAAW,CAAC,QAAQ;YACpB,WAAW,CAAC,SAAS;YACrB,WAAW,CAAC,MAAM;+BACf,WAAW;YACd,WAAW,CAAC,SAAS;mBAEzB,WAAW,EAAE,uBAAuB,EAAE,EACtC,gBAAgB,EAAE,IAAI,2CAAoB,CACtC,UAAU,EACV,MAAA,OAAO,CAAC,YAAY,mCAAI,oBAAoB,CAC/C,EACD,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,uBAAuB,IACtE,IAAA,6EAAqC,EAAC,OAAO,CAAC,GAC9C,cAAc,CAAC,WAAW,CAAC,GAC3B,uBAAuB,EAC5B;AACN,CAAC;AAjCD,gEAiCC;AAED,SAAS,uBAAuB;IAC5B,oHAAoH;IACpH,IAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;IAE7C,OAAO;QACH,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvD,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;QACrC,QAAQ,EACJ,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;YAChC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;YAC/B,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC;KACvC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,SAAgB,uBAAuB,CAAC,IAAY;IAChD,OAAO,IAAI,CAAC;AAChB,CAAC;AAFD,0DAEC;AAED,SAAS,cAAc,CAAC,WAAwC;IAC5D,OAAO;QACH,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC,QAAQ,EAAE;QACzC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;QAC3C,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE;QACnC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE;QACrC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;QAC3C,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE;QACrC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;KAC9C,CAAC;AACN,CAAC;AAED,oDAAoD;AACpD,SAAS,oBAAoB,CAAC,KAAa;IACvC,OAAO,KAAK,CAAC;AACjB,CAAC","sourcesContent":["import { createStandaloneEditorCorePlugins } from '../corePlugin/createStandaloneEditorCorePlugins';\nimport { createStandaloneEditorDefaultSettings } from './createStandaloneEditorDefaultSettings';\nimport { DarkColorHandlerImpl } from './DarkColorHandlerImpl';\nimport { standaloneCoreApiMap } from './standaloneCoreApiMap';\nimport type { EditorPlugin } from 'roosterjs-editor-types';\nimport type {\n EditorEnvironment,\n StandaloneEditorCore,\n StandaloneEditorCorePluginState,\n StandaloneEditorCorePlugins,\n StandaloneEditorOptions,\n UnportedCoreApiMap,\n UnportedCorePluginState,\n} from 'roosterjs-content-model-types';\n\n/**\n * A temporary function to create Standalone Editor core\n * @param contentDiv Editor content DIV\n * @param options Editor options\n */\nexport function createStandaloneEditorCore(\n contentDiv: HTMLDivElement,\n options: StandaloneEditorOptions,\n unportedCoreApiMap: UnportedCoreApiMap,\n unportedCorePluginState: UnportedCorePluginState,\n tempPlugins: EditorPlugin[]\n): StandaloneEditorCore {\n const corePlugins = createStandaloneEditorCorePlugins(options, contentDiv);\n\n return {\n contentDiv,\n api: { ...standaloneCoreApiMap, ...unportedCoreApiMap, ...options.coreApiOverride },\n originalApi: { ...standaloneCoreApiMap, ...unportedCoreApiMap },\n plugins: [\n corePlugins.cache,\n corePlugins.format,\n corePlugins.copyPaste,\n corePlugins.domEvent,\n corePlugins.selection,\n corePlugins.entity,\n ...tempPlugins,\n corePlugins.lifecycle,\n ],\n environment: createEditorEnvironment(),\n darkColorHandler: new DarkColorHandlerImpl(\n contentDiv,\n options.getDarkColor ?? getDarkColorFallback\n ),\n trustedHTMLHandler: options.trustedHTMLHandler || defaultTrustHtmlHandler,\n ...createStandaloneEditorDefaultSettings(options),\n ...getPluginState(corePlugins),\n ...unportedCorePluginState,\n };\n}\n\nfunction createEditorEnvironment(): EditorEnvironment {\n // It is ok to use global window here since the environment should always be the same for all windows in one session\n const userAgent = window.navigator.userAgent;\n\n return {\n isMac: window.navigator.appVersion.indexOf('Mac') != -1,\n isAndroid: /android/i.test(userAgent),\n isSafari:\n userAgent.indexOf('Safari') >= 0 &&\n userAgent.indexOf('Chrome') < 0 &&\n userAgent.indexOf('Android') < 0,\n };\n}\n\n/**\n * @internal export for test only\n */\nexport function defaultTrustHtmlHandler(html: string) {\n return html;\n}\n\nfunction getPluginState(corePlugins: StandaloneEditorCorePlugins): StandaloneEditorCorePluginState {\n return {\n domEvent: corePlugins.domEvent.getState(),\n copyPaste: corePlugins.copyPaste.getState(),\n cache: corePlugins.cache.getState(),\n format: corePlugins.format.getState(),\n lifecycle: corePlugins.lifecycle.getState(),\n entity: corePlugins.entity.getState(),\n selection: corePlugins.selection.getState(),\n };\n}\n\n// A fallback function, always return original color\nfunction getDarkColorFallback(color: string) {\n return color;\n}\n"]}
@@ -101,6 +101,9 @@ define(["require", "exports", "./utils/findAllEntities", "roosterjs-content-mode
101
101
  if (operation == 'newEntity') {
102
102
  entity.entityFormat.id = _this.ensureUniqueId(entityType, id !== null && id !== void 0 ? id : '', wrapper);
103
103
  wrapper.className = (0, roosterjs_content_model_dom_1.generateEntityClassNames)(entity.entityFormat);
104
+ if (entity.entityFormat.isReadonly) {
105
+ wrapper.contentEditable = 'false';
106
+ }
104
107
  var eventResult = _this.triggerEvent(editor, wrapper, operation, rawEvent);
105
108
  _this.state.entityMap[entity.entityFormat.id] = {
106
109
  element: wrapper,
@@ -1 +1 @@
1
- {"version":3,"file":"EntityPlugin.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/corePlugin/EntityPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { findAllEntities } from './utils/findAllEntities';\nimport {\n createEntity,\n generateEntityClassNames,\n getAllEntityWrappers,\n getObjectKeys,\n isEntityElement,\n parseEntityClassName,\n} from 'roosterjs-content-model-dom';\nimport {\n ColorTransformDirection,\n EntityOperation as LegacyEntityOperation,\n PluginEventType,\n} from 'roosterjs-editor-types';\nimport type {\n ChangedEntity,\n ContentModelContentChangedEvent,\n ContentModelEntityFormat,\n EntityOperation,\n EntityPluginState,\n IStandaloneEditor,\n} from 'roosterjs-content-model-types';\nimport type {\n ContentChangedEvent,\n IEditor,\n PluginEvent,\n PluginMouseUpEvent,\n PluginWithState,\n} from 'roosterjs-editor-types';\n\nconst ENTITY_ID_REGEX = /_(\\d{1,8})$/;\n\n// This is only used for compatibility with old editor\n// TODO: Remove this map once we have standalone editor\nconst EntityOperationMap: Record<EntityOperation, LegacyEntityOperation> = {\n newEntity: LegacyEntityOperation.NewEntity,\n overwrite: LegacyEntityOperation.Overwrite,\n removeFromEnd: LegacyEntityOperation.RemoveFromEnd,\n removeFromStart: LegacyEntityOperation.RemoveFromStart,\n replaceTemporaryContent: LegacyEntityOperation.ReplaceTemporaryContent,\n updateEntityState: LegacyEntityOperation.UpdateEntityState,\n click: LegacyEntityOperation.Click,\n};\n\n/**\n * Entity Plugin helps handle all operations related to an entity and generate entity specified events\n */\nclass EntityPlugin implements PluginWithState<EntityPluginState> {\n private editor: (IEditor & IStandaloneEditor) | null = null;\n private state: EntityPluginState;\n\n /**\n * Construct a new instance of EntityPlugin\n */\n constructor() {\n this.state = {\n entityMap: {},\n };\n }\n\n /**\n * Get a friendly name of this plugin\n */\n getName() {\n return 'Entity';\n }\n\n /**\n * Initialize this plugin. This should only be called from Editor\n * @param editor Editor instance\n */\n initialize(editor: IEditor) {\n this.editor = editor as IStandaloneEditor & IEditor;\n }\n\n /**\n * Dispose this plugin\n */\n dispose() {\n this.editor = null;\n this.state.entityMap = {};\n }\n\n /**\n * Get plugin state object\n */\n getState() {\n return this.state;\n }\n\n /**\n * Handle events triggered from editor\n * @param event PluginEvent object\n */\n onPluginEvent(event: PluginEvent) {\n if (this.editor) {\n switch (event.eventType) {\n case PluginEventType.MouseUp:\n this.handleMouseUpEvent(this.editor, event);\n break;\n case PluginEventType.ContentChanged:\n this.handleContentChangedEvent(this.editor, event);\n break;\n\n case PluginEventType.EditorReady:\n this.handleContentChangedEvent(this.editor);\n break;\n case PluginEventType.ExtractContentWithDom:\n this.handleExtractContentWithDomEvent(this.editor, event.clonedRoot);\n break;\n }\n }\n }\n\n private handleMouseUpEvent(editor: IEditor & IStandaloneEditor, event: PluginMouseUpEvent) {\n const { rawEvent, isClicking } = event;\n let node: Node | null = rawEvent.target as Node;\n\n if (isClicking && this.editor) {\n while (node && this.editor.contains(node)) {\n if (isEntityElement(node)) {\n this.triggerEvent(editor, node as HTMLElement, 'click', rawEvent);\n break;\n } else {\n node = node.parentNode;\n }\n }\n }\n }\n\n private handleContentChangedEvent(\n editor: IStandaloneEditor & IEditor,\n event?: ContentChangedEvent\n ) {\n const modifiedEntities: ChangedEntity[] =\n (event as ContentModelContentChangedEvent)?.changedEntities ??\n this.getChangedEntities(editor);\n\n modifiedEntities.forEach(entry => {\n const { entity, operation, rawEvent } = entry;\n const {\n entityFormat: { id, entityType, isFakeEntity },\n wrapper,\n } = entity;\n\n if (entityType && !isFakeEntity) {\n if (operation == 'newEntity') {\n entity.entityFormat.id = this.ensureUniqueId(entityType, id ?? '', wrapper);\n wrapper.className = generateEntityClassNames(entity.entityFormat);\n\n const eventResult = this.triggerEvent(editor, wrapper, operation, rawEvent);\n\n this.state.entityMap[entity.entityFormat.id] = {\n element: wrapper,\n canPersist: eventResult?.shouldPersist,\n };\n\n if (editor.isDarkMode()) {\n editor.transformToDarkColor(wrapper, ColorTransformDirection.LightToDark);\n }\n } else if (id) {\n const mapEntry = this.state.entityMap[id];\n\n if (mapEntry) {\n mapEntry.isDeleted = true;\n }\n\n this.triggerEvent(editor, wrapper, operation, rawEvent);\n }\n }\n });\n }\n\n private getChangedEntities(editor: IStandaloneEditor): ChangedEntity[] {\n const result: ChangedEntity[] = [];\n\n findAllEntities(editor.createContentModel(), result);\n\n getObjectKeys(this.state.entityMap).forEach(id => {\n const entry = this.state.entityMap[id];\n\n if (!entry.isDeleted) {\n const index = result.findIndex(\n x =>\n x.operation == 'newEntity' &&\n x.entity.entityFormat.id == id &&\n x.entity.wrapper == entry.element\n );\n\n if (index >= 0) {\n // Found matched entity in editor, so there is no change to this entity,\n // we can safely remove it from the new entity array\n result.splice(index, 1);\n } else {\n // Entity is not in editor, which means it is deleted, use a temporary entity here to represent this entity\n const tempEntity = createEntity(entry.element);\n let isEntity = false;\n\n entry.element.classList.forEach(name => {\n isEntity = parseEntityClassName(name, tempEntity.entityFormat) || isEntity;\n });\n\n if (isEntity) {\n result.push({\n entity: tempEntity,\n operation: 'overwrite',\n });\n }\n }\n }\n });\n\n return result;\n }\n\n private handleExtractContentWithDomEvent(\n editor: IEditor & IStandaloneEditor,\n root: HTMLElement\n ) {\n getAllEntityWrappers(root).forEach(element => {\n element.removeAttribute('contentEditable');\n\n this.triggerEvent(editor, element, 'replaceTemporaryContent');\n });\n }\n\n private triggerEvent(\n editor: IEditor & IStandaloneEditor,\n wrapper: HTMLElement,\n operation: EntityOperation,\n rawEvent?: Event\n ) {\n const format: ContentModelEntityFormat = {};\n wrapper.classList.forEach(name => {\n parseEntityClassName(name, format);\n });\n\n return format.id && format.entityType && !format.isFakeEntity\n ? editor.triggerPluginEvent(PluginEventType.EntityOperation, {\n operation: EntityOperationMap[operation],\n rawEvent,\n entity: {\n id: format.id,\n type: format.entityType,\n isReadonly: !!format.isReadonly,\n wrapper,\n },\n })\n : null;\n }\n\n private ensureUniqueId(type: string, id: string, wrapper: HTMLElement): string {\n const match = ENTITY_ID_REGEX.exec(id);\n const baseId = (match ? id.substr(0, id.length - match[0].length) : id) || type;\n\n // Make sure entity id is unique\n let newId = '';\n\n for (let num = (match && parseInt(match[1])) || 0; ; num++) {\n newId = num > 0 ? `${baseId}_${num}` : baseId;\n\n const item = this.state.entityMap[newId];\n\n if (!item || item.element == wrapper) {\n break;\n }\n }\n\n return newId;\n }\n}\n\n/**\n * @internal\n * Create a new instance of EntityPlugin.\n */\nexport function createEntityPlugin(): PluginWithState<EntityPluginState> {\n return new EntityPlugin();\n}\n"]}
1
+ {"version":3,"file":"EntityPlugin.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/corePlugin/EntityPlugin.ts"],"names":[],"mappings":";;;;IA8BA,IAAM,eAAe,GAAG,aAAa,CAAC;IAEtC,sDAAsD;IACtD,uDAAuD;IACvD,IAAM,kBAAkB,GAAmD;QACvE,SAAS,mBAAiC;QAC1C,SAAS,mBAAiC;QAC1C,aAAa,uBAAqC;QAClD,eAAe,yBAAuC;QACtD,uBAAuB,iCAA+C;QACtE,iBAAiB,4BAAyC;QAC1D,KAAK,eAA6B;KACrC,CAAC;IAEF;;OAEG;IACH;QAII;;WAEG;QACH;YANQ,WAAM,GAAyC,IAAI,CAAC;YAOxD,IAAI,CAAC,KAAK,GAAG;gBACT,SAAS,EAAE,EAAE;aAChB,CAAC;QACN,CAAC;QAED;;WAEG;QACH,8BAAO,GAAP;YACI,OAAO,QAAQ,CAAC;QACpB,CAAC;QAED;;;WAGG;QACH,iCAAU,GAAV,UAAW,MAAe;YACtB,IAAI,CAAC,MAAM,GAAG,MAAqC,CAAC;QACxD,CAAC;QAED;;WAEG;QACH,8BAAO,GAAP;YACI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,EAAE,CAAC;QAC9B,CAAC;QAED;;WAEG;QACH,+BAAQ,GAAR;YACI,OAAO,IAAI,CAAC,KAAK,CAAC;QACtB,CAAC;QAED;;;WAGG;QACH,oCAAa,GAAb,UAAc,KAAkB;YAC5B,IAAI,IAAI,CAAC,MAAM,EAAE;gBACb,QAAQ,KAAK,CAAC,SAAS,EAAE;oBACrB;wBACI,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;wBAC5C,MAAM;oBACV;wBACI,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;wBACnD,MAAM;oBAEV;wBACI,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;wBAC5C,MAAM;oBACV;wBACI,IAAI,CAAC,gCAAgC,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;wBACrE,MAAM;iBACb;aACJ;QACL,CAAC;QAEO,yCAAkB,GAA1B,UAA2B,MAAmC,EAAE,KAAyB;YAC7E,IAAA,QAAQ,GAAiB,KAAK,SAAtB,EAAE,UAAU,GAAK,KAAK,WAAV,CAAW;YACvC,IAAI,IAAI,GAAgB,QAAQ,CAAC,MAAc,CAAC;YAEhD,IAAI,UAAU,IAAI,IAAI,CAAC,MAAM,EAAE;gBAC3B,OAAO,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;oBACvC,IAAI,IAAA,6CAAe,EAAC,IAAI,CAAC,EAAE;wBACvB,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,IAAmB,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;wBAClE,MAAM;qBACT;yBAAM;wBACH,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;qBAC1B;iBACJ;aACJ;QACL,CAAC;QAEO,gDAAyB,GAAjC,UACI,MAAmC,EACnC,KAA2B;YAF/B,iBA6CC;;YAzCG,IAAM,gBAAgB,GAClB,MAAA,MAAC,KAAyC,0CAAE,eAAe,mCAC3D,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAEpC,gBAAgB,CAAC,OAAO,CAAC,UAAA,KAAK;gBAClB,IAAA,MAAM,GAA0B,KAAK,OAA/B,EAAE,SAAS,GAAe,KAAK,UAApB,EAAE,QAAQ,GAAK,KAAK,SAAV,CAAW;gBAE1C,IAAA,KAEA,MAAM,aAFwC,EAA9B,EAAE,QAAA,EAAE,UAAU,gBAAA,EAAE,YAAY,kBAAA,EAC5C,OAAO,GACP,MAAM,QADC,CACA;gBAEX,IAAI,UAAU,IAAI,CAAC,YAAY,EAAE;oBAC7B,IAAI,SAAS,IAAI,WAAW,EAAE;wBAC1B,MAAM,CAAC,YAAY,CAAC,EAAE,GAAG,KAAI,CAAC,cAAc,CAAC,UAAU,EAAE,EAAE,aAAF,EAAE,cAAF,EAAE,GAAI,EAAE,EAAE,OAAO,CAAC,CAAC;wBAC5E,OAAO,CAAC,SAAS,GAAG,IAAA,sDAAwB,EAAC,MAAM,CAAC,YAAY,CAAC,CAAC;wBAElE,IAAI,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE;4BAChC,OAAO,CAAC,eAAe,GAAG,OAAO,CAAC;yBACrC;wBAED,IAAM,WAAW,GAAG,KAAI,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;wBAE5E,KAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG;4BAC3C,OAAO,EAAE,OAAO;4BAChB,UAAU,EAAE,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,aAAa;yBACzC,CAAC;wBAEF,IAAI,MAAM,CAAC,UAAU,EAAE,EAAE;4BACrB,MAAM,CAAC,oBAAoB,CAAC,OAAO,sBAAsC,CAAC;yBAC7E;qBACJ;yBAAM,IAAI,EAAE,EAAE;wBACX,IAAM,QAAQ,GAAG,KAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;wBAE1C,IAAI,QAAQ,EAAE;4BACV,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC;yBAC7B;wBAED,KAAI,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;qBAC3D;iBACJ;YACL,CAAC,CAAC,CAAC;QACP,CAAC;QAEO,yCAAkB,GAA1B,UAA2B,MAAyB;YAApD,iBAwCC;YAvCG,IAAM,MAAM,GAAoB,EAAE,CAAC;YAEnC,IAAA,iCAAe,EAAC,MAAM,CAAC,kBAAkB,EAAE,EAAE,MAAM,CAAC,CAAC;YAErD,IAAA,2CAAa,EAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,UAAA,EAAE;gBAC1C,IAAM,KAAK,GAAG,KAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;gBAEvC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;oBAClB,IAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAC1B,UAAA,CAAC;wBACG,OAAA,CAAC,CAAC,SAAS,IAAI,WAAW;4BAC1B,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE;4BAC9B,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO;oBAFjC,CAEiC,CACxC,CAAC;oBAEF,IAAI,KAAK,IAAI,CAAC,EAAE;wBACZ,wEAAwE;wBACxE,oDAAoD;wBACpD,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;qBAC3B;yBAAM;wBACH,2GAA2G;wBAC3G,IAAM,YAAU,GAAG,IAAA,0CAAY,EAAC,KAAK,CAAC,OAAO,CAAC,CAAC;wBAC/C,IAAI,UAAQ,GAAG,KAAK,CAAC;wBAErB,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,UAAA,IAAI;4BAChC,UAAQ,GAAG,IAAA,kDAAoB,EAAC,IAAI,EAAE,YAAU,CAAC,YAAY,CAAC,IAAI,UAAQ,CAAC;wBAC/E,CAAC,CAAC,CAAC;wBAEH,IAAI,UAAQ,EAAE;4BACV,MAAM,CAAC,IAAI,CAAC;gCACR,MAAM,EAAE,YAAU;gCAClB,SAAS,EAAE,WAAW;6BACzB,CAAC,CAAC;yBACN;qBACJ;iBACJ;YACL,CAAC,CAAC,CAAC;YAEH,OAAO,MAAM,CAAC;QAClB,CAAC;QAEO,uDAAgC,GAAxC,UACI,MAAmC,EACnC,IAAiB;YAFrB,iBASC;YALG,IAAA,kDAAoB,EAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAA,OAAO;gBACtC,OAAO,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC;gBAE3C,KAAI,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,yBAAyB,CAAC,CAAC;YAClE,CAAC,CAAC,CAAC;QACP,CAAC;QAEO,mCAAY,GAApB,UACI,MAAmC,EACnC,OAAoB,EACpB,SAA0B,EAC1B,QAAgB;YAEhB,IAAM,MAAM,GAA6B,EAAE,CAAC;YAC5C,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,UAAA,IAAI;gBAC1B,IAAA,kDAAoB,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACvC,CAAC,CAAC,CAAC;YAEH,OAAO,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,UAAU,IAAI,CAAC,MAAM,CAAC,YAAY;gBACzD,CAAC,CAAC,MAAM,CAAC,kBAAkB,2BAAkC;oBACvD,SAAS,EAAE,kBAAkB,CAAC,SAAS,CAAC;oBACxC,QAAQ,UAAA;oBACR,MAAM,EAAE;wBACJ,EAAE,EAAE,MAAM,CAAC,EAAE;wBACb,IAAI,EAAE,MAAM,CAAC,UAAU;wBACvB,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU;wBAC/B,OAAO,SAAA;qBACV;iBACJ,CAAC;gBACJ,CAAC,CAAC,IAAI,CAAC;QACf,CAAC;QAEO,qCAAc,GAAtB,UAAuB,IAAY,EAAE,EAAU,EAAE,OAAoB;YACjE,IAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACvC,IAAM,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;YAEhF,gCAAgC;YAChC,IAAI,KAAK,GAAG,EAAE,CAAC;YAEf,KAAK,IAAI,GAAG,GAAG,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAI,GAAG,EAAE,EAAE;gBACxD,KAAK,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAI,MAAM,SAAI,GAAK,CAAC,CAAC,CAAC,MAAM,CAAC;gBAE9C,IAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAEzC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,OAAO,EAAE;oBAClC,MAAM;iBACT;aACJ;YAED,OAAO,KAAK,CAAC;QACjB,CAAC;QACL,mBAAC;IAAD,CAAC,AAnOD,IAmOC;IAED;;;OAGG;IACH,SAAgB,kBAAkB;QAC9B,OAAO,IAAI,YAAY,EAAE,CAAC;IAC9B,CAAC;IAFD,gDAEC","sourcesContent":["import { findAllEntities } from './utils/findAllEntities';\nimport {\n createEntity,\n generateEntityClassNames,\n getAllEntityWrappers,\n getObjectKeys,\n isEntityElement,\n parseEntityClassName,\n} from 'roosterjs-content-model-dom';\nimport {\n ColorTransformDirection,\n EntityOperation as LegacyEntityOperation,\n PluginEventType,\n} from 'roosterjs-editor-types';\nimport type {\n ChangedEntity,\n ContentModelContentChangedEvent,\n ContentModelEntityFormat,\n EntityOperation,\n EntityPluginState,\n IStandaloneEditor,\n} from 'roosterjs-content-model-types';\nimport type {\n ContentChangedEvent,\n IEditor,\n PluginEvent,\n PluginMouseUpEvent,\n PluginWithState,\n} from 'roosterjs-editor-types';\n\nconst ENTITY_ID_REGEX = /_(\\d{1,8})$/;\n\n// This is only used for compatibility with old editor\n// TODO: Remove this map once we have standalone editor\nconst EntityOperationMap: Record<EntityOperation, LegacyEntityOperation> = {\n newEntity: LegacyEntityOperation.NewEntity,\n overwrite: LegacyEntityOperation.Overwrite,\n removeFromEnd: LegacyEntityOperation.RemoveFromEnd,\n removeFromStart: LegacyEntityOperation.RemoveFromStart,\n replaceTemporaryContent: LegacyEntityOperation.ReplaceTemporaryContent,\n updateEntityState: LegacyEntityOperation.UpdateEntityState,\n click: LegacyEntityOperation.Click,\n};\n\n/**\n * Entity Plugin helps handle all operations related to an entity and generate entity specified events\n */\nclass EntityPlugin implements PluginWithState<EntityPluginState> {\n private editor: (IEditor & IStandaloneEditor) | null = null;\n private state: EntityPluginState;\n\n /**\n * Construct a new instance of EntityPlugin\n */\n constructor() {\n this.state = {\n entityMap: {},\n };\n }\n\n /**\n * Get a friendly name of this plugin\n */\n getName() {\n return 'Entity';\n }\n\n /**\n * Initialize this plugin. This should only be called from Editor\n * @param editor Editor instance\n */\n initialize(editor: IEditor) {\n this.editor = editor as IStandaloneEditor & IEditor;\n }\n\n /**\n * Dispose this plugin\n */\n dispose() {\n this.editor = null;\n this.state.entityMap = {};\n }\n\n /**\n * Get plugin state object\n */\n getState() {\n return this.state;\n }\n\n /**\n * Handle events triggered from editor\n * @param event PluginEvent object\n */\n onPluginEvent(event: PluginEvent) {\n if (this.editor) {\n switch (event.eventType) {\n case PluginEventType.MouseUp:\n this.handleMouseUpEvent(this.editor, event);\n break;\n case PluginEventType.ContentChanged:\n this.handleContentChangedEvent(this.editor, event);\n break;\n\n case PluginEventType.EditorReady:\n this.handleContentChangedEvent(this.editor);\n break;\n case PluginEventType.ExtractContentWithDom:\n this.handleExtractContentWithDomEvent(this.editor, event.clonedRoot);\n break;\n }\n }\n }\n\n private handleMouseUpEvent(editor: IEditor & IStandaloneEditor, event: PluginMouseUpEvent) {\n const { rawEvent, isClicking } = event;\n let node: Node | null = rawEvent.target as Node;\n\n if (isClicking && this.editor) {\n while (node && this.editor.contains(node)) {\n if (isEntityElement(node)) {\n this.triggerEvent(editor, node as HTMLElement, 'click', rawEvent);\n break;\n } else {\n node = node.parentNode;\n }\n }\n }\n }\n\n private handleContentChangedEvent(\n editor: IStandaloneEditor & IEditor,\n event?: ContentChangedEvent\n ) {\n const modifiedEntities: ChangedEntity[] =\n (event as ContentModelContentChangedEvent)?.changedEntities ??\n this.getChangedEntities(editor);\n\n modifiedEntities.forEach(entry => {\n const { entity, operation, rawEvent } = entry;\n const {\n entityFormat: { id, entityType, isFakeEntity },\n wrapper,\n } = entity;\n\n if (entityType && !isFakeEntity) {\n if (operation == 'newEntity') {\n entity.entityFormat.id = this.ensureUniqueId(entityType, id ?? '', wrapper);\n wrapper.className = generateEntityClassNames(entity.entityFormat);\n\n if (entity.entityFormat.isReadonly) {\n wrapper.contentEditable = 'false';\n }\n\n const eventResult = this.triggerEvent(editor, wrapper, operation, rawEvent);\n\n this.state.entityMap[entity.entityFormat.id] = {\n element: wrapper,\n canPersist: eventResult?.shouldPersist,\n };\n\n if (editor.isDarkMode()) {\n editor.transformToDarkColor(wrapper, ColorTransformDirection.LightToDark);\n }\n } else if (id) {\n const mapEntry = this.state.entityMap[id];\n\n if (mapEntry) {\n mapEntry.isDeleted = true;\n }\n\n this.triggerEvent(editor, wrapper, operation, rawEvent);\n }\n }\n });\n }\n\n private getChangedEntities(editor: IStandaloneEditor): ChangedEntity[] {\n const result: ChangedEntity[] = [];\n\n findAllEntities(editor.createContentModel(), result);\n\n getObjectKeys(this.state.entityMap).forEach(id => {\n const entry = this.state.entityMap[id];\n\n if (!entry.isDeleted) {\n const index = result.findIndex(\n x =>\n x.operation == 'newEntity' &&\n x.entity.entityFormat.id == id &&\n x.entity.wrapper == entry.element\n );\n\n if (index >= 0) {\n // Found matched entity in editor, so there is no change to this entity,\n // we can safely remove it from the new entity array\n result.splice(index, 1);\n } else {\n // Entity is not in editor, which means it is deleted, use a temporary entity here to represent this entity\n const tempEntity = createEntity(entry.element);\n let isEntity = false;\n\n entry.element.classList.forEach(name => {\n isEntity = parseEntityClassName(name, tempEntity.entityFormat) || isEntity;\n });\n\n if (isEntity) {\n result.push({\n entity: tempEntity,\n operation: 'overwrite',\n });\n }\n }\n }\n });\n\n return result;\n }\n\n private handleExtractContentWithDomEvent(\n editor: IEditor & IStandaloneEditor,\n root: HTMLElement\n ) {\n getAllEntityWrappers(root).forEach(element => {\n element.removeAttribute('contentEditable');\n\n this.triggerEvent(editor, element, 'replaceTemporaryContent');\n });\n }\n\n private triggerEvent(\n editor: IEditor & IStandaloneEditor,\n wrapper: HTMLElement,\n operation: EntityOperation,\n rawEvent?: Event\n ) {\n const format: ContentModelEntityFormat = {};\n wrapper.classList.forEach(name => {\n parseEntityClassName(name, format);\n });\n\n return format.id && format.entityType && !format.isFakeEntity\n ? editor.triggerPluginEvent(PluginEventType.EntityOperation, {\n operation: EntityOperationMap[operation],\n rawEvent,\n entity: {\n id: format.id,\n type: format.entityType,\n isReadonly: !!format.isReadonly,\n wrapper,\n },\n })\n : null;\n }\n\n private ensureUniqueId(type: string, id: string, wrapper: HTMLElement): string {\n const match = ENTITY_ID_REGEX.exec(id);\n const baseId = (match ? id.substr(0, id.length - match[0].length) : id) || type;\n\n // Make sure entity id is unique\n let newId = '';\n\n for (let num = (match && parseInt(match[1])) || 0; ; num++) {\n newId = num > 0 ? `${baseId}_${num}` : baseId;\n\n const item = this.state.entityMap[newId];\n\n if (!item || item.element == wrapper) {\n break;\n }\n }\n\n return newId;\n }\n}\n\n/**\n * @internal\n * Create a new instance of EntityPlugin.\n */\nexport function createEntityPlugin(): PluginWithState<EntityPluginState> {\n return new EntityPlugin();\n}\n"]}
@@ -4,9 +4,9 @@ import type { ColorKeyAndValue, DarkColorHandler, ModeIndependentColor } from 'r
4
4
  */
5
5
  export declare class DarkColorHandlerImpl implements DarkColorHandler {
6
6
  private contentDiv;
7
+ private getDarkColor;
7
8
  private knownColors;
8
- readonly baseLightness: number;
9
- constructor(contentDiv: HTMLElement, baseDarkColor?: string);
9
+ constructor(contentDiv: HTMLElement, getDarkColor: (color: string) => string);
10
10
  /**
11
11
  * Get a copy of known colors
12
12
  * @returns
@@ -1,9 +1,8 @@
1
- define(["require", "exports", "color", "roosterjs-editor-dom"], function (require, exports, Color, roosterjs_editor_dom_1) {
1
+ define(["require", "exports", "roosterjs-editor-dom"], function (require, exports, roosterjs_editor_dom_1) {
2
2
  "use strict";
3
3
  var _a, _b;
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.DarkColorHandlerImpl = void 0;
6
- var DefaultLightness = 21.25; // Lightness for #333333
7
6
  var VARIABLE_REGEX = /^\s*var\(\s*(\-\-[a-zA-Z0-9\-_]+)\s*(?:,\s*(.*))?\)\s*$/;
8
7
  var VARIABLE_PREFIX = 'var(';
9
8
  var COLOR_VAR_PREFIX = 'darkColor';
@@ -26,10 +25,10 @@ define(["require", "exports", "color", "roosterjs-editor-dom"], function (requir
26
25
  * @internal
27
26
  */
28
27
  var DarkColorHandlerImpl = /** @class */ (function () {
29
- function DarkColorHandlerImpl(contentDiv, baseDarkColor) {
28
+ function DarkColorHandlerImpl(contentDiv, getDarkColor) {
30
29
  this.contentDiv = contentDiv;
30
+ this.getDarkColor = getDarkColor;
31
31
  this.knownColors = {};
32
- this.baseLightness = getLightness(baseDarkColor);
33
32
  }
34
33
  /**
35
34
  * Get a copy of known colors
@@ -57,7 +56,7 @@ define(["require", "exports", "color", "roosterjs-editor-dom"], function (requir
57
56
  colorKey =
58
57
  colorKey || "--" + COLOR_VAR_PREFIX + "_" + lightModeColor.replace(/[^\d\w]/g, '_');
59
58
  if (!this.knownColors[colorKey]) {
60
- darkModeColor = darkModeColor || getDarkColor(lightModeColor, this.baseLightness);
59
+ darkModeColor = darkModeColor || this.getDarkColor(lightModeColor);
61
60
  this.knownColors[colorKey] = { lightModeColor: lightModeColor, darkModeColor: darkModeColor };
62
61
  this.contentDiv.style.setProperty(colorKey, darkModeColor);
63
62
  }
@@ -156,29 +155,5 @@ define(["require", "exports", "color", "roosterjs-editor-dom"], function (requir
156
155
  return DarkColorHandlerImpl;
157
156
  }());
158
157
  exports.DarkColorHandlerImpl = DarkColorHandlerImpl;
159
- function getDarkColor(color, baseLightness) {
160
- try {
161
- var computedColor = Color(color || undefined);
162
- var colorLab = computedColor.lab().array();
163
- var newLValue = (100 - colorLab[0]) * ((100 - baseLightness) / 100) + baseLightness;
164
- color = Color.lab(newLValue, colorLab[1], colorLab[2])
165
- .rgb()
166
- .alpha(computedColor.alpha())
167
- .toString();
168
- }
169
- catch (_a) { }
170
- return color;
171
- }
172
- function getLightness(color) {
173
- var result = DefaultLightness;
174
- if (color) {
175
- try {
176
- var computedColor = Color(color || undefined);
177
- result = computedColor.lab().array()[0];
178
- }
179
- catch (_a) { }
180
- }
181
- return result;
182
- }
183
158
  });
184
159
  //# sourceMappingURL=DarkColorHandlerImpl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DarkColorHandlerImpl.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/editor/DarkColorHandlerImpl.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Color from 'color';\nimport { getObjectKeys, parseColor, setColor } from 'roosterjs-editor-dom';\nimport type {\n ColorKeyAndValue,\n DarkColorHandler,\n ModeIndependentColor,\n} from 'roosterjs-editor-types';\n\nconst DefaultLightness = 21.25; // Lightness for #333333\nconst VARIABLE_REGEX = /^\\s*var\\(\\s*(\\-\\-[a-zA-Z0-9\\-_]+)\\s*(?:,\\s*(.*))?\\)\\s*$/;\nconst VARIABLE_PREFIX = 'var(';\nconst COLOR_VAR_PREFIX = 'darkColor';\nconst enum ColorAttributeEnum {\n CssColor = 0,\n HtmlColor = 1,\n}\nconst ColorAttributeName: { [key in ColorAttributeEnum]: string }[] = [\n {\n [ColorAttributeEnum.CssColor]: 'color',\n [ColorAttributeEnum.HtmlColor]: 'color',\n },\n {\n [ColorAttributeEnum.CssColor]: 'background-color',\n [ColorAttributeEnum.HtmlColor]: 'bgcolor',\n },\n];\n\n/**\n * @internal\n */\nexport class DarkColorHandlerImpl implements DarkColorHandler {\n private knownColors: Record<string, Readonly<ModeIndependentColor>> = {};\n readonly baseLightness: number;\n\n constructor(private contentDiv: HTMLElement, baseDarkColor?: string) {\n this.baseLightness = getLightness(baseDarkColor);\n }\n\n /**\n * Get a copy of known colors\n * @returns\n */\n getKnownColorsCopy() {\n return Object.values(this.knownColors);\n }\n\n /**\n * Given a light mode color value and an optional dark mode color value, register this color\n * so that editor can handle it, then return the CSS color value for current color mode.\n * @param lightModeColor Light mode color value\n * @param isDarkMode Whether current color mode is dark mode\n * @param darkModeColor Optional dark mode color value. If not passed, we will calculate one.\n */\n registerColor(lightModeColor: string, isDarkMode: boolean, darkModeColor?: string): string {\n const parsedColor = this.parseColorValue(lightModeColor);\n let colorKey: string | undefined;\n\n if (parsedColor) {\n lightModeColor = parsedColor.lightModeColor;\n darkModeColor = parsedColor.darkModeColor || darkModeColor;\n colorKey = parsedColor.key;\n }\n\n if (isDarkMode && lightModeColor) {\n colorKey =\n colorKey || `--${COLOR_VAR_PREFIX}_${lightModeColor.replace(/[^\\d\\w]/g, '_')}`;\n\n if (!this.knownColors[colorKey]) {\n darkModeColor = darkModeColor || getDarkColor(lightModeColor, this.baseLightness);\n\n this.knownColors[colorKey] = { lightModeColor, darkModeColor };\n this.contentDiv.style.setProperty(colorKey, darkModeColor);\n }\n\n return `var(${colorKey}, ${lightModeColor})`;\n } else {\n return lightModeColor;\n }\n }\n\n /**\n * Reset known color record, clean up registered color variables.\n */\n reset(): void {\n getObjectKeys(this.knownColors).forEach(key => this.contentDiv.style.removeProperty(key));\n this.knownColors = {};\n }\n\n /**\n * Parse an existing color value, if it is in variable-based color format, extract color key,\n * light color and query related dark color if any\n * @param color The color string to parse\n * @param isInDarkMode Whether current content is in dark mode. When set to true, if the color value is not in dark var format,\n * we will treat is as a dark mode color and try to find a matched dark mode color.\n */\n parseColorValue(color: string | undefined | null, isInDarkMode?: boolean): ColorKeyAndValue {\n let key: string | undefined;\n let lightModeColor = '';\n let darkModeColor: string | undefined;\n\n if (color) {\n const match = color.startsWith(VARIABLE_PREFIX) ? VARIABLE_REGEX.exec(color) : null;\n\n if (match) {\n if (match[2]) {\n key = match[1];\n lightModeColor = match[2];\n darkModeColor = this.knownColors[key]?.darkModeColor;\n } else {\n lightModeColor = '';\n }\n } else if (isInDarkMode) {\n // If editor is in dark mode but the color is not in dark color format, it is possible the color was inserted from external code\n // without any light color info. So we first try to see if there is a known dark color can match this color, and use its related\n // light color as light mode color. Otherwise we need to drop this color to avoid show \"white on white\" content.\n lightModeColor = this.findLightColorFromDarkColor(color) || '';\n\n if (lightModeColor) {\n darkModeColor = color;\n }\n } else {\n lightModeColor = color;\n }\n }\n\n return { key, lightModeColor, darkModeColor };\n }\n\n /**\n * Find related light mode color from dark mode color.\n * @param darkColor The existing dark color\n */\n findLightColorFromDarkColor(darkColor: string): string | null {\n const rgbSearch = parseColor(darkColor);\n\n if (rgbSearch) {\n const key = getObjectKeys(this.knownColors).find(key => {\n const rgbCurrent = parseColor(this.knownColors[key].darkModeColor);\n\n return (\n rgbCurrent &&\n rgbCurrent[0] == rgbSearch[0] &&\n rgbCurrent[1] == rgbSearch[1] &&\n rgbCurrent[2] == rgbSearch[2]\n );\n });\n\n if (key) {\n return this.knownColors[key].lightModeColor;\n }\n }\n\n return null;\n }\n\n /**\n * Transform element color, from dark to light or from light to dark\n * @param element The element to transform color\n * @param fromDarkMode Whether this is transforming color from dark mode\n * @param toDarkMode Whether this is transforming color to dark mode\n */\n transformElementColor(element: HTMLElement, fromDarkMode: boolean, toDarkMode: boolean): void {\n ColorAttributeName.forEach((names, i) => {\n const color = this.parseColorValue(\n element.style.getPropertyValue(names[ColorAttributeEnum.CssColor]) ||\n element.getAttribute(names[ColorAttributeEnum.HtmlColor]),\n !!fromDarkMode\n ).lightModeColor;\n\n element.style.setProperty(names[ColorAttributeEnum.CssColor], null);\n element.removeAttribute(names[ColorAttributeEnum.HtmlColor]);\n\n if (color && color != 'inherit') {\n setColor(element, color, i != 0, toDarkMode, false /*shouldAdaptFontColor*/, this);\n }\n });\n }\n}\n\nfunction getDarkColor(color: string, baseLightness: number): string {\n try {\n const computedColor = Color(color || undefined);\n const colorLab = computedColor.lab().array();\n const newLValue = (100 - colorLab[0]) * ((100 - baseLightness) / 100) + baseLightness;\n color = Color.lab(newLValue, colorLab[1], colorLab[2])\n .rgb()\n .alpha(computedColor.alpha())\n .toString();\n } catch {}\n\n return color;\n}\n\nfunction getLightness(color?: string): number {\n let result = DefaultLightness;\n\n if (color) {\n try {\n const computedColor = Color(color || undefined);\n result = computedColor.lab().array()[0];\n } catch {}\n }\n\n return result;\n}\n"]}
1
+ {"version":3,"file":"DarkColorHandlerImpl.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/editor/DarkColorHandlerImpl.ts"],"names":[],"mappings":"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","sourcesContent":["import { getObjectKeys, parseColor, setColor } from 'roosterjs-editor-dom';\nimport type {\n ColorKeyAndValue,\n DarkColorHandler,\n ModeIndependentColor,\n} from 'roosterjs-editor-types';\n\nconst VARIABLE_REGEX = /^\\s*var\\(\\s*(\\-\\-[a-zA-Z0-9\\-_]+)\\s*(?:,\\s*(.*))?\\)\\s*$/;\nconst VARIABLE_PREFIX = 'var(';\nconst COLOR_VAR_PREFIX = 'darkColor';\nconst enum ColorAttributeEnum {\n CssColor = 0,\n HtmlColor = 1,\n}\nconst ColorAttributeName: { [key in ColorAttributeEnum]: string }[] = [\n {\n [ColorAttributeEnum.CssColor]: 'color',\n [ColorAttributeEnum.HtmlColor]: 'color',\n },\n {\n [ColorAttributeEnum.CssColor]: 'background-color',\n [ColorAttributeEnum.HtmlColor]: 'bgcolor',\n },\n];\n\n/**\n * @internal\n */\nexport class DarkColorHandlerImpl implements DarkColorHandler {\n private knownColors: Record<string, Readonly<ModeIndependentColor>> = {};\n\n constructor(private contentDiv: HTMLElement, private getDarkColor: (color: string) => string) {}\n\n /**\n * Get a copy of known colors\n * @returns\n */\n getKnownColorsCopy() {\n return Object.values(this.knownColors);\n }\n\n /**\n * Given a light mode color value and an optional dark mode color value, register this color\n * so that editor can handle it, then return the CSS color value for current color mode.\n * @param lightModeColor Light mode color value\n * @param isDarkMode Whether current color mode is dark mode\n * @param darkModeColor Optional dark mode color value. If not passed, we will calculate one.\n */\n registerColor(lightModeColor: string, isDarkMode: boolean, darkModeColor?: string): string {\n const parsedColor = this.parseColorValue(lightModeColor);\n let colorKey: string | undefined;\n\n if (parsedColor) {\n lightModeColor = parsedColor.lightModeColor;\n darkModeColor = parsedColor.darkModeColor || darkModeColor;\n colorKey = parsedColor.key;\n }\n\n if (isDarkMode && lightModeColor) {\n colorKey =\n colorKey || `--${COLOR_VAR_PREFIX}_${lightModeColor.replace(/[^\\d\\w]/g, '_')}`;\n\n if (!this.knownColors[colorKey]) {\n darkModeColor = darkModeColor || this.getDarkColor(lightModeColor);\n\n this.knownColors[colorKey] = { lightModeColor, darkModeColor };\n this.contentDiv.style.setProperty(colorKey, darkModeColor);\n }\n\n return `var(${colorKey}, ${lightModeColor})`;\n } else {\n return lightModeColor;\n }\n }\n\n /**\n * Reset known color record, clean up registered color variables.\n */\n reset(): void {\n getObjectKeys(this.knownColors).forEach(key => this.contentDiv.style.removeProperty(key));\n this.knownColors = {};\n }\n\n /**\n * Parse an existing color value, if it is in variable-based color format, extract color key,\n * light color and query related dark color if any\n * @param color The color string to parse\n * @param isInDarkMode Whether current content is in dark mode. When set to true, if the color value is not in dark var format,\n * we will treat is as a dark mode color and try to find a matched dark mode color.\n */\n parseColorValue(color: string | undefined | null, isInDarkMode?: boolean): ColorKeyAndValue {\n let key: string | undefined;\n let lightModeColor = '';\n let darkModeColor: string | undefined;\n\n if (color) {\n const match = color.startsWith(VARIABLE_PREFIX) ? VARIABLE_REGEX.exec(color) : null;\n\n if (match) {\n if (match[2]) {\n key = match[1];\n lightModeColor = match[2];\n darkModeColor = this.knownColors[key]?.darkModeColor;\n } else {\n lightModeColor = '';\n }\n } else if (isInDarkMode) {\n // If editor is in dark mode but the color is not in dark color format, it is possible the color was inserted from external code\n // without any light color info. So we first try to see if there is a known dark color can match this color, and use its related\n // light color as light mode color. Otherwise we need to drop this color to avoid show \"white on white\" content.\n lightModeColor = this.findLightColorFromDarkColor(color) || '';\n\n if (lightModeColor) {\n darkModeColor = color;\n }\n } else {\n lightModeColor = color;\n }\n }\n\n return { key, lightModeColor, darkModeColor };\n }\n\n /**\n * Find related light mode color from dark mode color.\n * @param darkColor The existing dark color\n */\n findLightColorFromDarkColor(darkColor: string): string | null {\n const rgbSearch = parseColor(darkColor);\n\n if (rgbSearch) {\n const key = getObjectKeys(this.knownColors).find(key => {\n const rgbCurrent = parseColor(this.knownColors[key].darkModeColor);\n\n return (\n rgbCurrent &&\n rgbCurrent[0] == rgbSearch[0] &&\n rgbCurrent[1] == rgbSearch[1] &&\n rgbCurrent[2] == rgbSearch[2]\n );\n });\n\n if (key) {\n return this.knownColors[key].lightModeColor;\n }\n }\n\n return null;\n }\n\n /**\n * Transform element color, from dark to light or from light to dark\n * @param element The element to transform color\n * @param fromDarkMode Whether this is transforming color from dark mode\n * @param toDarkMode Whether this is transforming color to dark mode\n */\n transformElementColor(element: HTMLElement, fromDarkMode: boolean, toDarkMode: boolean): void {\n ColorAttributeName.forEach((names, i) => {\n const color = this.parseColorValue(\n element.style.getPropertyValue(names[ColorAttributeEnum.CssColor]) ||\n element.getAttribute(names[ColorAttributeEnum.HtmlColor]),\n !!fromDarkMode\n ).lightModeColor;\n\n element.style.setProperty(names[ColorAttributeEnum.CssColor], null);\n element.removeAttribute(names[ColorAttributeEnum.HtmlColor]);\n\n if (color && color != 'inherit') {\n setColor(element, color, i != 0, toDarkMode, false /*shouldAdaptFontColor*/, this);\n }\n });\n }\n}\n"]}
@@ -8,6 +8,7 @@ define(["require", "exports", "tslib", "../corePlugin/createStandaloneEditorCore
8
8
  * @param options Editor options
9
9
  */
10
10
  function createStandaloneEditorCore(contentDiv, options, unportedCoreApiMap, unportedCorePluginState, tempPlugins) {
11
+ var _a;
11
12
  var corePlugins = (0, createStandaloneEditorCorePlugins_1.createStandaloneEditorCorePlugins)(options, contentDiv);
12
13
  return (0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)({ contentDiv: contentDiv, api: (0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)({}, standaloneCoreApiMap_1.standaloneCoreApiMap), unportedCoreApiMap), options.coreApiOverride), originalApi: (0, tslib_1.__assign)((0, tslib_1.__assign)({}, standaloneCoreApiMap_1.standaloneCoreApiMap), unportedCoreApiMap), plugins: (0, tslib_1.__spreadArray)((0, tslib_1.__spreadArray)([
13
14
  corePlugins.cache,
@@ -18,7 +19,7 @@ define(["require", "exports", "tslib", "../corePlugin/createStandaloneEditorCore
18
19
  corePlugins.entity
19
20
  ], (0, tslib_1.__read)(tempPlugins), false), [
20
21
  corePlugins.lifecycle,
21
- ], false), environment: createEditorEnvironment(), darkColorHandler: new DarkColorHandlerImpl_1.DarkColorHandlerImpl(contentDiv, options.baseDarkColor), trustedHTMLHandler: options.trustedHTMLHandler || defaultTrustHtmlHandler }, (0, createStandaloneEditorDefaultSettings_1.createStandaloneEditorDefaultSettings)(options)), getPluginState(corePlugins)), unportedCorePluginState);
22
+ ], false), environment: createEditorEnvironment(), darkColorHandler: new DarkColorHandlerImpl_1.DarkColorHandlerImpl(contentDiv, (_a = options.getDarkColor) !== null && _a !== void 0 ? _a : getDarkColorFallback), trustedHTMLHandler: options.trustedHTMLHandler || defaultTrustHtmlHandler }, (0, createStandaloneEditorDefaultSettings_1.createStandaloneEditorDefaultSettings)(options)), getPluginState(corePlugins)), unportedCorePluginState);
22
23
  }
23
24
  exports.createStandaloneEditorCore = createStandaloneEditorCore;
24
25
  function createEditorEnvironment() {
@@ -50,5 +51,9 @@ define(["require", "exports", "tslib", "../corePlugin/createStandaloneEditorCore
50
51
  selection: corePlugins.selection.getState(),
51
52
  };
52
53
  }
54
+ // A fallback function, always return original color
55
+ function getDarkColorFallback(color) {
56
+ return color;
57
+ }
53
58
  });
54
59
  //# sourceMappingURL=createStandaloneEditorCore.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"createStandaloneEditorCore.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/editor/createStandaloneEditorCore.ts"],"names":[],"mappings":";;;;IAeA;;;;OAIG;IACH,SAAgB,0BAA0B,CACtC,UAA0B,EAC1B,OAAgC,EAChC,kBAAsC,EACtC,uBAAgD,EAChD,WAA2B;QAE3B,IAAM,WAAW,GAAG,IAAA,qEAAiC,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAE3E,2EACI,UAAU,YAAA,EACV,GAAG,wEAAO,2CAAoB,GAAK,kBAAkB,GAAK,OAAO,CAAC,eAAe,GACjF,WAAW,kDAAO,2CAAoB,GAAK,kBAAkB,GAC7D,OAAO;gBACH,WAAW,CAAC,KAAK;gBACjB,WAAW,CAAC,MAAM;gBAClB,WAAW,CAAC,SAAS;gBACrB,WAAW,CAAC,QAAQ;gBACpB,WAAW,CAAC,SAAS;gBACrB,WAAW,CAAC,MAAM;mCACf,WAAW;gBACd,WAAW,CAAC,SAAS;uBAEzB,WAAW,EAAE,uBAAuB,EAAE,EACtC,gBAAgB,EAAE,IAAI,2CAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,EAC7E,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,uBAAuB,IACtE,IAAA,6EAAqC,EAAC,OAAO,CAAC,GAC9C,cAAc,CAAC,WAAW,CAAC,GAC3B,uBAAuB,EAC5B;IACN,CAAC;IA9BD,gEA8BC;IAED,SAAS,uBAAuB;QAC5B,oHAAoH;QACpH,IAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;QAE7C,OAAO;YACH,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvD,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;YACrC,QAAQ,EACJ,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAChC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAC/B,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC;SACvC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,SAAgB,uBAAuB,CAAC,IAAY;QAChD,OAAO,IAAI,CAAC;IAChB,CAAC;IAFD,0DAEC;IAED,SAAS,cAAc,CAAC,WAAwC;QAC5D,OAAO;YACH,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC,QAAQ,EAAE;YACzC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;YAC3C,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE;YACnC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE;YACrC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;YAC3C,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE;YACrC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;SAC9C,CAAC;IACN,CAAC","sourcesContent":["import { createStandaloneEditorCorePlugins } from '../corePlugin/createStandaloneEditorCorePlugins';\nimport { createStandaloneEditorDefaultSettings } from './createStandaloneEditorDefaultSettings';\nimport { DarkColorHandlerImpl } from './DarkColorHandlerImpl';\nimport { standaloneCoreApiMap } from './standaloneCoreApiMap';\nimport type { EditorPlugin } from 'roosterjs-editor-types';\nimport type {\n EditorEnvironment,\n StandaloneEditorCore,\n StandaloneEditorCorePluginState,\n StandaloneEditorCorePlugins,\n StandaloneEditorOptions,\n UnportedCoreApiMap,\n UnportedCorePluginState,\n} from 'roosterjs-content-model-types';\n\n/**\n * A temporary function to create Standalone Editor core\n * @param contentDiv Editor content DIV\n * @param options Editor options\n */\nexport function createStandaloneEditorCore(\n contentDiv: HTMLDivElement,\n options: StandaloneEditorOptions,\n unportedCoreApiMap: UnportedCoreApiMap,\n unportedCorePluginState: UnportedCorePluginState,\n tempPlugins: EditorPlugin[]\n): StandaloneEditorCore {\n const corePlugins = createStandaloneEditorCorePlugins(options, contentDiv);\n\n return {\n contentDiv,\n api: { ...standaloneCoreApiMap, ...unportedCoreApiMap, ...options.coreApiOverride },\n originalApi: { ...standaloneCoreApiMap, ...unportedCoreApiMap },\n plugins: [\n corePlugins.cache,\n corePlugins.format,\n corePlugins.copyPaste,\n corePlugins.domEvent,\n corePlugins.selection,\n corePlugins.entity,\n ...tempPlugins,\n corePlugins.lifecycle,\n ],\n environment: createEditorEnvironment(),\n darkColorHandler: new DarkColorHandlerImpl(contentDiv, options.baseDarkColor),\n trustedHTMLHandler: options.trustedHTMLHandler || defaultTrustHtmlHandler,\n ...createStandaloneEditorDefaultSettings(options),\n ...getPluginState(corePlugins),\n ...unportedCorePluginState,\n };\n}\n\nfunction createEditorEnvironment(): EditorEnvironment {\n // It is ok to use global window here since the environment should always be the same for all windows in one session\n const userAgent = window.navigator.userAgent;\n\n return {\n isMac: window.navigator.appVersion.indexOf('Mac') != -1,\n isAndroid: /android/i.test(userAgent),\n isSafari:\n userAgent.indexOf('Safari') >= 0 &&\n userAgent.indexOf('Chrome') < 0 &&\n userAgent.indexOf('Android') < 0,\n };\n}\n\n/**\n * @internal export for test only\n */\nexport function defaultTrustHtmlHandler(html: string) {\n return html;\n}\n\nfunction getPluginState(corePlugins: StandaloneEditorCorePlugins): StandaloneEditorCorePluginState {\n return {\n domEvent: corePlugins.domEvent.getState(),\n copyPaste: corePlugins.copyPaste.getState(),\n cache: corePlugins.cache.getState(),\n format: corePlugins.format.getState(),\n lifecycle: corePlugins.lifecycle.getState(),\n entity: corePlugins.entity.getState(),\n selection: corePlugins.selection.getState(),\n };\n}\n"]}
1
+ {"version":3,"file":"createStandaloneEditorCore.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/editor/createStandaloneEditorCore.ts"],"names":[],"mappings":";;;;IAeA;;;;OAIG;IACH,SAAgB,0BAA0B,CACtC,UAA0B,EAC1B,OAAgC,EAChC,kBAAsC,EACtC,uBAAgD,EAChD,WAA2B;;QAE3B,IAAM,WAAW,GAAG,IAAA,qEAAiC,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAE3E,2EACI,UAAU,YAAA,EACV,GAAG,wEAAO,2CAAoB,GAAK,kBAAkB,GAAK,OAAO,CAAC,eAAe,GACjF,WAAW,kDAAO,2CAAoB,GAAK,kBAAkB,GAC7D,OAAO;gBACH,WAAW,CAAC,KAAK;gBACjB,WAAW,CAAC,MAAM;gBAClB,WAAW,CAAC,SAAS;gBACrB,WAAW,CAAC,QAAQ;gBACpB,WAAW,CAAC,SAAS;gBACrB,WAAW,CAAC,MAAM;mCACf,WAAW;gBACd,WAAW,CAAC,SAAS;uBAEzB,WAAW,EAAE,uBAAuB,EAAE,EACtC,gBAAgB,EAAE,IAAI,2CAAoB,CACtC,UAAU,EACV,MAAA,OAAO,CAAC,YAAY,mCAAI,oBAAoB,CAC/C,EACD,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,uBAAuB,IACtE,IAAA,6EAAqC,EAAC,OAAO,CAAC,GAC9C,cAAc,CAAC,WAAW,CAAC,GAC3B,uBAAuB,EAC5B;IACN,CAAC;IAjCD,gEAiCC;IAED,SAAS,uBAAuB;QAC5B,oHAAoH;QACpH,IAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;QAE7C,OAAO;YACH,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvD,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;YACrC,QAAQ,EACJ,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAChC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAC/B,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC;SACvC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,SAAgB,uBAAuB,CAAC,IAAY;QAChD,OAAO,IAAI,CAAC;IAChB,CAAC;IAFD,0DAEC;IAED,SAAS,cAAc,CAAC,WAAwC;QAC5D,OAAO;YACH,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC,QAAQ,EAAE;YACzC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;YAC3C,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE;YACnC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE;YACrC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;YAC3C,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE;YACrC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;SAC9C,CAAC;IACN,CAAC;IAED,oDAAoD;IACpD,SAAS,oBAAoB,CAAC,KAAa;QACvC,OAAO,KAAK,CAAC;IACjB,CAAC","sourcesContent":["import { createStandaloneEditorCorePlugins } from '../corePlugin/createStandaloneEditorCorePlugins';\nimport { createStandaloneEditorDefaultSettings } from './createStandaloneEditorDefaultSettings';\nimport { DarkColorHandlerImpl } from './DarkColorHandlerImpl';\nimport { standaloneCoreApiMap } from './standaloneCoreApiMap';\nimport type { EditorPlugin } from 'roosterjs-editor-types';\nimport type {\n EditorEnvironment,\n StandaloneEditorCore,\n StandaloneEditorCorePluginState,\n StandaloneEditorCorePlugins,\n StandaloneEditorOptions,\n UnportedCoreApiMap,\n UnportedCorePluginState,\n} from 'roosterjs-content-model-types';\n\n/**\n * A temporary function to create Standalone Editor core\n * @param contentDiv Editor content DIV\n * @param options Editor options\n */\nexport function createStandaloneEditorCore(\n contentDiv: HTMLDivElement,\n options: StandaloneEditorOptions,\n unportedCoreApiMap: UnportedCoreApiMap,\n unportedCorePluginState: UnportedCorePluginState,\n tempPlugins: EditorPlugin[]\n): StandaloneEditorCore {\n const corePlugins = createStandaloneEditorCorePlugins(options, contentDiv);\n\n return {\n contentDiv,\n api: { ...standaloneCoreApiMap, ...unportedCoreApiMap, ...options.coreApiOverride },\n originalApi: { ...standaloneCoreApiMap, ...unportedCoreApiMap },\n plugins: [\n corePlugins.cache,\n corePlugins.format,\n corePlugins.copyPaste,\n corePlugins.domEvent,\n corePlugins.selection,\n corePlugins.entity,\n ...tempPlugins,\n corePlugins.lifecycle,\n ],\n environment: createEditorEnvironment(),\n darkColorHandler: new DarkColorHandlerImpl(\n contentDiv,\n options.getDarkColor ?? getDarkColorFallback\n ),\n trustedHTMLHandler: options.trustedHTMLHandler || defaultTrustHtmlHandler,\n ...createStandaloneEditorDefaultSettings(options),\n ...getPluginState(corePlugins),\n ...unportedCorePluginState,\n };\n}\n\nfunction createEditorEnvironment(): EditorEnvironment {\n // It is ok to use global window here since the environment should always be the same for all windows in one session\n const userAgent = window.navigator.userAgent;\n\n return {\n isMac: window.navigator.appVersion.indexOf('Mac') != -1,\n isAndroid: /android/i.test(userAgent),\n isSafari:\n userAgent.indexOf('Safari') >= 0 &&\n userAgent.indexOf('Chrome') < 0 &&\n userAgent.indexOf('Android') < 0,\n };\n}\n\n/**\n * @internal export for test only\n */\nexport function defaultTrustHtmlHandler(html: string) {\n return html;\n}\n\nfunction getPluginState(corePlugins: StandaloneEditorCorePlugins): StandaloneEditorCorePluginState {\n return {\n domEvent: corePlugins.domEvent.getState(),\n copyPaste: corePlugins.copyPaste.getState(),\n cache: corePlugins.cache.getState(),\n format: corePlugins.format.getState(),\n lifecycle: corePlugins.lifecycle.getState(),\n entity: corePlugins.entity.getState(),\n selection: corePlugins.selection.getState(),\n };\n}\n\n// A fallback function, always return original color\nfunction getDarkColorFallback(color: string) {\n return color;\n}\n"]}
@@ -99,6 +99,9 @@ var EntityPlugin = /** @class */ (function () {
99
99
  if (operation == 'newEntity') {
100
100
  entity.entityFormat.id = _this.ensureUniqueId(entityType, id !== null && id !== void 0 ? id : '', wrapper);
101
101
  wrapper.className = generateEntityClassNames(entity.entityFormat);
102
+ if (entity.entityFormat.isReadonly) {
103
+ wrapper.contentEditable = 'false';
104
+ }
102
105
  var eventResult = _this.triggerEvent(editor, wrapper, operation, rawEvent);
103
106
  _this.state.entityMap[entity.entityFormat.id] = {
104
107
  element: wrapper,
@@ -1 +1 @@
1
- {"version":3,"file":"EntityPlugin.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/corePlugin/EntityPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { findAllEntities } from './utils/findAllEntities';\nimport {\n createEntity,\n generateEntityClassNames,\n getAllEntityWrappers,\n getObjectKeys,\n isEntityElement,\n parseEntityClassName,\n} from 'roosterjs-content-model-dom';\nimport {\n ColorTransformDirection,\n EntityOperation as LegacyEntityOperation,\n PluginEventType,\n} from 'roosterjs-editor-types';\nimport type {\n ChangedEntity,\n ContentModelContentChangedEvent,\n ContentModelEntityFormat,\n EntityOperation,\n EntityPluginState,\n IStandaloneEditor,\n} from 'roosterjs-content-model-types';\nimport type {\n ContentChangedEvent,\n IEditor,\n PluginEvent,\n PluginMouseUpEvent,\n PluginWithState,\n} from 'roosterjs-editor-types';\n\nconst ENTITY_ID_REGEX = /_(\\d{1,8})$/;\n\n// This is only used for compatibility with old editor\n// TODO: Remove this map once we have standalone editor\nconst EntityOperationMap: Record<EntityOperation, LegacyEntityOperation> = {\n newEntity: LegacyEntityOperation.NewEntity,\n overwrite: LegacyEntityOperation.Overwrite,\n removeFromEnd: LegacyEntityOperation.RemoveFromEnd,\n removeFromStart: LegacyEntityOperation.RemoveFromStart,\n replaceTemporaryContent: LegacyEntityOperation.ReplaceTemporaryContent,\n updateEntityState: LegacyEntityOperation.UpdateEntityState,\n click: LegacyEntityOperation.Click,\n};\n\n/**\n * Entity Plugin helps handle all operations related to an entity and generate entity specified events\n */\nclass EntityPlugin implements PluginWithState<EntityPluginState> {\n private editor: (IEditor & IStandaloneEditor) | null = null;\n private state: EntityPluginState;\n\n /**\n * Construct a new instance of EntityPlugin\n */\n constructor() {\n this.state = {\n entityMap: {},\n };\n }\n\n /**\n * Get a friendly name of this plugin\n */\n getName() {\n return 'Entity';\n }\n\n /**\n * Initialize this plugin. This should only be called from Editor\n * @param editor Editor instance\n */\n initialize(editor: IEditor) {\n this.editor = editor as IStandaloneEditor & IEditor;\n }\n\n /**\n * Dispose this plugin\n */\n dispose() {\n this.editor = null;\n this.state.entityMap = {};\n }\n\n /**\n * Get plugin state object\n */\n getState() {\n return this.state;\n }\n\n /**\n * Handle events triggered from editor\n * @param event PluginEvent object\n */\n onPluginEvent(event: PluginEvent) {\n if (this.editor) {\n switch (event.eventType) {\n case PluginEventType.MouseUp:\n this.handleMouseUpEvent(this.editor, event);\n break;\n case PluginEventType.ContentChanged:\n this.handleContentChangedEvent(this.editor, event);\n break;\n\n case PluginEventType.EditorReady:\n this.handleContentChangedEvent(this.editor);\n break;\n case PluginEventType.ExtractContentWithDom:\n this.handleExtractContentWithDomEvent(this.editor, event.clonedRoot);\n break;\n }\n }\n }\n\n private handleMouseUpEvent(editor: IEditor & IStandaloneEditor, event: PluginMouseUpEvent) {\n const { rawEvent, isClicking } = event;\n let node: Node | null = rawEvent.target as Node;\n\n if (isClicking && this.editor) {\n while (node && this.editor.contains(node)) {\n if (isEntityElement(node)) {\n this.triggerEvent(editor, node as HTMLElement, 'click', rawEvent);\n break;\n } else {\n node = node.parentNode;\n }\n }\n }\n }\n\n private handleContentChangedEvent(\n editor: IStandaloneEditor & IEditor,\n event?: ContentChangedEvent\n ) {\n const modifiedEntities: ChangedEntity[] =\n (event as ContentModelContentChangedEvent)?.changedEntities ??\n this.getChangedEntities(editor);\n\n modifiedEntities.forEach(entry => {\n const { entity, operation, rawEvent } = entry;\n const {\n entityFormat: { id, entityType, isFakeEntity },\n wrapper,\n } = entity;\n\n if (entityType && !isFakeEntity) {\n if (operation == 'newEntity') {\n entity.entityFormat.id = this.ensureUniqueId(entityType, id ?? '', wrapper);\n wrapper.className = generateEntityClassNames(entity.entityFormat);\n\n const eventResult = this.triggerEvent(editor, wrapper, operation, rawEvent);\n\n this.state.entityMap[entity.entityFormat.id] = {\n element: wrapper,\n canPersist: eventResult?.shouldPersist,\n };\n\n if (editor.isDarkMode()) {\n editor.transformToDarkColor(wrapper, ColorTransformDirection.LightToDark);\n }\n } else if (id) {\n const mapEntry = this.state.entityMap[id];\n\n if (mapEntry) {\n mapEntry.isDeleted = true;\n }\n\n this.triggerEvent(editor, wrapper, operation, rawEvent);\n }\n }\n });\n }\n\n private getChangedEntities(editor: IStandaloneEditor): ChangedEntity[] {\n const result: ChangedEntity[] = [];\n\n findAllEntities(editor.createContentModel(), result);\n\n getObjectKeys(this.state.entityMap).forEach(id => {\n const entry = this.state.entityMap[id];\n\n if (!entry.isDeleted) {\n const index = result.findIndex(\n x =>\n x.operation == 'newEntity' &&\n x.entity.entityFormat.id == id &&\n x.entity.wrapper == entry.element\n );\n\n if (index >= 0) {\n // Found matched entity in editor, so there is no change to this entity,\n // we can safely remove it from the new entity array\n result.splice(index, 1);\n } else {\n // Entity is not in editor, which means it is deleted, use a temporary entity here to represent this entity\n const tempEntity = createEntity(entry.element);\n let isEntity = false;\n\n entry.element.classList.forEach(name => {\n isEntity = parseEntityClassName(name, tempEntity.entityFormat) || isEntity;\n });\n\n if (isEntity) {\n result.push({\n entity: tempEntity,\n operation: 'overwrite',\n });\n }\n }\n }\n });\n\n return result;\n }\n\n private handleExtractContentWithDomEvent(\n editor: IEditor & IStandaloneEditor,\n root: HTMLElement\n ) {\n getAllEntityWrappers(root).forEach(element => {\n element.removeAttribute('contentEditable');\n\n this.triggerEvent(editor, element, 'replaceTemporaryContent');\n });\n }\n\n private triggerEvent(\n editor: IEditor & IStandaloneEditor,\n wrapper: HTMLElement,\n operation: EntityOperation,\n rawEvent?: Event\n ) {\n const format: ContentModelEntityFormat = {};\n wrapper.classList.forEach(name => {\n parseEntityClassName(name, format);\n });\n\n return format.id && format.entityType && !format.isFakeEntity\n ? editor.triggerPluginEvent(PluginEventType.EntityOperation, {\n operation: EntityOperationMap[operation],\n rawEvent,\n entity: {\n id: format.id,\n type: format.entityType,\n isReadonly: !!format.isReadonly,\n wrapper,\n },\n })\n : null;\n }\n\n private ensureUniqueId(type: string, id: string, wrapper: HTMLElement): string {\n const match = ENTITY_ID_REGEX.exec(id);\n const baseId = (match ? id.substr(0, id.length - match[0].length) : id) || type;\n\n // Make sure entity id is unique\n let newId = '';\n\n for (let num = (match && parseInt(match[1])) || 0; ; num++) {\n newId = num > 0 ? `${baseId}_${num}` : baseId;\n\n const item = this.state.entityMap[newId];\n\n if (!item || item.element == wrapper) {\n break;\n }\n }\n\n return newId;\n }\n}\n\n/**\n * @internal\n * Create a new instance of EntityPlugin.\n */\nexport function createEntityPlugin(): PluginWithState<EntityPluginState> {\n return new EntityPlugin();\n}\n"]}
1
+ {"version":3,"file":"EntityPlugin.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/corePlugin/EntityPlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import { findAllEntities } from './utils/findAllEntities';\nimport {\n createEntity,\n generateEntityClassNames,\n getAllEntityWrappers,\n getObjectKeys,\n isEntityElement,\n parseEntityClassName,\n} from 'roosterjs-content-model-dom';\nimport {\n ColorTransformDirection,\n EntityOperation as LegacyEntityOperation,\n PluginEventType,\n} from 'roosterjs-editor-types';\nimport type {\n ChangedEntity,\n ContentModelContentChangedEvent,\n ContentModelEntityFormat,\n EntityOperation,\n EntityPluginState,\n IStandaloneEditor,\n} from 'roosterjs-content-model-types';\nimport type {\n ContentChangedEvent,\n IEditor,\n PluginEvent,\n PluginMouseUpEvent,\n PluginWithState,\n} from 'roosterjs-editor-types';\n\nconst ENTITY_ID_REGEX = /_(\\d{1,8})$/;\n\n// This is only used for compatibility with old editor\n// TODO: Remove this map once we have standalone editor\nconst EntityOperationMap: Record<EntityOperation, LegacyEntityOperation> = {\n newEntity: LegacyEntityOperation.NewEntity,\n overwrite: LegacyEntityOperation.Overwrite,\n removeFromEnd: LegacyEntityOperation.RemoveFromEnd,\n removeFromStart: LegacyEntityOperation.RemoveFromStart,\n replaceTemporaryContent: LegacyEntityOperation.ReplaceTemporaryContent,\n updateEntityState: LegacyEntityOperation.UpdateEntityState,\n click: LegacyEntityOperation.Click,\n};\n\n/**\n * Entity Plugin helps handle all operations related to an entity and generate entity specified events\n */\nclass EntityPlugin implements PluginWithState<EntityPluginState> {\n private editor: (IEditor & IStandaloneEditor) | null = null;\n private state: EntityPluginState;\n\n /**\n * Construct a new instance of EntityPlugin\n */\n constructor() {\n this.state = {\n entityMap: {},\n };\n }\n\n /**\n * Get a friendly name of this plugin\n */\n getName() {\n return 'Entity';\n }\n\n /**\n * Initialize this plugin. This should only be called from Editor\n * @param editor Editor instance\n */\n initialize(editor: IEditor) {\n this.editor = editor as IStandaloneEditor & IEditor;\n }\n\n /**\n * Dispose this plugin\n */\n dispose() {\n this.editor = null;\n this.state.entityMap = {};\n }\n\n /**\n * Get plugin state object\n */\n getState() {\n return this.state;\n }\n\n /**\n * Handle events triggered from editor\n * @param event PluginEvent object\n */\n onPluginEvent(event: PluginEvent) {\n if (this.editor) {\n switch (event.eventType) {\n case PluginEventType.MouseUp:\n this.handleMouseUpEvent(this.editor, event);\n break;\n case PluginEventType.ContentChanged:\n this.handleContentChangedEvent(this.editor, event);\n break;\n\n case PluginEventType.EditorReady:\n this.handleContentChangedEvent(this.editor);\n break;\n case PluginEventType.ExtractContentWithDom:\n this.handleExtractContentWithDomEvent(this.editor, event.clonedRoot);\n break;\n }\n }\n }\n\n private handleMouseUpEvent(editor: IEditor & IStandaloneEditor, event: PluginMouseUpEvent) {\n const { rawEvent, isClicking } = event;\n let node: Node | null = rawEvent.target as Node;\n\n if (isClicking && this.editor) {\n while (node && this.editor.contains(node)) {\n if (isEntityElement(node)) {\n this.triggerEvent(editor, node as HTMLElement, 'click', rawEvent);\n break;\n } else {\n node = node.parentNode;\n }\n }\n }\n }\n\n private handleContentChangedEvent(\n editor: IStandaloneEditor & IEditor,\n event?: ContentChangedEvent\n ) {\n const modifiedEntities: ChangedEntity[] =\n (event as ContentModelContentChangedEvent)?.changedEntities ??\n this.getChangedEntities(editor);\n\n modifiedEntities.forEach(entry => {\n const { entity, operation, rawEvent } = entry;\n const {\n entityFormat: { id, entityType, isFakeEntity },\n wrapper,\n } = entity;\n\n if (entityType && !isFakeEntity) {\n if (operation == 'newEntity') {\n entity.entityFormat.id = this.ensureUniqueId(entityType, id ?? '', wrapper);\n wrapper.className = generateEntityClassNames(entity.entityFormat);\n\n if (entity.entityFormat.isReadonly) {\n wrapper.contentEditable = 'false';\n }\n\n const eventResult = this.triggerEvent(editor, wrapper, operation, rawEvent);\n\n this.state.entityMap[entity.entityFormat.id] = {\n element: wrapper,\n canPersist: eventResult?.shouldPersist,\n };\n\n if (editor.isDarkMode()) {\n editor.transformToDarkColor(wrapper, ColorTransformDirection.LightToDark);\n }\n } else if (id) {\n const mapEntry = this.state.entityMap[id];\n\n if (mapEntry) {\n mapEntry.isDeleted = true;\n }\n\n this.triggerEvent(editor, wrapper, operation, rawEvent);\n }\n }\n });\n }\n\n private getChangedEntities(editor: IStandaloneEditor): ChangedEntity[] {\n const result: ChangedEntity[] = [];\n\n findAllEntities(editor.createContentModel(), result);\n\n getObjectKeys(this.state.entityMap).forEach(id => {\n const entry = this.state.entityMap[id];\n\n if (!entry.isDeleted) {\n const index = result.findIndex(\n x =>\n x.operation == 'newEntity' &&\n x.entity.entityFormat.id == id &&\n x.entity.wrapper == entry.element\n );\n\n if (index >= 0) {\n // Found matched entity in editor, so there is no change to this entity,\n // we can safely remove it from the new entity array\n result.splice(index, 1);\n } else {\n // Entity is not in editor, which means it is deleted, use a temporary entity here to represent this entity\n const tempEntity = createEntity(entry.element);\n let isEntity = false;\n\n entry.element.classList.forEach(name => {\n isEntity = parseEntityClassName(name, tempEntity.entityFormat) || isEntity;\n });\n\n if (isEntity) {\n result.push({\n entity: tempEntity,\n operation: 'overwrite',\n });\n }\n }\n }\n });\n\n return result;\n }\n\n private handleExtractContentWithDomEvent(\n editor: IEditor & IStandaloneEditor,\n root: HTMLElement\n ) {\n getAllEntityWrappers(root).forEach(element => {\n element.removeAttribute('contentEditable');\n\n this.triggerEvent(editor, element, 'replaceTemporaryContent');\n });\n }\n\n private triggerEvent(\n editor: IEditor & IStandaloneEditor,\n wrapper: HTMLElement,\n operation: EntityOperation,\n rawEvent?: Event\n ) {\n const format: ContentModelEntityFormat = {};\n wrapper.classList.forEach(name => {\n parseEntityClassName(name, format);\n });\n\n return format.id && format.entityType && !format.isFakeEntity\n ? editor.triggerPluginEvent(PluginEventType.EntityOperation, {\n operation: EntityOperationMap[operation],\n rawEvent,\n entity: {\n id: format.id,\n type: format.entityType,\n isReadonly: !!format.isReadonly,\n wrapper,\n },\n })\n : null;\n }\n\n private ensureUniqueId(type: string, id: string, wrapper: HTMLElement): string {\n const match = ENTITY_ID_REGEX.exec(id);\n const baseId = (match ? id.substr(0, id.length - match[0].length) : id) || type;\n\n // Make sure entity id is unique\n let newId = '';\n\n for (let num = (match && parseInt(match[1])) || 0; ; num++) {\n newId = num > 0 ? `${baseId}_${num}` : baseId;\n\n const item = this.state.entityMap[newId];\n\n if (!item || item.element == wrapper) {\n break;\n }\n }\n\n return newId;\n }\n}\n\n/**\n * @internal\n * Create a new instance of EntityPlugin.\n */\nexport function createEntityPlugin(): PluginWithState<EntityPluginState> {\n return new EntityPlugin();\n}\n"]}
@@ -4,9 +4,9 @@ import type { ColorKeyAndValue, DarkColorHandler, ModeIndependentColor } from 'r
4
4
  */
5
5
  export declare class DarkColorHandlerImpl implements DarkColorHandler {
6
6
  private contentDiv;
7
+ private getDarkColor;
7
8
  private knownColors;
8
- readonly baseLightness: number;
9
- constructor(contentDiv: HTMLElement, baseDarkColor?: string);
9
+ constructor(contentDiv: HTMLElement, getDarkColor: (color: string) => string);
10
10
  /**
11
11
  * Get a copy of known colors
12
12
  * @returns
@@ -1,7 +1,5 @@
1
1
  var _a, _b;
2
- import * as Color from 'color';
3
2
  import { getObjectKeys, parseColor, setColor } from 'roosterjs-editor-dom';
4
- var DefaultLightness = 21.25; // Lightness for #333333
5
3
  var VARIABLE_REGEX = /^\s*var\(\s*(\-\-[a-zA-Z0-9\-_]+)\s*(?:,\s*(.*))?\)\s*$/;
6
4
  var VARIABLE_PREFIX = 'var(';
7
5
  var COLOR_VAR_PREFIX = 'darkColor';
@@ -24,10 +22,10 @@ var ColorAttributeName = [
24
22
  * @internal
25
23
  */
26
24
  var DarkColorHandlerImpl = /** @class */ (function () {
27
- function DarkColorHandlerImpl(contentDiv, baseDarkColor) {
25
+ function DarkColorHandlerImpl(contentDiv, getDarkColor) {
28
26
  this.contentDiv = contentDiv;
27
+ this.getDarkColor = getDarkColor;
29
28
  this.knownColors = {};
30
- this.baseLightness = getLightness(baseDarkColor);
31
29
  }
32
30
  /**
33
31
  * Get a copy of known colors
@@ -55,7 +53,7 @@ var DarkColorHandlerImpl = /** @class */ (function () {
55
53
  colorKey =
56
54
  colorKey || "--" + COLOR_VAR_PREFIX + "_" + lightModeColor.replace(/[^\d\w]/g, '_');
57
55
  if (!this.knownColors[colorKey]) {
58
- darkModeColor = darkModeColor || getDarkColor(lightModeColor, this.baseLightness);
56
+ darkModeColor = darkModeColor || this.getDarkColor(lightModeColor);
59
57
  this.knownColors[colorKey] = { lightModeColor: lightModeColor, darkModeColor: darkModeColor };
60
58
  this.contentDiv.style.setProperty(colorKey, darkModeColor);
61
59
  }
@@ -154,28 +152,4 @@ var DarkColorHandlerImpl = /** @class */ (function () {
154
152
  return DarkColorHandlerImpl;
155
153
  }());
156
154
  export { DarkColorHandlerImpl };
157
- function getDarkColor(color, baseLightness) {
158
- try {
159
- var computedColor = Color(color || undefined);
160
- var colorLab = computedColor.lab().array();
161
- var newLValue = (100 - colorLab[0]) * ((100 - baseLightness) / 100) + baseLightness;
162
- color = Color.lab(newLValue, colorLab[1], colorLab[2])
163
- .rgb()
164
- .alpha(computedColor.alpha())
165
- .toString();
166
- }
167
- catch (_a) { }
168
- return color;
169
- }
170
- function getLightness(color) {
171
- var result = DefaultLightness;
172
- if (color) {
173
- try {
174
- var computedColor = Color(color || undefined);
175
- result = computedColor.lab().array()[0];
176
- }
177
- catch (_a) { }
178
- }
179
- return result;
180
- }
181
155
  //# sourceMappingURL=DarkColorHandlerImpl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DarkColorHandlerImpl.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/editor/DarkColorHandlerImpl.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Color from 'color';\nimport { getObjectKeys, parseColor, setColor } from 'roosterjs-editor-dom';\nimport type {\n ColorKeyAndValue,\n DarkColorHandler,\n ModeIndependentColor,\n} from 'roosterjs-editor-types';\n\nconst DefaultLightness = 21.25; // Lightness for #333333\nconst VARIABLE_REGEX = /^\\s*var\\(\\s*(\\-\\-[a-zA-Z0-9\\-_]+)\\s*(?:,\\s*(.*))?\\)\\s*$/;\nconst VARIABLE_PREFIX = 'var(';\nconst COLOR_VAR_PREFIX = 'darkColor';\nconst enum ColorAttributeEnum {\n CssColor = 0,\n HtmlColor = 1,\n}\nconst ColorAttributeName: { [key in ColorAttributeEnum]: string }[] = [\n {\n [ColorAttributeEnum.CssColor]: 'color',\n [ColorAttributeEnum.HtmlColor]: 'color',\n },\n {\n [ColorAttributeEnum.CssColor]: 'background-color',\n [ColorAttributeEnum.HtmlColor]: 'bgcolor',\n },\n];\n\n/**\n * @internal\n */\nexport class DarkColorHandlerImpl implements DarkColorHandler {\n private knownColors: Record<string, Readonly<ModeIndependentColor>> = {};\n readonly baseLightness: number;\n\n constructor(private contentDiv: HTMLElement, baseDarkColor?: string) {\n this.baseLightness = getLightness(baseDarkColor);\n }\n\n /**\n * Get a copy of known colors\n * @returns\n */\n getKnownColorsCopy() {\n return Object.values(this.knownColors);\n }\n\n /**\n * Given a light mode color value and an optional dark mode color value, register this color\n * so that editor can handle it, then return the CSS color value for current color mode.\n * @param lightModeColor Light mode color value\n * @param isDarkMode Whether current color mode is dark mode\n * @param darkModeColor Optional dark mode color value. If not passed, we will calculate one.\n */\n registerColor(lightModeColor: string, isDarkMode: boolean, darkModeColor?: string): string {\n const parsedColor = this.parseColorValue(lightModeColor);\n let colorKey: string | undefined;\n\n if (parsedColor) {\n lightModeColor = parsedColor.lightModeColor;\n darkModeColor = parsedColor.darkModeColor || darkModeColor;\n colorKey = parsedColor.key;\n }\n\n if (isDarkMode && lightModeColor) {\n colorKey =\n colorKey || `--${COLOR_VAR_PREFIX}_${lightModeColor.replace(/[^\\d\\w]/g, '_')}`;\n\n if (!this.knownColors[colorKey]) {\n darkModeColor = darkModeColor || getDarkColor(lightModeColor, this.baseLightness);\n\n this.knownColors[colorKey] = { lightModeColor, darkModeColor };\n this.contentDiv.style.setProperty(colorKey, darkModeColor);\n }\n\n return `var(${colorKey}, ${lightModeColor})`;\n } else {\n return lightModeColor;\n }\n }\n\n /**\n * Reset known color record, clean up registered color variables.\n */\n reset(): void {\n getObjectKeys(this.knownColors).forEach(key => this.contentDiv.style.removeProperty(key));\n this.knownColors = {};\n }\n\n /**\n * Parse an existing color value, if it is in variable-based color format, extract color key,\n * light color and query related dark color if any\n * @param color The color string to parse\n * @param isInDarkMode Whether current content is in dark mode. When set to true, if the color value is not in dark var format,\n * we will treat is as a dark mode color and try to find a matched dark mode color.\n */\n parseColorValue(color: string | undefined | null, isInDarkMode?: boolean): ColorKeyAndValue {\n let key: string | undefined;\n let lightModeColor = '';\n let darkModeColor: string | undefined;\n\n if (color) {\n const match = color.startsWith(VARIABLE_PREFIX) ? VARIABLE_REGEX.exec(color) : null;\n\n if (match) {\n if (match[2]) {\n key = match[1];\n lightModeColor = match[2];\n darkModeColor = this.knownColors[key]?.darkModeColor;\n } else {\n lightModeColor = '';\n }\n } else if (isInDarkMode) {\n // If editor is in dark mode but the color is not in dark color format, it is possible the color was inserted from external code\n // without any light color info. So we first try to see if there is a known dark color can match this color, and use its related\n // light color as light mode color. Otherwise we need to drop this color to avoid show \"white on white\" content.\n lightModeColor = this.findLightColorFromDarkColor(color) || '';\n\n if (lightModeColor) {\n darkModeColor = color;\n }\n } else {\n lightModeColor = color;\n }\n }\n\n return { key, lightModeColor, darkModeColor };\n }\n\n /**\n * Find related light mode color from dark mode color.\n * @param darkColor The existing dark color\n */\n findLightColorFromDarkColor(darkColor: string): string | null {\n const rgbSearch = parseColor(darkColor);\n\n if (rgbSearch) {\n const key = getObjectKeys(this.knownColors).find(key => {\n const rgbCurrent = parseColor(this.knownColors[key].darkModeColor);\n\n return (\n rgbCurrent &&\n rgbCurrent[0] == rgbSearch[0] &&\n rgbCurrent[1] == rgbSearch[1] &&\n rgbCurrent[2] == rgbSearch[2]\n );\n });\n\n if (key) {\n return this.knownColors[key].lightModeColor;\n }\n }\n\n return null;\n }\n\n /**\n * Transform element color, from dark to light or from light to dark\n * @param element The element to transform color\n * @param fromDarkMode Whether this is transforming color from dark mode\n * @param toDarkMode Whether this is transforming color to dark mode\n */\n transformElementColor(element: HTMLElement, fromDarkMode: boolean, toDarkMode: boolean): void {\n ColorAttributeName.forEach((names, i) => {\n const color = this.parseColorValue(\n element.style.getPropertyValue(names[ColorAttributeEnum.CssColor]) ||\n element.getAttribute(names[ColorAttributeEnum.HtmlColor]),\n !!fromDarkMode\n ).lightModeColor;\n\n element.style.setProperty(names[ColorAttributeEnum.CssColor], null);\n element.removeAttribute(names[ColorAttributeEnum.HtmlColor]);\n\n if (color && color != 'inherit') {\n setColor(element, color, i != 0, toDarkMode, false /*shouldAdaptFontColor*/, this);\n }\n });\n }\n}\n\nfunction getDarkColor(color: string, baseLightness: number): string {\n try {\n const computedColor = Color(color || undefined);\n const colorLab = computedColor.lab().array();\n const newLValue = (100 - colorLab[0]) * ((100 - baseLightness) / 100) + baseLightness;\n color = Color.lab(newLValue, colorLab[1], colorLab[2])\n .rgb()\n .alpha(computedColor.alpha())\n .toString();\n } catch {}\n\n return color;\n}\n\nfunction getLightness(color?: string): number {\n let result = DefaultLightness;\n\n if (color) {\n try {\n const computedColor = Color(color || undefined);\n result = computedColor.lab().array()[0];\n } catch {}\n }\n\n return result;\n}\n"]}
1
+ {"version":3,"file":"DarkColorHandlerImpl.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/editor/DarkColorHandlerImpl.ts"],"names":[],"mappings":"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","sourcesContent":["import { getObjectKeys, parseColor, setColor } from 'roosterjs-editor-dom';\nimport type {\n ColorKeyAndValue,\n DarkColorHandler,\n ModeIndependentColor,\n} from 'roosterjs-editor-types';\n\nconst VARIABLE_REGEX = /^\\s*var\\(\\s*(\\-\\-[a-zA-Z0-9\\-_]+)\\s*(?:,\\s*(.*))?\\)\\s*$/;\nconst VARIABLE_PREFIX = 'var(';\nconst COLOR_VAR_PREFIX = 'darkColor';\nconst enum ColorAttributeEnum {\n CssColor = 0,\n HtmlColor = 1,\n}\nconst ColorAttributeName: { [key in ColorAttributeEnum]: string }[] = [\n {\n [ColorAttributeEnum.CssColor]: 'color',\n [ColorAttributeEnum.HtmlColor]: 'color',\n },\n {\n [ColorAttributeEnum.CssColor]: 'background-color',\n [ColorAttributeEnum.HtmlColor]: 'bgcolor',\n },\n];\n\n/**\n * @internal\n */\nexport class DarkColorHandlerImpl implements DarkColorHandler {\n private knownColors: Record<string, Readonly<ModeIndependentColor>> = {};\n\n constructor(private contentDiv: HTMLElement, private getDarkColor: (color: string) => string) {}\n\n /**\n * Get a copy of known colors\n * @returns\n */\n getKnownColorsCopy() {\n return Object.values(this.knownColors);\n }\n\n /**\n * Given a light mode color value and an optional dark mode color value, register this color\n * so that editor can handle it, then return the CSS color value for current color mode.\n * @param lightModeColor Light mode color value\n * @param isDarkMode Whether current color mode is dark mode\n * @param darkModeColor Optional dark mode color value. If not passed, we will calculate one.\n */\n registerColor(lightModeColor: string, isDarkMode: boolean, darkModeColor?: string): string {\n const parsedColor = this.parseColorValue(lightModeColor);\n let colorKey: string | undefined;\n\n if (parsedColor) {\n lightModeColor = parsedColor.lightModeColor;\n darkModeColor = parsedColor.darkModeColor || darkModeColor;\n colorKey = parsedColor.key;\n }\n\n if (isDarkMode && lightModeColor) {\n colorKey =\n colorKey || `--${COLOR_VAR_PREFIX}_${lightModeColor.replace(/[^\\d\\w]/g, '_')}`;\n\n if (!this.knownColors[colorKey]) {\n darkModeColor = darkModeColor || this.getDarkColor(lightModeColor);\n\n this.knownColors[colorKey] = { lightModeColor, darkModeColor };\n this.contentDiv.style.setProperty(colorKey, darkModeColor);\n }\n\n return `var(${colorKey}, ${lightModeColor})`;\n } else {\n return lightModeColor;\n }\n }\n\n /**\n * Reset known color record, clean up registered color variables.\n */\n reset(): void {\n getObjectKeys(this.knownColors).forEach(key => this.contentDiv.style.removeProperty(key));\n this.knownColors = {};\n }\n\n /**\n * Parse an existing color value, if it is in variable-based color format, extract color key,\n * light color and query related dark color if any\n * @param color The color string to parse\n * @param isInDarkMode Whether current content is in dark mode. When set to true, if the color value is not in dark var format,\n * we will treat is as a dark mode color and try to find a matched dark mode color.\n */\n parseColorValue(color: string | undefined | null, isInDarkMode?: boolean): ColorKeyAndValue {\n let key: string | undefined;\n let lightModeColor = '';\n let darkModeColor: string | undefined;\n\n if (color) {\n const match = color.startsWith(VARIABLE_PREFIX) ? VARIABLE_REGEX.exec(color) : null;\n\n if (match) {\n if (match[2]) {\n key = match[1];\n lightModeColor = match[2];\n darkModeColor = this.knownColors[key]?.darkModeColor;\n } else {\n lightModeColor = '';\n }\n } else if (isInDarkMode) {\n // If editor is in dark mode but the color is not in dark color format, it is possible the color was inserted from external code\n // without any light color info. So we first try to see if there is a known dark color can match this color, and use its related\n // light color as light mode color. Otherwise we need to drop this color to avoid show \"white on white\" content.\n lightModeColor = this.findLightColorFromDarkColor(color) || '';\n\n if (lightModeColor) {\n darkModeColor = color;\n }\n } else {\n lightModeColor = color;\n }\n }\n\n return { key, lightModeColor, darkModeColor };\n }\n\n /**\n * Find related light mode color from dark mode color.\n * @param darkColor The existing dark color\n */\n findLightColorFromDarkColor(darkColor: string): string | null {\n const rgbSearch = parseColor(darkColor);\n\n if (rgbSearch) {\n const key = getObjectKeys(this.knownColors).find(key => {\n const rgbCurrent = parseColor(this.knownColors[key].darkModeColor);\n\n return (\n rgbCurrent &&\n rgbCurrent[0] == rgbSearch[0] &&\n rgbCurrent[1] == rgbSearch[1] &&\n rgbCurrent[2] == rgbSearch[2]\n );\n });\n\n if (key) {\n return this.knownColors[key].lightModeColor;\n }\n }\n\n return null;\n }\n\n /**\n * Transform element color, from dark to light or from light to dark\n * @param element The element to transform color\n * @param fromDarkMode Whether this is transforming color from dark mode\n * @param toDarkMode Whether this is transforming color to dark mode\n */\n transformElementColor(element: HTMLElement, fromDarkMode: boolean, toDarkMode: boolean): void {\n ColorAttributeName.forEach((names, i) => {\n const color = this.parseColorValue(\n element.style.getPropertyValue(names[ColorAttributeEnum.CssColor]) ||\n element.getAttribute(names[ColorAttributeEnum.HtmlColor]),\n !!fromDarkMode\n ).lightModeColor;\n\n element.style.setProperty(names[ColorAttributeEnum.CssColor], null);\n element.removeAttribute(names[ColorAttributeEnum.HtmlColor]);\n\n if (color && color != 'inherit') {\n setColor(element, color, i != 0, toDarkMode, false /*shouldAdaptFontColor*/, this);\n }\n });\n }\n}\n"]}
@@ -9,6 +9,7 @@ import { standaloneCoreApiMap } from './standaloneCoreApiMap';
9
9
  * @param options Editor options
10
10
  */
11
11
  export function createStandaloneEditorCore(contentDiv, options, unportedCoreApiMap, unportedCorePluginState, tempPlugins) {
12
+ var _a;
12
13
  var corePlugins = createStandaloneEditorCorePlugins(options, contentDiv);
13
14
  return __assign(__assign(__assign({ contentDiv: contentDiv, api: __assign(__assign(__assign({}, standaloneCoreApiMap), unportedCoreApiMap), options.coreApiOverride), originalApi: __assign(__assign({}, standaloneCoreApiMap), unportedCoreApiMap), plugins: __spreadArray(__spreadArray([
14
15
  corePlugins.cache,
@@ -19,7 +20,7 @@ export function createStandaloneEditorCore(contentDiv, options, unportedCoreApiM
19
20
  corePlugins.entity
20
21
  ], __read(tempPlugins), false), [
21
22
  corePlugins.lifecycle,
22
- ], false), environment: createEditorEnvironment(), darkColorHandler: new DarkColorHandlerImpl(contentDiv, options.baseDarkColor), trustedHTMLHandler: options.trustedHTMLHandler || defaultTrustHtmlHandler }, createStandaloneEditorDefaultSettings(options)), getPluginState(corePlugins)), unportedCorePluginState);
23
+ ], false), environment: createEditorEnvironment(), darkColorHandler: new DarkColorHandlerImpl(contentDiv, (_a = options.getDarkColor) !== null && _a !== void 0 ? _a : getDarkColorFallback), trustedHTMLHandler: options.trustedHTMLHandler || defaultTrustHtmlHandler }, createStandaloneEditorDefaultSettings(options)), getPluginState(corePlugins)), unportedCorePluginState);
23
24
  }
24
25
  function createEditorEnvironment() {
25
26
  // It is ok to use global window here since the environment should always be the same for all windows in one session
@@ -49,4 +50,8 @@ function getPluginState(corePlugins) {
49
50
  selection: corePlugins.selection.getState(),
50
51
  };
51
52
  }
53
+ // A fallback function, always return original color
54
+ function getDarkColorFallback(color) {
55
+ return color;
56
+ }
52
57
  //# sourceMappingURL=createStandaloneEditorCore.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"createStandaloneEditorCore.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/editor/createStandaloneEditorCore.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,iCAAiC,EAAE,MAAM,iDAAiD,CAAC;AACpG,OAAO,EAAE,qCAAqC,EAAE,MAAM,yCAAyC,CAAC;AAChG,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAY9D;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CACtC,UAA0B,EAC1B,OAAgC,EAChC,kBAAsC,EACtC,uBAAgD,EAChD,WAA2B;IAE3B,IAAM,WAAW,GAAG,iCAAiC,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAE3E,oCACI,UAAU,YAAA,EACV,GAAG,iCAAO,oBAAoB,GAAK,kBAAkB,GAAK,OAAO,CAAC,eAAe,GACjF,WAAW,wBAAO,oBAAoB,GAAK,kBAAkB,GAC7D,OAAO;YACH,WAAW,CAAC,KAAK;YACjB,WAAW,CAAC,MAAM;YAClB,WAAW,CAAC,SAAS;YACrB,WAAW,CAAC,QAAQ;YACpB,WAAW,CAAC,SAAS;YACrB,WAAW,CAAC,MAAM;kBACf,WAAW;YACd,WAAW,CAAC,SAAS;mBAEzB,WAAW,EAAE,uBAAuB,EAAE,EACtC,gBAAgB,EAAE,IAAI,oBAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,EAC7E,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,uBAAuB,IACtE,qCAAqC,CAAC,OAAO,CAAC,GAC9C,cAAc,CAAC,WAAW,CAAC,GAC3B,uBAAuB,EAC5B;AACN,CAAC;AAED,SAAS,uBAAuB;IAC5B,oHAAoH;IACpH,IAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;IAE7C,OAAO;QACH,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvD,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;QACrC,QAAQ,EACJ,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;YAChC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;YAC/B,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC;KACvC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAChD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAS,cAAc,CAAC,WAAwC;IAC5D,OAAO;QACH,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC,QAAQ,EAAE;QACzC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;QAC3C,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE;QACnC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE;QACrC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;QAC3C,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE;QACrC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;KAC9C,CAAC;AACN,CAAC","sourcesContent":["import { createStandaloneEditorCorePlugins } from '../corePlugin/createStandaloneEditorCorePlugins';\nimport { createStandaloneEditorDefaultSettings } from './createStandaloneEditorDefaultSettings';\nimport { DarkColorHandlerImpl } from './DarkColorHandlerImpl';\nimport { standaloneCoreApiMap } from './standaloneCoreApiMap';\nimport type { EditorPlugin } from 'roosterjs-editor-types';\nimport type {\n EditorEnvironment,\n StandaloneEditorCore,\n StandaloneEditorCorePluginState,\n StandaloneEditorCorePlugins,\n StandaloneEditorOptions,\n UnportedCoreApiMap,\n UnportedCorePluginState,\n} from 'roosterjs-content-model-types';\n\n/**\n * A temporary function to create Standalone Editor core\n * @param contentDiv Editor content DIV\n * @param options Editor options\n */\nexport function createStandaloneEditorCore(\n contentDiv: HTMLDivElement,\n options: StandaloneEditorOptions,\n unportedCoreApiMap: UnportedCoreApiMap,\n unportedCorePluginState: UnportedCorePluginState,\n tempPlugins: EditorPlugin[]\n): StandaloneEditorCore {\n const corePlugins = createStandaloneEditorCorePlugins(options, contentDiv);\n\n return {\n contentDiv,\n api: { ...standaloneCoreApiMap, ...unportedCoreApiMap, ...options.coreApiOverride },\n originalApi: { ...standaloneCoreApiMap, ...unportedCoreApiMap },\n plugins: [\n corePlugins.cache,\n corePlugins.format,\n corePlugins.copyPaste,\n corePlugins.domEvent,\n corePlugins.selection,\n corePlugins.entity,\n ...tempPlugins,\n corePlugins.lifecycle,\n ],\n environment: createEditorEnvironment(),\n darkColorHandler: new DarkColorHandlerImpl(contentDiv, options.baseDarkColor),\n trustedHTMLHandler: options.trustedHTMLHandler || defaultTrustHtmlHandler,\n ...createStandaloneEditorDefaultSettings(options),\n ...getPluginState(corePlugins),\n ...unportedCorePluginState,\n };\n}\n\nfunction createEditorEnvironment(): EditorEnvironment {\n // It is ok to use global window here since the environment should always be the same for all windows in one session\n const userAgent = window.navigator.userAgent;\n\n return {\n isMac: window.navigator.appVersion.indexOf('Mac') != -1,\n isAndroid: /android/i.test(userAgent),\n isSafari:\n userAgent.indexOf('Safari') >= 0 &&\n userAgent.indexOf('Chrome') < 0 &&\n userAgent.indexOf('Android') < 0,\n };\n}\n\n/**\n * @internal export for test only\n */\nexport function defaultTrustHtmlHandler(html: string) {\n return html;\n}\n\nfunction getPluginState(corePlugins: StandaloneEditorCorePlugins): StandaloneEditorCorePluginState {\n return {\n domEvent: corePlugins.domEvent.getState(),\n copyPaste: corePlugins.copyPaste.getState(),\n cache: corePlugins.cache.getState(),\n format: corePlugins.format.getState(),\n lifecycle: corePlugins.lifecycle.getState(),\n entity: corePlugins.entity.getState(),\n selection: corePlugins.selection.getState(),\n };\n}\n"]}
1
+ {"version":3,"file":"createStandaloneEditorCore.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-core/lib/editor/createStandaloneEditorCore.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,iCAAiC,EAAE,MAAM,iDAAiD,CAAC;AACpG,OAAO,EAAE,qCAAqC,EAAE,MAAM,yCAAyC,CAAC;AAChG,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAY9D;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CACtC,UAA0B,EAC1B,OAAgC,EAChC,kBAAsC,EACtC,uBAAgD,EAChD,WAA2B;;IAE3B,IAAM,WAAW,GAAG,iCAAiC,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAE3E,oCACI,UAAU,YAAA,EACV,GAAG,iCAAO,oBAAoB,GAAK,kBAAkB,GAAK,OAAO,CAAC,eAAe,GACjF,WAAW,wBAAO,oBAAoB,GAAK,kBAAkB,GAC7D,OAAO;YACH,WAAW,CAAC,KAAK;YACjB,WAAW,CAAC,MAAM;YAClB,WAAW,CAAC,SAAS;YACrB,WAAW,CAAC,QAAQ;YACpB,WAAW,CAAC,SAAS;YACrB,WAAW,CAAC,MAAM;kBACf,WAAW;YACd,WAAW,CAAC,SAAS;mBAEzB,WAAW,EAAE,uBAAuB,EAAE,EACtC,gBAAgB,EAAE,IAAI,oBAAoB,CACtC,UAAU,EACV,MAAA,OAAO,CAAC,YAAY,mCAAI,oBAAoB,CAC/C,EACD,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,uBAAuB,IACtE,qCAAqC,CAAC,OAAO,CAAC,GAC9C,cAAc,CAAC,WAAW,CAAC,GAC3B,uBAAuB,EAC5B;AACN,CAAC;AAED,SAAS,uBAAuB;IAC5B,oHAAoH;IACpH,IAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;IAE7C,OAAO;QACH,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvD,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;QACrC,QAAQ,EACJ,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;YAChC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;YAC/B,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC;KACvC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAChD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAS,cAAc,CAAC,WAAwC;IAC5D,OAAO;QACH,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC,QAAQ,EAAE;QACzC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;QAC3C,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE;QACnC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE;QACrC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;QAC3C,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE;QACrC,SAAS,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;KAC9C,CAAC;AACN,CAAC;AAED,oDAAoD;AACpD,SAAS,oBAAoB,CAAC,KAAa;IACvC,OAAO,KAAK,CAAC;AACjB,CAAC","sourcesContent":["import { createStandaloneEditorCorePlugins } from '../corePlugin/createStandaloneEditorCorePlugins';\nimport { createStandaloneEditorDefaultSettings } from './createStandaloneEditorDefaultSettings';\nimport { DarkColorHandlerImpl } from './DarkColorHandlerImpl';\nimport { standaloneCoreApiMap } from './standaloneCoreApiMap';\nimport type { EditorPlugin } from 'roosterjs-editor-types';\nimport type {\n EditorEnvironment,\n StandaloneEditorCore,\n StandaloneEditorCorePluginState,\n StandaloneEditorCorePlugins,\n StandaloneEditorOptions,\n UnportedCoreApiMap,\n UnportedCorePluginState,\n} from 'roosterjs-content-model-types';\n\n/**\n * A temporary function to create Standalone Editor core\n * @param contentDiv Editor content DIV\n * @param options Editor options\n */\nexport function createStandaloneEditorCore(\n contentDiv: HTMLDivElement,\n options: StandaloneEditorOptions,\n unportedCoreApiMap: UnportedCoreApiMap,\n unportedCorePluginState: UnportedCorePluginState,\n tempPlugins: EditorPlugin[]\n): StandaloneEditorCore {\n const corePlugins = createStandaloneEditorCorePlugins(options, contentDiv);\n\n return {\n contentDiv,\n api: { ...standaloneCoreApiMap, ...unportedCoreApiMap, ...options.coreApiOverride },\n originalApi: { ...standaloneCoreApiMap, ...unportedCoreApiMap },\n plugins: [\n corePlugins.cache,\n corePlugins.format,\n corePlugins.copyPaste,\n corePlugins.domEvent,\n corePlugins.selection,\n corePlugins.entity,\n ...tempPlugins,\n corePlugins.lifecycle,\n ],\n environment: createEditorEnvironment(),\n darkColorHandler: new DarkColorHandlerImpl(\n contentDiv,\n options.getDarkColor ?? getDarkColorFallback\n ),\n trustedHTMLHandler: options.trustedHTMLHandler || defaultTrustHtmlHandler,\n ...createStandaloneEditorDefaultSettings(options),\n ...getPluginState(corePlugins),\n ...unportedCorePluginState,\n };\n}\n\nfunction createEditorEnvironment(): EditorEnvironment {\n // It is ok to use global window here since the environment should always be the same for all windows in one session\n const userAgent = window.navigator.userAgent;\n\n return {\n isMac: window.navigator.appVersion.indexOf('Mac') != -1,\n isAndroid: /android/i.test(userAgent),\n isSafari:\n userAgent.indexOf('Safari') >= 0 &&\n userAgent.indexOf('Chrome') < 0 &&\n userAgent.indexOf('Android') < 0,\n };\n}\n\n/**\n * @internal export for test only\n */\nexport function defaultTrustHtmlHandler(html: string) {\n return html;\n}\n\nfunction getPluginState(corePlugins: StandaloneEditorCorePlugins): StandaloneEditorCorePluginState {\n return {\n domEvent: corePlugins.domEvent.getState(),\n copyPaste: corePlugins.copyPaste.getState(),\n cache: corePlugins.cache.getState(),\n format: corePlugins.format.getState(),\n lifecycle: corePlugins.lifecycle.getState(),\n entity: corePlugins.entity.getState(),\n selection: corePlugins.selection.getState(),\n };\n}\n\n// A fallback function, always return original color\nfunction getDarkColorFallback(color: string) {\n return color;\n}\n"]}
package/package.json CHANGED
@@ -3,13 +3,12 @@
3
3
  "description": "Content Model for roosterjs (Under development)",
4
4
  "dependencies": {
5
5
  "tslib": "^2.3.1",
6
- "color": "^3.0.0",
7
6
  "roosterjs-editor-types": "^8.59.0",
8
7
  "roosterjs-editor-dom": "^8.59.0",
9
- "roosterjs-content-model-dom": "^0.21.0",
10
- "roosterjs-content-model-types": "^0.21.0"
8
+ "roosterjs-content-model-dom": "^0.21.2",
9
+ "roosterjs-content-model-types": "^0.21.2"
11
10
  },
12
- "version": "0.21.0",
11
+ "version": "0.21.2",
13
12
  "main": "./lib/index.js",
14
13
  "typings": "./lib/index.d.ts",
15
14
  "module": "./lib-mjs/index.js",