Browse Source

quote convert

master
rdrew 2 weeks ago
parent
commit
f14db3fc2d
  1. BIN
      fonts/.DS_Store
  2. 81
      js/quote-convert.js
  3. 1
      olivesbooks.libraries.yml

BIN
fonts/.DS_Store vendored

Binary file not shown.

81
js/quote-convert.js

@ -0,0 +1,81 @@
/**
* @file
* Cosmetic fix: converts straight quotes to typographic (curly) quotes
* in rendered field markup, on page load / AJAX render.
*
* IMPORTANT: This is a display-only patch. It does NOT change the stored
* field data in the database it only rewrites text nodes in the DOM
* after render. Treat it as a stopgap until the migrated content itself
* is corrected; remove this once that's done.
*
* Adjust SELECTOR below to match whichever field wrappers actually need
* this (e.g. body fields, specific content types). Keep it as narrow as
* you reasonably can this walks every text node inside each match.
*/
(function (Drupal, once) {
"use strict";
// CHANGE THIS to target only the fields that need it.
const SELECTOR = ".field--name-field-history-note";
// Tags whose text content should never be touched.
const SKIP_TAGS = new Set([
"SCRIPT",
"STYLE",
"TEXTAREA",
"INPUT",
"CODE",
"PRE",
]);
/**
* Converts straight quotes/apostrophes in a string to curly equivalents.
*
* Heuristic (same logic SmartyPants-style tools use):
* - A straight double quote at the start of the string, or preceded by
* whitespace / an opening bracket / a dash, is an OPENING quote.
* Everything else is a CLOSING quote.
* - A straight single quote in the same "opening" positions becomes an
* opening single quote (); every other straight single quote
* including apostrophes in contractions like don't becomes the
* closing/apostrophe glyph (), which is correct either way.
*/
function smartenQuotes(text) {
text = text.replace(/(^|[\s([{\-\u2014])"/g, "$1\u201C"); // opening “
text = text.replace(/"/g, "\u201D"); // remaining → ”
text = text.replace(/(^|[\s([{\-\u2014])'/g, "$1\u2018"); // opening ‘
text = text.replace(/'/g, "\u2019"); // remaining → ’ (also apostrophes)
return text;
}
function fixTextNodesIn(root) {
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
acceptNode: function (node) {
if (SKIP_TAGS.has(node.parentNode.nodeName)) {
return NodeFilter.FILTER_REJECT;
}
if (!/["']/.test(node.nodeValue)) {
return NodeFilter.FILTER_SKIP;
}
return NodeFilter.FILTER_ACCEPT;
},
});
const nodes = [];
let n;
while ((n = walker.nextNode())) {
nodes.push(n);
}
nodes.forEach(function (node) {
node.nodeValue = smartenQuotes(node.nodeValue);
});
}
Drupal.behaviors.smartQuotesCosmetic = {
attach: function (context) {
once("smart-quotes-cosmetic", SELECTOR, context).forEach(function (el) {
fixTextNodesIn(el);
});
},
};
})(Drupal, once);

1
olivesbooks.libraries.yml

@ -57,6 +57,7 @@ global-styling:
js: js:
js/checkbox.js: {} js/checkbox.js: {}
js/custom.js: {} js/custom.js: {}
js/quote-convert.js: {}
dependencies: dependencies:
- core/drupal - core/drupal

Loading…
Cancel
Save