mirror of
https://github.com/zadam/trilium.git
synced 2025-11-12 08:15:52 +01:00
chore(ckeditor5/plugins): integrate reference link
This commit is contained in:
@@ -1,14 +1,22 @@
|
||||
import "ckeditor5";
|
||||
|
||||
declare global {
|
||||
interface Component {
|
||||
triggerCommand(command: string): void;
|
||||
}
|
||||
|
||||
interface EditorComponent extends Component {
|
||||
loadReferenceLinkTitle($el: JQuery<HTMLElement>, href: string): Promise<void>;
|
||||
}
|
||||
|
||||
var glob: {
|
||||
getComponentByEl(el: unknown): {
|
||||
triggerCommand(command: string): void;
|
||||
};
|
||||
getComponentByEl<T extends Component>(el: unknown): T;
|
||||
getActiveContextNote(): {
|
||||
noteId: string;
|
||||
};
|
||||
getHeaders(): Promise<Record<string, string>>;
|
||||
getReferenceLinkTitle(href: string): Promise<string>;
|
||||
getReferenceLinkTitleSync(href: string): string;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ import UploadimagePlugin from "./plugins/uploadimage.js";
|
||||
import ItalicAsEmPlugin from "./plugins/italic_as_em.js";
|
||||
import StrikethroughAsDel from "./plugins/strikethrough_as_del.js";
|
||||
import InternalLinkPlugin from "./plugins/internallink.js";
|
||||
import ReferenceLink from "./plugins/referencelink.js";
|
||||
|
||||
const TRILIUM_PLUGINS: typeof Plugin[] = [
|
||||
CutToNotePlugin,
|
||||
ItalicAsEmPlugin,
|
||||
StrikethroughAsDel,
|
||||
ReferenceLink,
|
||||
UploadimagePlugin,
|
||||
InternalLinkPlugin
|
||||
];
|
||||
@@ -71,7 +73,6 @@ export const COMMON_PLUGINS: typeof Plugin[] = [
|
||||
// MarkdownImportPlugin,
|
||||
// MentionCustomization,
|
||||
// IncludeNote,
|
||||
// ReferenceLink,
|
||||
// indentBlockShortcutPlugin,
|
||||
// removeFormatLinksPlugin,
|
||||
PageBreak,
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import { ButtonView, Plugin } from 'ckeditor5';
|
||||
import internalLinkIcon from '../icons/trilium.svg?raw';
|
||||
import ReferenceLink from './referencelink';
|
||||
|
||||
export default class InternalLinkPlugin extends Plugin {
|
||||
|
||||
static get requires() {
|
||||
return [ ReferenceLink ];
|
||||
}
|
||||
|
||||
init() {
|
||||
const editor = this.editor;
|
||||
|
||||
|
||||
139
packages/ckeditor5/src/plugins/referencelink.ts
Normal file
139
packages/ckeditor5/src/plugins/referencelink.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
import { Command, Element, Plugin, toWidget, viewToModelPositionOutsideModelElement, Widget } from "ckeditor5";
|
||||
|
||||
export default class ReferenceLink extends Plugin {
|
||||
static get requires() {
|
||||
return [ ReferenceLinkEditing ];
|
||||
}
|
||||
}
|
||||
|
||||
class ReferenceLinkCommand extends Command {
|
||||
|
||||
execute({ href }: { href: string }) {
|
||||
if (!href?.trim()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const editor = this.editor;
|
||||
|
||||
// make sure the referenced note is in cache before adding the reference element
|
||||
glob.getReferenceLinkTitle(href).then(() => {
|
||||
editor.model.change(writer => {
|
||||
const placeholder = writer.createElement('reference', {href});
|
||||
|
||||
// ... and insert it into the document.
|
||||
editor.model.insertContent(placeholder);
|
||||
|
||||
// Put the selection on the inserted element.
|
||||
writer.setSelection(placeholder, 'after');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
refresh() {
|
||||
const model = this.editor.model;
|
||||
const selection = model.document.selection;
|
||||
this.isEnabled = selection.focus !== null && model.schema.checkChild(selection.focus.parent as Element, 'reference');
|
||||
}
|
||||
}
|
||||
|
||||
class ReferenceLinkEditing extends Plugin {
|
||||
static get requires() {
|
||||
return [ Widget ];
|
||||
}
|
||||
|
||||
init() {
|
||||
this._defineSchema();
|
||||
this._defineConverters();
|
||||
|
||||
this.editor.commands.add( 'referenceLink', new ReferenceLinkCommand( this.editor ) );
|
||||
|
||||
this.editor.editing.mapper.on(
|
||||
'viewToModelPosition',
|
||||
viewToModelPositionOutsideModelElement( this.editor.model,
|
||||
viewElement => viewElement.hasClass( 'reference-link' ) )
|
||||
);
|
||||
}
|
||||
|
||||
_defineSchema() {
|
||||
const schema = this.editor.model.schema;
|
||||
|
||||
schema.register( 'reference', {
|
||||
// Allow wherever a text is allowed:
|
||||
allowWhere: '$text',
|
||||
|
||||
isInline: true,
|
||||
|
||||
// The inline widget is self-contained, so it cannot be split by the caret, and it can be selected:
|
||||
isObject: true,
|
||||
|
||||
allowAttributes: [ 'href', 'uploadId', 'uploadStatus' ]
|
||||
} );
|
||||
}
|
||||
|
||||
_defineConverters() {
|
||||
const editor = this.editor;
|
||||
const conversion = editor.conversion;
|
||||
|
||||
conversion.for( 'upcast' ).elementToElement( {
|
||||
view: {
|
||||
name: 'a',
|
||||
classes: [ 'reference-link' ]
|
||||
},
|
||||
model: ( viewElement, { writer: modelWriter } ) => {
|
||||
const href = viewElement.getAttribute('href');
|
||||
|
||||
return modelWriter.createElement( 'reference', { href } );
|
||||
}
|
||||
} );
|
||||
|
||||
conversion.for( 'editingDowncast' ).elementToElement( {
|
||||
model: 'reference',
|
||||
view: ( modelItem, { writer: viewWriter } ) => {
|
||||
const href = modelItem.getAttribute('href') as string;
|
||||
|
||||
const referenceLinkView = viewWriter.createContainerElement( 'a', {
|
||||
href,
|
||||
class: 'reference-link'
|
||||
},
|
||||
{
|
||||
renderUnsafeAttributes: [ 'href' ]
|
||||
} );
|
||||
|
||||
const noteTitleView = viewWriter.createUIElement('span', {}, function( domDocument ) {
|
||||
const domElement = this.toDomElement( domDocument );
|
||||
|
||||
const editorEl = editor.editing.view.getDomRoot();
|
||||
const component = glob.getComponentByEl<EditorComponent>(editorEl);
|
||||
|
||||
component.loadReferenceLinkTitle($(domElement), href);
|
||||
|
||||
return domElement;
|
||||
});
|
||||
|
||||
viewWriter.insert( viewWriter.createPositionAt( referenceLinkView, 0 ), noteTitleView );
|
||||
|
||||
// Enable widget handling on a reference element inside the editing view.
|
||||
return toWidget( referenceLinkView, viewWriter );
|
||||
}
|
||||
} );
|
||||
|
||||
conversion.for( 'dataDowncast' ).elementToElement( {
|
||||
model: 'reference',
|
||||
view: ( modelItem, { writer: viewWriter } ) => {
|
||||
const href = modelItem.getAttribute('href') as string;
|
||||
|
||||
const referenceLinkView = viewWriter.createContainerElement( 'a', {
|
||||
href: href,
|
||||
class: 'reference-link'
|
||||
} );
|
||||
|
||||
const title = glob.getReferenceLinkTitleSync(href);
|
||||
|
||||
const innerText = viewWriter.createText(title);
|
||||
viewWriter.insert(viewWriter.createPositionAt(referenceLinkView, 0), innerText);
|
||||
|
||||
return referenceLinkView;
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user