Skip to content

Commit

Permalink
Merge branch 'master' into u/juliaroldi/sanitizeLinks
Browse files Browse the repository at this point in the history
  • Loading branch information
juliaroldi authored Dec 9, 2022
2 parents 5d4a80d + b99aa8b commit f29dd84
Show file tree
Hide file tree
Showing 54 changed files with 3,695 additions and 1,251 deletions.
Original file line number Diff line number Diff line change
@@ -1,23 +1,76 @@
import * as React from 'react';
import { BackgroundColorFormatRenderer } from '../format/formatPart/BackgroundColorFormatRenderer';
import { BlockGroupContentView } from './BlockGroupContentView';
import { ContentModelQuote, hasSelectionInBlock } from 'roosterjs-content-model';
import { BorderFormatRenderers } from '../format/formatPart/BorderFormatRenderers';
import { ContentModelView } from '../ContentModelView';
import { DirectionFormatRenderers } from '../format/formatPart/DirectionFormatRenderers';
import { FontFamilyFormatRenderer } from '../format/formatPart/FontFamilyFormatRenderer';
import { FontSizeFormatRenderer } from '../format/formatPart/FontSizeFormatRenderer';
import { FormatRenderer } from '../format/utils/FormatRenderer';
import { FormatView } from '../format/FormatView';
import { LineHeightFormatRenderer } from '../format/formatPart/LineHeightFormatRenderer';
import { MarginFormatRenderer } from '../format/formatPart/MarginFormatRenderer';
import { PaddingFormatRenderer } from '../format/formatPart/PaddingFormatRenderer';
import { TextColorFormatRenderer } from '../format/formatPart/TextColorFormatRenderer';
import { WhiteSpaceFormatRenderer } from '../format/formatPart/WhiteSpaceFormatRenderer';
import {
ContentModelQuote,
ContentModelQuoteFormat,
ContentModelSegmentFormat,
hasSelectionInBlock,
} from 'roosterjs-content-model';
import {
BoldFormatRenderer,
ItalicFormatRenderer,
UnderlineFormatRenderer,
} from '../format/formatPart/BasicFormatRenderers';

const styles = require('./ContentModelQuoteView.scss');

const QuoteBlockFormatRenders: FormatRenderer<ContentModelQuoteFormat>[] = [
BackgroundColorFormatRenderer,
...DirectionFormatRenderers,
MarginFormatRenderer,
PaddingFormatRenderer,
LineHeightFormatRenderer,
WhiteSpaceFormatRenderer,
...BorderFormatRenderers,
];
const QuoteSegmentFormatRenders: FormatRenderer<ContentModelSegmentFormat>[] = [
TextColorFormatRenderer,
FontSizeFormatRenderer,
FontFamilyFormatRenderer,
BoldFormatRenderer,
ItalicFormatRenderer,
UnderlineFormatRenderer,
];

