fixed issues

This commit is contained in:
Tom Aitken 2024-08-30 00:04:29 +10:00
parent e11c36e5b5
commit 7e08b63636
5 changed files with 22 additions and 104 deletions

View File

@ -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 );

View File

@ -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 }` );
} }

View File

@ -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;

View File

@ -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' );
} }
/** /**

View File

@ -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;
};