Skip to content

Commit

Permalink
Merge branch 'master' into u/juliaroldi/delete-link-on-image
Browse files Browse the repository at this point in the history
  • Loading branch information
juliaroldi authored Sep 18, 2023
2 parents ad07b90 + e8e0462 commit afe360c
Show file tree
Hide file tree
Showing 70 changed files with 991 additions and 761 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { DefaultImplicitFormatMap } from 'roosterjs-content-model-types';

/**
* @internal
* A map from tag name to its default implicit formats
*/
export const defaultContentModelFormatMap: DefaultImplicitFormatMap = {
a: {
underline: true,
},
blockquote: {
marginTop: '1em',
marginBottom: '1em',
marginLeft: '40px',
marginRight: '40px',
},
code: {
fontFamily: 'monospace',
},
h1: {
fontWeight: 'bold',
fontSize: '2em',
},
h2: {
fontWeight: 'bold',
fontSize: '1.5em',
},
h3: {
fontWeight: 'bold',
fontSize: '1.17em',
},
h4: {
fontWeight: 'bold',
fontSize: '1em', // Set this default value here to overwrite existing font size when change heading level
},
h5: {
fontWeight: 'bold',
fontSize: '0.83em',
},
h6: {
fontWeight: 'bold',
fontSize: '0.67em',
},
p: {
marginTop: '1em',
marginBottom: '1em',
},
pre: {
fontFamily: 'monospace',
whiteSpace: 'pre',
marginTop: '1em',
marginBottom: '1em',
},
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DefaultImplicitFormatMap, DefaultStyleMap } from 'roosterjs-content-model-types';
import { DefaultStyleMap } from 'roosterjs-content-model-types';

