-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13149 from ckeditor/ck/13026
Other (alignment): Rewrite ckeditor5-page-break to TypeScript. Closes #13026.
- Loading branch information
Showing
14 changed files
with
355 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/** | ||
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license | ||
*/ | ||
|
||
/** | ||
* @module page-break | ||
*/ | ||
|
||
export { default as PageBreak } from './pagebreak'; | ||
export { default as PageBreakEditing } from './pagebreakediting'; | ||
export { default as PageBreakUI } from './pagebreakui'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/** | ||
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license | ||
*/ | ||
|
||
/** | ||
* @module page-break/pagebreak | ||
*/ | ||
|
||
import { Plugin, type PluginDependencies } from 'ckeditor5/src/core'; | ||
import { Widget } from 'ckeditor5/src/widget'; | ||
|
||
import PageBreakEditing from './pagebreakediting'; | ||
import PageBreakUI from './pagebreakui'; | ||
|
||
/** | ||
* The page break feature. | ||
* | ||
* It provides the possibility to insert a page break into the rich-text editor. | ||
* | ||
* For a detailed overview, check the {@glink features/page-break Page break feature} documentation. | ||
*/ | ||
export default class PageBreak extends Plugin { | ||
/** | ||
* @inheritDoc | ||
*/ | ||
public static get requires(): PluginDependencies { | ||
return [ PageBreakEditing, PageBreakUI, Widget ]; | ||
} | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
public static get pluginName(): 'PageBreak' { | ||
return 'PageBreak'; | ||
} | ||
} | ||
|
||
declare module '@ckeditor/ckeditor5-core' { | ||
interface PluginsMap { | ||
[ PageBreak.pluginName ]: PageBreak; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/** | ||
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license | ||
*/ | ||
|
||
/** | ||
* @module page-break/pagebreakcommand | ||
*/ | ||
|
||
import { Command } from 'ckeditor5/src/core'; | ||
import { findOptimalInsertionRange } from 'ckeditor5/src/widget'; | ||
import type { DocumentSelection, Element, Model, Schema } from 'ckeditor5/src/engine'; | ||
|
||
/** | ||
* The page break command. | ||
* | ||
* The command is registered by {@link module:page-break/pagebreakediting~PageBreakEditing} as `'pageBreak'`. | ||
* | ||
* To insert a page break at the current selection, execute the command: | ||
* | ||
* editor.execute( 'pageBreak' ); | ||
*/ | ||
export default class PageBreakCommand extends Command { | ||
/** | ||
* @inheritDoc | ||
*/ | ||
public override refresh(): void { | ||
const model = this.editor.model; | ||
const schema = model.schema; | ||
const selection = model.document.selection; | ||
|
||
this.isEnabled = isPageBreakAllowedInParent( selection, schema, model ); | ||
} | ||
|
||
/** | ||
* Executes the command. | ||
* | ||
* @fires execute | ||
*/ | ||
public override execute(): void { | ||
const model = this.editor.model; | ||
|
||
model.change( writer => { | ||
const pageBreakElement = writer.createElement( 'pageBreak' ); | ||
|
||
model.insertObject( pageBreakElement, null, null, { | ||
setSelection: 'after' | ||
} ); | ||
} ); | ||
} | ||
} | ||
|
||
/** | ||
* Checks if a page break is allowed by the schema in the optimal insertion parent. | ||
*/ | ||
function isPageBreakAllowedInParent( selection: DocumentSelection, schema: Schema, model: Model ): boolean { | ||
const parent = getInsertPageBreakParent( selection, model ); | ||
|
||
return schema.checkChild( parent, 'pageBreak' ); | ||
} | ||
|
||
/** | ||
* Returns a node that will be used to insert a page break with `model.insertContent` to check if the page break can be placed there. | ||
*/ | ||
function getInsertPageBreakParent( selection: DocumentSelection, model: Model ): Element { | ||
const insertionRange = findOptimalInsertionRange( selection, model ); | ||
const parent = insertionRange.start.parent; | ||
|
||
if ( parent.isEmpty && !parent.is( 'element', '$root' ) ) { | ||
return parent.parent as Element; | ||
} | ||
|
||
return parent as Element; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
/** | ||
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license | ||
*/ | ||
|
||
/** | ||
* @module page-break/pagebreakediting | ||
*/ | ||
|
||
import { Plugin } from 'ckeditor5/src/core'; | ||
import { toWidget } from 'ckeditor5/src/widget'; | ||
import type { DowncastWriter, ViewElement } from 'ckeditor5/src/engine'; | ||
|
||
import PageBreakCommand from './pagebreakcommand'; | ||
|
||
import '../theme/pagebreak.css'; | ||
|
||
/** | ||
* The page break editing feature. | ||
*/ | ||
export default class PageBreakEditing extends Plugin { | ||
/** | ||
* @inheritDoc | ||
*/ | ||
public static get pluginName(): 'PageBreakEditing' { | ||
return 'PageBreakEditing'; | ||
} | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
public init(): void { | ||
const editor = this.editor; | ||
const schema = editor.model.schema; | ||
const t = editor.t; | ||
const conversion = editor.conversion; | ||
|
||
schema.register( 'pageBreak', { | ||
inheritAllFrom: '$blockObject' | ||
} ); | ||
|
||
conversion.for( 'dataDowncast' ).elementToStructure( { | ||
model: 'pageBreak', | ||
view: ( modelElement, { writer } ) => { | ||
const divElement = writer.createContainerElement( 'div', | ||
{ | ||
class: 'page-break', | ||
// If user has no `.ck-content` styles, it should always break a page during print. | ||
style: 'page-break-after: always' | ||
}, | ||
// For a rationale of using span inside a div see: | ||
// https://github.com/ckeditor/ckeditor5-page-break/pull/1#discussion_r328934062. | ||
writer.createContainerElement( 'span', { | ||
style: 'display: none' | ||
} ) | ||
); | ||
|
||
return divElement; | ||
} | ||
} ); | ||
|
||
conversion.for( 'editingDowncast' ).elementToStructure( { | ||
model: 'pageBreak', | ||
view: ( modelElement, { writer } ) => { | ||
const label = t( 'Page break' ); | ||
const viewWrapper = writer.createContainerElement( 'div' ); | ||
const viewLabelElement = writer.createRawElement( | ||
'span', | ||
{ class: 'page-break__label' }, | ||
function( domElement ) { | ||
domElement.innerText = t( 'Page break' ); | ||
} | ||
); | ||
|
||
writer.addClass( 'page-break', viewWrapper ); | ||
writer.insert( writer.createPositionAt( viewWrapper, 0 ), viewLabelElement ); | ||
|
||
return toPageBreakWidget( viewWrapper, writer, label ); | ||
} | ||
} ); | ||
|
||
conversion.for( 'upcast' ) | ||
.elementToElement( { | ||
view: element => { | ||
// For upcast conversion it's enough if we check for element style and verify if it's empty | ||
// or contains only hidden span element. | ||
|
||
const hasPageBreakBefore = element.getStyle( 'page-break-before' ) == 'always'; | ||
const hasPageBreakAfter = element.getStyle( 'page-break-after' ) == 'always'; | ||
|
||
if ( !hasPageBreakBefore && !hasPageBreakAfter ) { | ||
return null; | ||
} | ||
|
||
// The "page break" div accepts only single child or no child at all. | ||
if ( element.childCount == 1 ) { | ||
const viewSpan = element.getChild( 0 ); | ||
|
||
// The child must be the "span" element that is not displayed. | ||
if ( !viewSpan!.is( 'element', 'span' ) || viewSpan.getStyle( 'display' ) != 'none' ) { | ||
return null; | ||
} | ||
} else if ( element.childCount > 1 ) { | ||
return null; | ||
} | ||
|
||
return { name: true }; | ||
}, | ||
model: 'pageBreak', | ||
|
||
// This conversion must be checked before <br> conversion because some editors use | ||
// <br style="page-break-before:always"> as a page break marker. | ||
converterPriority: 'high' | ||
} ); | ||
|
||
editor.commands.add( 'pageBreak', new PageBreakCommand( editor ) ); | ||
} | ||
} | ||
|
||
/** | ||
* Converts a given {@link module:engine/view/element~Element} to a page break widget: | ||
* * Adds a {@link module:engine/view/element~Element#_setCustomProperty custom property} allowing to | ||
* recognize the page break widget element. | ||
* * Calls the {@link module:widget/utils~toWidget} function with the proper element's label creator. | ||
*/ | ||
function toPageBreakWidget( viewElement: ViewElement, writer: DowncastWriter, label: string ): ViewElement { | ||
writer.setCustomProperty( 'pageBreak', true, viewElement ); | ||
|
||
return toWidget( viewElement, writer, { label } ); | ||
} | ||
|
||
declare module '@ckeditor/ckeditor5-core' { | ||
interface CommandsMap { | ||
pageBreak: PageBreakCommand; | ||
} | ||
|
||
interface PluginsMap { | ||
[ PageBreakEditing.pluginName ]: PageBreakEditing; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/** | ||
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license | ||
*/ | ||
|
||
/** | ||
* @module page-break/pagebreakui | ||
*/ | ||
|
||
import { Plugin } from 'ckeditor5/src/core'; | ||
import { ButtonView } from 'ckeditor5/src/ui'; | ||
|
||
import pageBreakIcon from '../theme/icons/pagebreak.svg'; | ||
|
||
/** | ||
* The page break UI plugin. | ||
*/ | ||
export default class PageBreakUI extends Plugin { | ||
/** | ||
* @inheritDoc | ||
*/ | ||
public static get pluginName(): 'PageBreakUI' { | ||
return 'PageBreakUI'; | ||
} | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
public init(): void { | ||
const editor = this.editor; | ||
const t = editor.t; | ||
|
||
// Add pageBreak button to feature components. | ||
editor.ui.componentFactory.add( 'pageBreak', locale => { | ||
const command = editor.commands.get( 'pageBreak' )!; | ||
const view = new ButtonView( locale ); | ||
|
||
view.set( { | ||
label: t( 'Page break' ), | ||
icon: pageBreakIcon, | ||
tooltip: true | ||
} ); | ||
|
||
view.bind( 'isEnabled' ).to( command, 'isEnabled' ); | ||
|
||
// Execute command. | ||
this.listenTo( view, 'execute', () => { | ||
editor.execute( 'pageBreak' ); | ||
editor.editing.view.focus(); | ||
} ); | ||
|
||
return view; | ||
} ); | ||
} | ||
} | ||
|
||
declare module '@ckeditor/ckeditor5-core' { | ||
interface PluginsMap { | ||
[ PageBreakUI.pluginName ]: PageBreakUI; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"extends": "ckeditor5/tsconfig.json", | ||
"include": [ | ||
"src", | ||
"../../typings" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"extends": "../../tsconfig.release.json", | ||
"include": [ | ||
"./src/", | ||
"../../typings/" | ||
], | ||
"exclude": [ | ||
"./tests/" | ||
] | ||
} |