Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change htmlAttributes to htmlXAttributes #14271

Merged
merged 3 commits into from
May 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 30 additions & 15 deletions packages/ckeditor5-html-support/src/converters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
setViewAttributes,
mergeViewElementAttributes,
updateViewAttributes,
getHtmlAttributeName,
type GHSViewAttributes
} from './utils';
import type DataFilter from './datafilter';
Expand Down Expand Up @@ -62,7 +63,7 @@ export function toObjectWidgetConverter(
const widgetLabel = t( 'HTML object' );

const viewElement = createObjectView( viewName!, modelElement, writer );
const viewAttributes = modelElement.getAttribute( 'htmlAttributes' );
const viewAttributes = modelElement.getAttribute( getHtmlAttributeName( viewName! ) );

writer.addClass( 'html-object-embed__content', viewElement );

Expand Down Expand Up @@ -162,7 +163,7 @@ export function attributeToViewInlineConverter( { priority, view: viewName }: Da
/**
* View-to-model conversion helper preserving allowed attributes on block element.
*
* All matched attributes will be preserved on `htmlAttributes` attribute.
* All matched attributes will be preserved on `html*Attributes` attribute.
*
* @returns Returns a conversion callback.
*/
Expand All @@ -179,31 +180,45 @@ export function viewToModelBlockAttributeConverter( { view: viewName }: DataSche

const viewAttributes = dataFilter.processViewAttributes( data.viewItem, conversionApi );

if ( viewAttributes ) {
conversionApi.writer.setAttribute( 'htmlAttributes', viewAttributes, data.modelRange );
if ( !viewAttributes ) {
return;
}

conversionApi.writer.setAttribute(
getHtmlAttributeName( data.viewItem.name ),
viewAttributes,
data.modelRange
);
}, { priority: 'low' } );
};
}

