]> git.frustrated-labs.net Git - nicos-weg-vocab-exporter-firefox.git/commitdiff
init
authorAlexander Goussas <[email protected]>
Sun, 5 Apr 2026 03:32:36 +0000 (22:32 -0500)
committerAlexander Goussas <[email protected]>
Sun, 5 Apr 2026 03:32:36 +0000 (22:32 -0500)
.gitignore [new file with mode: 0644]
exporter.js [new file with mode: 0644]
manifest.json [new file with mode: 0644]
panel.css [new file with mode: 0644]
panel.html [new file with mode: 0644]
panel.js [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..a547bf3
--- /dev/null
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/exporter.js b/exporter.js
new file mode 100644 (file)
index 0000000..49527ae
--- /dev/null
@@ -0,0 +1,13 @@
+(function() {
+  const els = document.getElementsByClassName("srr46ge")
+
+  const defs = []
+
+  for (const el of els) {
+    const w = el.firstChild.innerText.replace("\n", "<br>")
+    const t = el.lastChild.innerText.replace("\n", "<br>")
+    defs.push({ w, t })
+  }
+
+  return defs;
+})();
diff --git a/manifest.json b/manifest.json
new file mode 100644 (file)
index 0000000..b1137f0
--- /dev/null
@@ -0,0 +1,17 @@
+{
+  "manifest_version": 2,
+  "name": "Nicos Weg Vocab Exporter",
+  "description": "",
+  "version": "1.0",
+  "browser_specific_settings": {
+    "gecko": {
+      "strict_min_version": "54.0a1"
+    }
+  },
+  "sidebar_action": {
+    "default_icon": "icons/star.png",
+    "default_title" : "Export vocabulary",
+    "default_panel": "panel.html"
+  },
+  "permissions": ["<all_urls>", "scripting", "clipboardWrite", "downloads"]
+}
diff --git a/panel.css b/panel.css
new file mode 100644 (file)
index 0000000..88f0f38
--- /dev/null
+++ b/panel.css
@@ -0,0 +1,15 @@
+#output {
+  position: relative;
+  width: 100%;
+  margin-top: 10px;
+
+  #output-field {
+    min-height: 169px;
+  }
+
+  #output-copy {
+    position: absolute;
+    right: 10px;
+    top: 10px;
+  }
+}
diff --git a/panel.html b/panel.html
new file mode 100644 (file)
index 0000000..5663d79
--- /dev/null
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+
+<html>
+  <head>
+    <meta charset="utf-8">
+    <link rel="stylesheet" href="panel.css"/>
+    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn/beer.min.css" rel="stylesheet">
+    <script type="module" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn/beer.min.js"></script>
+    <script type="module" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn/material-dynamic-colors.min.js"></script>
+  </head>
+
+  <body>
+    <main class="responsive">
+      <p>
+      Configure the deck and card type before exporting.
+      </p>
+      <form id="vocab-form">
+        <div class="field label border" id="deck">
+          <input type="text" placeholder="Deck" id="deck-input"/>
+          <label>Deck</label>
+          <output id="deck-hint">The deck name</output>
+        </div>
+        <div class="field label border" id="cardtype">
+          <input type="text" placeholder="Card type" id="card-type-input"/>
+          <label>Card type</label>
+          <output id="card-type-hint">The card type</output>
+        </div>
+        <button class="responsive">
+          Export
+        </button>
+      </form>
+      <div id="output" class="responsive">
+        <pre id="output-field"></pre>
+        <button class="square extra" id="output-copy">
+          <i>content_copy</i>
+        </button>
+      </div>
+    </main>
+    <script src="panel.js"></script>
+  </body>
+
+</html>
diff --git a/panel.js b/panel.js
new file mode 100644 (file)
index 0000000..a478836
--- /dev/null
+++ b/panel.js
@@ -0,0 +1,97 @@
+const deckContainer = document.getElementById("deck")
+const deckInput = document.getElementById("deck-input")
+const deckHint = document.getElementById("deck-hint");
+
+const cardTypeContainer = document.getElementById("cardtype")
+const cardTypeInput = document.getElementById("card-type-input")
+const cardTypeHint = document.getElementById("card-type-hint");
+
+const form = document.getElementById("vocab-form")
+
+const outputField = document.getElementById("output-field");
+const outputCopy = document.getElementById("output-copy");
+
+function validate(
+  el,
+  cond,
+) {
+  if (cond) {
+    el.classList.add("invalid");
+  } else {
+    el.classList.remove("invalid");
+  }
+}
+
+function onSubmit(e) {
+  e.preventDefault()
+
+  const deck = deckInput.value;
+  const cardType = cardTypeInput.value;
+
+  validate(deckContainer, !deck);
+  validate(deckHint, !deck);
+  validate(cardTypeContainer, !cardType);
+  validate(cardTypeHint, !cardType);
+
+  if (!deck || !cardType) {
+    return;
+  }
+
+  doExport(deck, cardType);
+}
+
+async function doExport(
+  deck,
+  cardType
+) {
+
+  const [tab] = await browser.tabs.query({
+    active: true,
+    currentWindow: true,
+  });
+
+  const results = await browser.scripting.executeScript({
+    target: {
+      tabId: tab.id
+    },
+    files: ['exporter.js']
+  })
+
+  let s = `#separator:Comma
+#html:true
+#notetype:${cardType}
+#deck:${deck}
+`;
+
+  for (const { w, t } of results[0].result) {
+    s += `"${w}","${t}"\n`
+  }
+
+  outputField.innerText = s;
+  download(s);
+}
+
+function download(s) {
+  const blob = new Blob([s], {
+    type: 'text/plain'
+  })
+
+  const url = URL.createObjectURL(blob);
+
+  browser.downloads.download({
+    url,
+    saveAs: true,
+    filename: "Nicos Weg Vocabulary.txt"
+  })
+}
+
+form.addEventListener("submit", onSubmit);
+
+outputCopy.addEventListener("click", () => {
+  if (outputField.innerText) {
+    navigator.clipboard.writeText(outputField.innerText);
+    alert("Vocabulary was copied to clipboard")
+  } else {
+    alert("There is nothing to copy!")
+  }
+});