Auto-commited changes
This commit is contained in:
41
src/popup.js
41
src/popup.js
@@ -25,6 +25,7 @@ const imgCount = document.getElementById("img-count");
|
||||
const pageTitle = document.getElementById("page-title");
|
||||
const visibilityEl = document.getElementById("visibility-select");
|
||||
const attachCheck = document.getElementById("attach-images");
|
||||
const stripLinksCheck = document.getElementById("strip-links");
|
||||
const modeToggle = document.getElementById("mode-toggle");
|
||||
const sendBtn = document.getElementById("send-btn");
|
||||
const reloadBtn = document.getElementById("reload-btn");
|
||||
@@ -61,6 +62,7 @@ async function getActiveTab() {
|
||||
state.mode = state.settings.clipMode || "page";
|
||||
if (state.settings.visibility) visibilityEl.value = state.settings.visibility;
|
||||
if (state.settings.includeImages === false) attachCheck.checked = false;
|
||||
if (state.settings.includeTags) tagsInput.value = "#clipped";
|
||||
|
||||
updateModeButton();
|
||||
await clip();
|
||||
@@ -82,7 +84,7 @@ async function clip() {
|
||||
} catch (_) { /* already injected or restricted page */ }
|
||||
|
||||
const response = await new Promise((resolve, reject) => {
|
||||
chrome.tabs.sendMessage(tab.id, { action: "getContent", mode: state.mode }, (res) => {
|
||||
chrome.tabs.sendMessage(tab.id, { action: "getContent", mode: state.mode, stripLinks: stripLinksCheck.checked }, (res) => {
|
||||
if (chrome.runtime.lastError) reject(new Error(chrome.runtime.lastError.message));
|
||||
else resolve(res);
|
||||
});
|
||||
@@ -249,17 +251,17 @@ mdEditor.addEventListener("input", updateCharCounter);
|
||||
// ── Tags input ────────────────────────────────────────────────────────────────
|
||||
const tagsInput = document.getElementById("tags-input");
|
||||
|
||||
// Load saved tags default
|
||||
getSettings().then((s) => {
|
||||
if (s.includeTags) tagsInput.value = "#clipped";
|
||||
});
|
||||
|
||||
// ── Mode toggle ───────────────────────────────────────────────────────────────
|
||||
const modeLabel = document.getElementById("mode-label");
|
||||
|
||||
function updateModeButton() {
|
||||
modeToggle.title = state.mode === "page"
|
||||
? "Currently: full page — click for selection mode"
|
||||
: "Currently: selection — click for full page mode";
|
||||
modeToggle.classList.toggle("mode-selection", state.mode === "selection");
|
||||
const isSelection = state.mode === "selection";
|
||||
modeToggle.title = isSelection
|
||||
? "Currently: selection — click for full page mode"
|
||||
: "Currently: full page — click for selection mode";
|
||||
modeToggle.classList.toggle("mode-selection", isSelection);
|
||||
modeLabel.textContent = isSelection ? "Selection" : "Full page";
|
||||
}
|
||||
|
||||
modeToggle.addEventListener("click", async () => {
|
||||
@@ -268,6 +270,9 @@ modeToggle.addEventListener("click", async () => {
|
||||
await clip();
|
||||
});
|
||||
|
||||
// ── Strip links toggle ────────────────────────────────────────────────────────
|
||||
stripLinksCheck.addEventListener("change", () => clip());
|
||||
|
||||
// ── Reload ────────────────────────────────────────────────────────────────────
|
||||
reloadBtn.addEventListener("click", () => clip());
|
||||
|
||||
@@ -295,6 +300,14 @@ sendBtn.addEventListener("click", async () => {
|
||||
sendBtn.disabled = true;
|
||||
|
||||
try {
|
||||
// Validate Memos URL scheme to prevent accidental non-HTTP destinations
|
||||
try {
|
||||
const u = new URL(baseUrl);
|
||||
if (u.protocol !== "http:" && u.protocol !== "https:") throw new Error();
|
||||
} catch {
|
||||
throw new Error("Invalid Memos URL in settings. Must start with http:// or https://");
|
||||
}
|
||||
|
||||
// 1. Create the memo first (with original image URLs)
|
||||
sendBtn.textContent = "Creating memo…";
|
||||
|
||||
@@ -342,7 +355,9 @@ sendBtn.addEventListener("click", async () => {
|
||||
const attachmentUrl = `${baseUrl}/file/${attachName}`;
|
||||
const escapedUrl = origUrl.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
const re = new RegExp(`!\\[(.*?)\\]\\(${escapedUrl}\\)`, 'g');
|
||||
contentWithImages = contentWithImages.replace(re, ``);
|
||||
// Escape $ in replacement to prevent backreference interpretation
|
||||
const safeReplacement = `})`;
|
||||
contentWithImages = contentWithImages.replace(re, safeReplacement);
|
||||
}
|
||||
|
||||
// Append any uploaded attachments not already referenced in the markdown
|
||||
@@ -353,7 +368,7 @@ sendBtn.addEventListener("click", async () => {
|
||||
}
|
||||
}
|
||||
|
||||
await fetch(`${baseUrl}/api/v1/${memoName}`, {
|
||||
const patchRes = await fetch(`${baseUrl}/api/v1/${memoName}`, {
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -361,6 +376,10 @@ sendBtn.addEventListener("click", async () => {
|
||||
},
|
||||
body: JSON.stringify({ content: contentWithImages }),
|
||||
});
|
||||
if (!patchRes.ok) {
|
||||
const txt = await patchRes.text();
|
||||
console.warn(`Memo patch failed ${patchRes.status}: ${txt.slice(0, 200)}`);
|
||||
}
|
||||
}
|
||||
|
||||
let memoId = "";
|
||||
|
||||
Reference in New Issue
Block a user