/**
* Model-to-view conversion helper applying attributes preserved in `htmlAttributes` attribute
* Model-to-view conversion helper applying attributes preserved in `html*Attributes` attribute
* for block elements.
*
* @returns Returns a conversion callback.
*/
export function modelToViewBlockAttributeConverter( { model: modelName }: DataSchemaBlockElementDefinition ) {
export function modelToViewBlockAttributeConverter( { view: viewName, model: modelName }: DataSchemaBlockElementDefinition ) {
return ( dispatcher: DowncastDispatcher ): void => {
dispatcher.on<DowncastAttributeEvent>( `attribute:htmlAttributes:${ modelName }`, ( evt, data, conversionApi ) => {
if ( !conversionApi.consumable.consume( data.item, evt.name ) ) {
return;
}
dispatcher.on<DowncastAttributeEvent>(
`attribute:${ getHtmlAttributeName( viewName! ) }:${ modelName }`,
( evt, data, conversionApi ) => {
if ( !conversionApi.consumable.consume( data.item, evt.name ) ) {
return;
}

const { attributeOldValue, attributeNewValue } = data;
const viewWriter = conversionApi.writer;
const viewElement = conversionApi.mapper.toViewElement( data.item as Element )!;
const { attributeOldValue, attributeNewValue } = data;
const viewWriter = conversionApi.writer;
const viewElement = conversionApi.mapper.toViewElement( data.item as Element )!;

updateViewAttributes( viewWriter, attributeOldValue as GHSViewAttributes, attributeNewValue as GHSViewAttributes, viewElement );
} );
updateViewAttributes(
viewWriter,
attributeOldValue as GHSViewAttributes,
attributeNewValue as GHSViewAttributes,
viewElement
);
}
);
};
}
13 changes: 7 additions & 6 deletions packages/ckeditor5-html-support/src/datafilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ import {
type DataSchemaInlineElementDefinition
} from './dataschema';

import type { GHSViewAttributes } from './utils';
import {
getHtmlAttributeName,
type GHSViewAttributes
} from './utils';

import { isPlainObject, pull as removeItemFromArray } from 'lodash-es';

Expand Down Expand Up @@ -498,7 +501,7 @@ export default class DataFilter extends Plugin {
}

schema.extend( definition.model, {
allowAttributes: [ 'htmlAttributes', 'htmlContent' ]
allowAttributes: [ getHtmlAttributeName( viewName ), 'htmlContent' ]
} );

// Store element content in special `$rawContent` custom property to
Expand All @@ -519,9 +522,7 @@ export default class DataFilter extends Plugin {
conversion.for( 'editingDowncast' ).elementToStructure( {
model: {
name: modelName,
attributes: [
'htmlAttributes'
]
attributes: [ getHtmlAttributeName( viewName ) ]
},
view: toObjectWidgetConverter( editor, definition as DataSchemaInlineElementDefinition )
} );
Expand Down Expand Up @@ -570,7 +571,7 @@ export default class DataFilter extends Plugin {
}

schema.extend( definition.model, {
allowAttributes: 'htmlAttributes'
allowAttributes: getHtmlAttributeName( viewName )
} );

conversion.for( 'upcast' ).add( viewToModelBlockAttributeConverter( definition, this ) );
Expand Down
6 changes: 3 additions & 3 deletions packages/ckeditor5-html-support/src/generalhtmlsupport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import StyleElementSupport from './integrations/style';
import DocumentListElementSupport from './integrations/documentlist';
import CustomElementSupport from './integrations/customelement';
import type { DataSchemaInlineElementDefinition } from './dataschema';
import type { DocumentSelection, Item, Model, Range, Selectable, Writer } from 'ckeditor5/src/engine';
import { modifyGhsAttribute } from './utils';
import type { DocumentSelection, Item, Model, Range, Selectable } from 'ckeditor5/src/engine';
import { getHtmlAttributeName, modifyGhsAttribute } from './utils';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import type { GeneralHtmlSupportConfig } from './generalhtmlsupportconfig';

Expand Down Expand Up @@ -90,7 +90,7 @@ export default class GeneralHtmlSupport extends Plugin {
return inlineDefinition.model;
}

return 'htmlAttributes';
return getHtmlAttributeName( viewElementName );
}

/**
Expand Down
13 changes: 8 additions & 5 deletions packages/ckeditor5-html-support/src/integrations/codeblock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import type {
} from 'ckeditor5/src/engine';
import { Plugin } from 'ckeditor5/src/core';

import { updateViewAttributes, type GHSViewAttributes } from '../utils';
import {
updateViewAttributes,
type GHSViewAttributes
} from '../utils';
import DataFilter, { type DataFilterRegisterEvent } from '../datafilter';

/**
Expand Down Expand Up @@ -59,7 +62,7 @@ export default class CodeBlockElementSupport extends Plugin {

// Extend codeBlock to allow attributes required by attribute filtration.
schema.extend( 'codeBlock', {
allowAttributes: [ 'htmlAttributes', 'htmlContentAttributes' ]
allowAttributes: [ 'htmlPreAttributes', 'htmlContentAttributes' ]
} );

conversion.for( 'upcast' ).add( viewToModelCodeBlockAttributeConverter( dataFilter ) );
Expand All @@ -74,7 +77,7 @@ export default class CodeBlockElementSupport extends Plugin {
* View-to-model conversion helper preserving allowed attributes on {@link module:code-block/codeblock~CodeBlock Code Block}
* feature model element.
*
* Attributes are preserved as a value of `htmlAttributes` model attribute.
* Attributes are preserved as a value of `html*Attributes` model attribute.
* @param dataFilter
* @returns Returns a conversion callback.
*/
Expand All @@ -88,7 +91,7 @@ function viewToModelCodeBlockAttributeConverter( dataFilter: DataFilter ) {
return;
}

preserveElementAttributes( viewPreElement, 'htmlAttributes' );
preserveElementAttributes( viewPreElement, 'htmlPreAttributes' );
preserveElementAttributes( viewCodeElement, 'htmlContentAttributes' );

function preserveElementAttributes( viewElement: ViewElement, attributeName: string ) {
Expand All @@ -109,7 +112,7 @@ function viewToModelCodeBlockAttributeConverter( dataFilter: DataFilter ) {
*/
function modelToViewCodeBlockAttributeConverter() {
return ( dispatcher: DowncastDispatcher ) => {
dispatcher.on<DowncastAttributeEvent>( 'attribute:htmlAttributes:codeBlock', ( evt, data, conversionApi ) => {
dispatcher.on<DowncastAttributeEvent>( 'attribute:htmlPreAttributes:codeBlock', ( evt, data, conversionApi ) => {
if ( !conversionApi.consumable.consume( data.item, evt.name ) ) {
return;
}
Expand Down
24 changes: 16 additions & 8 deletions packages/ckeditor5-html-support/src/integrations/customelement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export default class CustomElementSupport extends Plugin {

schema.register( definition.model, definition.modelSchema );
schema.extend( definition.model, {
allowAttributes: [ 'htmlElementName', 'htmlAttributes', 'htmlContent' ],
allowAttributes: [ 'htmlElementName', 'htmlCustomElementAttributes', 'htmlContent' ],
isContent: true
} );

Expand Down Expand Up @@ -92,7 +92,7 @@ export default class CustomElementSupport extends Plugin {
const htmlAttributes = dataFilter.processViewAttributes( viewElement, conversionApi );

if ( htmlAttributes ) {
conversionApi.writer.setAttribute( 'htmlAttributes', htmlAttributes, modelElement );
conversionApi.writer.setAttribute( 'htmlCustomElementAttributes', htmlAttributes, modelElement );
}

// Store the whole element in the attribute so that DomConverter will be able to use the pre like element context.
Expand All @@ -117,14 +117,18 @@ export default class CustomElementSupport extends Plugin {
conversion.for( 'editingDowncast' ).elementToElement( {
model: {
name: definition.model,
attributes: [ 'htmlElementName', 'htmlAttributes', 'htmlContent' ]
attributes: [ 'htmlElementName', 'htmlCustomElementAttributes', 'htmlContent' ]
},
view: ( modelElement, { writer } ) => {
const viewName = modelElement.getAttribute( 'htmlElementName' ) as string;
const viewElement = writer.createRawElement( viewName );

if ( modelElement.hasAttribute( 'htmlAttributes' ) ) {
setViewAttributes( writer, modelElement.getAttribute( 'htmlAttributes' ) as GHSViewAttributes, viewElement );
if ( modelElement.hasAttribute( 'htmlCustomElementAttributes' ) ) {
setViewAttributes(
writer,
modelElement.getAttribute( 'htmlCustomElementAttributes' ) as GHSViewAttributes,
viewElement
);
}

return viewElement;
Expand All @@ -134,7 +138,7 @@ export default class CustomElementSupport extends Plugin {
conversion.for( 'dataDowncast' ).elementToElement( {
model: {
name: definition.model,
attributes: [ 'htmlElementName', 'htmlAttributes', 'htmlContent' ]
attributes: [ 'htmlElementName', 'htmlCustomElementAttributes', 'htmlContent' ]
},
view: ( modelElement, { writer } ) => {
const viewName = modelElement.getAttribute( 'htmlElementName' ) as string;
Expand All @@ -154,8 +158,12 @@ export default class CustomElementSupport extends Plugin {
}
} );

if ( modelElement.hasAttribute( 'htmlAttributes' ) ) {
setViewAttributes( writer, modelElement.getAttribute( 'htmlAttributes' ) as GHSViewAttributes, viewElement );
if ( modelElement.hasAttribute( 'htmlCustomElementAttributes' ) ) {
setViewAttributes(
writer,
modelElement.getAttribute( 'htmlCustomElementAttributes' ) as GHSViewAttributes,
viewElement
);
}

return viewElement;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from '../converters';
import DataFilter, { type DataFilterRegisterEvent } from '../datafilter';
import type { DataSchemaBlockElementDefinition } from '../dataschema';
import { getHtmlAttributeName } from '../utils';

/**
* Provides the General HTML Support integration for elements which can behave like sectioning element (e.g. article) or
Expand Down Expand Up @@ -139,7 +140,7 @@ export default class DualContentModelElementSupport extends Plugin {
const dataFilter = editor.plugins.get( DataFilter );

editor.model.schema.extend( definition.model, {
allowAttributes: 'htmlAttributes'
allowAttributes: getHtmlAttributeName( definition.view! )
} );

conversion.for( 'upcast' ).add( viewToModelBlockAttributeConverter( definition, dataFilter ) );
Expand Down
11 changes: 6 additions & 5 deletions packages/ckeditor5-html-support/src/integrations/heading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import {
} from 'ckeditor5/src/enter';

import DataSchema from '../dataschema';
import { modifyGhsAttribute } from '../utils';
import { getHtmlAttributeName, modifyGhsAttribute } from '../utils';
import type { HeadingElementOption } from '@ckeditor/ckeditor5-heading/src/headingconfig';

/**
* Provides the General HTML Support integration with {@link module:heading/heading~Heading Heading} feature.
Expand Down Expand Up @@ -80,20 +81,20 @@ export default class HeadingElementSupport extends Plugin {
}

/**
* Removes css classes from "htmlAttributes" of new paragraph created when hitting "enter" in heading.
* Removes css classes from "html*Attributes" of new paragraph created when hitting "enter" in heading.
*/
private removeClassesOnEnter( editor: Editor, options: Array<HeadingOption> ): void {
const enterCommand: EnterCommand = editor.commands.get( 'enter' )!;

this.listenTo<EnterCommandAfterExecuteEvent>( enterCommand, 'afterExecute', ( evt, data ) => {
const positionParent = editor.model.document.selection.getFirstPosition()!.parent;
const isHeading = options.some( option => positionParent.is( 'element', option.model ) );
const heading = options.find( ( option ): option is HeadingElementOption => positionParent.is( 'element', option.model ) );

if ( isHeading && positionParent.childCount === 0 ) {
if ( heading && positionParent.childCount === 0 ) {
modifyGhsAttribute(
data.writer,
positionParent as Item,
'htmlAttributes',
getHtmlAttributeName( heading.view as string ),
'classes',
classes => classes.clear()
);
Expand Down
12 changes: 6 additions & 6 deletions packages/ckeditor5-html-support/src/integrations/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type {
ViewElement } from 'ckeditor5/src/engine';

import DataFilter, { type DataFilterRegisterEvent } from '../datafilter';
import { type GHSViewAttributes, setViewAttributes, updateViewAttributes } from '../utils';
import { type GHSViewAttributes, setViewAttributes, updateViewAttributes, getHtmlAttributeName } from '../utils';
import { getDescendantElement } from './integrationutils';

/**
Expand Down Expand Up @@ -64,7 +64,7 @@ export default class ImageElementSupport extends Plugin {
if ( schema.isRegistered( 'imageBlock' ) ) {
schema.extend( 'imageBlock', {
allowAttributes: [
'htmlAttributes',
'htmlImgAttributes',
// Figure and Link don't have model counterpart.
// We will preserve attributes on image model element using these attribute keys.
'htmlFigureAttributes',
Expand All @@ -78,7 +78,7 @@ export default class ImageElementSupport extends Plugin {
allowAttributes: [
// `htmlA` is needed for standard GHS link integration.
'htmlA',
'htmlAttributes'
'htmlImgAttributes'
]
} );
}
Expand Down Expand Up @@ -107,7 +107,7 @@ function viewToModelImageAttributeConverter( dataFilter: DataFilter ) {
const viewImageElement = data.viewItem;
const viewContainerElement = viewImageElement.parent;

preserveElementAttributes( viewImageElement, 'htmlAttributes' );
preserveElementAttributes( viewImageElement, 'htmlImgAttributes' );

if ( viewContainerElement.is( 'element', 'a' ) ) {
preserveLinkAttributes( viewContainerElement );
Expand Down Expand Up @@ -161,9 +161,9 @@ function viewToModelFigureAttributeConverter( dataFilter: DataFilter ) {
*/
function modelToViewImageAttributeConverter() {
return ( dispatcher: DowncastDispatcher ) => {
addInlineAttributeConversion( 'htmlAttributes' );
addInlineAttributeConversion( 'htmlImgAttributes' );

addBlockAttributeConversion( 'img', 'htmlAttributes' );
addBlockAttributeConversion( 'img', 'htmlImgAttributes' );
addBlockAttributeConversion( 'figure', 'htmlFigureAttributes' );
addBlockAttributeConversion( 'a', 'htmlLinkAttributes' );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Plugin } from 'ckeditor5/src/core';

import DataFilter, { type DataFilterRegisterEvent } from '../datafilter';
import DataSchema from '../dataschema';
import { updateViewAttributes, type GHSViewAttributes } from '../utils';
import { updateViewAttributes, type GHSViewAttributes, getHtmlAttributeName } from '../utils';
import type {
DowncastAttributeEvent,
DowncastDispatcher,
Expand Down Expand Up @@ -75,7 +75,7 @@ export default class MediaEmbedElementSupport extends Plugin {

schema.extend( 'media', {
allowAttributes: [
'htmlAttributes',
getHtmlAttributeName( mediaElementName ),
'htmlFigureAttributes'
]
} );
Expand All @@ -92,7 +92,7 @@ function viewToModelMediaAttributesConverter( dataFilter: DataFilter, mediaEleme
const upcastMedia: GetCallback<UpcastElementEvent> = ( evt, data, conversionApi ) => {
const viewMediaElement = data.viewItem;

preserveElementAttributes( viewMediaElement, 'htmlAttributes' );
preserveElementAttributes( viewMediaElement, getHtmlAttributeName( mediaElementName ) );

function preserveElementAttributes( viewElement: ViewElement, attributeName: string ) {
const viewAttributes = dataFilter.processViewAttributes( viewElement, conversionApi );
Expand Down Expand Up @@ -133,7 +133,7 @@ function viewToModelFigureAttributesConverter( dataFilter: DataFilter ) {

function modelToViewMediaAttributeConverter( mediaElementName: string ) {
return ( dispatcher: DowncastDispatcher ) => {
addAttributeConversionDispatcherHandler( mediaElementName, 'htmlAttributes' );
addAttributeConversionDispatcherHandler( mediaElementName, getHtmlAttributeName( mediaElementName ) );
addAttributeConversionDispatcherHandler( 'figure', 'htmlFigureAttributes' );

function addAttributeConversionDispatcherHandler( elementName: string, attributeName: string ) {
Expand Down
Loading