const blockElement: Partial<CSSStyleDeclaration> = {
display: 'block',
Expand All @@ -7,7 +7,7 @@ const blockElement: Partial<CSSStyleDeclaration> = {
/**
* @internal
*/
export const defaultStyleMap: DefaultStyleMap = {
export const defaultHTMLStyleMap: DefaultStyleMap = {
address: blockElement,
article: blockElement,
aside: blockElement,
Expand Down Expand Up @@ -123,69 +123,3 @@ export const defaultStyleMap: DefaultStyleMap = {
},
ul: blockElement,
};

/**
* @internal
*/
export const enum PseudoTagNames {
childOfPre = 'pre *', // This value is not a CSS selector, it just to tell this will impact elements under PRE tag. Any unique value here can work actually
}

/**
* A map from tag name to its default implicit formats
*/
export const defaultImplicitFormatMap: DefaultImplicitFormatMap = {
a: {
underline: true,
},
blockquote: {
marginTop: '1em',
marginBottom: '1em',
marginLeft: '40px',
marginRight: '40px',
},
code: {
fontFamily: 'monospace',
},
h1: {
fontWeight: 'bold',
fontSize: '2em',
},
h2: {
fontWeight: 'bold',
fontSize: '1.5em',
},
h3: {
fontWeight: 'bold',
fontSize: '1.17em',
},
h4: {
fontWeight: 'bold',
fontSize: '1em', // Set this default value here to overwrite existing font size when change heading level
},
h5: {
fontWeight: 'bold',
fontSize: '0.83em',
},
h6: {
fontWeight: 'bold',
fontSize: '0.67em',
},
p: {
marginTop: '1em',
marginBottom: '1em',
},
pre: {
fontFamily: 'monospace',
whiteSpace: 'pre',
marginTop: '1em',
marginBottom: '1em',
},

// For PRE tag, the following styles will be included from the PRE tag.
// Adding this implicit style here so no need to generate these style for child elements
[PseudoTagNames.childOfPre]: {
fontFamily: 'monospace',
whiteSpace: 'pre',
},
};
Original file line number Diff line number Diff line change
@@ -1,31 +1,62 @@
import { defaultFormatParsers, getFormatParsers } from '../../formatHandlers/defaultFormatHandlers';
import { defaultProcessorMap } from './defaultProcessors';
import { defaultStyleMap } from '../../formatHandlers/utils/defaultStyles';
import { DomToModelContext, DomToModelOption, EditorContext } from 'roosterjs-content-model-types';
import { SelectionRangeEx } from 'roosterjs-editor-types';
import { getObjectKeys } from 'roosterjs-editor-dom';
import {
defaultFormatKeysPerCategory,
defaultFormatParsers,
} from '../../formatHandlers/defaultFormatHandlers';
import {
ContentModelBlockFormat,
DomToModelContext,
DomToModelDecoratorContext,
DomToModelFormatContext,
DomToModelOption,
DomToModelSelectionContext,
DomToModelSettings,
EditorContext,
FormatParser,
FormatParsers,
FormatParsersPerCategory,
} from 'roosterjs-content-model-types';

/**
* Create context object form DOM to Content Model conversion
* Create context object for DOM to Content Model conversion
* @param editorContext Context of editor
* @param options Options for this context
* @param selection Selection that already exists in content
* @param options Option array to customize the DOM to Model conversion behavior
*/
export function createDomToModelContext(
editorContext?: EditorContext,
options?: DomToModelOption,
selection?: SelectionRangeEx
...options: (DomToModelOption | undefined)[]
): DomToModelContext {
const context: DomToModelContext = {
...editorContext,
return Object.assign(
{},
editorContext,
createDomToModelSelectionContext(),
createDomToModelFormatContext(editorContext?.isRootRtl),
createDomToModelDecoratorContext(),
createDomToModelSettings(options)
);
}

function createDomToModelSelectionContext(): DomToModelSelectionContext {
return { isInSelection: false };
}

blockFormat: {},
function createDomToModelFormatContext(isRootRtl?: boolean): DomToModelFormatContext {
const blockFormat: ContentModelBlockFormat = isRootRtl ? { direction: 'rtl' } : {};

return {
blockFormat,
segmentFormat: {},
isInSelection: false,

listFormat: {
levels: [],
threadItemCounts: [],
},
};
}

function createDomToModelDecoratorContext(): DomToModelDecoratorContext {
return {
link: {
format: {},
dataset: {},
Expand All @@ -37,33 +68,54 @@ export function createDomToModelContext(
format: {},
tagName: '',
},
};
}

elementProcessors: {
...defaultProcessorMap,
...(options?.processorOverride || {}),
},

defaultStyles: {
...defaultStyleMap,
...(options?.defaultStyleOverride || {}),
},

formatParsers: getFormatParsers(
options?.formatParserOverride,
options?.additionalFormatParsers
function createDomToModelSettings(options: (DomToModelOption | undefined)[]): DomToModelSettings {
return {
elementProcessors: Object.assign(
{},
defaultProcessorMap,
...options.map(x => x?.processorOverride)
),
formatParsers: buildFormatParsers(
options.map(x => x?.formatParserOverride),
options.map(x => x?.additionalFormatParsers)
),

defaultElementProcessors: defaultProcessorMap,
defaultFormatParsers: defaultFormatParsers,
defaultFormatParsers,
};
}

/**
* @internal Export for test only
* Build format parsers used by DOM to Content Model conversion
* @param override
* @param additionalParsersArray
* @returns
*/
export function buildFormatParsers(
overrides: (Partial<FormatParsers> | undefined)[] = [],
additionalParsersArray: (Partial<FormatParsersPerCategory> | undefined)[] = []
): FormatParsersPerCategory {
const combinedOverrides = Object.assign({}, ...overrides);

if (editorContext?.isRootRtl) {
context.blockFormat.direction = 'rtl';
}
return getObjectKeys(defaultFormatKeysPerCategory).reduce((result, key) => {
const value = defaultFormatKeysPerCategory[key]
.map(
formatKey =>
(combinedOverrides[formatKey] === undefined
? defaultFormatParsers[formatKey]
: combinedOverrides[formatKey]) as FormatParser<any>
)
.concat(
...additionalParsersArray.map(
parsers => (parsers?.[key] ?? []) as FormatParser<any>[]
)
);

if (selection) {
context.rangeEx = selection;
}
result[key] = value;

return context;
return result;
}, {} as FormatParsersPerCategory);
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,23 @@
import { ContentModelDocument, DomToModelContext } from 'roosterjs-content-model-types';
import { createContentModelDocument } from '../modelApi/creators/createContentModelDocument';
import { createDomToModelContext } from './context/createDomToModelContext';
import { normalizeContentModel } from '../modelApi/common/normalizeContentModel';
import { SelectionRangeEx } from 'roosterjs-editor-types';
import {
ContentModelDocument,
DomToModelOption,
EditorContext,
} from 'roosterjs-content-model-types';

/**
* Create Content Model from DOM tree in this editor
* @param root Root element of DOM tree to create Content Model from
* @param option The option to customize the behavior of DOM to Content Model conversion
* @param editorContext Context of content model editor
* @param selection Existing selection range in editor
* @param context Context object for DOM to Content Model conversion
* @param selection Selection that already exists in content
* @returns A ContentModelDocument object that contains all the models created from the give root element
*/
export function domToContentModel(
root: HTMLElement | DocumentFragment,
option?: DomToModelOption,
editorContext?: EditorContext,
context: DomToModelContext,
selection?: SelectionRangeEx
): ContentModelDocument {
const model = createContentModelDocument(editorContext?.defaultFormat);
const context = createDomToModelContext(editorContext, option, selection);
const model = createContentModelDocument(context.defaultFormat);

context.rangeEx = selection;
context.elementProcessors.child(model, root, context);

normalizeContentModel(model);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { defaultHTMLStyleMap } from '../../config/defaultHTMLStyleMap';
import { DefaultStyleMap, DomToModelContext } from 'roosterjs-content-model-types';

/**
Expand All @@ -13,5 +14,5 @@ export function getDefaultStyle(
): Partial<CSSStyleDeclaration> {
let tag = element.tagName.toLowerCase() as keyof DefaultStyleMap;

return context.defaultStyles[tag] || {};
return defaultHTMLStyleMap[tag] || {};
}
Loading

0 comments on commit afe360c

Please sign in to comment.