mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	feat(admonitions): allow selecting admonition type
This commit is contained in:
		| @@ -16,6 +16,10 @@ import type { DocumentFragment, Element, Position, Range, Schema, Writer } from | |||||||
|  * |  * | ||||||
|  * @extends module:core/command~Command |  * @extends module:core/command~Command | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | // TODO: Change me. | ||||||
|  | type AdmonitionType = string; | ||||||
|  |  | ||||||
| export default class AdmonitionCommand extends Command { | export default class AdmonitionCommand extends Command { | ||||||
| 	/** | 	/** | ||||||
| 	 * Whether the selection starts in a block quote. | 	 * Whether the selection starts in a block quote. | ||||||
| @@ -23,7 +27,7 @@ export default class AdmonitionCommand extends Command { | |||||||
| 	 * @observable | 	 * @observable | ||||||
| 	 * @readonly | 	 * @readonly | ||||||
| 	 */ | 	 */ | ||||||
| 	declare public value: boolean; | 	declare public value: AdmonitionType | false; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @inheritDoc | 	 * @inheritDoc | ||||||
| @@ -43,7 +47,7 @@ export default class AdmonitionCommand extends Command { | |||||||
| 	 * @param options.forceValue If set, it will force the command behavior. If `true`, the command will apply a block quote, | 	 * @param options.forceValue If set, it will force the command behavior. If `true`, the command will apply a block quote, | ||||||
| 	 * otherwise the command will remove the block quote. If not set, the command will act basing on its current value. | 	 * otherwise the command will remove the block quote. If not set, the command will act basing on its current value. | ||||||
| 	 */ | 	 */ | ||||||
| 	public override execute( options: { forceValue?: boolean } = {} ): void { | 	public override execute( options: { forceValue?: AdmonitionType } = {} ): void { | ||||||
| 		const model = this.editor.model; | 		const model = this.editor.model; | ||||||
| 		const schema = model.schema; | 		const schema = model.schema; | ||||||
| 		const selection = model.document.selection; | 		const selection = model.document.selection; | ||||||
| @@ -51,6 +55,8 @@ export default class AdmonitionCommand extends Command { | |||||||
| 		const blocks = Array.from( selection.getSelectedBlocks() ); | 		const blocks = Array.from( selection.getSelectedBlocks() ); | ||||||
|  |  | ||||||
| 		const value = ( options.forceValue === undefined ) ? !this.value : options.forceValue; | 		const value = ( options.forceValue === undefined ) ? !this.value : options.forceValue; | ||||||
|  | 		// TODO: Fix me. | ||||||
|  | 		const valueString = (typeof value === "string" ? value : "note"); | ||||||
|  |  | ||||||
| 		model.change( writer => { | 		model.change( writer => { | ||||||
| 			if ( !value ) { | 			if ( !value ) { | ||||||
| @@ -62,7 +68,7 @@ export default class AdmonitionCommand extends Command { | |||||||
| 					return findQuote( block ) || checkCanBeQuoted( schema, block ); | 					return findQuote( block ) || checkCanBeQuoted( schema, block ); | ||||||
| 				} ); | 				} ); | ||||||
|  |  | ||||||
| 				this._applyQuote( writer, blocksToQuote ); | 				this._applyQuote( writer, blocksToQuote, valueString); | ||||||
| 			} | 			} | ||||||
| 		} ); | 		} ); | ||||||
| 	} | 	} | ||||||
| @@ -70,13 +76,15 @@ export default class AdmonitionCommand extends Command { | |||||||
| 	/** | 	/** | ||||||
| 	 * Checks the command's {@link #value}. | 	 * Checks the command's {@link #value}. | ||||||
| 	 */ | 	 */ | ||||||
| 	private _getValue(): boolean { | 	private _getValue(): AdmonitionType | false { | ||||||
| 		const selection = this.editor.model.document.selection; | 		const selection = this.editor.model.document.selection; | ||||||
|  |  | ||||||
| 		const firstBlock = first( selection.getSelectedBlocks() ); | 		const firstBlock = first( selection.getSelectedBlocks() ); | ||||||
|  |  | ||||||
| 		// In the current implementation, the block quote must be an immediate parent of a block element. | 		// In the current implementation, the block quote must be an immediate parent of a block element. | ||||||
| 		return !!( firstBlock && findQuote( firstBlock ) ); | 		// TODO: Read correct quote. | ||||||
|  | 		const result = !!( firstBlock && findQuote( firstBlock ) ); | ||||||
|  | 		return result ? "note" : false; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -143,7 +151,7 @@ export default class AdmonitionCommand extends Command { | |||||||
| 	/** | 	/** | ||||||
| 	 * Applies the quote to given blocks. | 	 * Applies the quote to given blocks. | ||||||
| 	 */ | 	 */ | ||||||
| 	private _applyQuote( writer: Writer, blocks: Array<Element> ): void { | 	private _applyQuote( writer: Writer, blocks: Array<Element>, type?: AdmonitionType | false): void { | ||||||
| 		const quotesToMerge: Array<Element | DocumentFragment> = []; | 		const quotesToMerge: Array<Element | DocumentFragment> = []; | ||||||
|  |  | ||||||
| 		// Quote all groups of block. Iterate in the reverse order to not break following ranges. | 		// Quote all groups of block. Iterate in the reverse order to not break following ranges. | ||||||
| @@ -151,7 +159,7 @@ export default class AdmonitionCommand extends Command { | |||||||
| 			let quote = findQuote( groupRange.start ); | 			let quote = findQuote( groupRange.start ); | ||||||
|  |  | ||||||
| 			if ( !quote ) { | 			if ( !quote ) { | ||||||
| 				quote = writer.createElement( 'aside' ); | 				quote = writer.createElement( 'aside', { type }); | ||||||
|  |  | ||||||
| 				writer.wrap( groupRange, quote ); | 				writer.wrap( groupRange, quote ); | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ import { Enter, type ViewDocumentEnterEvent } from 'ckeditor5/src/enter.js'; | |||||||
| import { Delete, type ViewDocumentDeleteEvent } from 'ckeditor5/src/typing.js'; | import { Delete, type ViewDocumentDeleteEvent } from 'ckeditor5/src/typing.js'; | ||||||
|  |  | ||||||
| import AdmonitionCommand from './admonitioncommand.js'; | import AdmonitionCommand from './admonitioncommand.js'; | ||||||
|  | import { ADMONITION_TYPES } from './admonitionui.js'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * The block quote editing. |  * The block quote editing. | ||||||
| @@ -45,14 +46,38 @@ export default class AdmonitionEditing extends Plugin { | |||||||
| 		editor.commands.add( 'admonition', new AdmonitionCommand( editor ) ); | 		editor.commands.add( 'admonition', new AdmonitionCommand( editor ) ); | ||||||
|  |  | ||||||
| 		schema.register( 'aside', { | 		schema.register( 'aside', { | ||||||
| 			inheritAllFrom: '$container' | 			inheritAllFrom: '$container', | ||||||
|  | 			allowAttributes: "type" | ||||||
| 		} ); | 		} ); | ||||||
|  |  | ||||||
| 		editor.conversion.elementToElement( { | 		editor.conversion.for("upcast").elementToElement({ | ||||||
| 			model: 'aside', |  | ||||||
| 			view: { | 			view: { | ||||||
| 				name: "aside", | 				name: "aside", | ||||||
| 				classes: "admonition" | 				classes: "admonition", | ||||||
|  | 			}, | ||||||
|  | 			model: (viewElement, { writer }) => { | ||||||
|  | 				let type = "note"; | ||||||
|  | 				const allowedTypes = Object.keys(ADMONITION_TYPES); | ||||||
|  | 				for (const className of viewElement.getClassNames()) { | ||||||
|  | 					if (className !== "admonition" && allowedTypes.includes(className)) { | ||||||
|  | 						type = className; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				return writer.createElement("aside", { | ||||||
|  | 					type | ||||||
|  | 				}); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  |  | ||||||
|  | 		editor.conversion.for("downcast").elementToElement( { | ||||||
|  | 			model: 'aside', | ||||||
|  | 			view: (modelElement, { writer }) => { | ||||||
|  | 				return writer.createContainerElement( | ||||||
|  | 					"aside", { | ||||||
|  | 						class: [ "admonition", modelElement.getAttribute("type") ].join(" ") | ||||||
|  | 					} | ||||||
|  | 				) | ||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ interface AdmonitionDefinition { | |||||||
| 	title: string; | 	title: string; | ||||||
| } | } | ||||||
|  |  | ||||||
| const ADMONITION_TYPES: Record<string, AdmonitionDefinition> = { | export const ADMONITION_TYPES: Record<string, AdmonitionDefinition> = { | ||||||
| 	"note": { | 	"note": { | ||||||
| 		title: "Note" | 		title: "Note" | ||||||
| 	}, | 	}, | ||||||
| @@ -71,28 +71,28 @@ export default class AdmonitionUI extends Plugin { | |||||||
| 		const editor = this.editor; | 		const editor = this.editor; | ||||||
| 		const locale = editor.locale; | 		const locale = editor.locale; | ||||||
| 		const command = editor.commands.get( 'admonition' )!; | 		const command = editor.commands.get( 'admonition' )!; | ||||||
| 		const view = createDropdown(locale); | 		const dropdownView = createDropdown(locale); | ||||||
| 		const t = locale.t; | 		const t = locale.t; | ||||||
|  |  | ||||||
| 		addListToDropdown(view, this._getDropdownItems()) | 		addListToDropdown(dropdownView, this._getDropdownItems()) | ||||||
|  |  | ||||||
| 		view.buttonView.set( { | 		dropdownView.buttonView.set( { | ||||||
| 			label: t( 'Admonition' ), | 			label: t( 'Admonition' ), | ||||||
| 			icon: admonitionIcon, | 			icon: admonitionIcon, | ||||||
| 			isToggleable: true, | 			isToggleable: true, | ||||||
| 			tooltip: true | 			tooltip: true | ||||||
| 		} ); | 		} ); | ||||||
|  |  | ||||||
| 		view.bind( 'isEnabled' ).to( command, 'isEnabled' ); | 		dropdownView.bind( 'isEnabled' ).to( command, 'isEnabled' ); | ||||||
| 		// view.buttonView.bind( 'isOn' ).to( command, 'value' ); | 		// view.buttonView.bind( 'isOn' ).to( command, 'value' ); | ||||||
|  |  | ||||||
| 		// Execute the command. | 		// Execute the command. | ||||||
| 		this.listenTo( view, 'execute', () => { | 		this.listenTo(dropdownView, 'execute', evt => { | ||||||
| 			editor.execute( 'admonition' ); | 			editor.execute("admonition", { forceValue: ( evt.source as any ).commandParam } ); | ||||||
| 			editor.editing.view.focus(); | 			editor.editing.view.focus(); | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
| 		return view; | 		return dropdownView; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	private _getDropdownItems() { | 	private _getDropdownItems() { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user