FEATURE Complete change of footnote behaviour. Now injecting a footnote independant tag
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
699a2efe1b
commit
f487c95751
|
|
@ -21,7 +21,7 @@ body {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 11px !important;
|
font-size: 11px !important;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-right: 3px;
|
margin-right: 0px;
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-rich-text'), 'version' => '4e7e470686a7bd3035eb');
|
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-rich-text'), 'version' => 'bb1996ad8ebf6f6ac5a4');
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ body {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 11px !important;
|
font-size: 11px !important;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-left: 3px;
|
margin-left: 0px;
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"index.css","mappings":";;;AAAA;CACC,6BAA6B;AAC9B;AACA;CACC,iCAAiC;CACjC,kBAAkB;CAClB,YAAY;;CAEZ;EACC,mDAAmD;EACnD,WAAW;EACX,WAAW;EACX,YAAY;EACZ,kBAAkB;EAClB,gCAAgC;EAChC,oBAAoB;EACpB,uBAAuB;EACvB,mBAAmB;EACnB,0BAA0B;EAC1B,gBAAgB;EAChB,gBAAgB;EAChB,iBAAiB;CAClB;AACD;;AAEA;;CAEC;EACC,0BAA0B;EAC1B,6BAA6B;EAC7B,wDAAwD;EACxD,8BAA8B;EAC9B,0BAA0B;CAC3B;AACD;;AAEA;CACC;EACC,wBAAwB;EACxB,gBAAgB;CACjB;CACA;EACC,aAAa;EACb,yBAAyB;EACzB,SAAS;EACT,gBAAgB;;EAEhB;GACC,oCAAoC;GACpC,sBAAsB;EACvB;;EAEA;GACC,8DAA8D;GAC9D,sBAAsB;EACvB;CACD;AACD;;;;;ACzDA;CACC,yBAAyB;AAC1B","sources":["webpack:///./src/footnotes/footnote.css","webpack:///./src/uppercased-small-title/uppercased-small-title.css"],"sourcesContent":["body {\r\n\tcounter-reset: footnote-index;\r\n}\r\n.footnote-reference {\r\n\tcounter-increment: footnote-index;\r\n\tposition: relative;\r\n\tcolor: unset;\r\n\r\n\t&::after {\r\n\t\tbackground-color: var(--wp--preset--color--primary);\r\n\t\tcolor: #fff;\r\n\t\twidth: 22px;\r\n\t\theight: 22px;\r\n\t\tborder-radius: 50%;\r\n\t\tcontent: counter(footnote-index);\r\n\t\tdisplay: inline-flex;\r\n\t\tjustify-content: center;\r\n\t\talign-items: center;\r\n\t\tfont-size: 11px !important;\r\n\t\tfont-weight: 600;\r\n\t\tmargin-left: 3px;\r\n\t\tmargin-right: 3px;\r\n\t}\r\n}\r\n\r\n// Editor\r\n.footnote-reference {\r\n\t.wp-block-post-content & {\r\n\t\ttext-decoration: underline;\r\n\t\ttext-decoration-style: dotted;\r\n\t\ttext-decoration-color: var(--wp--preset--color--primary);\r\n\t\ttext-decoration-thickness: 2px;\r\n\t\ttext-underline-offset: 2px;\r\n\t}\r\n}\r\n\r\n.popover_footnote_field {\r\n\t.components-popover__content {\r\n\t\tpadding: 10px !important;\r\n\t\tmin-width: 500px;\r\n\t}\r\n\t.popover_footnote_field_buttons {\r\n\t\tdisplay: flex;\r\n\t\tjustify-content: flex-end;\r\n\t\tgap: 10px;\r\n\t\tmargin-top: 10px;\r\n\r\n\t\tbutton.is-destructive {\r\n\t\t\tbackground-color: #cc1818 !important;\r\n\t\t\tcolor: #fff !important;\r\n\t\t}\r\n\r\n\t\tbutton.is-primary {\r\n\t\t\tbackground-color: var(--wp--preset--color--primary) !important;\r\n\t\t\tcolor: #fff !important;\r\n\t\t}\r\n\t}\r\n}\r\n",".uppercased-small-title {\r\n\ttext-transform: uppercase;\r\n}\r\n"],"names":[],"sourceRoot":""}
|
{"version":3,"file":"index.css","mappings":";;;AAAA;CACC,6BAA6B;AAC9B;AACA;CACC,iCAAiC;CACjC,kBAAkB;CAClB,YAAY;;CAEZ;EACC,mDAAmD;EACnD,WAAW;EACX,WAAW;EACX,YAAY;EACZ,kBAAkB;EAClB,gCAAgC;EAChC,oBAAoB;EACpB,uBAAuB;EACvB,mBAAmB;EACnB,0BAA0B;EAC1B,gBAAgB;EAChB,gBAAgB;EAChB,iBAAiB;CAClB;AACD;;AAEA;;CAEC;EACC,0BAA0B;EAC1B,6BAA6B;EAC7B,wDAAwD;EACxD,8BAA8B;EAC9B,0BAA0B;CAC3B;AACD;;AAEA;CACC;EACC,wBAAwB;EACxB,gBAAgB;CACjB;CACA;EACC,aAAa;EACb,yBAAyB;EACzB,SAAS;EACT,gBAAgB;;EAEhB;GACC,oCAAoC;GACpC,sBAAsB;EACvB;;EAEA;GACC,8DAA8D;GAC9D,sBAAsB;EACvB;CACD;AACD;;;;;ACzDA;CACC,yBAAyB;AAC1B","sources":["webpack:///./src/footnotes/footnote.css","webpack:///./src/uppercased-small-title/uppercased-small-title.css"],"sourcesContent":["body {\r\n\tcounter-reset: footnote-index;\r\n}\r\n.footnote-reference {\r\n\tcounter-increment: footnote-index;\r\n\tposition: relative;\r\n\tcolor: unset;\r\n\r\n\t&::after {\r\n\t\tbackground-color: var(--wp--preset--color--primary);\r\n\t\tcolor: #fff;\r\n\t\twidth: 22px;\r\n\t\theight: 22px;\r\n\t\tborder-radius: 50%;\r\n\t\tcontent: counter(footnote-index);\r\n\t\tdisplay: inline-flex;\r\n\t\tjustify-content: center;\r\n\t\talign-items: center;\r\n\t\tfont-size: 11px !important;\r\n\t\tfont-weight: 600;\r\n\t\tmargin-left: 0px;\r\n\t\tmargin-right: 3px;\r\n\t}\r\n}\r\n\r\n// Editor\r\n.footnote-reference {\r\n\t.wp-block-post-content & {\r\n\t\ttext-decoration: underline;\r\n\t\ttext-decoration-style: dotted;\r\n\t\ttext-decoration-color: var(--wp--preset--color--primary);\r\n\t\ttext-decoration-thickness: 2px;\r\n\t\ttext-underline-offset: 2px;\r\n\t}\r\n}\r\n\r\n.popover_footnote_field {\r\n\t.components-popover__content {\r\n\t\tpadding: 10px !important;\r\n\t\tmin-width: 500px;\r\n\t}\r\n\t.popover_footnote_field_buttons {\r\n\t\tdisplay: flex;\r\n\t\tjustify-content: flex-end;\r\n\t\tgap: 10px;\r\n\t\tmargin-top: 10px;\r\n\r\n\t\tbutton.is-destructive {\r\n\t\t\tbackground-color: #cc1818 !important;\r\n\t\t\tcolor: #fff !important;\r\n\t\t}\r\n\r\n\t\tbutton.is-primary {\r\n\t\t\tbackground-color: var(--wp--preset--color--primary) !important;\r\n\t\t\tcolor: #fff !important;\r\n\t\t}\r\n\t}\r\n}\r\n",".uppercased-small-title {\r\n\ttext-transform: uppercase;\r\n}\r\n"],"names":[],"sourceRoot":""}
|
||||||
|
|
@ -116,6 +116,7 @@ const FootnoteFormatButton = props => {
|
||||||
onChange
|
onChange
|
||||||
} = props;
|
} = props;
|
||||||
const [isPopoverOpen, setIsPopoverOpen] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_4__.useState)(false);
|
const [isPopoverOpen, setIsPopoverOpen] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_4__.useState)(false);
|
||||||
|
const hasSelection = value.start !== value.end;
|
||||||
|
|
||||||
// Vérifier si on est dans un article (post type 'post')
|
// Vérifier si on est dans un article (post type 'post')
|
||||||
const postType = (0,_wordpress_data__WEBPACK_IMPORTED_MODULE_5__.useSelect)(select => {
|
const postType = (0,_wordpress_data__WEBPACK_IMPORTED_MODULE_5__.useSelect)(select => {
|
||||||
|
|
@ -123,7 +124,7 @@ const FootnoteFormatButton = props => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Ne pas afficher le bouton si ce n'est pas un article
|
// Ne pas afficher le bouton si ce n'est pas un article
|
||||||
if (postType !== "articles") {
|
if (postType !== "articles" || !isActive && hasSelection) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const activeFormat = (0,_wordpress_rich_text__WEBPACK_IMPORTED_MODULE_1__.getActiveFormats)(value).filter(format => format.type === formatName)[0];
|
const activeFormat = (0,_wordpress_rich_text__WEBPACK_IMPORTED_MODULE_1__.getActiveFormats)(value).filter(format => format.type === formatName)[0];
|
||||||
|
|
@ -132,6 +133,41 @@ const FootnoteFormatButton = props => {
|
||||||
}
|
}
|
||||||
function removeFormat() {
|
function removeFormat() {
|
||||||
setIsPopoverOpen(false);
|
setIsPopoverOpen(false);
|
||||||
|
const {
|
||||||
|
text,
|
||||||
|
formats,
|
||||||
|
start,
|
||||||
|
end
|
||||||
|
} = value;
|
||||||
|
const textLength = text ? text.length : 0;
|
||||||
|
const isFootnoteAtIndex = index => {
|
||||||
|
if (!formats || index < 0 || index >= (formats?.length || 0)) return false;
|
||||||
|
const charFormats = formats[index];
|
||||||
|
if (!charFormats) return false;
|
||||||
|
return charFormats.some(f => f && f.type === formatName);
|
||||||
|
};
|
||||||
|
if (textLength > 0) {
|
||||||
|
let pos = Math.min(start, textLength - 1);
|
||||||
|
// If caret is just after the formatted run, step back one char
|
||||||
|
if (!isFootnoteAtIndex(pos) && pos > 0 && isFootnoteAtIndex(pos - 1)) {
|
||||||
|
pos = pos - 1;
|
||||||
|
}
|
||||||
|
if (isFootnoteAtIndex(pos)) {
|
||||||
|
let left = pos;
|
||||||
|
let right = pos;
|
||||||
|
while (left >= 0 && isFootnoteAtIndex(left)) left--;
|
||||||
|
while (right < textLength && isFootnoteAtIndex(right)) right++;
|
||||||
|
const spanStart = left + 1;
|
||||||
|
const spanEnd = right; // exclusive
|
||||||
|
|
||||||
|
// Supprimer toujours le texte complet de la footnote
|
||||||
|
onChange((0,_wordpress_rich_text__WEBPACK_IMPORTED_MODULE_1__.remove)(value, spanStart, spanEnd));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: si aucune footnote n'est trouvée à la position du curseur,
|
||||||
|
// enlever juste le formatage
|
||||||
onChange((0,_wordpress_rich_text__WEBPACK_IMPORTED_MODULE_1__.toggleFormat)(value, {
|
onChange((0,_wordpress_rich_text__WEBPACK_IMPORTED_MODULE_1__.toggleFormat)(value, {
|
||||||
type: formatName
|
type: formatName
|
||||||
}));
|
}));
|
||||||
|
|
@ -144,6 +180,17 @@ const FootnoteFormatButton = props => {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
function insertFormat(footnoteContent) {
|
||||||
|
const text = "[NOTE]";
|
||||||
|
const start = value.start; // position du curseur avant insertion
|
||||||
|
const nextValue = (0,_wordpress_rich_text__WEBPACK_IMPORTED_MODULE_1__.insert)(value, text);
|
||||||
|
onChange((0,_wordpress_rich_text__WEBPACK_IMPORTED_MODULE_1__.applyFormat)(nextValue, {
|
||||||
|
type: formatName,
|
||||||
|
attributes: {
|
||||||
|
dataFootnoteContent: footnoteContent
|
||||||
|
}
|
||||||
|
}, start, start + text.length));
|
||||||
|
}
|
||||||
return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_7__.jsx)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_7__.Fragment, {
|
return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_7__.jsx)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_7__.Fragment, {
|
||||||
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxs)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_2__.BlockControls, {
|
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxs)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_2__.BlockControls, {
|
||||||
children: [isPopoverOpen && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__.Popover, {
|
children: [isPopoverOpen && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__.Popover, {
|
||||||
|
|
@ -173,7 +220,13 @@ const FootnoteFormatButton = props => {
|
||||||
icon: _wordpress_icons__WEBPACK_IMPORTED_MODULE_8__["default"],
|
icon: _wordpress_icons__WEBPACK_IMPORTED_MODULE_8__["default"],
|
||||||
isPressed: isActive,
|
isPressed: isActive,
|
||||||
label: !isActive ? "Ajouter une note de bas de page" : "Éditer la note de bas de page",
|
label: !isActive ? "Ajouter une note de bas de page" : "Éditer la note de bas de page",
|
||||||
onClick: () => setIsPopoverOpen(true)
|
onClick: () => {
|
||||||
|
if (!isActive) {
|
||||||
|
insertFormat();
|
||||||
|
} else {
|
||||||
|
setIsPopoverOpen(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})]
|
})]
|
||||||
})
|
})
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -18,7 +18,7 @@ body {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: 11px !important;
|
font-size: 11px !important;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-left: 3px;
|
margin-left: 0px;
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { __ } from "@wordpress/i18n";
|
import { __ } from "@wordpress/i18n";
|
||||||
import { registerFormatType, toggleFormat, applyFormat, getActiveFormats } from "@wordpress/rich-text";
|
import { registerFormatType, toggleFormat, applyFormat, getActiveFormats, insert, remove } from "@wordpress/rich-text";
|
||||||
|
|
||||||
import { BlockControls, __experimentalLinkControl as LinkControl } from "@wordpress/block-editor";
|
import { BlockControls, __experimentalLinkControl as LinkControl } from "@wordpress/block-editor";
|
||||||
import { Popover, ToolbarGroup, ToolbarButton, TextControl, TextareaControl, Button } from "@wordpress/components";
|
import { Popover, ToolbarGroup, ToolbarButton, TextControl, TextareaControl, Button } from "@wordpress/components";
|
||||||
|
|
@ -15,6 +15,7 @@ const formatName = "carhop-format/footnote";
|
||||||
const FootnoteFormatButton = (props) => {
|
const FootnoteFormatButton = (props) => {
|
||||||
const { isActive, value, onChange } = props;
|
const { isActive, value, onChange } = props;
|
||||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
||||||
|
const hasSelection = value.start !== value.end;
|
||||||
|
|
||||||
// Vérifier si on est dans un article (post type 'post')
|
// Vérifier si on est dans un article (post type 'post')
|
||||||
const postType = useSelect((select) => {
|
const postType = useSelect((select) => {
|
||||||
|
|
@ -22,7 +23,7 @@ const FootnoteFormatButton = (props) => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Ne pas afficher le bouton si ce n'est pas un article
|
// Ne pas afficher le bouton si ce n'est pas un article
|
||||||
if (postType !== "articles") {
|
if (postType !== "articles" || (!isActive && hasSelection)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,6 +35,40 @@ const FootnoteFormatButton = (props) => {
|
||||||
|
|
||||||
function removeFormat() {
|
function removeFormat() {
|
||||||
setIsPopoverOpen(false);
|
setIsPopoverOpen(false);
|
||||||
|
const { text, formats, start, end } = value;
|
||||||
|
const textLength = text ? text.length : 0;
|
||||||
|
|
||||||
|
const isFootnoteAtIndex = (index) => {
|
||||||
|
if (!formats || index < 0 || index >= (formats?.length || 0)) return false;
|
||||||
|
const charFormats = formats[index];
|
||||||
|
if (!charFormats) return false;
|
||||||
|
return charFormats.some((f) => f && f.type === formatName);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (textLength > 0) {
|
||||||
|
let pos = Math.min(start, textLength - 1);
|
||||||
|
// If caret is just after the formatted run, step back one char
|
||||||
|
if (!isFootnoteAtIndex(pos) && pos > 0 && isFootnoteAtIndex(pos - 1)) {
|
||||||
|
pos = pos - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFootnoteAtIndex(pos)) {
|
||||||
|
let left = pos;
|
||||||
|
let right = pos;
|
||||||
|
while (left >= 0 && isFootnoteAtIndex(left)) left--;
|
||||||
|
while (right < textLength && isFootnoteAtIndex(right)) right++;
|
||||||
|
|
||||||
|
const spanStart = left + 1;
|
||||||
|
const spanEnd = right; // exclusive
|
||||||
|
|
||||||
|
// Supprimer toujours le texte complet de la footnote
|
||||||
|
onChange(remove(value, spanStart, spanEnd));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: si aucune footnote n'est trouvée à la position du curseur,
|
||||||
|
// enlever juste le formatage
|
||||||
onChange(
|
onChange(
|
||||||
toggleFormat(value, {
|
toggleFormat(value, {
|
||||||
type: formatName,
|
type: formatName,
|
||||||
|
|
@ -50,6 +85,23 @@ const FootnoteFormatButton = (props) => {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
function insertFormat(footnoteContent) {
|
||||||
|
const text = "[NOTE]";
|
||||||
|
const start = value.start; // position du curseur avant insertion
|
||||||
|
const nextValue = insert(value, text);
|
||||||
|
|
||||||
|
onChange(
|
||||||
|
applyFormat(
|
||||||
|
nextValue,
|
||||||
|
{
|
||||||
|
type: formatName,
|
||||||
|
attributes: { dataFootnoteContent: footnoteContent },
|
||||||
|
},
|
||||||
|
start,
|
||||||
|
start + text.length
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -88,7 +140,13 @@ const FootnoteFormatButton = (props) => {
|
||||||
? "Ajouter une note de bas de page"
|
? "Ajouter une note de bas de page"
|
||||||
: "Éditer la note de bas de page"
|
: "Éditer la note de bas de page"
|
||||||
}
|
}
|
||||||
onClick={() => setIsPopoverOpen(true)}
|
onClick={() => {
|
||||||
|
if (!isActive) {
|
||||||
|
insertFormat();
|
||||||
|
} else {
|
||||||
|
setIsPopoverOpen(true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</ToolbarGroup>
|
</ToolbarGroup>
|
||||||
</BlockControls>
|
</BlockControls>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user