30 changed files with 268 additions and 1669 deletions
@ -1,85 +0,0 @@
|
||||
2010-03-xx Footnotes 7.x-2.5 |
||||
|
||||
- First Drupal 7 release. No major feature changes over 6.x-2.5. |
||||
|
||||
2010-12-31 Footnotes 2.5 |
||||
|
||||
Major features |
||||
|
||||
- Add new addon module: Footnotes with Views by AlexisWilke. [#939738] |
||||
|
||||
Smaller fixes |
||||
|
||||
- Remove "DEPRECATED" text from Better URL filter and instead have a small |
||||
"Note" about it not being available in Footnotes 7.x-x.x. [#1002436] |
||||
- Correctly ignore also a tag containing linebreak between the > and <. |
||||
Fixes bug [#1002434] |
||||
- Add textarea to ignored tags. Anything inside a textarea will be ignored. |
||||
Bug [#974760] |
||||
|
||||
The intention is to branch a Drupal 7 version out of this release. |
||||
|
||||
2010-10-03 Footnotes 2.4 |
||||
|
||||
Major features |
||||
|
||||
- Add Footnotes Wysiwyg module with TinyMCE AND CKEditor support. |
||||
This deprecates Footnotes TinyMCE module, which is kept around for backward |
||||
compatibility. |
||||
[#728642] |
||||
- Add i18n support via Drupal.t() also to TinyMCE module. [#672034] |
||||
- New feature (option): Collapse identical footnotes into one, as if using same |
||||
value="". [#808214] |
||||
- Implement [#728658] Highlight footnote when clicking the link. Add mention in |
||||
README.txt how to change the highlight color if needed (Footnotes cannot know |
||||
what is an appropriate color, I picked #eeeeee as the safest choice). |
||||
|
||||
Smaller fixes |
||||
|
||||
- Bug [#761390] |
||||
Two small improper CSS names |
||||
...was fixed by changing underscores to dashes in css selectors/classes. |
||||
- Deprecate Better URL filter as it is committed to Drupal 7 now. [#296208] |
||||
- Bug [#761664] |
||||
Footnotes are double numbered when CSS is not used, such as in RSS feeds. |
||||
(Due to using OL list) |
||||
...was fixed by migrating to UL list. This is also appropriate since after |
||||
introduction of the value="" parameter the footnotes needn't comprise an |
||||
ordered list. |
||||
|
||||
|
||||
2010-02-25 Footnotes 2.3 |
||||
|
||||
- Reset $used_values in _footnotes_replace_callback() after use. [#723446] |
||||
|
||||
2010-01-17 Footnotes 2.2 |
||||
|
||||
- Add TinyMCE support as a separate plugin tinymce_footnotes |
||||
(thanks elgreg #464066) |
||||
- Can have multiple references to same footnote in body by repeating value="" |
||||
(#636808) |
||||
Small fixes |
||||
- Move translations from "po" to "translations" subdirectory. #430656 |
||||
- Rename footnotes-alternative_layout.css due to typo in filename. |
||||
- fix css: Use "ol.footnotes li" instead of "ol.footnotes" as selector for |
||||
"list-style-type: none." Makes it stronger. |
||||
- fix html: columns="" should be cols="" bug: #687244 |
||||
|
||||
2008-09-07 Footnotes 2.1 |
||||
|
||||
- Add "clear: both" to css of footnotes section. http://drupal.org/node/303828 |
||||
|
||||
2008-07-30 Footnotes 2.0 |
||||
|
||||
- Add support for using [fn]square brackets[/fn] (268026) |
||||
- Change documentation to talk about [fn] by default, but <fn> is still |
||||
supported |
||||
- Add support for specifying "value" attribute. (emfabric 282104) |
||||
- Mention http://drupal.org/node/279420 in known issues |
||||
- Adding Better URL filter (fork from core). http://drupal.org/node/161217 |
||||
- There appears to also be a French translation now. Thanks Beginner! |
||||
(Japanese already done earlier.) |
||||
- Fix bug where teaser might cut into the middle of a footnote: |
||||
http://drupal.org/node/253326 |
||||
- Start using the Drupal theme system, footnotes can now be themed by site |
||||
admins (emfabric 221156) |
||||
@ -1,57 +0,0 @@
|
||||
INTRODUCTION |
||||
------------------ |
||||
|
||||
The Footnotes module is used to easily create automatically numbered footnote references in an article or post (such as a reference to a URL). |
||||
|
||||
* For a full description of the module, visit the project page: |
||||
https://www.drupal.org/project/footnotes |
||||
|
||||
* To submit bug reports and feature suggestions, or track changes: |
||||
https://www.drupal.org/project/issues/footnotes |
||||
|
||||
REQUIREMENTS |
||||
------------------ |
||||
|
||||
The Footnote module for Drupal 8 requires the following modules and plugins: |
||||
|
||||
* FakeObjects (https://www.drupal.org/project/fakeobjects) |
||||
* CKEditor plugin (http://ckeditor.com/addon/fakeobjects) |
||||
|
||||
INSTALLATION |
||||
---------------- |
||||
* Before you can use the FakeObjects module, you need to download the plugin from http://ckeditor.com/addon/fakeobjects and place it in /libraries/fakeobjects. |
||||
|
||||
* In all other steps, install the module as you would normally install a contributed Drupal module. Visit |
||||
https://www.drupal.org/docs/8/extending-drupal-8/installing-drupal-8-modules for further information. |
||||
|
||||
CONFIGURATION |
||||
------------------- |
||||
* To use the footnotes filter in some input formats, go to Configuration -> |
||||
Text formats. |
||||
|
||||
* For the Text formats you want to support footnotes markup, select configure and activate a suitable footnotes filter. |
||||
|
||||
* In the place where you want to add a footnote enclose the footnote text within an fn tag:<code>[fn]like this[/fn]</code>. By default, footnotes are placed at the end of the text. You can also use a <code>[footnotes]</code> or <code>[footnotes /]</code> tag to position it anywhere you want. |
||||
|
||||
* The filter will take the text within the tag and move it to a footnote at the |
||||
bottom of the page. In it's place it will place a number which is also a link to |
||||
the footnote. Footnotes supports both <code>[fn]square brackets[/fn]</code> and <code><fn>angle brackets</fn></code>. |
||||
|
||||
* You can also use a "value" attribute to a) set the numbering to start from the given value, or b) to set an arbitrary text string as label. |
||||
|
||||
Ex: |
||||
|
||||
[fn value="5"]This becomes footnote #5. Subsequent are #6, #7...[/fn] |
||||
[fn value="*"]This footnote is assigned the label "*"[/fn] |
||||
|
||||
Using value="" you can have multiple references to the same footnote in the text body. |
||||
|
||||
[fn value="5"]This becomes footnote #5.[/fn] |
||||
[fn value="5"]This is a reference to the same footnote #5, this text itself is discarded.[/fn] |
||||
|
||||
TROUBLESHOOTING & FAQ |
||||
------------------------------ |
||||
|
||||
Q: When trying to install the Footnotes module, I get the message: Before you can use the FakeObjects module, you need to download the plugin from ckeditor.com and place it in /libraries/fakeobjects." |
||||
|
||||
A: To avoid this error message, please follow the guidelines in the Required modules and the Installation sections of this Readme file. Please mind that the Drupal 8.x-2.x branch of the Footnotes module only supports the CKEditor and does not support the TinyMCE. |
||||
@ -1,75 +0,0 @@
|
||||
/* |
||||
* CSS specific to Footnotes module. |
||||
* |
||||
* This is an alternative layout, it is not so nice but overcomes |
||||
* the layout bugs on IE. http://drupal.org/node/166628 |
||||
* To use this layout, just rename this file to footnotes.css. |
||||
*/ |
||||
|
||||
/* Add empty space before footnotes and a black line on top. */ |
||||
.footnotes { |
||||
clear: both; |
||||
margin-top: 4em; |
||||
margin-bottom: 2em; |
||||
border-top: 1px solid #000; |
||||
} |
||||
/* Make footnotes appear in a smaller font */ |
||||
.footnotes { |
||||
font-size: 0.9em; |
||||
} |
||||
/* |
||||
Make the footnote a supertext^1 |
||||
*/ |
||||
.see-footnote { |
||||
vertical-align: top; |
||||
position: relative; |
||||
top: -0.25em; |
||||
font-size: 0.9em; |
||||
} |
||||
/* Hide the bullet of the UL list of footnotes */ |
||||
|
||||
ul.footnotes { |
||||
list-style-type: none; |
||||
margin-left: 0; |
||||
padding-left: 0; |
||||
} |
||||
ul.footnotes li { |
||||
margin-left: 0.5em; |
||||
list-style-type: none; |
||||
background: none; /* Garland theme sets a bullet via background image, this must be unset! See bug 861634 */ |
||||
} |
||||
.footnotes .footnote-label { |
||||
vertical-align: top; |
||||
position: relative; |
||||
top: -0.35em; |
||||
left: -0.35em; |
||||
font-size: 0.8em; |
||||
} |
||||
/* Highlight the target footnote (or ref number, if a backlink was used) when user clicks a footnote. */ |
||||
.see-footnote:target, |
||||
.footnotes .footnote:target { |
||||
background-color: #eee; |
||||
} |
||||
.see-footnote:target { |
||||
border: solid 1px #aaa; |
||||
} |
||||
/* |
||||
Make the multiple backlinks a supertext^1 |
||||
*/ |
||||
.footnotes .footnote-multi { |
||||
vertical-align: top; |
||||
position: relative; |
||||
top: -0.25em; |
||||
font-size: 0.75em; |
||||
} |
||||
/* |
||||
* Textile Footnotes |
||||
*/ |
||||
/* First footnote */ |
||||
#fn1 { |
||||
border-top: 1px solid #000; |
||||
margin-top: 3em; |
||||
} |
||||
.footnote { |
||||
font-size: 0.9em; |
||||
} |
||||
@ -1,82 +0,0 @@
|
||||
/* |
||||
* CSS specific to Footnotes module. |
||||
* |
||||
* Thanks to binford2k@lug.wsu.edu for this tip and drinkypoo |
||||
* for the question leading up to it. http://drupal.org/node/80538 |
||||
*/ |
||||
|
||||
/* Add empty space before footnotes and a black line on top. */ |
||||
.footnotes { |
||||
clear: both; |
||||
margin-top: 4em; |
||||
margin-bottom: 2em; |
||||
border-top: 1px solid #000; |
||||
} |
||||
/* Make footnotes appear in a smaller font */ |
||||
.footnotes { |
||||
font-size: 0.9em; |
||||
} |
||||
/* |
||||
Make the footnote a supertext^1 |
||||
*/ |
||||
.see-footnote { |
||||
vertical-align: top; |
||||
position: relative; |
||||
top: -0.25em; |
||||
font-size: 0.9em; |
||||
} |
||||
/* Hide the bullet of the UL list of footnotes */ |
||||
|
||||
ul.footnotes { |
||||
list-style-type: none; |
||||
margin-left: 0; |
||||
padding-left: 0; |
||||
} |
||||
ul.footnotes li { |
||||
margin-left: 2.5em; |
||||
list-style-type: none; |
||||
background: none; /* Garland theme sets a bullet via background image, this must be unset! See bug 861634 */ |
||||
} |
||||
/* Move the footnote number outside of the margin for footnote text (hanging indent) */ |
||||
ul.footnotes { |
||||
/* This is apparently very needed for the "position: absolute;" below to work correctly */ |
||||
position: relative; |
||||
} |
||||
.footnotes .footnote-label { |
||||
position: absolute; |
||||
left: 0; |
||||
z-index: 2; |
||||
} |
||||
/* Highlight the target footnote (or ref number, if a backlink was used) when user clicks a footnote. */ |
||||
.see-footnote:target, |
||||
.footnotes .footnote:target { |
||||
background-color: #eee; |
||||
} |
||||
.see-footnote:target { |
||||
border: solid 1px #aaa; |
||||
} |
||||
/* Note: This CSS has a minor bug on all versions of IE in that the footnote numbers |
||||
are aligned with the absolute bottom of their space, thus being a couple of pixels |
||||
lower than their corresponding line of text. IE5.5 has a serious bug in that the numbers |
||||
are not shifted left at all, thus being garbled together with the start of their text. */ |
||||
|
||||
/* |
||||
Make the multiple backlinks a supertext^1 |
||||
*/ |
||||
.footnotes .footnote-multi { |
||||
vertical-align: top; |
||||
position: relative; |
||||
top: -0.25em; |
||||
font-size: 0.75em; |
||||
} |
||||
/* |
||||
* Textile Footnotes |
||||
*/ |
||||
/* First footnote */ |
||||
#fn1 { |
||||
border-top: 1px solid #000; |
||||
margin-top: 3em; |
||||
} |
||||
.footnote { |
||||
font-size: 0.9em; |
||||
} |
||||
@ -1,60 +0,0 @@
|
||||
/** |
||||
* @file |
||||
*/ |
||||
|
||||
function footnotesDialog(editor, isEdit) { |
||||
return { |
||||
title: Drupal.t("Footnotes Dialog"), |
||||
minWidth: 500, |
||||
minHeight: 50, |
||||
contents: [ |
||||
{ |
||||
id: "info", |
||||
label: Drupal.t("Add a footnote"), |
||||
title: Drupal.t("Add a footnote"), |
||||
elements: [ |
||||
{ |
||||
id: "footnote", |
||||
type: "text", |
||||
label: Drupal.t("Footnote text :"), |
||||
setup(element) { |
||||
if (isEdit) { |
||||
this.setValue(element.getHtml()); |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
id: "value", |
||||
type: "text", |
||||
label: Drupal.t("Value :"), |
||||
setup(element) { |
||||
if (isEdit) { |
||||
this.setValue(element.getAttribute("value")); |
||||
} |
||||
} |
||||
} |
||||
] |
||||
} |
||||
], |
||||
onShow() { |
||||
if (isEdit) { |
||||
this.fakeObj = CKEDITOR.plugins.footnotes.getSelectedFootnote(editor); |
||||
this.realObj = editor.restoreRealElement(this.fakeObj); |
||||
} |
||||
this.setupContent(this.realObj); |
||||
}, |
||||
onOk() { |
||||
CKEDITOR.plugins.footnotes.createFootnote( |
||||
editor, |
||||
this.realObj, |
||||
this.getValueOf("info", "footnote"), |
||||
this.getValueOf("info", "value") |
||||
); |
||||
delete this.fakeObj; |
||||
delete this.realObj; |
||||
} |
||||
}; |
||||
} |
||||
|
||||
CKEDITOR.dialog.add("createfootnotes", editor => footnotesDialog(editor)); |
||||
CKEDITOR.dialog.add("editfootnotes", editor => footnotesDialog(editor, 1)); |
||||
|
Before Width: | Height: | Size: 262 B |
|
Before Width: | Height: | Size: 263 B |
@ -1,151 +0,0 @@
|
||||
/** |
||||
* @file |
||||
* A CKeditor plugin to insert footnotes as in-place <fn> elements (consumed by Footnotes module in Drupal). |
||||
* |
||||
* This is a rather sophisticated plugin to show a dialog to insert |
||||
* <fn> footnotes or edit existing ones. It produces and understands |
||||
* the <fn>angle bracket</fn> variant and uses the fakeObjects API to |
||||
* show a nice icon to the user, while producing proper <fn> tags when |
||||
* the text is saved or View Source is pressed. |
||||
* |
||||
* If a text contains footnotes of the [fn]square bracket[/fn] variant, |
||||
* they will be visible in the text and this plugin will not react to them. |
||||
* |
||||
* This plugin uses Drupal.t() to translate strings and will not as such |
||||
* work outside of Drupal. (But removing those functions would be the only |
||||
* change needed.) While being part of a Wysiwyg compatible module, it could |
||||
* also be used together with the CKEditor module. |
||||
* |
||||
* Drupal Wysiwyg requirement: The first argument to CKEDITOR.plugins.add() |
||||
* must be equal to the key used in $plugins[] in hook_wysiwyg_plugin(). |
||||
*/ |
||||
|
||||
CKEDITOR.plugins.add("footnotes", { |
||||
requires: ["fakeobjects", "dialog"], |
||||
icons: "footnotes", |
||||
onLoad() { |
||||
const iconPath = `${window.location.origin + this.path}icons/fn_icon2.png`; |
||||
CKEDITOR.addCss( |
||||
`${".cke_footnote{background-image: url("}${CKEDITOR.getUrl( |
||||
iconPath |
||||
)});` +
|
||||
`background - position: center center;` + |
||||
`background - repeat: no - repeat;` + |
||||
`width: 16px;` + |
||||
`height: 16px;` + |
||||
`}` |
||||
); |
||||
}, |
||||
init(editor) { |
||||
editor.addCommand( |
||||
"createfootnotes", |
||||
new CKEDITOR.dialogCommand("createfootnotes", { |
||||
allowedContent: "fn[value]" |
||||
}) |
||||
); |
||||
editor.addCommand( |
||||
"editfootnotes", |
||||
new CKEDITOR.dialogCommand("editfootnotes", { |
||||
allowedContent: "fn[value]" |
||||
}) |
||||
); |
||||
|
||||
// Drupal Wysiwyg requirement: The first argument to editor.ui.addButton()
|
||||
// must be equal to the key used in $plugins[<pluginName>]['buttons'][<key>]
|
||||
// in hook_wysiwyg_plugin().
|
||||
if (editor.ui.addButton) { |
||||
editor.ui.addButton("footnotes", { |
||||
label: Drupal.t("Add a footnote"), |
||||
command: "createfootnotes", |
||||
icon: "footnotes" |
||||
}); |
||||
} |
||||
|
||||
if (editor.addMenuItems) { |
||||
editor.addMenuGroup("footnotes", 100); |
||||
editor.addMenuItems({ |
||||
footnotes: { |
||||
label: Drupal.t("Edit footnote"), |
||||
command: "editfootnotes", |
||||
icon: "footnotes", |
||||
group: "footnotes" |
||||
} |
||||
}); |
||||
} |
||||
if (editor.contextMenu) { |
||||
editor.contextMenu.addListener(element => { |
||||
if (!element || element.data("cke-real-element-type") !== "fn") { |
||||
return null; |
||||
} |
||||
return { footnotes: CKEDITOR.TRISTATE_ON }; |
||||
}); |
||||
} |
||||
|
||||
editor.on("doubleclick", evt => { |
||||
if (CKEDITOR.plugins.footnotes.getSelectedFootnote(editor)) { |
||||
evt.data.dialog = "editfootnotes"; |
||||
} |
||||
}); |
||||
|
||||
CKEDITOR.dialog.add("createfootnotes", `${this.path}dialogs/footnotes.js`); |
||||
CKEDITOR.dialog.add("editfootnotes", `${this.path}dialogs/footnotes.js`); |
||||
}, |
||||
afterInit(editor) { |
||||
const { dataProcessor } = editor; |
||||
const { dataFilter } = dataProcessor; |
||||
|
||||
if (dataFilter) { |
||||
dataFilter.addRules({ |
||||
elements: { |
||||
fn(element) { |
||||
return editor.createFakeParserElement( |
||||
element, |
||||
"cke_footnote", |
||||
"hiddenfield", |
||||
false |
||||
); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
CKEDITOR.plugins.footnotes = { |
||||
createFootnote(editor, origElement, text, value) { |
||||
let realElement; |
||||
if (!origElement) { |
||||
realElement = CKEDITOR.dom.element.createFromHtml("<fn></fn>"); |
||||
} else { |
||||
realElement = origElement; |
||||
} |
||||
|
||||
if (text && text.length > 0) { |
||||
realElement.setHtml(text); |
||||
} |
||||
if (value && value.length > 0) { |
||||
realElement.setAttribute("value", value); |
||||
} |
||||
|
||||
const fakeElement = editor.createFakeElement( |
||||
realElement, |
||||
"cke_footnote", |
||||
"hiddenfield", |
||||
false |
||||
); |
||||
editor.insertElement(fakeElement); |
||||
}, |
||||
|
||||
getSelectedFootnote(editor) { |
||||
const selection = editor.getSelection(); |
||||
const element = selection.getSelectedElement(); |
||||
const seltype = selection.getType(); |
||||
|
||||
if ( |
||||
seltype === CKEDITOR.SELECTION_ELEMENT && |
||||
element.data("cke-real-element-type") === "hiddenfield" |
||||
) { |
||||
return element; |
||||
} |
||||
} |
||||
}; |
||||
@ -1,9 +0,0 @@
|
||||
reference_footnotes: |
||||
ckeditor5: |
||||
plugins: |
||||
- ReferenceFootnotes |
||||
drupal: |
||||
label: 'Reference Footnotes' |
||||
toolbar_items: |
||||
referenceFootnotes: |
||||
label: 'Reference Footnotes' |
||||
@ -1,17 +0,0 @@
|
||||
bibcite_footnotes_2_footnote_picker: |
||||
ckeditor5: |
||||
plugins: |
||||
- footnotepicker2.FootnotePicker2 |
||||
|
||||
drupal: |
||||
label: 'Footnote/Citation (Test)' |
||||
library: bibcite_footnotes_2/footnote_picker |
||||
admin_library: bibcite_footnotes_2/footnote_picker |
||||
|
||||
toolbar_items: |
||||
footnotePicker2: |
||||
label: 'Footnoe' |
||||
icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path d="M6.5 4.5c-.6 0-1 .4-1 1v4.2c0 .6.4 1 1 1h.8v1.7H6.2c-.6 0-1 .4-1 1v.4h3.3c.6 0 1-.4 1-1V10c0-.5-.3-.9-.7-1.1.4-.3.7-.7.7-1.3V5.5c0-.6-.4-1-1-1H6.5z"/><path d="M11 6h7v1.4h-7V6zm0 3h7v1.4h-7V9zm0 3h5v1.4h-5V12z"/></svg>' |
||||
|
||||
elements: |
||||
- <fn> |
||||
@ -1,7 +0,0 @@
|
||||
name: 'Bibcite Footnotes CKEditor 5' |
||||
type: module |
||||
description: 'Provides a CKEditor 5 plugin for inserting and editing reference footnotes.' |
||||
package: 'Custom' |
||||
core_version_requirement: '^10.2 || ^11' |
||||
dependencies: |
||||
- drupal:ckeditor5 |
||||
@ -1,19 +0,0 @@
|
||||
reference_footnotes: |
||||
js: |
||||
js/ckeditor5/reference-footnotes.js: { type: module } |
||||
css: |
||||
theme: |
||||
css/reference-footnotes.css: {} |
||||
|
||||
footnote_picker: |
||||
css: |
||||
theme: |
||||
css/footnote_picker.admin.css: { } |
||||
css/footnote_picker.dialog.css: {} |
||||
js: |
||||
js/ckeditor5_plugins/footnotepicker2/build/footnotepicker2.js: {} |
||||
dependencies: |
||||
- core/ckeditor5 |
||||
- core/drupal |
||||
- core/drupal.dialog |
||||
- core/jquery |
||||
@ -1,10 +0,0 @@
|
||||
name: Footnotes |
||||
description: 'Add automatically numbered footnotes to your posts.' |
||||
|
||||
type: module |
||||
core_version_requirement: ^8 || ^9 |
||||
|
||||
dependencies: |
||||
- 'fakeobjects:fakeobjects' |
||||
test_dependencies: |
||||
- 'fakeobjects:fakeobjects' |
||||
@ -1,45 +0,0 @@
|
||||
<?php |
||||
|
||||
/** |
||||
* @file |
||||
* Install, update and uninstall functions for the Footnotes module. |
||||
*/ |
||||
|
||||
/** |
||||
* Implements hook_requirements(). |
||||
*/ |
||||
function footnotes_requirements($phase) { |
||||
if ($phase != 'runtime') { |
||||
return []; |
||||
} |
||||
|
||||
// Check if fakeobjects module is enabled and properly configured. |
||||
$fakeobjects_exist = \Drupal::moduleHandler()->moduleExists('fakeobjects'); |
||||
if ($fakeobjects_exist) { |
||||
$fakeobjects_requirements = fakeobjects_requirements($phase); |
||||
if ($fakeobjects_requirements['fakeobjects']['severity'] === REQUIREMENT_OK) { |
||||
$requirements['footnotes'] = [ |
||||
'title' => t('Footnotes'), |
||||
'value' => t('Footnotes requirements are OK.'), |
||||
'severity' => REQUIREMENT_OK, |
||||
]; |
||||
} |
||||
else { |
||||
$requirements['footnotes'] = [ |
||||
'title' => t('Footnotes'), |
||||
'value' => t('Footnotes requirements are not properly configured. Please check Fakeobjects module requirements.'), |
||||
'severity' => REQUIREMENT_ERROR, |
||||
]; |
||||
} |
||||
} |
||||
else { |
||||
$requirements['footnotes'] = [ |
||||
'title' => t('Footnotes'), |
||||
'value' => t("<a href=':href'>Fakeobjects module</a> isn't installed/enabled.", [':href' => 'https://www.drupal.org/project/fakeobjects']), |
||||
'severity' => REQUIREMENT_ERROR, |
||||
'description' => t('Footnotes module has a dependency on Fakeobjects module. Ensure that Fakeobjects module is enabled and configured.'), |
||||
]; |
||||
} |
||||
|
||||
return $requirements; |
||||
} |
||||
@ -1,5 +0,0 @@
|
||||
footnotes: |
||||
version: VERSION |
||||
css: |
||||
component: |
||||
assets/css/footnotes.css: {} |
||||
@ -1,92 +0,0 @@
|
||||
<?php |
||||
|
||||
/** |
||||
* @file |
||||
* This file contains the hooks for Footnotes module. |
||||
* |
||||
* The Footnotes module is a filter that can be used to insert |
||||
* automatically numbered footnotes into Drupal texts. |
||||
*/ |
||||
|
||||
use Drupal\Core\Routing\RouteMatchInterface; |
||||
use Drupal\Core\Url; |
||||
|
||||
/** |
||||
* Implements hook_help(). |
||||
*/ |
||||
function footnotes_help($route_name, RouteMatchInterface $route_match) { |
||||
switch ($route_name) { |
||||
case 'help.page.footnotes': |
||||
return t("Insert automatically numbered footnotes using <fn> or [fn] tags. Enable the footnotes text filter <a href=':href'>here</a>", [ |
||||
':href' => Url::fromRoute('filter.admin_overview')->toString(), |
||||
]); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Implements hook_theme(). |
||||
* |
||||
* Thanks to emfabric for this implementation. http://drupal.org/node/221156 |
||||
*/ |
||||
function footnotes_theme() { |
||||
return [ |
||||
'footnote_link' => [ |
||||
'variables' => [ |
||||
'fn' => NULL, |
||||
], |
||||
], |
||||
'footnote_list' => [ |
||||
'variables' => [ |
||||
'footnotes'=> NULL, |
||||
], |
||||
], |
||||
]; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Helper for other filters, check if Footnotes is present in your filter chain. |
||||
* |
||||
* Note: Due to changes in Filter API, the arguments to this function have |
||||
* changed in Drupal 7. |
||||
* |
||||
* Other filters may leverage the Footnotes functionality in a simple way: |
||||
* by outputting markup with <fn>...</fn> tags within. |
||||
* |
||||
* This creates a dependency, the Footnotes filter must be present later in |
||||
* "Input format". By calling this helper function the other filters that |
||||
* depend on Footnotes may check whether Footnotes is present later in the chain |
||||
* of filters in the current Input format. |
||||
* |
||||
* If this function returns true, the caller may depend on Footnotes. Function |
||||
* returns false if caller may not depend on Footnotes. |
||||
* |
||||
* You should also put "dependencies = footnotes" in your module.info file. |
||||
* |
||||
* Example usage: |
||||
* <code> |
||||
* _filter_example_process( $text, $filter, $format ) { |
||||
* ... |
||||
* if(footnotes_is_footnotes_later($format, $filter)) { |
||||
* //output markup which may include [fn] tags |
||||
* } |
||||
* else { |
||||
* // must make do without footnotes features |
||||
* // can also emit warning/error that user should install and configure |
||||
* // footnotes module |
||||
* } |
||||
* ... |
||||
* } |
||||
* </code> |
||||
* |
||||
* @param object $format |
||||
* The text format object caller is part of. |
||||
* @param object $caller_filter |
||||
* The filter object representing the caller (in this text format). |
||||
* |
||||
* @return True |
||||
* If Footnotes is present after $caller in $format. |
||||
*/ |
||||
function footnotes_is_footnotes_later($format, $caller_filter) { |
||||
return $format['filter_footnotes']['weight'] > $caller_filter['weight']; |
||||
} |
||||
|
Before Width: | Height: | Size: 282 B |
@ -1,198 +0,0 @@
|
||||
import { Plugin } from 'ckeditor5/src/core'; |
||||
import { ButtonView } from 'ckeditor5/src/ui'; |
||||
import { Widget, toWidget } from 'ckeditor5/src/widget'; |
||||
import icon from './reference-footnotes-icon.svg'; |
||||
|
||||
/** |
||||
* ReferenceFootnotes CKEditor 5 plugin. |
||||
* |
||||
* Provides: |
||||
* - A toolbar button that inserts a <fn> element. |
||||
* - Double-click editing of existing <fn> elements. |
||||
* - Simple browser-prompt based dialog for editing attributes. |
||||
* |
||||
* This keeps the implementation simple and reliable in Drupal's environment. |
||||
* If you later want a full ContextualBalloon-based dialog, this is the place |
||||
* to extend. |
||||
*/ |
||||
export default class ReferenceFootnotes extends Plugin { |
||||
static get requires() { |
||||
return [ Widget ]; |
||||
} |
||||
|
||||
static get pluginName() { |
||||
return 'ReferenceFootnotes'; |
||||
} |
||||
|
||||
init() { |
||||
const editor = this.editor; |
||||
|
||||
// --- SCHEMA -------------------------------------------------
|
||||
// Model element: <fn value="" page="" reference="">text</fn>
|
||||
editor.model.schema.register('fn', { |
||||
allowWhere: '$text', |
||||
allowContentOf: '$text', |
||||
isInline: true, |
||||
isObject: true, |
||||
allowAttributes: [ 'value', 'page', 'reference' ] |
||||
}); |
||||
|
||||
// --- MODEL → VIEW (editing) --------------------------------
|
||||
// Show an inline widget with a class that you can style with an icon.
|
||||
editor.conversion.for('editingDowncast').elementToElement({ |
||||
model: 'fn', |
||||
view: (modelElement, { writer }) => { |
||||
const viewElement = writer.createContainerElement('span', { |
||||
class: 'reference-footnote', |
||||
'data-value': modelElement.getAttribute('value') || '', |
||||
'data-reference': modelElement.getAttribute('reference') || '', |
||||
'data-page': modelElement.getAttribute('page') || '' |
||||
}); |
||||
|
||||
return toWidget(viewElement, writer, { label: editor.t('Reference footnote') }); |
||||
} |
||||
}); |
||||
|
||||
// --- MODEL → VIEW (data/HTML) -------------------------------
|
||||
// Persist as <fn ...>TEXT</fn> in the saved HTML.
|
||||
editor.conversion.for('dataDowncast').elementToElement({ |
||||
model: 'fn', |
||||
view: (modelElement, { writer }) => { |
||||
const attrs = { |
||||
value: modelElement.getAttribute('value') || '', |
||||
reference: modelElement.getAttribute('reference') || '', |
||||
page: modelElement.getAttribute('page') || '' |
||||
}; |
||||
|
||||
const fnElement = writer.createContainerElement('fn', attrs); |
||||
|
||||
// Put inner text into the <fn> element.
|
||||
const firstChild = modelElement.getChild(0); |
||||
const textData = firstChild && firstChild.is( 'text' ) ? firstChild.data : ''; |
||||
if (textData) { |
||||
const textNode = writer.createText(textData); |
||||
writer.insert(textNode, fnElement, 0); |
||||
} |
||||
|
||||
return fnElement; |
||||
} |
||||
}); |
||||
|
||||
// --- VIEW → MODEL (upcast) ---------------------------------
|
||||
// Convert <fn> tags back into model elements.
|
||||
editor.conversion.for('upcast').elementToElement({ |
||||
view: { |
||||
name: 'fn' |
||||
}, |
||||
model: (viewElement, { writer }) => { |
||||
return writer.createElement('fn', { |
||||
value: viewElement.getAttribute('value') || '', |
||||
reference: viewElement.getAttribute('reference') || '', |
||||
page: viewElement.getAttribute('page') || '' |
||||
}); |
||||
} |
||||
}); |
||||
|
||||
// --- TOOLBAR BUTTON -----------------------------------------
|
||||
editor.ui.componentFactory.add('referenceFootnotes', locale => { |
||||
const view = new ButtonView(locale); |
||||
|
||||
view.set({ |
||||
label: editor.t('Add reference footnote'), |
||||
icon, |
||||
tooltip: true |
||||
}); |
||||
|
||||
view.on('execute', () => { |
||||
this.openFootnoteDialog(null); |
||||
}); |
||||
|
||||
return view; |
||||
}); |
||||
|
||||
// --- DOUBLE CLICK HANDLER -----------------------------------
|
||||
editor.editing.view.document.on('dblclick', (evt, data) => { |
||||
const viewElement = data.target; |
||||
const modelElement = editor.editing.mapper.toModelElement(viewElement); |
||||
|
||||
if (modelElement && modelElement.name === 'fn') { |
||||
this.openFootnoteDialog(modelElement); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Opens a simple "dialog" (browser prompts) to create or edit a footnote. |
||||
* |
||||
* @param {?module:engine/model/element~Element} existingFn |
||||
* The existing <fn> model element, or null for a new one. |
||||
*/ |
||||
openFootnoteDialog(existingFn) { |
||||
const editor = this.editor; |
||||
|
||||
// --- Read existing values (if editing) ----------------------
|
||||
let currentText = ''; |
||||
let currentValue = ''; |
||||
let currentReference = ''; |
||||
let currentPage = ''; |
||||
|
||||
if (existingFn) { |
||||
const firstChild = existingFn.getChild(0); |
||||
currentText = firstChild && firstChild.is('text') ? firstChild.data : ''; |
||||
|
||||
currentValue = existingFn.getAttribute('value') || ''; |
||||
currentReference = existingFn.getAttribute('reference') || ''; |
||||
currentPage = existingFn.getAttribute('page') || ''; |
||||
} |
||||
|
||||
// --- Simple prompts for now --------------------------------
|
||||
const text = window.prompt(editor.t('Footnote text:'), currentText || ''); |
||||
if (text === null) { |
||||
return; // user cancelled
|
||||
} |
||||
|
||||
const value = window.prompt(editor.t('Footnote value (e.g. 1, 2, 3):'), currentValue || ''); |
||||
if (value === null) { |
||||
return; |
||||
} |
||||
|
||||
const reference = window.prompt(editor.t('Reference (optional):'), currentReference || ''); |
||||
if (reference === null) { |
||||
return; |
||||
} |
||||
|
||||
const page = window.prompt(editor.t('Page (optional):'), currentPage || ''); |
||||
if (page === null) { |
||||
return; |
||||
} |
||||
|
||||
// --- Write changes to the model -----------------------------
|
||||
editor.model.change(writer => { |
||||
if (!existingFn) { |
||||
// Insert a brand new <fn> element at the selection.
|
||||
const fnElement = writer.createElement('fn', { |
||||
value: value, |
||||
reference: reference, |
||||
page: page |
||||
}); |
||||
|
||||
// Insert the element and then its visible text.
|
||||
editor.model.insertObject(fnElement, editor.model.document.selection); |
||||
writer.insertText(text, fnElement, 0); |
||||
} |
||||
else { |
||||
// Update attributes.
|
||||
writer.setAttribute('value', value, existingFn); |
||||
writer.setAttribute('reference', reference, existingFn); |
||||
writer.setAttribute('page', page, existingFn); |
||||
|
||||
// Replace inner text.
|
||||
const children = Array.from(existingFn.getChildren()); |
||||
for (const child of children) { |
||||
writer.remove(child); |
||||
} |
||||
writer.insertText(text, existingFn, 0); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
@ -1,19 +0,0 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\bibcite_footnotes_2\Plugin\CKEditor5Plugin; |
||||
|
||||
use Drupal\ckeditor5\Plugin\CKEditor5PluginDefault; |
||||
use Drupal\Core\StringTranslation\TranslatableMarkup; |
||||
|
||||
#[CKEditor5Plugin( |
||||
id: 'reference_footnotes', |
||||
label: new TranslatableMarkup('Reference Footnotes'), |
||||
ckeditor5: 'reference_footnotes', |
||||
library: 'bibcite_footnotes_2/reference_footnotes', |
||||
elements: [ |
||||
'<fn value page reference>', |
||||
], |
||||
)] |
||||
class ReferenceFootnotes extends CKEditor5PluginDefault { |
||||
|
||||
} |
||||
@ -1,54 +0,0 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\footnotes\Plugin\CKEditorPlugin; |
||||
|
||||
use Drupal\ckeditor\CKEditorPluginBase; |
||||
use Drupal\editor\Entity\Editor; |
||||
use Drupal\Core\StringTranslation\StringTranslationTrait; |
||||
|
||||
/** |
||||
* Defines the "Footnotes" plugin. |
||||
* |
||||
* @CKEditorPlugin( |
||||
* id = "footnotes", |
||||
* label = @Translation("FootnotesButton") |
||||
* ) |
||||
*/ |
||||
class Footnotes extends CKEditorPluginBase { |
||||
|
||||
use StringTranslationTrait; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getDependencies(Editor $editor) { |
||||
return ['fakeobjects']; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getFile() { |
||||
return drupal_get_path('module', 'footnotes') . '/assets/js/ckeditor/plugin.js'; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getButtons() { |
||||
return [ |
||||
'footnotes' => [ |
||||
'label' => $this->t('Footnotes'), |
||||
'image' => drupal_get_path('module', 'footnotes') . '/assets/js/ckeditor/icons/footnotes.png', |
||||
], |
||||
]; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getConfig(Editor $editor) { |
||||
return []; |
||||
} |
||||
|
||||
} |
||||
@ -1,2 +0,0 @@
|
||||
{# footnotes/footnote-link.html.twig #} |
||||
<a class="see-footnote" id="{{ fn.ref_id }}" title="{{ fn.text_clean }}" href="#{{ fn.fn_id }}">{{ fn.value }}</a> |
||||
@ -1,23 +0,0 @@
|
||||
{# footnotes/footnote-list.html.twig #} |
||||
<ul class="footnotes"> |
||||
{% for fn in footnotes %} |
||||
{% if fn.ref_id is iterable %} |
||||
{# |
||||
// Output footnote that has more than one reference to it in the body. |
||||
// The only difference is to insert backlinks to all references. |
||||
// Helper: we need to enumerate a, b, c... |
||||
#} |
||||
{% set abc = "abcdefghijklmnopqrstuvwxyz"|split('') %} |
||||
{% set i = 0 %} |
||||
<li class="footnote" id="{{ fn.fn_id }}"><a href="#{{ fn.ref_id.0 }}" class="footnote-label">{{ fn.value }}</a> |
||||
{% for ref in fn.ref_id %} |
||||
<a class="footnote-multi" href="#{{ ref }}">{{ attribute(abc, i) }}</a> |
||||
{% set i = i + 1 %} |
||||
{% endfor %} |
||||
{{ fn.text|raw }}</li> |
||||
{% else %} |
||||
{# Output normal footnote. #} |
||||
<li class="footnote" id="{{ fn.fn_id }}"><a class="footnote-label" href="#{{ fn.ref_id }}">{{ fn.value }}</a>{{ fn.text|raw }}</li> |
||||
{% endif %} |
||||
{% endfor %} |
||||
</ul> |
||||
@ -1,168 +0,0 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\Tests\footnotes\Functional; |
||||
|
||||
use Drupal\Core\Session\AccountInterface; |
||||
use Drupal\Core\StringTranslation\StringTranslationTrait; |
||||
use Drupal\Tests\BrowserTestBase; |
||||
|
||||
/** |
||||
* Contains Footnotes Filter plugin functionality tests. |
||||
* |
||||
* @group footnotes |
||||
*/ |
||||
class FootnotesFilterPluginTest extends BrowserTestBase { |
||||
|
||||
use StringTranslationTrait; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected static $modules = [ |
||||
'fakeobjects', |
||||
'footnotes', |
||||
'node', |
||||
]; |
||||
|
||||
/** |
||||
* An user with permissions to proper permissions. |
||||
* |
||||
* @var \Drupal\user\UserInterface |
||||
*/ |
||||
protected $adminUser; |
||||
|
||||
/** |
||||
* Text format name. |
||||
* |
||||
* @var string |
||||
*/ |
||||
protected $formatName; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function setUp() { |
||||
parent::setUp(); |
||||
|
||||
// Create a filter admin user. |
||||
$permissions = [ |
||||
'administer filters', |
||||
'administer nodes', |
||||
'access administration pages', |
||||
'administer site configuration', |
||||
]; |
||||
$this->adminUser = $this->drupalCreateUser($permissions); |
||||
$this->formatName = strtolower($this->randomMachineName()); |
||||
|
||||
$this->drupalLogin($this->adminUser); |
||||
$this->createTextFormat(); |
||||
$this->drupalCreateContentType(['type' => 'page']); |
||||
} |
||||
|
||||
/** |
||||
* Tests CKEditor Filter plugin functionality. |
||||
*/ |
||||
public function testDefaultFunctionality() { |
||||
// Verify a title with HTML entities is properly escaped. |
||||
$text1 = 'This is the note one.'; |
||||
$note1 = '[fn]' . $text1 . '[/fn]'; |
||||
$text2 = 'And this is the note two.'; |
||||
$note2 = "<fn>$text2</fn>"; |
||||
|
||||
$body = '<p>' . $this->randomMachineName(100) . $note1 . '</p><p>' . |
||||
$this->randomMachineName(100) . $note2 . '</p>'; |
||||
|
||||
// Create a node. |
||||
$node = $this->drupalCreateNode([ |
||||
'title' => $this->randomString(), |
||||
'body' => [ |
||||
0 => [ |
||||
'value' => $body, |
||||
'format' => $this->formatName, |
||||
], |
||||
], |
||||
]); |
||||
|
||||
$this->drupalGet('node/' . $node->id()); |
||||
|
||||
// Footnote with [fn]. |
||||
$this->assertNoRaw($note1); |
||||
$this->assertText($text1); |
||||
|
||||
// Footnote with <fn>. |
||||
$this->assertNoRaw($note2); |
||||
$this->assertText($text2); |
||||
|
||||
// Css file: |
||||
$this->assertRaw('/assets/css/footnotes.css'); |
||||
// @todo currently additional settings doesn't work as expected. |
||||
// So we don't check additional settings for now. |
||||
// $this->createTextFormat(TRUE); |
||||
$text1 = 'This is the note one.'; |
||||
$note1 = "[fn value='1']{$text1}[/fn]"; |
||||
$text2 = 'And this is the note two.'; |
||||
$note2 = "<fn value='1'>{$text2}</fn>"; |
||||
|
||||
$body = '<p>' . $this->randomMachineName(100) . $note1 . '</p><p>' . |
||||
$this->randomMachineName(100) . $note2 . '</p>'; |
||||
|
||||
// Create a node. |
||||
$node = $this->drupalCreateNode([ |
||||
'title' => $this->randomString(), |
||||
'body' => [ |
||||
0 => [ |
||||
'value' => $body, |
||||
'format' => $this->formatName, |
||||
], |
||||
], |
||||
]); |
||||
|
||||
$this->drupalGet('node/' . $node->id()); |
||||
|
||||
// Footnote with [fn]. |
||||
$this->assertNoRaw($note1); |
||||
$this->assertText($text1); |
||||
|
||||
// Elements with the same value should be collapsed. |
||||
// @todo This should work only if footnotes_collapse setting is enabled. |
||||
$this->assertNoRaw($note2); |
||||
$this->assertNoText($text2); |
||||
} |
||||
|
||||
/** |
||||
* Create a new text format. |
||||
* |
||||
* @param bool $additional_settings |
||||
* Indicates if filter settings should be enabled. |
||||
*/ |
||||
protected function createTextFormat($additional_settings = FALSE) { |
||||
$button_groups = json_encode([ |
||||
[ |
||||
[ |
||||
'name' => 'Tools', |
||||
'items' => ['Source', 'footnotes'], |
||||
], |
||||
], |
||||
]); |
||||
|
||||
$edit = [ |
||||
'format' => $this->formatName, |
||||
'name' => $this->formatName, |
||||
'roles[' . AccountInterface::AUTHENTICATED_ROLE . ']' => TRUE, |
||||
'editor[editor]' => 'ckeditor', |
||||
'filters[filter_footnotes][status]' => TRUE, |
||||
]; |
||||
$this->drupalGet("admin/config/content/formats/add"); |
||||
// Keep the "CKEditor" editor selected and click the "Configure" button. |
||||
$this->drupalPostForm(NULL, $edit, 'editor_configure'); |
||||
$edit['editor[settings][toolbar][button_groups]'] = $button_groups; |
||||
$edit['filters[filter_footnotes][settings][footnotes_collapse]'] = $button_groups; |
||||
if ($additional_settings) { |
||||
$edit['filters[filter_footnotes][settings][footnotes_collapse]'] = 1; |
||||
$edit['filters[filter_footnotes][settings][footnotes_html]'] = 1; |
||||
} |
||||
$this->drupalPostForm(NULL, $edit, $this->t('Save configuration')); |
||||
$this->assertText($this->t('Added text format @format.', ['@format' => $this->formatName])); |
||||
} |
||||
|
||||
} |
||||
@ -1,176 +0,0 @@
|
||||
<?php |
||||
|
||||
namespace Drupal\Tests\footnotes\FunctionalJavascript; |
||||
|
||||
use Drupal\Core\Entity\Entity\EntityFormDisplay; |
||||
use Drupal\Core\StringTranslation\StringTranslationTrait; |
||||
use Drupal\editor\Entity\Editor; |
||||
use Drupal\field\Entity\FieldConfig; |
||||
use Drupal\field\Entity\FieldStorageConfig; |
||||
use Drupal\filter\Entity\FilterFormat; |
||||
use Drupal\FunctionalJavascriptTests\WebDriverTestBase; |
||||
use Drupal\node\Entity\NodeType; |
||||
use Drupal\Tests\ckeditor\Traits\CKEditorTestTrait; |
||||
|
||||
/** |
||||
* Contains Footnotes CKEditor plugin functionality tests. |
||||
* |
||||
* @group footnotes |
||||
*/ |
||||
class FootnotesCkeditorPluginTest extends WebDriverTestBase |
||||
{ |
||||
|
||||
use StringTranslationTrait; |
||||
use CKEditorTestTrait; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected $defaultTheme = 'stark'; |
||||
|
||||
/** |
||||
* The account. |
||||
* |
||||
* @var \Drupal\user\UserInterface |
||||
*/ |
||||
protected $account; |
||||
|
||||
/** |
||||
* The FilterFormat config entity used for testing. |
||||
* |
||||
* @var \Drupal\filter\FilterFormatInterface |
||||
*/ |
||||
protected $filterFormat; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public static $modules = ['node', 'ckeditor', 'filter', 'ckeditor_test', 'fakeobjects', 'footnotes']; |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
protected function setUp() |
||||
{ |
||||
parent::setUp(); |
||||
|
||||
// Create a text format and associate CKEditor. |
||||
$this->filterFormat = FilterFormat::create([ |
||||
'format' => 'filtered_html', |
||||
'name' => 'Filtered HTML', |
||||
'filters' => [ |
||||
'filter_footnotes' => [ |
||||
'status' => TRUE, |
||||
'settings' => [ |
||||
'footnotes_collapse' => 0, |
||||
'footnotes_html' => 0 |
||||
], |
||||
], |
||||
], |
||||
]); |
||||
$this->filterFormat->save(); |
||||
|
||||
Editor::create([ |
||||
'format' => 'filtered_html', |
||||
'editor' => 'ckeditor', |
||||
'settings' => [ |
||||
'toolbar' => [ |
||||
'rows' => [ |
||||
[ |
||||
[ |
||||
'name' => 'All the things', |
||||
'items' => [ |
||||
'Source', |
||||
'Bold', |
||||
'Italic', |
||||
'footnotes', |
||||
], |
||||
], |
||||
], |
||||
], |
||||
], |
||||
], |
||||
])->save(); |
||||
|
||||
// Create a node type for testing. |
||||
NodeType::create(['type' => 'page', 'name' => 'page'])->save(); |
||||
|
||||
$field_storage = FieldStorageConfig::loadByName('node', 'body'); |
||||
|
||||
// Create a body field instance for the 'page' node type. |
||||
FieldConfig::create([ |
||||
'field_storage' => $field_storage, |
||||
'bundle' => 'page', |
||||
'label' => 'Body', |
||||
'settings' => ['display_summary' => TRUE], |
||||
'required' => TRUE, |
||||
])->save(); |
||||
|
||||
// Assign widget settings for the 'default' form mode. |
||||
EntityFormDisplay::create([ |
||||
'targetEntityType' => 'node', |
||||
'bundle' => 'page', |
||||
'mode' => 'default', |
||||
'status' => TRUE, |
||||
])->setComponent('body', ['type' => 'text_textarea_with_summary']) |
||||
->save(); |
||||
|
||||
$this->account = $this->drupalCreateUser([ |
||||
'administer nodes', |
||||
'create page content', |
||||
'use text format filtered_html', |
||||
]); |
||||
$this->drupalLogin($this->account); |
||||
} |
||||
|
||||
/** |
||||
* Tests CKEditor plugin functionality for body field. |
||||
*/ |
||||
public function testUi() |
||||
{ |
||||
$session = $this->getSession(); |
||||
$assert_session = $this->assertSession(); |
||||
|
||||
$this->drupalGet("node/add/page"); |
||||
$page = $session->getPage(); |
||||
|
||||
$this->waitForEditor(); |
||||
$this->pressEditorButton('footnotes'); |
||||
$this->assertNotEmpty( |
||||
$assert_session->waitForElementVisible('css', '.cke_1.cke_editor_edit-body-0-value_dialog') |
||||
); |
||||
$assert_session->elementTextContains('css', 'table.cke_dialog .cke_dialog_title', $this->t('Footnotes Dialog')); |
||||
$assert_session->elementTextContains('css', '.cke_dialog_page_contents table tr:first-child', $this->t('Footnote text :')); |
||||
$assert_session->elementTextContains('css', '.cke_dialog_page_contents table tr:last-child', $this->t('Value :')); |
||||
$page->find('css', 'a.cke_dialog_ui_button_cancel')->click(); |
||||
|
||||
$this->assertEmpty($assert_session->elementExists('css', '.cke_1.cke_editor_edit-body-0-value_dialog')->isVisible()); |
||||
|
||||
$texts = ['Text one.', 'Text two.', 'Text tree', 'Text four', 'Text five']; |
||||
foreach ($texts as $key => $value) { |
||||
$this->pressEditorButton('footnotes'); |
||||
$this->assertNotEmpty( |
||||
$assert_session->waitForElementVisible('css', '.cke_1.cke_editor_edit-body-0-value_dialog') |
||||
); |
||||
$assert_session->elementExists('css', '.cke_dialog_page_contents table tr:last-child input')->setValue($key); |
||||
$assert_session->elementExists('css', '.cke_dialog_page_contents table tr:first-child input')->setValue($value); |
||||
$page->find('css', 'a.cke_dialog_ui_button_ok')->click(); |
||||
|
||||
$this->assertEmpty($assert_session->elementExists('css', '.cke_1.cke_editor_edit-body-0-value_dialog')->isVisible()); |
||||
} |
||||
$this->pressEditorButton('source'); |
||||
$body_value = $assert_session->elementExists('css', '.cke .cke_contents .cke_source')->getValue(); |
||||
|
||||
$body_value = str_replace(["\r\n", "\r", "\n"], "", $body_value); |
||||
$body_value = trim($body_value); |
||||
|
||||
$expected_value = '<p>'; |
||||
foreach ($texts as $key => $value) { |
||||
$expected_value .= '<fn value="' . $key . '">' . $value . '</fn>'; |
||||
} |
||||
$expected_value .= '</p>'; |
||||
|
||||
$this->assertEqual($body_value, $expected_value, $this->t('String, formed by CKEditor, is correct.')); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue