-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TRY: Footnotes #2818
TRY: Footnotes #2818
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,10 +13,12 @@ import { | |
find, | ||
defer, | ||
noop, | ||
pick, | ||
} from 'lodash'; | ||
import { nodeListToReact } from 'dom-react'; | ||
import { Fill } from 'react-slot-fill'; | ||
import 'element-closest'; | ||
import uuid from 'uuid/v4'; | ||
|
||
/** | ||
* WordPress dependencies | ||
|
@@ -93,6 +95,8 @@ export default class Editable extends Component { | |
empty: ! value || ! value.length, | ||
selectedNodeId: 0, | ||
}; | ||
|
||
this.footnotes = props.footnotes || {}; | ||
} | ||
|
||
getSettings( settings ) { | ||
|
@@ -233,7 +237,34 @@ export default class Editable extends Component { | |
|
||
this.savedContent = this.getContent(); | ||
this.editor.save(); | ||
this.props.onChange( this.savedContent ); | ||
this.footnotes = pick( this.footnotes, this.getFootnoteIds( this.savedContent ) ); | ||
this.props.onChange( { content: this.savedContent, footnotes: this.footnotes } ); | ||
} | ||
|
||
getFootnoteIds( content ) { | ||
const footnoteIds = []; | ||
const nodesToVisit = [ ...content ]; | ||
let node = nodesToVisit.pop(); | ||
|
||
while ( node !== undefined ) { | ||
if ( typeof node !== 'string' ) { | ||
if ( node.type === 'a' && node.props[ 'data-footnote-id' ] ) { | ||
footnoteIds.push( node.props[ 'data-footnote-id' ] ); | ||
} | ||
|
||
if ( node.props.children ) { | ||
if ( Array.isArray( node.props.children ) ) { | ||
node.props.children.forEach( n => nodesToVisit.push( n ) ); | ||
} else { | ||
nodesToVisit.push( node.props.children ); | ||
} | ||
} | ||
} | ||
|
||
node = nodesToVisit.pop(); | ||
} | ||
|
||
return footnoteIds; | ||
} | ||
|
||
getEditorSelectionRect() { | ||
|
@@ -564,6 +595,10 @@ export default class Editable extends Component { | |
} else { | ||
this.editor.execCommand( 'Unlink' ); | ||
} | ||
} else if ( format === 'footnote' ) { | ||
const footnoteId = uuid(); | ||
this.footnotes[ footnoteId ] = formatValue.text; | ||
this.editor.selection.setContent( `<a href="#footnote-${ footnoteId }" data-footnote-id="${ footnoteId }" contenteditable="false"><sup>[*]</sup></a>` ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is being persisted into the saved content of the post, which is problematic because we don't want/care for this editor-specific attribute to be present on the front-end of the site. Also, it's causing React to log a warning into the developer console. |
||
} else { | ||
const isActive = this.isFormatActive( format ); | ||
if ( isActive && ! formatValue ) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { mapKeys } from 'lodash'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. /**
* External dependencies
*/ |
||
|
||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { __ } from '@wordpress/i18n'; | ||
|
||
import { registerBlockType } from '../../api'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. /**
* Internal dependencies
*/ |
||
|
||
registerBlockType( 'core/footnotes', { | ||
title: __( 'Footnotes' ), | ||
|
||
icon: 'button', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guessing this block could use the |
||
|
||
category: 'layout', | ||
|
||
attributes: { | ||
footnotes: { | ||
type: 'object', | ||
}, | ||
}, | ||
|
||
save( { attributes } ) { | ||
const { footnotes = {} } = attributes; | ||
|
||
const footnoteElements = Object.keys( footnotes ).map( footnoteId => <p key={ footnoteId } id={ `footnote-${ footnoteId }` }>{footnotes[ footnoteId ]}</p> ); | ||
|
||
return ( | ||
<div> | ||
<h2>{ __( 'Footnotes' ) }</h2> | ||
{ footnoteElements } | ||
</div> | ||
); | ||
}, | ||
} ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,3 +22,5 @@ import './text-columns'; | |
import './verse'; | ||
import './video'; | ||
import './audio'; | ||
import './footnotes'; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,6 +61,9 @@ registerBlockType( 'core/paragraph', { | |
fontSize: { | ||
type: 'number', | ||
}, | ||
footnotes: { | ||
type: 'object', | ||
}, | ||
}, | ||
|
||
transforms: { | ||
|
@@ -158,8 +161,10 @@ registerBlockType( 'core/paragraph', { | |
} } | ||
value={ content } | ||
onChange={ ( nextContent ) => { | ||
|
||
setAttributes( { | ||
content: nextContent, | ||
content: nextContent.content, | ||
footnotes: nextContent.footnotes, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is causing paragraph blocks to include an empty |
||
} ); | ||
} } | ||
focus={ focus } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Related: #2474
This is begging to be extensible behavior, not engrained into the toolbar itself.