mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +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 | ||||
|  */ | ||||
|  | ||||
| // TODO: Change me. | ||||
| type AdmonitionType = string; | ||||
|  | ||||
| export default class AdmonitionCommand extends Command { | ||||
| 	/** | ||||
| 	 * Whether the selection starts in a block quote. | ||||
| @@ -23,7 +27,7 @@ export default class AdmonitionCommand extends Command { | ||||
| 	 * @observable | ||||
| 	 * @readonly | ||||
| 	 */ | ||||
| 	declare public value: boolean; | ||||
| 	declare public value: AdmonitionType | false; | ||||
|  | ||||
| 	/** | ||||
| 	 * @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, | ||||
| 	 * 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 schema = model.schema; | ||||
| 		const selection = model.document.selection; | ||||
| @@ -51,6 +55,8 @@ export default class AdmonitionCommand extends Command { | ||||
| 		const blocks = Array.from( selection.getSelectedBlocks() ); | ||||
|  | ||||
| 		const value = ( options.forceValue === undefined ) ? !this.value : options.forceValue; | ||||
| 		// TODO: Fix me. | ||||
| 		const valueString = (typeof value === "string" ? value : "note"); | ||||
|  | ||||
| 		model.change( writer => { | ||||
| 			if ( !value ) { | ||||
| @@ -62,7 +68,7 @@ export default class AdmonitionCommand extends Command { | ||||
| 					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}. | ||||
| 	 */ | ||||
| 	private _getValue(): boolean { | ||||
| 	private _getValue(): AdmonitionType | false { | ||||
| 		const selection = this.editor.model.document.selection; | ||||
|  | ||||
| 		const firstBlock = first( selection.getSelectedBlocks() ); | ||||
|  | ||||
| 		// 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. | ||||
| 	 */ | ||||
| 	private _applyQuote( writer: Writer, blocks: Array<Element> ): void { | ||||
| 	private _applyQuote( writer: Writer, blocks: Array<Element>, type?: AdmonitionType | false): void { | ||||
| 		const quotesToMerge: Array<Element | DocumentFragment> = []; | ||||
|  | ||||
| 		// 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 ); | ||||
|  | ||||
| 			if ( !quote ) { | ||||
| 				quote = writer.createElement( 'aside' ); | ||||
| 				quote = writer.createElement( 'aside', { type }); | ||||
|  | ||||
| 				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 AdmonitionCommand from './admonitioncommand.js'; | ||||
| import { ADMONITION_TYPES } from './admonitionui.js'; | ||||
|  | ||||
| /** | ||||
|  * The block quote editing. | ||||
| @@ -45,14 +46,38 @@ export default class AdmonitionEditing extends Plugin { | ||||
| 		editor.commands.add( 'admonition', new AdmonitionCommand( editor ) ); | ||||
|  | ||||
| 		schema.register( 'aside', { | ||||
| 			inheritAllFrom: '$container' | ||||
| 			inheritAllFrom: '$container', | ||||
| 			allowAttributes: "type" | ||||
| 		} ); | ||||
|  | ||||
| 		editor.conversion.elementToElement( { | ||||
| 			model: 'aside', | ||||
| 		editor.conversion.for("upcast").elementToElement({ | ||||
| 			view: { | ||||
| 				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; | ||||
| } | ||||
|  | ||||
| const ADMONITION_TYPES: Record<string, AdmonitionDefinition> = { | ||||
| export const ADMONITION_TYPES: Record<string, AdmonitionDefinition> = { | ||||
| 	"note": { | ||||
| 		title: "Note" | ||||
| 	}, | ||||
| @@ -71,28 +71,28 @@ export default class AdmonitionUI extends Plugin { | ||||
| 		const editor = this.editor; | ||||
| 		const locale = editor.locale; | ||||
| 		const command = editor.commands.get( 'admonition' )!; | ||||
| 		const view = createDropdown(locale); | ||||
| 		const dropdownView = createDropdown(locale); | ||||
| 		const t = locale.t; | ||||
|  | ||||
| 		addListToDropdown(view, this._getDropdownItems()) | ||||
| 		addListToDropdown(dropdownView, this._getDropdownItems()) | ||||
|  | ||||
| 		view.buttonView.set( { | ||||
| 		dropdownView.buttonView.set( { | ||||
| 			label: t( 'Admonition' ), | ||||
| 			icon: admonitionIcon, | ||||
| 			isToggleable: true, | ||||
| 			tooltip: true | ||||
| 		} ); | ||||
|  | ||||
| 		view.bind( 'isEnabled' ).to( command, 'isEnabled' ); | ||||
| 		dropdownView.bind( 'isEnabled' ).to( command, 'isEnabled' ); | ||||
| 		// view.buttonView.bind( 'isOn' ).to( command, 'value' ); | ||||
|  | ||||
| 		// Execute the command. | ||||
| 		this.listenTo( view, 'execute', () => { | ||||
| 			editor.execute( 'admonition' ); | ||||
| 		this.listenTo(dropdownView, 'execute', evt => { | ||||
| 			editor.execute("admonition", { forceValue: ( evt.source as any ).commandParam } ); | ||||
| 			editor.editing.view.focus(); | ||||
| 		} ); | ||||
| 		}); | ||||
|  | ||||
| 		return view; | ||||
| 		return dropdownView; | ||||
| 	} | ||||
|  | ||||
| 	private _getDropdownItems() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user