') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Add plugin local asset collection by ang-zeyu · Pull Request #1129 · MarkBind/markbind · GitHub
Skip to content

Add plugin local asset collection - #1129

Merged
ang-zeyu merged 4 commits into
MarkBind:masterfrom
ang-zeyu:encapsulate-anchor-plugin
Apr 11, 2020
Merged

Add plugin local asset collection#1129
ang-zeyu merged 4 commits into
MarkBind:masterfrom
ang-zeyu:encapsulate-anchor-plugin

Conversation

@ang-zeyu

@ang-zeyuang-zeyu commented Mar 16, 2020

Copy link
Copy Markdown
Contributor

What is the purpose of this pull request? (put "X" next to an item, remove the rest)

• [x] Documentation update
• [x] Enhancement to an existing feature

Resolves#839

#442 - fixed with stopPropagation instead of relying on runtime window.location.href shifting
#433's hiding/displaying of anchor icons - done using css instead

What is the rationale for this request?

There is some degree of logic within the markbind core code that is related to plugins.
This is because the plugin getLinks and getScripts methods only allow linking to external sources.

We can enhance the API hence, allowing us to encapsulate plugin logic within itself, which should lead to better code readability.

What changes did you make? (Give an overview)
Commit organization:

  1. Add local plugin asset collection, and small update to docs accordingly
  2. Encapsulate markbind-plugin-anchors using this new feature
  3. Add and update tests for (1)
  4. Update tests for (2)

Is there anything you'd like reviewers to focus on?
Was there a reason #433 was done using runtime jQuery?

Testing instructions:

  • npm run test should pass

Proposed commit message: (wrap lines at 72 characters)
Add local asset collection for plugins

Plugins might want to package their own assets for use instead of
relying on external sources only.
The main markbind code also has some amount of logic and styles
relating to the anchor plugin.

Let's add this, allowing the getLinks and getScripts methods to return
link and script elements that have a relative or absolute file path as
its src or href attributes.
Let's encapsulate the anchor plugin's logic and styles within the
plugin itself, which should lead to better code readability.
This also allows the user to turn off the plugin without risk of side
effects.

