manage
This commit is contained in:
1 parent
1911d55d5e
commit
58d3e58759
7 files changed
+274
-95
No files matched your search
+94
-55
@@ -14,6 +14,7 @@ body_class %}layout-wide{% endblock %}{% block content %}
|
||||
id="file-upload"
|
||||
style="display: none"
|
||||
accept=".html,.htm,.md,.txt,.markdown"
|
||||
multiple
|
||||
/>
|
||||
<span
|
||||
id="file-name"
|
||||
@@ -34,6 +35,9 @@ body_class %}layout-wide{% endblock %}{% block content %}
|
||||
<button onclick="extractLinks('markdown')" class="btn">
|
||||
Extract from Markdown
|
||||
</button>
|
||||
<button onclick="extractLinks('jumblang')" class="btn">
|
||||
Extract from Messy Text
|
||||
</button>
|
||||
<button onclick="extractLinks('auto')" class="btn btn-primary">
|
||||
Auto Detect & Extract
|
||||
</button>
|
||||
@@ -81,41 +85,61 @@ body_class %}layout-wide{% endblock %}{% block content %}
|
||||
// File Upload Handler
|
||||
/** @type {HTMLInputElement} */
|
||||
const fileInput = document.getElementById("file-upload");
|
||||
|
||||
fileInput.addEventListener("change", function (e) {
|
||||
/** @type {File} */
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
document.getElementById("file-name").textContent = file.name;
|
||||
fileInput.addEventListener("change", async function (e) {
|
||||
/** @type {FileList} */
|
||||
const files = e.target.files;
|
||||
if (!files || files.length === 0) return;
|
||||
|
||||
document.getElementById(
|
||||
"file-name"
|
||||
).textContent = `${files.length} file(s) selected`;
|
||||
|
||||
/** @type {HTMLTextAreaElement} */
|
||||
const textarea = document.getElementById("input-content");
|
||||
textarea.value = ""; // Clear previous content
|
||||
|
||||
// Read all files
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
const text = await readFileAsText(file);
|
||||
textarea.value += `\n\n<!-- File: ${file.name} -->\n${text}`;
|
||||
}
|
||||
|
||||
// Auto-detect mode based on the first file's extension (heuristic)
|
||||
const firstFile = files[0];
|
||||
if (
|
||||
firstFile.name.endsWith(".md") ||
|
||||
firstFile.name.endsWith(".markdown")
|
||||
) {
|
||||
extractLinks("markdown");
|
||||
} else if (
|
||||
firstFile.name.endsWith(".html") ||
|
||||
firstFile.name.endsWith(".htm")
|
||||
) {
|
||||
extractLinks("html");
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Reads a file as text using a Promise wrapper around FileReader.
|
||||
* @param {File} file
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
function readFileAsText(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
/** @type {HTMLTextAreaElement} */
|
||||
const textarea = document.getElementById("input-content");
|
||||
textarea.value = e.target.result;
|
||||
|
||||
// Optional: Auto-detect mode based on extension
|
||||
if (
|
||||
file.name.endsWith(".md") ||
|
||||
file.name.endsWith(".markdown")
|
||||
) {
|
||||
extractLinks("markdown");
|
||||
} else if (
|
||||
file.name.endsWith(".html") ||
|
||||
file.name.endsWith(".htm")
|
||||
) {
|
||||
extractLinks("html");
|
||||
}
|
||||
};
|
||||
reader.onload = (e) => resolve(e.target.result);
|
||||
reader.onerror = (e) => reject(e);
|
||||
reader.readAsText(file);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts links from the input content based on the specified mode.
|
||||
* @param {'html' | 'markdown' | 'auto'} mode
|
||||
* @param {'html' | 'markdown' | 'auto' | 'jumblang'} mode
|
||||
*/
|
||||
function extractLinks(mode) {
|
||||
async function extractLinks(mode) {
|
||||
/** @type {string} */
|
||||
const content = document.getElementById("input-content").value;
|
||||
if (!content.trim()) return;
|
||||
@@ -123,38 +147,53 @@ body_class %}layout-wide{% endblock %}{% block content %}
|
||||
/** @type {string[]} */
|
||||
let links = [];
|
||||
|
||||
if (mode === "auto") {
|
||||
// Simple heuristic: if it has <a href, it's likely HTML.
|
||||
mode =
|
||||
content.includes("<a href") ||
|
||||
content.includes("<!DOCTYPE html>")
|
||||
? "html"
|
||||
: "markdown";
|
||||
}
|
||||
|
||||
if (mode === "html") {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(content, "text/html");
|
||||
const anchors = doc.querySelectorAll("a[href]");
|
||||
links = Array.from(anchors)
|
||||
.map((a) => a.href)
|
||||
.filter((h) => h.startsWith("http"));
|
||||
if (mode === "jumblang") {
|
||||
try {
|
||||
const response = await fetch("/api/extract/jumblang", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ text: content }),
|
||||
});
|
||||
if (!response.ok) throw new Error("Extraction failed");
|
||||
links = await response.json();
|
||||
} catch (e) {
|
||||
alert("Extraction failed: " + e.message);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Markdown regex for [text](url) and <url>
|
||||
const mdLinkRegex = /\[.*?\]\((https?:\/\/[^\s)]+)\)/g;
|
||||
const rawLinkRegex = /<(https?:\/\/[^>]+)>/g;
|
||||
|
||||
let match;
|
||||
while ((match = mdLinkRegex.exec(content)) !== null) {
|
||||
links.push(match[1]);
|
||||
}
|
||||
while ((match = rawLinkRegex.exec(content)) !== null) {
|
||||
links.push(match[1]);
|
||||
if (mode === "auto") {
|
||||
// Simple heuristic: if it has <a href, it's likely HTML.
|
||||
mode =
|
||||
content.includes("<a href") ||
|
||||
content.includes("<!DOCTYPE html>")
|
||||
? "html"
|
||||
: "markdown";
|
||||
}
|
||||
|
||||
// Also catch plain URLs if they are on their own line or space-separated
|
||||
// This is a bit aggressive, so maybe optional? For now let's stick to explicit MD syntax
|
||||
// or use a library if we want full robustness.
|
||||
if (mode === "html") {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(content, "text/html");
|
||||
const anchors = doc.querySelectorAll("a[href]");
|
||||
links = Array.from(anchors)
|
||||
.map((a) => a.href)
|
||||
.filter((h) => h.startsWith("http"));
|
||||
} else {
|
||||
// Markdown regex for [text](url) and <url>
|
||||
const mdLinkRegex = /\[.*?\]\((https?:\/\/[^\s)]+)\)/g;
|
||||
const rawLinkRegex = /<(https?:\/\/[^>]+)>/g;
|
||||
|
||||
let match;
|
||||
while ((match = mdLinkRegex.exec(content)) !== null) {
|
||||
links.push(match[1]);
|
||||
}
|
||||
while ((match = rawLinkRegex.exec(content)) !== null) {
|
||||
links.push(match[1]);
|
||||
}
|
||||
|
||||
// Also catch plain URLs if they are on their own line or space-separated
|
||||
// This is a bit aggressive, so maybe optional? For now let's stick to explicit MD syntax
|
||||
// or use a library if we want full robustness.
|
||||
}
|
||||
}
|
||||
|
||||
// Deduplicate
|
||||
|
||||
Reference in new issue
Block a user