acdev 1.0.15 → 1.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/public/app.js +153 -8
- package/public/styles.css +62 -6
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -1051,6 +1051,148 @@ function sortedJobs() {
|
|
|
1051
1051
|
);
|
|
1052
1052
|
}
|
|
1053
1053
|
|
|
1054
|
+
/**
|
|
1055
|
+
* @param {string} raw
|
|
1056
|
+
* @returns {string}
|
|
1057
|
+
*/
|
|
1058
|
+
function escapeHtml(raw) {
|
|
1059
|
+
return String(raw)
|
|
1060
|
+
.replaceAll('&', '&')
|
|
1061
|
+
.replaceAll('<', '<')
|
|
1062
|
+
.replaceAll('>', '>')
|
|
1063
|
+
.replaceAll('"', '"')
|
|
1064
|
+
.replaceAll("'", ''');
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
/**
|
|
1068
|
+
* @param {string} raw
|
|
1069
|
+
* @returns {string | null}
|
|
1070
|
+
*/
|
|
1071
|
+
function safeMarkdownHref(raw) {
|
|
1072
|
+
const href = String(raw || '').trim();
|
|
1073
|
+
if (!href) return null;
|
|
1074
|
+
if (href.startsWith('#') || href.startsWith('/')) return href;
|
|
1075
|
+
try {
|
|
1076
|
+
const url = new URL(href, window.location.href);
|
|
1077
|
+
return ['http:', 'https:', 'mailto:'].includes(url.protocol) ? url.href : null;
|
|
1078
|
+
} catch {
|
|
1079
|
+
return null;
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
/**
|
|
1084
|
+
* @param {string} raw
|
|
1085
|
+
* @returns {string}
|
|
1086
|
+
*/
|
|
1087
|
+
function renderInlineMarkdown(raw) {
|
|
1088
|
+
const stash = [];
|
|
1089
|
+
const hold = (html) => `\u0000${stash.push(html) - 1}\u0000`;
|
|
1090
|
+
let out = escapeHtml(raw);
|
|
1091
|
+
out = out.replace(/`([^`]+)`/g, (_, code) => hold(`<code>${code}</code>`));
|
|
1092
|
+
out = out.replace(/\*\*([^*]+)\*\*/g, (_, body) => hold(`<strong>${body}</strong>`));
|
|
1093
|
+
out = out.replace(/__([^_]+)__/g, (_, body) => hold(`<strong>${body}</strong>`));
|
|
1094
|
+
out = out.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, label, href) => {
|
|
1095
|
+
const safe = safeMarkdownHref(href);
|
|
1096
|
+
if (!safe) return label;
|
|
1097
|
+
return hold(
|
|
1098
|
+
`<a href="${escapeHtml(safe)}" target="_blank" rel="noopener noreferrer">${label}</a>`
|
|
1099
|
+
);
|
|
1100
|
+
});
|
|
1101
|
+
return out.replace(/\u0000(\d+)\u0000/g, (_, idx) => stash[Number(idx)] || '');
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
/**
|
|
1105
|
+
* @param {HTMLElement | null} container
|
|
1106
|
+
* @param {string} raw
|
|
1107
|
+
*/
|
|
1108
|
+
function renderMarkdownBlock(container, raw) {
|
|
1109
|
+
if (!container) return;
|
|
1110
|
+
container.innerHTML = '';
|
|
1111
|
+
const text = String(raw || '').replace(/\r\n/g, '\n').trim();
|
|
1112
|
+
if (!text) return;
|
|
1113
|
+
|
|
1114
|
+
const lines = text.split('\n');
|
|
1115
|
+
let paragraph = [];
|
|
1116
|
+
let listEl = null;
|
|
1117
|
+
let listType = '';
|
|
1118
|
+
|
|
1119
|
+
const flushParagraph = () => {
|
|
1120
|
+
if (!paragraph.length) return;
|
|
1121
|
+
const p = document.createElement('p');
|
|
1122
|
+
p.innerHTML = renderInlineMarkdown(paragraph.join(' '));
|
|
1123
|
+
container.appendChild(p);
|
|
1124
|
+
paragraph = [];
|
|
1125
|
+
};
|
|
1126
|
+
|
|
1127
|
+
const flushList = () => {
|
|
1128
|
+
if (!listEl) return;
|
|
1129
|
+
container.appendChild(listEl);
|
|
1130
|
+
listEl = null;
|
|
1131
|
+
listType = '';
|
|
1132
|
+
};
|
|
1133
|
+
|
|
1134
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
1135
|
+
const line = lines[i];
|
|
1136
|
+
if (!line.trim()) {
|
|
1137
|
+
flushParagraph();
|
|
1138
|
+
flushList();
|
|
1139
|
+
continue;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
const fence = line.match(/^```([\w-]+)?\s*$/);
|
|
1143
|
+
if (fence) {
|
|
1144
|
+
flushParagraph();
|
|
1145
|
+
flushList();
|
|
1146
|
+
const codeLines = [];
|
|
1147
|
+
for (i += 1; i < lines.length; i += 1) {
|
|
1148
|
+
if (/^```\s*$/.test(lines[i])) break;
|
|
1149
|
+
codeLines.push(lines[i]);
|
|
1150
|
+
}
|
|
1151
|
+
const pre = document.createElement('pre');
|
|
1152
|
+
pre.className = 'markdown-code';
|
|
1153
|
+
const code = document.createElement('code');
|
|
1154
|
+
if (fence[1]) code.dataset.language = fence[1];
|
|
1155
|
+
code.textContent = codeLines.join('\n');
|
|
1156
|
+
pre.appendChild(code);
|
|
1157
|
+
container.appendChild(pre);
|
|
1158
|
+
continue;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
const heading = line.match(/^(#{1,6})\s+(.*)$/);
|
|
1162
|
+
if (heading) {
|
|
1163
|
+
flushParagraph();
|
|
1164
|
+
flushList();
|
|
1165
|
+
const tag = `h${heading[1].length}`;
|
|
1166
|
+
const el = document.createElement(tag);
|
|
1167
|
+
el.className = `markdown-heading markdown-heading-${heading[1].length}`;
|
|
1168
|
+
el.innerHTML = renderInlineMarkdown(heading[2]);
|
|
1169
|
+
container.appendChild(el);
|
|
1170
|
+
continue;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
const bullet = line.match(/^\s*([-*+])\s+(.*)$/);
|
|
1174
|
+
const ordered = line.match(/^\s*\d+\.\s+(.*)$/);
|
|
1175
|
+
if (bullet || ordered) {
|
|
1176
|
+
flushParagraph();
|
|
1177
|
+
const type = bullet ? 'ul' : 'ol';
|
|
1178
|
+
if (!listEl || listType !== type) {
|
|
1179
|
+
flushList();
|
|
1180
|
+
listEl = document.createElement(type);
|
|
1181
|
+
listType = type;
|
|
1182
|
+
}
|
|
1183
|
+
const li = document.createElement('li');
|
|
1184
|
+
li.innerHTML = renderInlineMarkdown((bullet || ordered)[2] || (bullet || ordered)[1] || '');
|
|
1185
|
+
listEl.appendChild(li);
|
|
1186
|
+
continue;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
paragraph.push(line.trim());
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
flushParagraph();
|
|
1193
|
+
flushList();
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1054
1196
|
/**
|
|
1055
1197
|
* @param {HTMLElement | null} container
|
|
1056
1198
|
* @param {object | null | undefined} pr
|
|
@@ -1089,8 +1231,8 @@ function renderPrStatusNotes(container, pr) {
|
|
|
1089
1231
|
|
|
1090
1232
|
if (review.body) {
|
|
1091
1233
|
const body = document.createElement('div');
|
|
1092
|
-
body.className = 'pr-status-note-body';
|
|
1093
|
-
body
|
|
1234
|
+
body.className = 'pr-status-note-body markdown-view';
|
|
1235
|
+
renderMarkdownBlock(body, review.body);
|
|
1094
1236
|
item.appendChild(body);
|
|
1095
1237
|
}
|
|
1096
1238
|
|
|
@@ -1107,6 +1249,10 @@ function renderPrStatusNotes(container, pr) {
|
|
|
1107
1249
|
container.appendChild(requested);
|
|
1108
1250
|
}
|
|
1109
1251
|
}
|
|
1252
|
+
if (typeof window !== 'undefined') {
|
|
1253
|
+
window.__acdevMarkdownRender = renderMarkdownBlock;
|
|
1254
|
+
window.__acdevMarkdownInline = renderInlineMarkdown;
|
|
1255
|
+
}
|
|
1110
1256
|
function formatTime(ts) {
|
|
1111
1257
|
try {
|
|
1112
1258
|
return new Date(ts).toLocaleTimeString([], {
|
|
@@ -1771,8 +1917,8 @@ function renderDiff(diff, opts = {}) {
|
|
|
1771
1917
|
const chip = document.createElement('div');
|
|
1772
1918
|
chip.className = 'diff-pending-chip';
|
|
1773
1919
|
const body = document.createElement('div');
|
|
1774
|
-
body.className = 'diff-pending-chip-body';
|
|
1775
|
-
body
|
|
1920
|
+
body.className = 'diff-pending-chip-body markdown-view';
|
|
1921
|
+
renderMarkdownBlock(body, c.body);
|
|
1776
1922
|
const actions = document.createElement('div');
|
|
1777
1923
|
actions.className = 'diff-pending-chip-actions';
|
|
1778
1924
|
const edit = document.createElement('button');
|
|
@@ -1922,8 +2068,7 @@ function renderDiff(diff, opts = {}) {
|
|
|
1922
2068
|
}
|
|
1923
2069
|
continue;
|
|
1924
2070
|
}
|
|
1925
|
-
|
|
1926
|
-
if (line.startsWith('@@')) {
|
|
2071
|
+
if (line.startsWith('@@ ')) {
|
|
1927
2072
|
const m = line.match(/@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
|
|
1928
2073
|
if (m) {
|
|
1929
2074
|
leftNo = Number(m[1]);
|
|
@@ -2065,8 +2210,8 @@ function renderPendingCommentList(jobId) {
|
|
|
2065
2210
|
}
|
|
2066
2211
|
|
|
2067
2212
|
const body = document.createElement('div');
|
|
2068
|
-
body.className = 'review-pending-item-body';
|
|
2069
|
-
body
|
|
2213
|
+
body.className = 'review-pending-item-body markdown-view';
|
|
2214
|
+
renderMarkdownBlock(body, c.body);
|
|
2070
2215
|
main.appendChild(body);
|
|
2071
2216
|
const actions = document.createElement('div');
|
|
2072
2217
|
actions.className = 'review-pending-item-actions';
|
package/public/styles.css
CHANGED
|
@@ -1620,15 +1620,67 @@ a { color: var(--primary); text-underline-offset: 3px; }
|
|
|
1620
1620
|
background: var(--surface-2);
|
|
1621
1621
|
}
|
|
1622
1622
|
|
|
1623
|
-
.
|
|
1623
|
+
.markdown-view {
|
|
1624
|
+
line-height: 1.45;
|
|
1625
|
+
word-break: break-word;
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
.markdown-view > :first-child {
|
|
1629
|
+
margin-top: 0;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
.markdown-view > :last-child {
|
|
1633
|
+
margin-bottom: 0;
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
.markdown-view p,
|
|
1637
|
+
.markdown-view ul,
|
|
1638
|
+
.markdown-view ol,
|
|
1639
|
+
.markdown-view pre,
|
|
1640
|
+
.markdown-view blockquote,
|
|
1641
|
+
.markdown-view h1,
|
|
1642
|
+
.markdown-view h2,
|
|
1643
|
+
.markdown-view h3,
|
|
1644
|
+
.markdown-view h4,
|
|
1645
|
+
.markdown-view h5,
|
|
1646
|
+
.markdown-view h6 {
|
|
1647
|
+
margin: 0 0 8px;
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
.markdown-view ul,
|
|
1651
|
+
.markdown-view ol {
|
|
1652
|
+
padding-left: 20px;
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
.markdown-view code {
|
|
1656
|
+
font-family: "JetBrains Mono", ui-monospace, monospace;
|
|
1624
1657
|
font-size: 12px;
|
|
1625
|
-
|
|
1626
|
-
|
|
1658
|
+
padding: 1px 4px;
|
|
1659
|
+
background: var(--bg);
|
|
1660
|
+
border-radius: 4px;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
.markdown-view pre {
|
|
1664
|
+
margin: 0 0 8px;
|
|
1665
|
+
padding: 8px 10px;
|
|
1666
|
+
background: var(--bg);
|
|
1667
|
+
border: 1px solid var(--border-soft);
|
|
1668
|
+
border-radius: 8px;
|
|
1669
|
+
overflow-x: auto;
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
.markdown-view pre code {
|
|
1673
|
+
padding: 0;
|
|
1674
|
+
background: transparent;
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
.markdown-view a {
|
|
1678
|
+
color: var(--primary);
|
|
1679
|
+
text-decoration: underline;
|
|
1627
1680
|
}
|
|
1628
1681
|
|
|
1629
1682
|
.pr-status-note-body {
|
|
1630
|
-
|
|
1631
|
-
line-height: 1.45;
|
|
1683
|
+
font-size: 13px;
|
|
1632
1684
|
}
|
|
1633
1685
|
|
|
1634
1686
|
/* —— Review file selection —— */
|
|
@@ -1943,7 +1995,7 @@ body.diff-fs-open {
|
|
|
1943
1995
|
|
|
1944
1996
|
.diff-pending-chip-body {
|
|
1945
1997
|
color: var(--text);
|
|
1946
|
-
|
|
1998
|
+
font-size: 12px;
|
|
1947
1999
|
}
|
|
1948
2000
|
|
|
1949
2001
|
.diff-pending-chip-actions {
|
|
@@ -1953,6 +2005,10 @@ body.diff-fs-open {
|
|
|
1953
2005
|
flex-wrap: wrap;
|
|
1954
2006
|
}
|
|
1955
2007
|
|
|
2008
|
+
.review-pending-item-body {
|
|
2009
|
+
font-size: 13px;
|
|
2010
|
+
}
|
|
2011
|
+
|
|
1956
2012
|
.review-pending-list {
|
|
1957
2013
|
display: flex;
|
|
1958
2014
|
flex-direction: column;
|