-
Notifications
You must be signed in to change notification settings - Fork 469
Expand file tree
/
Copy pathbear-markdown.js
More file actions
119 lines (100 loc) · 3.3 KB
/
Copy pathbear-markdown.js
File metadata and controls
119 lines (100 loc) · 3.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
function decodeEntities(value) {
const entities = {
amp: "&",
apos: "'",
gt: ">",
lt: "<",
nbsp: " ",
quot: "\""
};
return value.replace(/&(#x?[0-9a-f]+|[a-z]+);/gi, function(match, entity) {
if (entity[0] === "#") {
const radix = entity[1].toLowerCase() === "x" ? 16 : 10;
const code = parseInt(entity.replace(/^#x?/i, ""), radix);
return isNaN(code) ? match : String.fromCharCode(code);
}
return entities[entity.toLowerCase()] || match;
});
}
function cellToMarkdown(html) {
return decodeEntities(html)
.replace(/<br\s*\/?>/gi, " ")
.replace(/<\/p\s*>/gi, " ")
.replace(/<a\b[^>]*href=["']([^"']+)["'][^>]*>([\s\S]*?)<\/a>/gi, "[$2]($1)")
.replace(/<[^>]+>/g, "")
.replace(/\s+/g, " ")
.replace(/\|/g, "\\|")
.trim();
}
function tableToMarkdown(tableHtml) {
const rows = [];
const rowMatches = tableHtml.match(/<tr\b[\s\S]*?<\/tr>/gi) || [];
for (const rowHtml of rowMatches) {
const cells = [];
const cellRegex = /<t[hd]\b[^>]*>([\s\S]*?)<\/t[hd]>/gi;
let match;
while ((match = cellRegex.exec(rowHtml)) !== null) {
cells.push(cellToMarkdown(match[1]));
}
if (cells.length > 0) {
rows.push(cells);
}
}
if (rows.length === 0) {
return "";
}
const columnCount = rows.reduce(function(max, row) {
return Math.max(max, row.length);
}, 0);
const normalizedRows = rows.map(function(row) {
const normalized = row.slice();
while (normalized.length < columnCount) {
normalized.push("");
}
return normalized;
});
const separator = [];
for (let index = 0; index < columnCount; index++) {
separator.push("---");
}
return [
"| " + normalizedRows[0].join(" | ") + " |",
"| " + separator.join(" | ") + " |"
].concat(normalizedRows.slice(1).map(function(row) {
return "| " + row.join(" | ") + " |";
})).join("\n");
}
function htmlToMarkdownWithTables(html) {
const converted = decodeEntities(html)
.replace(/<table\b[\s\S]*?<\/table>/gi, function(tableHtml) {
return "\n\n" + tableToMarkdown(tableHtml) + "\n\n";
})
.replace(/<h([1-6])\b[^>]*>([\s\S]*?)<\/h\1>/gi, function(match, level, content) {
const prefix = "#".repeat(parseInt(level, 10));
return "\n\n" + prefix + " " + cellToMarkdown(content) + "\n\n";
})
.replace(/<br\s*\/?>/gi, "\n")
.replace(/<\/(p|div|section|article|header|footer|h[1-6]|li)\s*>/gi, "\n")
.replace(/<a\b[^>]*href=["']([^"']+)["'][^>]*>([\s\S]*?)<\/a>/gi, "[$2]($1)")
.replace(/<(strong|b)\b[^>]*>([\s\S]*?)<\/\1>/gi, "**$2**")
.replace(/<(em|i)\b[^>]*>([\s\S]*?)<\/\1>/gi, "_$2_")
.replace(/<[^>]+>/g, "")
.replace(/[ \t]+\n/g, "\n")
.replace(/\n{3,}/g, "\n\n")
.trim();
return converted || popclip.input.markdown || popclip.input.text;
}
const html = popclip.input.html || "";
let markdown = /<table\b/i.test(html)
? htmlToMarkdownWithTables(html)
: (popclip.input.markdown || popclip.input.text);
const browserUrl = popclip.context.browserUrl;
const browserTitle = popclip.context.browserTitle || "Source";
if (browserUrl) {
markdown += "\n\n---\n\nSource: [" + browserTitle + "](" + browserUrl + ")";
}
const url = "bear://x-callback-url/create"
+ "?text=" + encodeURIComponent(markdown)
+ "&open_note=yes"
+ "&edit=yes";
popclip.openUrl(url);