mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-08-19 00:42:29 +08:00
fixed issues
This commit is contained in:
parent
e11c36e5b5
commit
7e08b63636
@ -7,7 +7,7 @@ import {
|
|||||||
toWidgetEditable } from 'ckeditor5';
|
toWidgetEditable } from 'ckeditor5';
|
||||||
|
|
||||||
import { ATTRIBUTES, CLASSES, ELEMENTS } from '../constants.js';
|
import { ATTRIBUTES, CLASSES, ELEMENTS } from '../constants.js';
|
||||||
import { viewQueryElement, viewQueryText } from '../utils.js';
|
import { viewQueryElement } from '../utils.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines methods for converting between model, data view, and editing view representations of each element type.
|
* Defines methods for converting between model, data view, and editing view representations of each element type.
|
||||||
@ -107,7 +107,6 @@ export const defineConverters = ( editor: Editor ): void => {
|
|||||||
[ ATTRIBUTES.footnoteContent ]: '',
|
[ ATTRIBUTES.footnoteContent ]: '',
|
||||||
class: CLASSES.footnoteContent
|
class: CLASSES.footnoteContent
|
||||||
} );
|
} );
|
||||||
console.log( 'section', section );
|
|
||||||
|
|
||||||
return toWidgetEditable( section, viewWriter );
|
return toWidgetEditable( section, viewWriter );
|
||||||
}
|
}
|
||||||
@ -163,6 +162,7 @@ export const defineConverters = ( editor: Editor ): void => {
|
|||||||
const modelWriter = conversionApi.writer;
|
const modelWriter = conversionApi.writer;
|
||||||
const index = viewElement.getAttribute( ATTRIBUTES.footnoteIndex );
|
const index = viewElement.getAttribute( ATTRIBUTES.footnoteIndex );
|
||||||
const id = viewElement.getAttribute( ATTRIBUTES.footnoteId );
|
const id = viewElement.getAttribute( ATTRIBUTES.footnoteId );
|
||||||
|
|
||||||
if ( index === undefined || id === undefined ) {
|
if ( index === undefined || id === undefined ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -179,7 +179,6 @@ export const defineConverters = ( editor: Editor ): void => {
|
|||||||
view: ( modelElement, conversionApi ) => {
|
view: ( modelElement, conversionApi ) => {
|
||||||
const viewWriter = conversionApi.writer;
|
const viewWriter = conversionApi.writer;
|
||||||
const footnoteReferenceViewElement = createFootnoteReferenceViewElement( modelElement, conversionApi );
|
const footnoteReferenceViewElement = createFootnoteReferenceViewElement( modelElement, conversionApi );
|
||||||
console.log( 'footnoteReferenceViewElement', footnoteReferenceViewElement );
|
|
||||||
return toWidget( footnoteReferenceViewElement, viewWriter );
|
return toWidget( footnoteReferenceViewElement, viewWriter );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
@ -193,13 +192,13 @@ export const defineConverters = ( editor: Editor ): void => {
|
|||||||
* When that event fires, the callback function below updates the displayed view of the footnote reference in the
|
* When that event fires, the callback function below updates the displayed view of the footnote reference in the
|
||||||
* editor to match the new index.
|
* editor to match the new index.
|
||||||
*/
|
*/
|
||||||
// conversion.for( 'editingDowncast' ).add( dispatcher => {
|
conversion.for( 'editingDowncast' ).add( dispatcher => {
|
||||||
// dispatcher.on(
|
dispatcher.on(
|
||||||
// `attribute:${ ATTRIBUTES.footnoteIndex }:${ ELEMENTS.footnoteReference }`,
|
`attribute:${ ATTRIBUTES.footnoteIndex }:${ ELEMENTS.footnoteReference }`,
|
||||||
// ( _, data, conversionApi ) => updateFootnoteReferenceView( data, conversionApi, editor ),
|
( _, data, conversionApi ) => updateFootnoteReferenceView( data, conversionApi, editor ),
|
||||||
// { priority: 'high' }
|
{ priority: 'high' }
|
||||||
// );
|
);
|
||||||
// } );
|
} );
|
||||||
|
|
||||||
/** *********************************Footnote Back Link Conversion************************************/
|
/** *********************************Footnote Back Link Conversion************************************/
|
||||||
|
|
||||||
@ -274,7 +273,6 @@ function createFootnoteReferenceViewElement(
|
|||||||
modelElement: Element,
|
modelElement: Element,
|
||||||
conversionApi: DowncastConversionApi
|
conversionApi: DowncastConversionApi
|
||||||
): ViewContainerElement {
|
): ViewContainerElement {
|
||||||
console.log( 'createFootnoteReferenceViewElement' );
|
|
||||||
const viewWriter = conversionApi.writer;
|
const viewWriter = conversionApi.writer;
|
||||||
const index = `${ modelElement.getAttribute( ATTRIBUTES.footnoteIndex ) }`;
|
const index = `${ modelElement.getAttribute( ATTRIBUTES.footnoteIndex ) }`;
|
||||||
const id = `${ modelElement.getAttribute( ATTRIBUTES.footnoteId ) }`;
|
const id = `${ modelElement.getAttribute( ATTRIBUTES.footnoteId ) }`;
|
||||||
@ -285,9 +283,6 @@ function createFootnoteReferenceViewElement(
|
|||||||
throw new Error( 'Footnote reference has no provided id.' );
|
throw new Error( 'Footnote reference has no provided id.' );
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log( 'index', index );
|
|
||||||
console.log( 'id', id );
|
|
||||||
|
|
||||||
const footnoteReferenceView = viewWriter.createContainerElement( 'span', {
|
const footnoteReferenceView = viewWriter.createContainerElement( 'span', {
|
||||||
class: CLASSES.footnoteReference,
|
class: CLASSES.footnoteReference,
|
||||||
[ ATTRIBUTES.footnoteReference ]: '',
|
[ ATTRIBUTES.footnoteReference ]: '',
|
||||||
@ -364,15 +359,14 @@ function updateFootnoteReferenceView(
|
|||||||
|
|
||||||
const viewWriter = conversionApi.writer;
|
const viewWriter = conversionApi.writer;
|
||||||
|
|
||||||
const textNode = viewQueryText( editor, footnoteReferenceView, _ => true );
|
|
||||||
const anchor = viewQueryElement( editor, footnoteReferenceView, element => element.name === 'a' );
|
const anchor = viewQueryElement( editor, footnoteReferenceView, element => element.name === 'a' );
|
||||||
|
const textNode = anchor?.getChild( 0 );
|
||||||
|
|
||||||
if ( !textNode || !anchor ) {
|
if ( !textNode || !anchor ) {
|
||||||
viewWriter.remove( footnoteReferenceView );
|
viewWriter.remove( footnoteReferenceView );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error TextNode not accepted
|
|
||||||
viewWriter.remove( textNode );
|
viewWriter.remove( textNode );
|
||||||
const innerText = viewWriter.createText( `[${ newIndex }]` );
|
const innerText = viewWriter.createText( `[${ newIndex }]` );
|
||||||
viewWriter.insert( viewWriter.createPositionAt( anchor, 0 ), innerText );
|
viewWriter.insert( viewWriter.createPositionAt( anchor, 0 ), innerText );
|
||||||
|
@ -53,7 +53,6 @@ export default class FootnoteEditing extends Plugin {
|
|||||||
'change:data',
|
'change:data',
|
||||||
( eventInfo, batch ) => {
|
( eventInfo, batch ) => {
|
||||||
const eventSource: any = eventInfo.source;
|
const eventSource: any = eventInfo.source;
|
||||||
console.log( eventSource.differ.getChanges() );
|
|
||||||
const diffItems = [ ...eventSource.differ.getChanges() ];
|
const diffItems = [ ...eventSource.differ.getChanges() ];
|
||||||
// If a footnote reference is inserted, ensure that footnote references remain ordered.
|
// If a footnote reference is inserted, ensure that footnote references remain ordered.
|
||||||
if ( diffItems.some( diffItem => diffItem.type === 'insert' && diffItem.name === ELEMENTS.footnoteReference ) ) {
|
if ( diffItems.some( diffItem => diffItem.type === 'insert' && diffItem.name === ELEMENTS.footnoteReference ) ) {
|
||||||
@ -71,7 +70,6 @@ export default class FootnoteEditing extends Plugin {
|
|||||||
this._updateReferenceIndices( batch, `${ footnoteId }`, newFootnoteIndex );
|
this._updateReferenceIndices( batch, `${ footnoteId }`, newFootnoteIndex );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
console.log( 'reached end of change:data' );
|
|
||||||
},
|
},
|
||||||
{ priority: 'high' }
|
{ priority: 'high' }
|
||||||
);
|
);
|
||||||
@ -302,17 +300,17 @@ export default class FootnoteEditing extends Plugin {
|
|||||||
for ( const footnote of modelQueryElementsAll( this.editor, footnoteSection, e =>
|
for ( const footnote of modelQueryElementsAll( this.editor, footnoteSection, e =>
|
||||||
e.is( 'element', ELEMENTS.footnoteItem )
|
e.is( 'element', ELEMENTS.footnoteItem )
|
||||||
) ) {
|
) ) {
|
||||||
const index = `${ footnoteSection?.getChildIndex( footnote ) ?? -1 + 1 }`;
|
const index = `${ ( footnoteSection?.getChildIndex( footnote ) ?? -1 ) + 1 }`;
|
||||||
if ( footnote ) {
|
if ( footnote ) {
|
||||||
writer.setAttribute( ATTRIBUTES.footnoteIndex, index, footnote );
|
writer.setAttribute( ATTRIBUTES.footnoteIndex, index, footnote );
|
||||||
}
|
}
|
||||||
const id = footnote.getAttribute( ATTRIBUTES.footnoteId );
|
const id = footnote.getAttribute( ATTRIBUTES.footnoteId );
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* unfortunately the following line seems to be necessary, even though updateReferenceIndices
|
// * unfortunately the following line seems to be necessary, even though updateReferenceIndices
|
||||||
* should fire from the attribute change immediately above. It seems that events initiated by
|
// * should fire from the attribute change immediately above. It seems that events initiated by
|
||||||
* a `change:data` event do not themselves fire another `change:data` event.
|
// * a `change:data` event do not themselves fire another `change:data` event.
|
||||||
*/
|
// */
|
||||||
if ( id ) {
|
if ( id ) {
|
||||||
this._updateReferenceIndices( batch, `${ id }`, `${ index }` );
|
this._updateReferenceIndices( batch, `${ id }`, `${ index }` );
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ export default class FootnoteUI extends Plugin {
|
|||||||
dropdownView.on(
|
dropdownView.on(
|
||||||
'change:isOpen',
|
'change:isOpen',
|
||||||
( evt, propertyName, newValue ) => {
|
( evt, propertyName, newValue ) => {
|
||||||
|
dropdownView?.listView?.items.clear();
|
||||||
if ( newValue ) {
|
if ( newValue ) {
|
||||||
addListToDropdown(
|
addListToDropdown(
|
||||||
dropdownView,
|
dropdownView,
|
||||||
@ -49,18 +50,19 @@ export default class FootnoteUI extends Plugin {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
dropdownView?.listView?.items.clear();
|
dropdownView?.listView?.items.clear();
|
||||||
|
const listElement = dropdownView?.listView?.element;
|
||||||
|
if ( listElement && listElement.parentNode ) {
|
||||||
|
listElement.parentNode.removeChild( listElement );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// Execute the command when the dropdown item is clicked (executed).
|
// Execute the command when the dropdown item is clicked (executed).
|
||||||
this.listenTo( dropdownView, 'execute', evt => {
|
this.listenTo( dropdownView, 'execute', evt => {
|
||||||
console.log( 'commandParam', ( evt.source as any ).commandParam );
|
|
||||||
editor.execute( COMMANDS.insertFootnote, {
|
editor.execute( COMMANDS.insertFootnote, {
|
||||||
footnoteIndex: ( evt.source as any ).commandParam
|
footnoteIndex: ( evt.source as any ).commandParam
|
||||||
} );
|
} );
|
||||||
console.log( 'completed execution' );
|
|
||||||
editor.editing.view.focus();
|
editor.editing.view.focus();
|
||||||
console.log( 'post focus' );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
return dropdownView;
|
return dropdownView;
|
||||||
|
@ -47,11 +47,9 @@ export default class InsertFootnoteCommand extends Command {
|
|||||||
modelWriter.setSelection( footnoteReference, 'after' );
|
modelWriter.setSelection( footnoteReference, 'after' );
|
||||||
// if referencing an existing footnote
|
// if referencing an existing footnote
|
||||||
if ( footnoteIndex !== 0 ) {
|
if ( footnoteIndex !== 0 ) {
|
||||||
console.log( 'erroneous footnoteIndex' );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log( 'we made it here' );
|
|
||||||
const footnoteContent = modelWriter.createElement( ELEMENTS.footnoteContent );
|
const footnoteContent = modelWriter.createElement( ELEMENTS.footnoteContent );
|
||||||
const footnoteItem = modelWriter.createElement( ELEMENTS.footnoteItem, {
|
const footnoteItem = modelWriter.createElement( ELEMENTS.footnoteItem, {
|
||||||
[ ATTRIBUTES.footnoteId ]: id,
|
[ ATTRIBUTES.footnoteId ]: id,
|
||||||
@ -62,13 +60,11 @@ export default class InsertFootnoteCommand extends Command {
|
|||||||
modelWriter.append( p, footnoteContent );
|
modelWriter.append( p, footnoteContent );
|
||||||
modelWriter.append( footnoteContent, footnoteItem );
|
modelWriter.append( footnoteContent, footnoteItem );
|
||||||
modelWriter.insert( footnoteBackLink, footnoteItem, 0 );
|
modelWriter.insert( footnoteBackLink, footnoteItem, 0 );
|
||||||
console.log( 'we made it here 1' );
|
|
||||||
|
|
||||||
this.editor.model.insertContent(
|
this.editor.model.insertContent(
|
||||||
footnoteItem,
|
footnoteItem,
|
||||||
modelWriter.createPositionAt( footnoteSection, footnoteSection.maxOffset )
|
modelWriter.createPositionAt( footnoteSection, footnoteSection.maxOffset )
|
||||||
);
|
);
|
||||||
console.log( 'we made it here 2' );
|
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,11 +74,9 @@ export default class InsertFootnoteCommand extends Command {
|
|||||||
*/
|
*/
|
||||||
public override refresh(): void {
|
public override refresh(): void {
|
||||||
const model = this.editor.model;
|
const model = this.editor.model;
|
||||||
console.log( 'over here' );
|
|
||||||
const lastPosition = model.document.selection.getLastPosition();
|
const lastPosition = model.document.selection.getLastPosition();
|
||||||
const allowedIn = lastPosition && model.schema.findAllowedParent( lastPosition, ELEMENTS.footnoteSection );
|
const allowedIn = lastPosition && model.schema.findAllowedParent( lastPosition, ELEMENTS.footnoteSection );
|
||||||
this.isEnabled = allowedIn !== null;
|
this.isEnabled = allowedIn !== null;
|
||||||
console.log( 'now here' );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
72
src/utils.ts
72
src/utils.ts
@ -1,4 +1,4 @@
|
|||||||
import { type Editor, Element, Text, TextProxy, ViewElement, ViewText } from 'ckeditor5';
|
import { type Editor, Element, Text, TextProxy, ViewElement } from 'ckeditor5';
|
||||||
|
|
||||||
// There's ample DRY violation in this file; type checking
|
// There's ample DRY violation in this file; type checking
|
||||||
// polymorphism without full typescript is just incredibly finicky.
|
// polymorphism without full typescript is just incredibly finicky.
|
||||||
@ -53,54 +53,6 @@ export const modelQueryTextAll = (
|
|||||||
return output;
|
return output;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array of all descendant elements of
|
|
||||||
* the root for which the provided predicate returns true.
|
|
||||||
*/
|
|
||||||
export const viewQueryElementsAll = (
|
|
||||||
editor: Editor,
|
|
||||||
rootElement: ViewElement,
|
|
||||||
predicate: ( item: ViewElement ) => boolean = _ => true
|
|
||||||
): Array<ViewElement> => {
|
|
||||||
const range = editor.editing.view.createRangeIn( rootElement );
|
|
||||||
const output: Array<ViewElement> = [];
|
|
||||||
|
|
||||||
for ( const item of range.getItems() ) {
|
|
||||||
if ( !( item instanceof ViewElement ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( predicate( item ) ) {
|
|
||||||
output.push( item );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array of all descendant text nodes and text proxies of
|
|
||||||
* the root for which the provided predicate returns true.
|
|
||||||
*/
|
|
||||||
export const viewQueryTextAll = (
|
|
||||||
editor: Editor,
|
|
||||||
rootElement: ViewElement,
|
|
||||||
predicate: ( item: ViewText | TextProxy ) => boolean = _ => true
|
|
||||||
): Array<ViewText | TextProxy> => {
|
|
||||||
const range = editor.editing.view.createRangeIn( rootElement );
|
|
||||||
const output: Array<ViewText | TextProxy> = [];
|
|
||||||
|
|
||||||
for ( const item of range.getItems() ) {
|
|
||||||
if ( !( item instanceof ViewText || item instanceof TextProxy ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( predicate( item ) ) {
|
|
||||||
output.push( item );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the first descendant element of the root for which the provided
|
* Returns the first descendant element of the root for which the provided
|
||||||
* predicate returns true, or null if no such element is found.
|
* predicate returns true, or null if no such element is found.
|
||||||
@ -170,25 +122,3 @@ export const viewQueryElement = (
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the first descendant text node or text proxy of the root for which the provided
|
|
||||||
* predicate returns true, or null if no such element is found.
|
|
||||||
*/
|
|
||||||
export const viewQueryText = (
|
|
||||||
editor: Editor,
|
|
||||||
rootElement: ViewElement,
|
|
||||||
predicate: ( item: ViewText | TextProxy ) => boolean = _ => true
|
|
||||||
): ViewText | TextProxy | null => {
|
|
||||||
const range = editor.editing.view.createRangeIn( rootElement );
|
|
||||||
|
|
||||||
for ( const item of range.getItems() ) {
|
|
||||||
if ( !( item instanceof ViewText || item instanceof TextProxy ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( predicate( item ) ) {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user