docbrown/app/javascript/utilities/gist.js
Julien Maury a2677cc0a9
Remove defer attributes from inline scripts - gist embeds (#13407)
* replace inline attribute defer with external js - show.html.erb

* fix typo in filename

* disable no-undef and bail if not defined

* put js on subfolder utilities

* refactor jsx instead of loading chunk with defer

* fix typo in desc

* better name for global gist helper

* use InstantClick

* working script on preview AND single view, not dynamic import, though

* embed only if gists

* combine all approaches to make dynamic import work

* make gist embeds work on submit comment form

* make gist embeds work on preview comment

* refactor - preview comments and submit

* add pack editComment + helper embedGistsInComments

* comment gist helper

* delete useless file utility

* use new syntax for events

* put code in method embedGistsInComments

* delete older pack gist

* handle edge case 'view full discussion'

* resolve conflict with package ibm-openapi-validator

* resolve conflict with package husky

* empty commit to test random error travis

* better name for class dismiss

* handle future events submit

* delete test code on click toggle form

* delete unused file

* rename pack as js file, not jsx

* Added POC using MutationObserver.

* missing case: notification page

* use custom pack notification page

* add e2e test for comment with embed gist

* add e2e test for preview post with embed gist

* add an extra step in tests to check gist is present

Co-authored-by: Nick Taylor <nick@dev.to>
Co-authored-by: Suzanne Aitchison <suzanne@forem.com>
2021-06-11 08:22:50 +01:00

74 lines
1.8 KiB
JavaScript

let postscribeImport;
async function getPostScribe() {
if (postscribeImport) {
// Grab the cached import so we're not always fetching it from the network.
return postscribeImport;
}
const { default: postscribe } = await import('postscribe');
postscribeImport = postscribe;
return postscribeImport;
}
function getGistTags(nodes) {
const gistNodes = [];
for (const node of nodes) {
if (node.nodeType === 1) {
if (node.classList.contains('ltag_gist-liquid-tag')) {
gistNodes.push(node);
}
gistNodes.push(...node.querySelectorAll('.ltag_gist-liquid-tag'));
}
}
return gistNodes;
}
function loadEmbeddedGists(postscribe, gistTags) {
for (const gistTag of gistTags) {
postscribe(gistTag, gistTag.firstElementChild.outerHTML, {
beforeWrite(text) {
return gistTag.childElementCount > 3 ? '' : text;
},
});
}
}
function watchForGistTagInsertion(targetNode, postscribe) {
const config = { attributes: false, childList: true, subtree: true };
const callback = function (mutationsList) {
for (const { type, addedNodes } of mutationsList) {
if (type === 'childList' && addedNodes.length > 0) {
loadEmbeddedGists(postscribe, getGistTags(addedNodes));
}
}
};
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
InstantClick.on('change', () => {
observer.disconnect();
});
window.addEventListener('beforeunload', () => {
observer.disconnect();
});
}
export async function embedGists(targetNode) {
const postscribe = await getPostScribe();
// Load gist tags that were rendered server-side
loadEmbeddedGists(
postscribe,
document.querySelectorAll('.ltag_gist-liquid-tag'),
);
watchForGistTagInsertion(targetNode, postscribe);
}