UNPKG

ndf-elements

Version:

My collection of useful custom elements.

115 lines (86 loc) 3.44 kB
/** * Embed a bookmarklet Javascript. * * @copyright © Nick Freear, 23-Jan-2022. * * @see ../demo/my-bookmarklet.html * @class MyBookmarkletElement */ import MyElement from '../MyElement.js'; const { fetch } = window; export class MyBookmarkletElement extends MyElement { static getTag () { return 'my-bookmarklet'; } get name () { return this.getAttribute('name') || this.textContent || 'Bookmarklet'; } get _bookmarkletScriptJs () { return '../BookmarkletScript.js'; } get _externalCdnJs () { return '../external-cdn.js'; } fromFunction (theFunction) { console.assert(typeof theFunction === 'function'); const EL = document.createElement('a'); const FUNC = theFunction.toString(); const BODY = FUNC.slice(FUNC.indexOf('{') + 1, FUNC.lastIndexOf('}')); EL.href = `javascript:${BODY}`; EL.textContent = this.name; EL.setAttribute('part', 'a'); this.attachShadow({ mode: 'open' }).appendChild(EL); console.debug(`my-bookmarklet. From function - "${this.name}":`, BODY); } async connectedCallback () { const src = this.getAttribute('src') || null; const useTemplate = !this.getAttribute('no-template'); if (!src) { return console.debug("my-bookmarklet: No 'src' attribute is specified."); // Was: throw new Error("The 'src' attribute is required on <my-bookmarklet>"); } const { codeEl, scriptLinkEl, nameEl } = await this._loadBmTemplate(useTemplate); const RESP = await fetch(src); const rawScript = await RESP.text(); // const markletScript = this._stripComments(rawScript); const { BookmarkletScript } = await import(this._bookmarkletScriptJs); const bookmarklet = new BookmarkletScript(); const RES = await bookmarklet.parse(rawScript); scriptLinkEl.href = bookmarklet.scriptLink; // this._markletScriptLink(RES.minScript); nameEl.textContent = this.name; if (useTemplate) { this._displayScript(codeEl, RES.displayScript); } console.debug('my-bookmarklet:', this.name, src, RES, this); } async _loadBmTemplate (useTemp) { const ANC = document.createElement('a'); if (useTemp) { await this.getTemplate('my-bookmarklet'); } else { ANC.part = 'a'; this.attachShadow({ mode: 'open' }).appendChild(ANC); } const codeEl = useTemp ? this.shadowRoot.querySelector('pre code') : null; const scriptLinkEl = useTemp ? this.shadowRoot.querySelector('#js-link') : ANC; const nameEl = useTemp ? this.shadowRoot.querySelector('#name') : ANC; scriptLinkEl.addEventListener('click', ev => { ev.preventDefault(); console.debug('my-bookmarklet - Click block:', ev); }); return { codeEl, scriptLinkEl, nameEl }; } async _displayScript (elem, markletScript) { const { rainbowViaCdn } = await import(this._externalCdnJs); const Rainbow = await rainbowViaCdn(); Rainbow.color(markletScript, 'javascript', (hiCode) => { elem.innerHTML = hiCode; console.debug('Rainbow:', markletScript); }); } _markletScriptLink (script) { return 'javascript:' + this._stripNewlinesSpaces(script); } _stripComments (script) { const RES = script.match(/\/\*\*?([^/]+)\*\//m); console.debug('Regex:', RES); return script; // .replace(/\/\*\*?([.\n]+)\*\/\n+/mg, ''); } _stripNewlinesSpaces (script) { return script.replace(/\n/g, '').replace(/[ ]{2,}/g, ' '); } }