From eb8e661f105363163699e54559b1a65d7253958c Mon Sep 17 00:00:00 2001 From: horihiro Date: Sat, 22 Jun 2024 07:51:00 +0900 Subject: [PATCH 1/4] Typescriptizing --- .gitignore | 10 + .vscode/launch.json | 21 +- .vscode/tasks.json | 37 +- content/css/blur.css | 21 - content/js/diff.min.js | 1 - content/js/main.js | 746 ---------------- manifest.json | 7 +- package-lock.json | 803 ++++++++++++++++++ package.json | 31 + {popup => public}/css/main.css | 0 {popup => public}/img/ATTRIBUTIONS.txt | 0 {popup => public}/img/arrow.svg | 0 {popup => public}/img/case-sensitive.svg | 0 {popup => public}/img/comment.svg | 0 {popup => public}/img/regex.svg | 0 {popup => public}/img/symbol-string.svg | 0 {popup => public}/img/tab-title.svg | 0 {popup => public}/main.html | 4 +- .../background/background.ts | 10 +- src/content/blurrer/DOMBlurrer.ts | 468 ++++++++++ src/content/blurrer/IBlurrer.ts | 13 + src/content/blurrer/InputBlurrer.ts | 240 ++++++ src/content/blurrer/TitleBlurrer.ts | 58 ++ src/content/contentScript.ts | 78 ++ popup/js/main.js => src/popup/popup.ts | 112 ++- util/common.js => src/utils/common.ts | 2 +- tsconfig.json | 5 + 27 files changed, 1805 insertions(+), 862 deletions(-) create mode 100644 .gitignore delete mode 100644 content/css/blur.css delete mode 100644 content/js/diff.min.js delete mode 100644 content/js/main.js create mode 100644 package-lock.json create mode 100644 package.json rename {popup => public}/css/main.css (100%) rename {popup => public}/img/ATTRIBUTIONS.txt (100%) rename {popup => public}/img/arrow.svg (100%) rename {popup => public}/img/case-sensitive.svg (100%) rename {popup => public}/img/comment.svg (100%) rename {popup => public}/img/regex.svg (100%) rename {popup => public}/img/symbol-string.svg (100%) rename {popup => public}/img/tab-title.svg (100%) rename {popup => public}/main.html (94%) rename background/service-worker.js => src/background/background.ts (55%) create mode 100644 src/content/blurrer/DOMBlurrer.ts create mode 100644 src/content/blurrer/IBlurrer.ts create mode 100644 src/content/blurrer/InputBlurrer.ts create mode 100644 src/content/blurrer/TitleBlurrer.ts create mode 100644 src/content/contentScript.ts rename popup/js/main.js => src/popup/popup.ts (74%) rename util/common.js => src/utils/common.ts (57%) create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d1cb1ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# dependencies +node_modules + +# production +dist + +# misc +.DS_Store + +npm-debug.log* diff --git a/.vscode/launch.json b/.vscode/launch.json index 7d73300..b23b18e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -3,17 +3,28 @@ "configurations": [ { "type": "chrome", - "request": "attach", + "request": "launch", "name": "Debug on Chrome", "port": 9222, - "preLaunchTask": "Launch Chrome" + "webRoot": "${workspaceFolder}", + "runtimeArgs": [ + "--load-extension=${workspaceFolder}", + "--enable-extensions-developer-mode", + "https://example.com", + ], + "preLaunchTask": "build" }, { "type": "msedge", - "request": "attach", - "name": "Debug on Edge", + "request": "launch", + "name": "Attach to Edge", "port": 9222, - "preLaunchTask": "Launch Edge" + "runtimeArgs": [ + "--load-extension=${workspaceFolder}", + "--enable-extensions-developer-mode", + "https://example.com", + ], + "preLaunchTask": "build" } ] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index dd19816..82fe39c 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -3,37 +3,12 @@ "tasks": [ { "type": "shell", - "label": "Launch Chrome", - "windows": { - "command": "${env:PROGRAMFILES}\\Google\\Chrome\\Application\\chrome.exe\"", - "args": [ - "--remote-debugging-port=9222", - "--load-extension=${workspaceFolder}", // this is the path to the extension folder - "https://example.com/" - ], - "options": { - "env": { - "CHROME_DEVELOPER_TOOLS": true - } - } + "label": "build", + "command": "npm run build:dev", + "group": { + "kind": "build", + "isDefault": true } - }, - { - "type": "shell", - "label": "Launch Edge", - "windows": { - "command": "${env:ProgramFiles(x86)}\\Microsoft\\Edge\\Application\\msedge.exe\"", - "args": [ - "--remote-debugging-port=9222", - "--load-extension=${workspaceFolder}", // this is the path to the extension folder - "https://example.com/" - ], - "options": { - "env": { - "CHROME_DEVELOPER_TOOLS": true - } - } - }, } ] -} \ No newline at end of file +} diff --git a/content/css/blur.css b/content/css/blur.css deleted file mode 100644 index b378d48..0000000 --- a/content/css/blur.css +++ /dev/null @@ -1,21 +0,0 @@ -.blurred { - filter: blur(5px); -} - -.mask { - border: none; - overflow: hidden; -} - -#__inputClone, .mask, .textLayer { - position: absolute; - top: 0px; - left: 0px; - border: none; - overflow: hidden; - white-space: nowrap; -} - -#__inputClone { - visibility: hidden; -} \ No newline at end of file diff --git a/content/js/diff.min.js b/content/js/diff.min.js deleted file mode 100644 index 078bcc5..0000000 --- a/content/js/diff.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e=e||self).Diff={})}(this,function(e){"use strict";function t(){}t.prototype={diff:function(s,a,e){var n,t=2=c&&f<=v+1)return d([{value:this.join(a),count:a.length}]);var m=-1/0,g=1/0;function w(){for(var e=Math.max(m,-p);e<=Math.min(g,p);e+=2){var n=void 0,t=h[e-1],r=h[e+1];t&&(h[e-1]=void 0);var i,o=!1;r&&(i=r.oldPos-e,o=r&&0<=i&&i=c&&f<=v+1)return d(function(e,n,t,r,i){var o,l=[];for(;n;)l.push(n),o=n.previousComponent,delete n.previousComponent,n=o;l.reverse();for(var s=0,a=l.length,u=0,d=0;se.length?t:e}),p.value=e.join(c)):p.value=e.join(t.slice(u,u+p.count)),u+=p.count,p.added||(d+=p.count))}var h=l[a-1];1=c&&(g=Math.min(g,e-1)),f<=v+1&&(m=Math.max(m,e+1))}else h[e]=void 0}p++}if(r)!function e(){setTimeout(function(){return il?r():void(w()||e())},0)}();else for(;p<=i&&Date.now()<=l;){var y=w();if(y)return y}},addToPath:function(e,n,t,r){var i=e.lastComponent;return i&&i.added===n&&i.removed===t?{oldPos:e.oldPos+r,lastComponent:{count:i.count+1,added:n,removed:t,previousComponent:i.previousComponent}}:{oldPos:e.oldPos+r,lastComponent:{count:1,added:n,removed:t,previousComponent:i}}},extractCommon:function(e,n,t,r){for(var i=n.length,o=t.length,l=e.oldPos,s=l-r,a=0;s+1e.length)&&(n=e.length);for(var t=0,r=new Array(n);t=c.length-2&&a.length<=f.context&&(i=/\n$/.test(u),o=/\n$/.test(d),l=0==a.length&&m.length>r.oldLines,!i&&l&&0e.length)return!1;for(var t=0;t"):i.removed&&t.push(""),t.push((n=i.value,n.replace(/&/g,"&").replace(//g,">").replace(/"/g,"""))),i.added?t.push(""):i.removed&&t.push("")}return t.join("")},e.createPatch=function(e,n,t,r,i,o){return b(e,e,n,t,r,i,o)},e.createTwoFilesPatch=b,e.diffArrays=function(e,n,t){return g.diff(e,n,t)},e.diffChars=function(e,n,t){return r.diff(e,n,t)},e.diffCss=function(e,n,t){return d.diff(e,n,t)},e.diffJson=function(e,n,t){return v.diff(e,n,t)},e.diffLines=L,e.diffSentences=function(e,n,t){return u.diff(e,n,t)},e.diffTrimmedLines=function(e,n,t){var r=i(t,{ignoreWhitespace:!0});return a.diff(e,n,r)},e.diffWords=function(e,n,t){return t=i(t,{ignoreWhitespace:!0}),s.diff(e,n,t)},e.diffWordsWithSpace=function(e,n,t){return s.diff(e,n,t)},e.formatPatch=S,e.merge=function(e,n,t){e=N(e,t),n=N(n,t);var r={};(e.index||n.index)&&(r.index=e.index||n.index),(e.newFileName||n.newFileName)&&(P(e)?P(n)?(r.oldFileName=j(r,e.oldFileName,n.oldFileName),r.newFileName=j(r,e.newFileName,n.newFileName),r.oldHeader=j(r,e.oldHeader,n.oldHeader),r.newHeader=j(r,e.newHeader,n.newHeader)):(r.oldFileName=e.oldFileName,r.newFileName=e.newFileName,r.oldHeader=e.oldHeader,r.newHeader=e.newHeader):(r.oldFileName=n.oldFileName||e.oldFileName,r.newFileName=n.newFileName||e.newFileName,r.oldHeader=n.oldHeader||e.oldHeader,r.newHeader=n.newHeader||e.newHeader)),r.hunks=[];for(var i=0,o=0,l=0,s=0;i { - const src = chrome.runtime.getURL('util/common.js'); - const { escapeRegExp } = await import(src); - const w = window; - const inputs = []; - const observedNodes = []; - - const SKIP_NODE_NAMES = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'HEAD', 'META', 'LINK', 'HTML', 'TEXTAREA', 'TITLE', '#comment']; - const BLOCK_ELEMENT_NAMES = [ - 'ADDRESS', 'ARTICLE', 'ASIDE', 'BLOCKQUOTE', 'BODY', 'CANVAS', 'DD', 'DIV', 'DL', 'DT', 'FIELDSET', 'FIGCAPTION', - 'FIGURE', 'FOOTER', 'FORM', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'HEADER', 'HR', 'LI', 'MAIN', 'NAV', 'NOSCRIPT', - 'OL', 'P', 'PRE', 'SCRIPT', 'SECTION', 'TABLE', 'TFOOT', 'UL', 'VIDEO' - ]; - const CLASS_NAME_BLURRED = 'tb-blurred'; - const CLASS_PREFIX_BLURRED_GROUP = 'tb-blurred-group-'; - const CLASS_NAME_KEEP = 'tb-keep-this'; - const ATTR_NAME_ORIGINAL_TITLE = 'data-tb-original-title'; - const CLASS_NAME_MASK_CONTAINER = 'tb-mask-container'; - const CLASS_NAME_TEXT_LAYER = 'tb-mask-text-layer'; - const CLASS_NAME_CODEMIRROR_EDITOR = 'cm-editor'; - const ID_INPUT_CLONE = 'tb-input-clone'; - const ID_GLOBAL_STYLE = '__blurring-style'; - const GLOBAL_STYLE = `.${CLASS_NAME_BLURRED} { - filter: blur(5px)!important; -} -.${CLASS_NAME_MASK_CONTAINER} { - border: none!important; - overflow: hidden!important; -} - -#${ID_INPUT_CLONE}, .${CLASS_NAME_MASK_CONTAINER}, .${CLASS_NAME_TEXT_LAYER} { - position: absolute!important; - border: none!important; - overflow: hidden!important; - white-space: nowrap!important; -} - -#${ID_INPUT_CLONE} { - visibility: hidden!important; - white-space-collapse: preserve!important; -}`; - - const send2popup = async (message) => { - chrome.runtime.sendMessage(message); - } - - chrome.runtime.onMessage.addListener(async (message, sender) => { - if (message.method === 'getUrl') { - await send2popup({ - method: 'getUrlResponse', - isTop: window.top === window, - numOfChildren: Array.from(document.querySelectorAll('iframe,frame')).filter(f => /^https?:\/\//.test(f.src)).length, - url: location.href - }); - } - }); - - const shouldBeSkipped = (node) => { - if (node.nodeType !== 1) return shouldBeSkipped(node.parentNode); - - if (isBlurred(node)) { - console.debug(`Skipped. Reason: Already blurred`); - return true; - } - if (SKIP_NODE_NAMES.includes(node.nodeName)) { - console.debug(`Skipped. Reason: The nodeName is ${node.nodeName}`); - return true; - } - if (!!node.closest(`.${CLASS_NAME_CODEMIRROR_EDITOR}`)) { - console.debug(`Skipped. Reason: CodeMirror`); - return true; - } - // if (node.isContentEditable) { - // console.debug(`Skipped. Reason: The node is contentEditable`); - // return true; - // } - return false; - } - - const getNextTextNode = (e, root) => { - if (!e) return null; - if (e.firstChild && !SKIP_NODE_NAMES.includes(e.nodeName)) return e.firstChild.nodeName === '#text' ? e.firstChild : getNextTextNode(e.firstChild, root); - if (e.nextSibling) return e.nextSibling.nodeName === '#text' ? e.nextSibling : getNextTextNode(e.nextSibling, root); - let parent = e.parentNode; - while (parent != root && parent) { - if (parent.nextSibling) return parent.nextSibling.nodeName === '#text' ? parent.nextSibling : getNextTextNode(parent.nextSibling, root); - parent = parent.parentNode; - } - return null; - } - - const getPreviousTextNode = (e, root) => { - if (!e) return null; - if (e.lastChild) return e.lastChild.nodeName === '#text' ? e.lastChild : getPreviousTextNode(e.lastChild, root); - if (e.previousSibling) return e.previousSibling.nodeName === '#text' ? e.previousSibling : getPreviousTextNode(e.previousSibling, root); - - let parent = e.parentNode; - while (parent != root && parent) { - if (parent.previousSibling) return parent.previousSibling.nodeName === '#text' ? parent.previousSibling : getPreviousTextNode(parent.previousSibling, root); - parent = parent.parentNode; - } - return null; - } - - // https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Whitespace#how_does_css_process_whitespace - const inlineFormatting = (str) => { - return str ? str - .replace(/ *\n */g, '\n') // step.1 - .replace(/[\n\t]/g, ' ') // step.2&3 - .replace(/ +/g, ' ') // step.4 - .trim() // step.5 - .replace(/\u00a0/g, ' ') // additional - : '' - } - - const blockContents = (node) => { - return Array.from(node.childNodes).reduce((lines, child) => { - if (SKIP_NODE_NAMES.includes(child.nodeName)) return lines; - if (child.nodeType >= 3) { - lines[lines.length - 1] += child.textContent; - } else { - const childText = blockContents(child); - !BLOCK_ELEMENT_NAMES.includes(child.nodeName) && (lines[lines.length - 1] += childText.shift()); - lines.push(...childText); - BLOCK_ELEMENT_NAMES.includes(child.nodeName) && lines.push(''); - } - return lines; - }, [""]); - } - - const getPositionFromDiff = (diff, positions) => { - let posPre = 0, posPost = 0, index = 0; - const ret = []; - - diff.some((df) => { - if (!df.added) posPre += df.count; - if (!df.removed) posPost += df.count; - while (true) { - if (posPost <= positions[index] - 1 || index >= positions.length) break; - - ret.push(posPre - posPost + positions[index]); - index++; - } - return index >= positions.length; - }); - return ret; - } - - const isBlurred = (node) => { - return !!(node.nodeType == 1 ? node : node.parentNode).closest(`.${CLASS_NAME_BLURRED}`) - } - - const blockAndBlur = (pattern, target, options) => { - let textNode = getNextTextNode(target, target), pos = 0; - if (!textNode) return; - let _startsFrom = 0; - const blockedContents = blockContents(target).map((l, index) => { - const startsFrom = _startsFrom; - _startsFrom += l.length; - return { - index, - contents: l, - startsFrom, - } - }); - _startsFrom = 0; - const formattedBlockedContents = blockedContents.map(l => { - const contents = inlineFormatting(l.contents) - const startsFrom = _startsFrom; - const matches = []; - let start = 0; - while (true) { - const match = contents.slice(start).match(pattern); - if (!match || match[0].length == 0) break; - matches.push({ - keyword: match[0], - index: start + match.index, - }); - start += match.index + match[0].length; - } - _startsFrom += contents.length; - return { - index: l.index, - contents, - matches: matches.length > 0 ? matches : null, - startsFrom, - } - }); - textNode = target; - formattedBlockedContents.filter(l => !!l.matches).forEach((block) => { - const formatted = block.contents; - const original = blockedContents[block.index].contents; - const diff = Diff.diffChars(original, formatted); - block.matches && block.matches.forEach((match) => { - const positions = getPositionFromDiff(diff, [match.index, match.index + match.keyword.length - 1]); - - const startIndex = blockedContents[block.index].startsFrom + positions[0]; - while (pos <= startIndex) { - textNode = getNextTextNode(textNode, target); - pos += textNode.textContent.length; - } - const from = { - node: textNode, - index: 0, - }; - const textNodeArray = [textNode]; - - const endIndex = blockedContents[block.index].startsFrom + positions[1]; - while (pos <= endIndex) { - textNode = getNextTextNode(textNode, target); - textNodeArray.push(textNode); - pos += textNode.textContent.length; - } - const to = { - node: textNode, - index: 0, - }; - const str1 = textNodeArray.map(t => t.textContent).join(''); - const str2 = inlineFormatting(str1); - const partialDiff = Diff.diffChars(str1, str2); - const partialMatch = str2.match(pattern) || str2.match(match.keyword); - const partialPositions = getPositionFromDiff(partialDiff, [partialMatch.index, partialMatch.index + partialMatch[0].length - 1]); - from.index = partialPositions[0]; - to.index = to.node.textContent.length - (str1.length - partialPositions[1]); - - const nodeBeforeBlurred = document.createTextNode(from.node.textContent.slice(0, from.index)); - const nodeAfterBlurred = document.createTextNode(to.node.textContent.slice(to.index + 1)); - const insertNodes = []; - const removeNodes = []; - if (!from.node.parentNode || !to.node.parentNode - || shouldBeSkipped(from.node) || shouldBeSkipped(to.node)) return; - - const currentRange = getCuretPosition(from.node); - if (from.node == to.node) { - const computedStyle = getComputedStyle(from.node.parentNode); - const size = Math.floor(parseFloat(computedStyle.fontSize) / 4); - if (from.node.textContent === match.keyword && from.node.parentNode.childNodes.length == 1 && computedStyle.filter === 'none') { - from.node.parentNode.classList.add(CLASS_NAME_BLURRED); - from.node.parentNode.classList.add(CLASS_NAME_KEEP); - if (options?.showValue) { - const originalTitle = from.node.parentNode.getAttribute('title'); - if (originalTitle) { - from.node.parentNode.setAttribute('data-tb-original-title', originalTitle); - } - from.node.parentNode.setAttribute('title', match.keyword); - } - if (size > 5) from.node.parentNode.style.filter += ` blur(${size}px)`; - return; - } - const nodeBlurred = document.createElement('span'); - nodeBlurred.classList.add(CLASS_NAME_BLURRED); - nodeBlurred.textContent = from.node.textContent.slice(from.index, to.index + 1); - options?.showValue && nodeBlurred.setAttribute('title', match.keyword); - insertNodes.push({ node: nodeBeforeBlurred, refNode: from.node, target: from.node.parentNode }); - insertNodes.push({ node: nodeBlurred, refNode: from.node, target: from.node.parentNode }); - insertNodes.push({ node: nodeAfterBlurred, refNode: from.node, target: from.node.parentNode }); - removeNodes.push(from.node); - } else { - const now = Date.now(); - - const nodeBlurredFrom = document.createElement('span'); - nodeBlurredFrom.classList.add(CLASS_NAME_BLURRED); - nodeBlurredFrom.classList.add(`${CLASS_PREFIX_BLURRED_GROUP}${now}`); - nodeBlurredFrom.textContent = from.node.textContent.slice(from.index); - insertNodes.push({ node: nodeBeforeBlurred, refNode: from.node, target: from.node.parentNode }); - insertNodes.push({ node: nodeBlurredFrom, refNode: from.node, target: from.node.parentNode }); - - let workingTextNode = getNextTextNode(from.node, target); - removeNodes.push(from.node); - while (workingTextNode != to.node) { - const nodeBlurred = document.createElement('span'); - nodeBlurred.textContent = workingTextNode.textContent; - nodeBlurred.classList.add(CLASS_NAME_BLURRED); - nodeBlurred.classList.add(`${CLASS_PREFIX_BLURRED_GROUP}${now}`); - insertNodes.push({ node: nodeBlurred, refNode: workingTextNode, target: workingTextNode.parentNode }); - removeNodes.push(workingTextNode); - workingTextNode = getNextTextNode(workingTextNode, target); - } - - const nodeBlurredTo = document.createElement('span'); - nodeBlurredTo.classList.add(CLASS_NAME_BLURRED); - nodeBlurredTo.classList.add(`${CLASS_PREFIX_BLURRED_GROUP}${now}`); - nodeBlurredTo.textContent = to.node.textContent.slice(0, to.index + 1); - insertNodes.push({ node: nodeBlurredTo, refNode: to.node, target: to.node.parentNode }); - insertNodes.push({ node: nodeAfterBlurred, refNode: to.node, target: to.node.parentNode }); - removeNodes.push(to.node); - } - insertNodes.reduce((p, n) => { - n.target.insertBefore(n.node, n.refNode); - if (currentRange && removeNodes.includes(currentRange.endContainer) && p + n.node.textContent.length >= currentRange.endOffset) { - currentRange.startOffset = currentRange.endOffset = currentRange.endOffset - p; - currentRange.endContainer = currentRange.startContainer = n.node.nodeName === '#text' ? n.node : Array.from(n.node.childNodes).findLast(n => n.nodeName === '#text'); - setCuretPosition(currentRange); - } - if (!isBlurred(n.node)) return p + n.node.textContent.length; - const node = n.node.nodeName === '#text' ? n.node.parentNode : n.node; - options?.showValue && node.setAttribute('title', match.keyword); - const computedStyle = getComputedStyle(node); - const size = Math.floor(parseFloat(computedStyle.fontSize) / 4); - if (size > 5) node.style.filter += ` blur(${size}px)`; - return p + n.node.textContent.length - }, 0); - removeNodes.forEach((n) => { - n.parentNode.removeChild(n); - }); - textNode = nodeAfterBlurred; - }); - }); - }; - - const blurByRegExpPattern = (pattern, options, target) => { - const now = Date.now(); - - if (target.classList && target.classList.contains(CLASS_NAME_BLURRED) && !pattern.test(target.textContent)) { - if (!Array.from(target.classList).some((className) => className.startsWith(CLASS_PREFIX_BLURRED_GROUP))) unblurCore(target); - else { - const groupedClass = Array.from(target.classList).filter((className) => className.startsWith(CLASS_PREFIX_BLURRED_GROUP))[0]; - const blurredGroup = document.querySelectorAll(`.${groupedClass}`); - !pattern.test(Array.from(blurredGroup).map((blurred) => blurred.textContent).join('')) && blurredGroup.forEach((blurred) => { - unblurCore(blurred); - }); - } - } - target.querySelectorAll(`.${CLASS_NAME_BLURRED}`).forEach((n) => { unblurCore(n) }); - blockAndBlur(pattern, target || document.body, options); - - const blurInShadowRoot = (target) => { - target.shadowRoot && blur(pattern, options, target.shadowRoot); - target.childNodes.forEach((n) => { - n.nodeName !== '#text' && blurInShadowRoot(n); - }); - }; - blurInShadowRoot(target); - - options?.blurInput && ['HTMLBodyElement', 'ShadowRoot'].includes(Object.prototype.toString.call(target).slice(8, -1)) && [...target.querySelectorAll('input')].reduce((inputs, input) => { - const inputObj = (() => { - const array = inputs.filter((inputObj) => inputObj.element == input); - if (array.length > 0) return array[0]; - inputs.push({ element: input, masks: {} }); - return inputs[inputs.length - 1]; - })(); - if (inputObj.inputHandler) return inputs; - inputObj.inputHandler = inputOnInput.bind({ pattern, root: target, options }); - input.addEventListener('input', inputObj.inputHandler); - input.addEventListener('focus', inputOnFocus); - input.addEventListener('blur', inputOnBlur); - input.dispatchEvent(new InputEvent('input', { data: input.value })); - return inputs; - }, inputs); - console.debug(`Took ${Date.now() - now} ms`) - }; - - const inputOnInput = function (e) { - const input = e.target; - const options = this.options; - - const inputObj = inputs.filter(i => i.element == input)[0]; - if (!inputObj) return; - const pattern = this.pattern; - - const patternStr = `/${pattern.source}/${pattern.flags}`; - if (!inputObj.masks[patternStr]) inputObj.masks[patternStr] = []; - while (inputObj.masks[patternStr].length > 0) { - inputObj.masks[patternStr][0].parentNode && inputObj.masks[patternStr][0].parentNode.removeChild(inputObj.masks[patternStr][0]); - inputObj.masks[patternStr].shift(); - } - inputObj.masks[patternStr].length = 0; - - if (!pattern.test(input.value)) return; - - const clone = (() => { - return this.root.querySelector(`#${ID_INPUT_CLONE}`) || document.createElement('div'); - })(); - if (!clone.parentNode) { - clone.id = ID_INPUT_CLONE; - this.root.appendChild(clone); - } - clone.textCotent = ''; - const inputStyle = getComputedStyle(input); - while (clone.firstChild) { - clone.removeChild(clone.firstChild); - } - for (let s in inputStyle) { - if (!isNaN(parseInt(s))) continue; - if (!['display', 'position', 'visibility', 'top', 'left', 'overflow', 'white-space'].includes(s)) clone.style.setProperty(s, inputStyle.getPropertyValue(s)); - } - - const inputBoundingBox = input.getBoundingClientRect(); - const size = Math.floor(parseFloat(inputStyle.fontSize) / 4); - - const textArray = input.value.split(pattern); - const matched = input.value.match(new RegExp(pattern.source, `g${pattern.flags}`)); - clone.appendChild(document.createTextNode(textArray.shift())); - const referenceNode = clone.lastChild.nextSibling; - textArray.forEach((t) => { - const blurredSpan = document.createElement('span'); - blurredSpan.classList.add(CLASS_NAME_BLURRED); - blurredSpan.textContent = matched.shift(); - if (size > 5) blurredSpan.style.filter = `blur(${size}px)`; - clone.insertBefore(blurredSpan, referenceNode); - clone.insertBefore(document.createTextNode(t), referenceNode); - - const mask = document.createElement('div'); - mask.classList.add(CLASS_NAME_MASK_CONTAINER); - mask.appendChild(document.createElement('div')); - mask.lastChild.classList.add(CLASS_NAME_TEXT_LAYER); - mask.lastChild.textContent = blurredSpan.textContent; - mask.lastChild.style.setProperty('width', '100%'); - mask.lastChild.style.setProperty('height', '100%'); - input.parentNode.appendChild(mask); - options?.showValue && mask.lastChild.setAttribute('title', blurredSpan.textContent); - mask.addEventListener('click', () => { - input.focus(); - }) - - const blurredBoundingBox = blurredSpan.getBoundingClientRect(); - - for (let s in inputStyle) { - if (!isNaN(parseInt(s))) continue; - if (!['position', 'filter', 'margin', 'padding', 'border', 'top', 'left', 'overflow', 'height', 'width', 'outline'].includes(s)) { - mask.style.setProperty(s, inputStyle.getPropertyValue(s)); - } - } - - const verticalGap = (parseFloat(inputStyle.getPropertyValue('height')) - parseFloat(inputStyle.getPropertyValue('font-size'))); - const isBorderBox = inputStyle.getPropertyValue('box-sizing') === 'border-box'; - mask.style.setProperty('left', `${blurredSpan.offsetLeft + input.offsetLeft - + (isBorderBox ? 0 : parseFloat(inputStyle.getPropertyValue('border-left-width'))) - }px`); - mask.style.setProperty('top', `${input.offsetTop + input.offsetHeight - blurredSpan.offsetHeight - - (verticalGap > 0 ? verticalGap / 2 : 0) - - (isBorderBox ? - parseFloat(inputStyle.getPropertyValue('border-top-width')) : parseFloat(inputStyle.getPropertyValue('border-bottom-width'))) - - parseFloat(inputStyle.getPropertyValue('padding-bottom')) - }px`); - const maskBoundingBox = mask.getBoundingClientRect(); - const tmpWidth = inputBoundingBox.width + inputBoundingBox.left - maskBoundingBox.left - parseFloat(inputStyle.getPropertyValue('border-left-width')); - mask.style.setProperty('width', `${tmpWidth > blurredBoundingBox.width - ? blurredBoundingBox.width - : tmpWidth > 0 - ? tmpWidth - : 0}px`); - mask.style.setProperty('height', `${blurredBoundingBox.height}px`); - mask.style.setProperty('z-index', `${parseInt(inputStyle.getPropertyValue('z-index')) + 1}`); - mask.style.setProperty('border', 'none'); - - mask.style.setProperty('background-color', getBackgroundColorAlongDOMTree(input)); - mask.lastChild.classList.add(CLASS_NAME_BLURRED); - e.isTrusted && mask.style.setProperty('display', 'none'); - - inputObj.masks[patternStr].push(mask); - }); - } - const getBackgroundColorAlongDOMTree = (element) => { - if (element == document) return ''; - const computedStyle = getComputedStyle(element); - return (!/(?:^| )rgba *\( *\d+ *, *\d+ *, *\d+ *, *0 *\)(?:$| )/.test(computedStyle.getPropertyValue('background-color'))) - ? computedStyle.getPropertyValue('background-color').replace(/rgba *\( *(\d+) *, *(\d+) *, *(\d+) *, *[^)]+ *\)/, 'rgb($1, $2, $3)') - : getBackgroundColorAlongDOMTree(element.parentNode); - } - const inputOnFocus = (e) => { - const input = e.target; - const inputObj = inputs.filter(i => i.element == input)[0]; - if (!inputObj) return; - for (let p in inputObj.masks) { - inputObj.masks[p].forEach(m => m.style.setProperty('display', 'none')); - } - } - const inputOnBlur = (e) => { - const input = e.target; - const inputObj = inputs.filter(i => i.element == input)[0]; - if (!inputObj) return; - for (let p in inputObj.masks) { - inputObj.masks[p].forEach(m => m.style.setProperty('display', '')); - } - } - const blur = (pattern, options, target) => { - const observed = target || document.body; - if (observedNodes.includes(observed)) return; - - const style = document.createElement('style'); - style.innerHTML = GLOBAL_STYLE; - style.id = ID_GLOBAL_STYLE; - !observed.querySelector(`#${style.id}`) && (observed == document.body ? document.head : observed).appendChild(style); - observedNodes.push(observed); - if (!w.__observer) { - w.__observer = new MutationObserver((records) => { - if (!records.some(record => { - return record.type === 'characterData' || record.removedNodes.length > 0 || Array.from(record.addedNodes).some(node => { - return !['SCRIPT', 'STYLE', '#comment'].includes(node.nodeName); - }); - })) return; - const targets = records.reduce((targets, record) => { - const isContained = targets.some((target) => { - return target.contains(record.target); - }); - if (isContained) return targets; - let blockElement = record.target; - while (blockElement && !BLOCK_ELEMENT_NAMES.includes(blockElement.nodeName)) { - blockElement = blockElement.parentNode; - } - if (!blockElement) return targets; - const array = targets.reduce((prev, target) => { - if (!blockElement.contains(target) && target != blockElement) { - prev.push(target) - } - return prev; - }, []); - array.push(blockElement); - return array; - }, []); - w.__observer.disconnect(); - targets.forEach(target => blurByRegExpPattern(pattern, options, target)); - observedNodes.forEach((target) => { - w.__observer.observe(target, { - childList: true, - subtree: true, - characterData: true - }); - }); - }); - } - const inputClone = (() => { - return document.querySelector(`#${ID_INPUT_CLONE}`) || document.createElement('div'); - })(); - if (!inputClone.parentNode) { - inputClone.id = ID_INPUT_CLONE; - document.body.appendChild(inputClone); - } - - blurByRegExpPattern(pattern, options, observed); - w.__observer.observe(observed, { - childList: true, - subtree: true, - characterData: true - }); - }; - const unblur = () => { - if (!w.__observer) return; - w.__observer.disconnect(); - delete w.__observer - - inputs.forEach((inputObj) => { - inputObj.element.removeEventListener('input', inputObj.inputHandler); - inputObj.element.removeEventListener('focus', inputOnFocus); - inputObj.element.removeEventListener('blur', inputOnBlur); - for (let pattern in inputObj.masks) { - inputObj.masks[pattern].forEach((mask) => { - mask.parentNode.removeChild(mask); - }) - } - }); - inputs.length = 0; - - const m = observedNodes.reduce((array, target) => { - const GLOBAL_STYLE = target.querySelector(`#${ID_GLOBAL_STYLE}`); - GLOBAL_STYLE && GLOBAL_STYLE.parentNode.removeChild(GLOBAL_STYLE); - const inputClone = target.querySelector(`#${ID_INPUT_CLONE}`); - inputClone && inputClone.parentNode.removeChild(inputClone); - - array.push(...target.querySelectorAll(`.${CLASS_NAME_BLURRED}`)); - return array; - }, []); - observedNodes.length = 0; - - if (m.length === 0) return; - - const now = Date.now(); - m.forEach((n) => { - unblurCore(n); - }); - console.debug(`Took ${Date.now() - now} ms`) - }; - - const unblurCore = (n) => { - if (n.classList.contains(CLASS_NAME_BLURRED) && n.classList.contains(CLASS_NAME_KEEP)) { - // restore title - const originalTitle = n.getAttribute(ATTR_NAME_ORIGINAL_TITLE); - if (originalTitle) { - n.setAttribute('title', originalTitle); - n.removeAttribute(ATTR_NAME_ORIGINAL_TITLE); - } - else n.removeAttribute('title'); - - // restore class - n.classList.remove(CLASS_NAME_BLURRED); - n.classList.remove(CLASS_NAME_KEEP); - if (n.classList.length == 0) n.removeAttribute('class'); - - // restore style - n.style.filter = n.style.filter.replace(/blur\([^\)]+\)/, '').trim(); - if (n.style.length == 0) n.removeAttribute('style'); - return; - } - const currentRange = getCuretPosition(n); - const p = n.parentNode; - n.childNodes.forEach((c) => { - if (c.nodeName !== '#text') { - p.insertBefore(c, n); - return; - } - - let textContainer = n.previousSibling; - do { - if (!textContainer || textContainer.nodeName !== '#text') { - p.insertBefore(c, n); - break; - } - if (textContainer.previousSibling && textContainer.textContent === '') { - textContainer = textContainer.previousSibling; - continue; - } - textContainer.textContent += c.textContent; - if (currentRange) { - switch (currentRange.endContainer) { - case c: - currentRange.endContainer = currentRange.startContainer = textContainer; - currentRange.startOffset += (textContainer.textContent.length - c.textContent.length); - currentRange.endOffset += (textContainer.textContent.length - c.textContent.length); - case textContainer: - setCuretPosition(currentRange); - } - } - - if (n.nextSibling?.nodeName === '#text') { - n.previousSibling.textContent += n.nextSibling.textContent; - if (currentRange) { - switch (currentRange.endContainer) { - case n.nextSibling: - currentRange.endContainer = currentRange.startContainer = n.previousSibling; - currentRange.endOffset = currentRange.startOffset = n.previousSibling.textContent.length - n.nextSibling.textContent.length + currentRange.startOffset; - case n.previousSibling: - setCuretPosition(currentRange); - } - } - p.removeChild(n.nextSibling); - } - break; - } while (true); - }); - p.removeChild(n); - }; - - const getCuretPosition = (target) => { - const selection = window.getSelection(); - if (!target.isContentEditable && (!target.parentNode || !target.parentNode.isContentEditable) || selection.rangeCount == 0) return null; - return { - startContainer: selection.anchorNode, - startOffset: selection.anchorOffset, - endContainer: selection.focusNode, - endOffset: selection.focusOffset, - }; - } - const setCuretPosition = (newRange) => { - const selection = window.getSelection(); - const range = document.createRange(); - range.setStart(newRange.startContainer, newRange.startOffset); - range.setEnd(newRange.endContainer, newRange.endOffset); - selection.removeAllRanges(); - selection.addRange(range); - }; - - const unblurTabTitle = () => { - const title = document.querySelector('title'); - if (!title) return; - if (title.getAttribute(ATTR_NAME_ORIGINAL_TITLE)) { - title.textContent = title.getAttribute(ATTR_NAME_ORIGINAL_TITLE); - title.removeAttribute(ATTR_NAME_ORIGINAL_TITLE); - } - if (!w.__titleObserver) return; - w.__titleObserver.disconnect(); - delete w.__titleObserver; - }; - - const blurTabTitleCore = (pattern, target) => { - const title = target.textContent; - let result = title.match(pattern); - let start = 0; - while (result && result[0].length > 0) { - const mask = new Array(result[0].length).fill('*').join(''); - target.textContent = target.textContent.replace(result[0], mask); - start += result.index + mask.length; - result = target.textContent.slice(start).match(pattern); - if (!target.getAttribute(ATTR_NAME_ORIGINAL_TITLE)) { - target.setAttribute(ATTR_NAME_ORIGINAL_TITLE, title); - } - } - }; - - const blurTabTitle = (pattern) => { - if (!w.__titleObserver) { - w.__titleObserver = new MutationObserver((records) => { - records.some((record) => { - return Array.from(record.addedNodes).some((node) => { - if (node.nodeName === 'TITLE') { - blurTabTitleCore(pattern, node); - return true; - } else if (node.nodeName === "#text" && node.parentNode && node.parentNode.nodeName === "TITLE") { - blurTabTitleCore(pattern, node.parentNode); - return true; - } - return false; - }); - }); - }); - } - const title = document.querySelector('title'); - title && blurTabTitleCore(pattern, title); - w.__titleObserver.observe(document.head, { - childList: true, - subtree: true, - characterData: true - }) - }; - - const keywords2RegExp = (keywords, mode, matchCase) => { - return new RegExp( - (keywords || '').split(/\n/) - .filter(k => - !!k.trim() && ( - mode !== 'regexp' || - !new RegExp(k).test('') - ) - ) - .map(k => `(?:${mode === 'regexp' ? k.trim() : escapeRegExp(k.trim())})`) - .join('|'), - matchCase ? '' : 'i' - ); - }; - - const init = async () => { - const { status, keywords, mode, matchCase, showValue, blurInput, blurTitle, exclusionUrls } = (await chrome.storage.local.get(['status', 'keywords', 'mode', 'matchCase', 'showValue', 'blurInput', 'blurTitle', 'exclusionUrls'])); - unblur(); - unblurTabTitle(); - if (status === 'disabled' || !keywords || keywords.trim() === '') return; - if (exclusionUrls && exclusionUrls.split(/\n/).length > 0 && exclusionUrls.split(/\n/).filter(l => !!l).some((url) => new RegExp(url).test(location.href))) return; - - const pattern = keywords2RegExp(keywords, mode, !!matchCase); - blur(pattern, { showValue, blurInput }); - blurTitle && blurTabTitle(pattern); - }; - chrome.storage.onChanged.addListener(async (changes, area) => { - if (area !== 'local') return; - await init(); - }); - await init(); -})(); \ No newline at end of file diff --git a/manifest.json b/manifest.json index cf84452..00b0b3e 100644 --- a/manifest.json +++ b/manifest.json @@ -10,11 +10,11 @@ ], "background": { "type": "module", - "service_worker": "background/service-worker.js" + "service_worker": "dist/background/service-worker.js" }, "action": { "default_icon": "img/icon128.png", - "default_popup": "popup/main.html" + "default_popup": "dist/popup/main.html" }, "icons": { "16": "img/icon16.png", @@ -28,8 +28,7 @@ "http://*/*" ], "js": [ - "content/js/diff.min.js", - "content/js/main.js" + "dist/contentScript/main.js" ] } ], diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..9285662 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,803 @@ +{ + "name": "template", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "template", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "diff": "^5.2.0" + }, + "devDependencies": { + "@types/chrome": "^0.0.248", + "@types/diff": "^5.2.1", + "esbuild": "^0.19.5", + "fs-extra": "^11.1.1", + "typescript": "^5.2.2" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/chrome": { + "version": "0.0.248", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.248.tgz", + "integrity": "sha512-qtBzxZD1v3eWZn8XxH1i07pAhzJDHnxJBBVy7bmntXxXKxjzNXYxD41teqa5yOcX/Yy8brRFGZESEzGoINvBDg==", + "dev": true, + "dependencies": { + "@types/filesystem": "*", + "@types/har-format": "*" + } + }, + "node_modules/@types/diff": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.1.tgz", + "integrity": "sha512-uxpcuwWJGhe2AR1g8hD9F5OYGCqjqWnBUQFD8gMZsDbv8oPHzxJF6iMO6n8Tk0AdzlxoaaoQhOYlIg/PukVU8g==", + "dev": true + }, + "node_modules/@types/filesystem": { + "version": "0.0.36", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.36.tgz", + "integrity": "sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==", + "dev": true, + "dependencies": { + "@types/filewriter": "*" + } + }, + "node_modules/@types/filewriter": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.33.tgz", + "integrity": "sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==", + "dev": true + }, + "node_modules/@types/har-format": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.15.tgz", + "integrity": "sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==", + "dev": true + }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + } + }, + "dependencies": { + "@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "dev": true, + "optional": true + }, + "@types/chrome": { + "version": "0.0.248", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.248.tgz", + "integrity": "sha512-qtBzxZD1v3eWZn8XxH1i07pAhzJDHnxJBBVy7bmntXxXKxjzNXYxD41teqa5yOcX/Yy8brRFGZESEzGoINvBDg==", + "dev": true, + "requires": { + "@types/filesystem": "*", + "@types/har-format": "*" + } + }, + "@types/diff": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.1.tgz", + "integrity": "sha512-uxpcuwWJGhe2AR1g8hD9F5OYGCqjqWnBUQFD8gMZsDbv8oPHzxJF6iMO6n8Tk0AdzlxoaaoQhOYlIg/PukVU8g==", + "dev": true + }, + "@types/filesystem": { + "version": "0.0.36", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.36.tgz", + "integrity": "sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==", + "dev": true, + "requires": { + "@types/filewriter": "*" + } + }, + "@types/filewriter": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.33.tgz", + "integrity": "sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==", + "dev": true + }, + "@types/har-format": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.15.tgz", + "integrity": "sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==", + "dev": true + }, + "diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==" + }, + "esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "requires": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true + }, + "universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..3bccfbf --- /dev/null +++ b/package.json @@ -0,0 +1,31 @@ +{ + "name": "template", + "description": "My Chrome Extension", + "version": "1.0.0", + "scripts": { + "clean": "node -e \"require('fs-extra').removeSync('./dist')\"", + "build:mkdir": "node -e \"const fs = require('fs-extra'); fs.ensureDirSync('./dist/popup/js'); fs.ensureDirSync('./dist/contentScript'); fs.ensureDirSync('./dist/background');\"", + "build": "npm run clean && npm run build:mkdir && npm run build:background && npm run build:content && npm run build:popup && npm run build:copyFiles", + "build:dev": "npm run clean && npm run build:mkdir && npm run build:dev:background && npm run build:dev:content && npm run build:dev:popup && npm run build:copyFiles", + "build:background": "esbuild ./src/background/background.ts --bundle --minify --outfile=./dist/background/service-worker.js", + "build:content": "esbuild ./src/content/contentScript.ts --bundle --minify --outfile=./dist/contentScript/main.js ", + "build:popup": " esbuild ./src/popup/popup.ts --bundle --minify --outfile=./dist/popup/js/bundle.js ", + "build:dev:background": "esbuild ./src/background/background.ts --bundle --sourcemap=inline --outfile=./dist/background/service-worker.js", + "build:dev:content": "esbuild ./src/content/contentScript.ts --bundle --sourcemap=inline --outfile=./dist/contentScript/main.js ", + "build:dev:popup": " esbuild ./src/popup/popup.ts --bundle --sourcemap=inline --outfile=./dist/popup/js/bundle.js ", + "build:copyFiles": "node -e \"const fs = require('fs-extra'); fs.copySync('./public', './dist/popup');\"", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "devDependencies": { + "@types/chrome": "^0.0.248", + "@types/diff": "^5.2.1", + "esbuild": "^0.19.5", + "fs-extra": "^11.1.1", + "typescript": "^5.2.2" + }, + "author": "", + "license": "ISC", + "dependencies": { + "diff": "^5.2.0" + } +} diff --git a/popup/css/main.css b/public/css/main.css similarity index 100% rename from popup/css/main.css rename to public/css/main.css diff --git a/popup/img/ATTRIBUTIONS.txt b/public/img/ATTRIBUTIONS.txt similarity index 100% rename from popup/img/ATTRIBUTIONS.txt rename to public/img/ATTRIBUTIONS.txt diff --git a/popup/img/arrow.svg b/public/img/arrow.svg similarity index 100% rename from popup/img/arrow.svg rename to public/img/arrow.svg diff --git a/popup/img/case-sensitive.svg b/public/img/case-sensitive.svg similarity index 100% rename from popup/img/case-sensitive.svg rename to public/img/case-sensitive.svg diff --git a/popup/img/comment.svg b/public/img/comment.svg similarity index 100% rename from popup/img/comment.svg rename to public/img/comment.svg diff --git a/popup/img/regex.svg b/public/img/regex.svg similarity index 100% rename from popup/img/regex.svg rename to public/img/regex.svg diff --git a/popup/img/symbol-string.svg b/public/img/symbol-string.svg similarity index 100% rename from popup/img/symbol-string.svg rename to public/img/symbol-string.svg diff --git a/popup/img/tab-title.svg b/public/img/tab-title.svg similarity index 100% rename from popup/img/tab-title.svg rename to public/img/tab-title.svg diff --git a/popup/main.html b/public/main.html similarity index 94% rename from popup/main.html rename to public/main.html index 5136247..6b8ab7d 100644 --- a/popup/main.html +++ b/public/main.html @@ -4,7 +4,7 @@ Text Blurrer Popup - + @@ -53,7 +53,7 @@