export function ContentModelQuoteView(props: { quote: ContentModelQuote }) {
const { quote } = props;
const getContent = React.useCallback(() => {
return <BlockGroupContentView group={quote} />;
}, [quote]);

const getFormat = React.useCallback(() => {
return (
<>
<FormatView format={quote.format} renderers={QuoteBlockFormatRenders} />
<FormatView
format={quote.quoteSegmentFormat}
renderers={QuoteSegmentFormatRenders}
/>
</>
);
}, [quote]);

return (
<ContentModelView
title="Quote"
className={styles.modelQuote}
hasSelection={hasSelectionInBlock(quote)}
jsonSource={quote}
getContent={getContent}
getFormat={getFormat}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { alignCenterButton } from './alignCenterButton';
import { alignLeftButton } from './alignLeftButton';
import { alignRightButton } from './alignRightButton';
import { backgroundColorButton } from './backgroundColorButton';
import { blockQuoteButton } from './blockQuoteButton';
import { boldButton } from './boldButton';
import { bulletedListButton } from './bulletedListButton';
import { decreaseFontSizeButton } from './decreaseFontSizeButton';
Expand Down Expand Up @@ -52,19 +53,20 @@ const buttons = [
numberedListButton,
decreaseIndentButton,
increaseIndentButton,
strikethroughButton,
superscriptButton,
subscriptButton,
blockQuoteButton,
alignLeftButton,
alignCenterButton,
alignRightButton,
insertTableButton,
superscriptButton,
subscriptButton,
strikethroughButton,
ltrButton,
rtlButton,
setHeaderLevelButton,
setBulletedListStyleButton,
setNumberedListStyleButton,
listStartNumberButton,
insertTableButton,
formatTableButton,
setTableCellShadeButton,
setTableHeaderButton,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import isContentModelEditor from '../../editor/isContentModelEditor';
import { QuoteButtonStringKey, RibbonButton } from 'roosterjs-react';
import { toggleBlockQuote } from 'roosterjs-content-model';

/**
* @internal
* "Block quote" button on the format ribbon
*/
export const blockQuoteButton: RibbonButton<QuoteButtonStringKey> = {
key: 'buttonNameQuote',
unlocalizedText: 'Quote',
iconName: 'RightDoubleQuote',
isChecked: formatState => !!formatState.isBlockQuote,
onClick: editor => {
if (isContentModelEditor(editor)) {
toggleBlockQuote(editor);
}
return true;
},
};
Original file line number Diff line number Diff line change
@@ -1,28 +1,46 @@
import { addBlock } from '../../modelApi/common/addBlock';
import { ContentModelQuoteFormat } from '../../publicTypes/format/ContentModelQuoteFormat';
import { ContentModelSegmentFormat } from '../../publicTypes/format/ContentModelSegmentFormat';
import { createQuote } from '../../modelApi/creators/createQuote';
import { ElementProcessor } from '../../publicTypes/context/ElementProcessor';
import { getObjectKeys, getStyles } from 'roosterjs-editor-dom';

const KnownQuoteStyleNames = ['margin-top', 'margin-bottom'];
import { getObjectKeys } from 'roosterjs-editor-dom';
import { knownElementProcessor } from './knownElementProcessor';
import { parseFormat } from '../utils/parseFormat';
import { stackFormat } from '../utils/stackFormat';

/**
* @internal
*/
export const quoteProcessor: ElementProcessor<HTMLQuoteElement> = (group, element, context) => {
const styles = getStyles(element);
if (element.style.borderLeft || element.style.borderRight) {
stackFormat(
context,
{
paragraph: 'empty',
segment: 'shallowCloneForBlock',
},
() => {
const quoteFormat: ContentModelQuoteFormat = {};
const segmentFormat: ContentModelSegmentFormat = {};

parseFormat(element, context.formatParsers.quote, quoteFormat, context);
parseFormat(element, context.formatParsers.segmentOnBlock, segmentFormat, context);

const quote = createQuote(quoteFormat, segmentFormat);

addBlock(group, quote);

if (
parseInt(element.style.marginTop) === 0 &&
parseInt(element.style.marginBottom) === 0 &&
getObjectKeys(styles).every(key => KnownQuoteStyleNames.indexOf(key) >= 0)
) {
// Temporary solution: Use Quote to provide indentation
// TODO: We should use CSS to do indentation, and only use Quote for quoted text
const quote = createQuote();
// These inline formats are overridden by quote, and will be applied onto BLOCKQUOTE element
// So no need to pass them down into segments.
// And when toggle blockquote (unwrap the quote model), no need to modify the inline format of segments
getObjectKeys(segmentFormat).forEach(key => {
delete context.segmentFormat[key];
});

addBlock(group, quote);
context.elementProcessors.child(quote, element, context);
context.elementProcessors.child(quote, element, context);
}
);
} else {
context.elementProcessors['*'](group, element, context);
knownElementProcessor(group, element, context);
}
};
Loading

0 comments on commit f29dd84

Please sign in to comment.