@ang-zeyu
ang-zeyuforce-pushed the encapsulate-anchor-plugin branch 3 times, most recently from 3a1202e to a4f55acCompareMarch 23, 2020 10:21
@le0tanle0tan added the pr.Enhancement 📈 Enhancement to an existing feature label Mar 29, 2020
@ang-zeyu
ang-zeyuforce-pushed the encapsulate-anchor-plugin branch 2 times, most recently from cd2227a to a17c456CompareMarch 31, 2020 15:09
Comment threadsrc/Page.js Outdated
* Collect page content inserted by plugins
*/
collectPluginsAssets(content) {
const getResolvedAssetElement = (html, tagName, attrName, plugin, pluginName) => {

@openorcloseopenorcloseApr 1, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only one suggestion:

The implementation of utils.buildScript and buildStyleSheet plus this getResolvedElement seems rather redundant, where build* produces <script src =...></script>, and getResolvedElement later reparses it. If buildScript could instead return something like

{type: 'scriptsrc',src: 'file.js'}

then we wouldn't need to use cheerio at all, just convert the src first and then return <script src =convertedsrc.js></script>.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One con with this suggestion would be that the user cannot manually return <script src = path></script>.

Maybe it's better to leave it in so the user has more choices?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworked the buildScript/buildStylesheet a little with the new pluginUtils from #1100, its the same from a plugin author's standpoint though ( changes are limited to the first of the 4 commits ).

{ type: 'scriptsrc', src: 'file.js' }

for this, I think returning <script/link> directly is more intuitive from a plugin standpoint, since we represent html in html and not in json. This way the author can also add other variables to the tag as well easily, e.g. <link prefetch ... />.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, but now the user has to use buildScript if they want an external link.

So they can't add other attributes like <link prefetch href = "externa.css" />.

The first implementation is probably better

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, reverted that. ( getResolvedAssetElement is able to stay in pluginUtils though )

@ang-zeyu
ang-zeyuforce-pushed the encapsulate-anchor-plugin branch from a17c456 to 0072df5CompareApril 1, 2020 16:17
@openorclose

Copy link
Copy Markdown
Contributor

Nice refactor!

LGTM, only one small suggestion.

@ang-zeyu
ang-zeyuforce-pushed the encapsulate-anchor-plugin branch 2 times, most recently from a6f73ab to a7420c0CompareApril 2, 2020 07:29
@ang-zeyu
ang-zeyuforce-pushed the encapsulate-anchor-plugin branch from a7420c0 to 093b59fCompareApril 4, 2020 13:46
@ang-zeyu
ang-zeyu requested a review from marvinchinApril 5, 2020 12:24
@ang-zeyu

ang-zeyu commented Apr 5, 2020

Copy link
Copy Markdown
ContributorAuthor

@marvinchin could I get your thoughts here as well? since you opened up #839 =)

The main change here being letting plugins add local assets instead of just ones from external cdns ( first of the 4 commits )

@marvinchin

Copy link
Copy Markdown
Contributor

Sorry for the delays 🙏 I'll look at this tomorrow!

@ang-zeyu

Copy link
Copy Markdown
ContributorAuthor

Sorry for the delays 🙏 I'll look at this tomorrow!

No rush, not in a hurry to get this merged! 😄

@nbriannlnbriannl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you rebase your PR 🙂

@ang-zeyu
ang-zeyuforce-pushed the encapsulate-anchor-plugin branch from 1a15f4c to 735b706CompareApril 10, 2020 12:17
@ang-zeyu
ang-zeyu requested a review from nbriannlApril 10, 2020 12:44
@ang-zeyu
ang-zeyuforce-pushed the encapsulate-anchor-plugin branch from 735b706 to ff4a5b4CompareApril 10, 2020 13:06

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation mostly looks good to me, just a couple of comments.

Comment threadsrc/Page.js Outdated
this.frontMatter, linkUtils);
let pluginLinks = plugin.getLinks(content, this.pluginsContext[pluginName],
this.frontMatter, linkUtils);
pluginLinks = pluginLinks.map(linkHtml => getResolvedAssetElement(linkHtml, this.baseUrl,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we keep pluginLinks and const and delcare a new const resolvedPluginLinks instead?

Comment threadsrc/util/pluginUtil.js Outdated
};

module.exports = pluginUtil;
/**

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the intention of pluginUtil is to contain a set of useful functions for plugin writers to use. getResolvedAssetElement seems to be something more internal to how markbind handles assets from plugins, and does not need to be exposed to plugin writers. So maybe it should belong somewhere else?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved it back to page

}
}

function flattenModals() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to confirm - this isn't needed anymore?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, its a leftover from the bootstrap-vue PR

Comment threadsrc/Site.js Outdated
this.plugins[plugin]._pluginAssetOutputPath = path.resolve(this.outputPath,
PLUGIN_SITE_ASSET_FOLDER_NAME, plugin);

fs.mkdirSync(this.plugins[plugin]._pluginAssetOutputPath, { recursive: true });

@marvinchinmarvinchinApr 10, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if plugins have assets, the sources might be urls right? In that case, there might not be any assets copied to the output folder. Should we defer the creation of the folder until the point that we are copying it over?

@marvinchin

Copy link
Copy Markdown
Contributor

Also just to note, this PR could have been split into two parts - one adding support for local assets, and then the other one using it to fix markbind-plugin-anchors 🙂 This way each PR could be focused and easier to review. Not necessary to split them up now though!

@ang-zeyu
ang-zeyuforce-pushed the encapsulate-anchor-plugin branch from ff4a5b4 to e8094a5CompareApril 10, 2020 16:03

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀

@marvinchinmarvinchin added this to the v2.13.2 milestone Apr 10, 2020
@ang-zeyu

ang-zeyu commented Apr 11, 2020

Copy link
Copy Markdown
ContributorAuthor

@nbriannl need you to remove the change request =X


updated below on latest, no changes

@ang-zeyu
ang-zeyuforce-pushed the encapsulate-anchor-plugin branch 2 times, most recently from dfab13c to 1fadfbbCompareApril 11, 2020 07:39
Plugins might want to package their own assets for use instead of
relying on external sources only.
Let's add this, allowing the getLinks and getScripts methods to return
link and script elements that have a relative or absolute file path as
its src or href attributes.
The main markbind code has some amount of logic and styles relating to
the anchor plugin.
Let's encapsulate the anchor plugin's logic and styles within the
plugin itself, which should lead to better code readability.
This also allows the user to turn off the plugin without risk of side
effects.
@ang-zeyu
ang-zeyuforce-pushed the encapsulate-anchor-plugin branch from 1fadfbb to f672dcfCompareApril 11, 2020 09:13
@ang-zeyu
ang-zeyu merged commit 248898d into MarkBind:masterApr 11, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr.Enhancement 📈Enhancement to an existing feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow plugins to add assets

5 participants

@ang-zeyu@openorclose@marvinchin@nbriannl@le0tan