czon 0.9.7 → 0.9.9
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/dist/process/checkLinks.js +5 -2
- package/dist/process/scanSourceFiles.js +22 -6
- package/dist/ssg/ContentPage.js +85 -153
- package/dist/ssg/style.js +86 -1
- package/dist/utils/isFile.js +16 -0
- package/package.json +1 -1
|
@@ -16,6 +16,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
16
16
|
const findEntries_1 = require("../findEntries");
|
|
17
17
|
const paths_1 = require("../paths");
|
|
18
18
|
const isExists_1 = require("../utils/isExists");
|
|
19
|
+
const isFile_1 = require("../utils/isFile");
|
|
19
20
|
/**
|
|
20
21
|
* 递归遍历 marked token 树,收集所有真实的 link 和 image token。
|
|
21
22
|
* 自动跳过 code(代码块)和 codespan(行内代码)中的内容。
|
|
@@ -192,7 +193,9 @@ async function checkLinks() {
|
|
|
192
193
|
}
|
|
193
194
|
// 再检查文件系统
|
|
194
195
|
const resolvedFullPath = path_1.default.join(paths_1.INPUT_DIR, resolvedRelative);
|
|
195
|
-
|
|
196
|
+
const targetExists = await (0, isExists_1.isExists)(resolvedFullPath);
|
|
197
|
+
const targetIsFile = targetExists ? await (0, isFile_1.isFile)(resolvedFullPath) : false;
|
|
198
|
+
if (!targetExists || !targetIsFile) {
|
|
196
199
|
// 通过 basename 模糊匹配,生成候选建议(最多 3 个)
|
|
197
200
|
const suggestions = [];
|
|
198
201
|
const targetBasename = path_1.default.basename(hrefWithoutHash);
|
|
@@ -209,7 +212,7 @@ async function checkLinks() {
|
|
|
209
212
|
raw: link.raw,
|
|
210
213
|
href: link.href,
|
|
211
214
|
type: 'dead-link',
|
|
212
|
-
message: '目标文件不存在',
|
|
215
|
+
message: targetExists ? '目标是目录,不是文件' : '目标文件不存在',
|
|
213
216
|
suggestions,
|
|
214
217
|
});
|
|
215
218
|
}
|
|
@@ -9,6 +9,8 @@ const path_1 = __importDefault(require("path"));
|
|
|
9
9
|
const findEntries_1 = require("../findEntries");
|
|
10
10
|
const metadata_1 = require("../metadata");
|
|
11
11
|
const paths_1 = require("../paths");
|
|
12
|
+
const isExists_1 = require("../utils/isExists");
|
|
13
|
+
const isFile_1 = require("../utils/isFile");
|
|
12
14
|
const extractLinksFromMarkdown = (content) => {
|
|
13
15
|
const linkRegex = /\[.*?\]\((.*?)\)/g;
|
|
14
16
|
const links = [];
|
|
@@ -43,11 +45,14 @@ async function scanSourceFiles() {
|
|
|
43
45
|
if (isVisited.has(fullPath))
|
|
44
46
|
continue;
|
|
45
47
|
isVisited.add(fullPath);
|
|
46
|
-
|
|
47
|
-
if (!isExists) {
|
|
48
|
+
if (!(await (0, isExists_1.isExists)(fullPath))) {
|
|
48
49
|
console.warn(`⚠️ File does not exist: ${fullPath}, skipping.`);
|
|
49
50
|
continue;
|
|
50
51
|
}
|
|
52
|
+
if (!(await (0, isFile_1.isFile)(fullPath))) {
|
|
53
|
+
console.warn(`⚠️ Path is not a file: ${fullPath}, skipping.`);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
51
56
|
const contentBuffer = await (0, promises_1.readFile)(fullPath);
|
|
52
57
|
paths.add(relativePath);
|
|
53
58
|
let meta = metadata_1.MetaData.files.find(f => f.path === relativePath);
|
|
@@ -65,10 +70,21 @@ async function scanSourceFiles() {
|
|
|
65
70
|
for (const link of links) {
|
|
66
71
|
if (URL.canParse(link))
|
|
67
72
|
continue;
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
if (!
|
|
71
|
-
|
|
73
|
+
const hrefWithoutHash = link.split('#')[0];
|
|
74
|
+
const hrefWithoutQuery = hrefWithoutHash.split('?')[0];
|
|
75
|
+
if (!hrefWithoutQuery)
|
|
76
|
+
continue;
|
|
77
|
+
const resolvedPath = path_1.default.resolve(path_1.default.dirname(fullPath), hrefWithoutQuery);
|
|
78
|
+
if ((await (0, isExists_1.isExists)(resolvedPath)) && !(await (0, isFile_1.isFile)(resolvedPath))) {
|
|
79
|
+
console.warn(`⚠️ Link target is a directory: ${link} in ${relativePath}, skipping.`);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const resolvedRelativePath = path_1.default.relative(paths_1.INPUT_DIR, resolvedPath);
|
|
83
|
+
if (resolvedRelativePath.startsWith('..') || path_1.default.isAbsolute(resolvedRelativePath))
|
|
84
|
+
continue;
|
|
85
|
+
const resolvedFullPath = path_1.default.join(paths_1.INPUT_DIR, resolvedRelativePath);
|
|
86
|
+
if (!isVisited.has(resolvedFullPath)) {
|
|
87
|
+
queue.push(resolvedRelativePath);
|
|
72
88
|
}
|
|
73
89
|
}
|
|
74
90
|
}
|
package/dist/ssg/ContentPage.js
CHANGED
|
@@ -90,20 +90,36 @@ const ContentPage = props => {
|
|
|
90
90
|
react_1.default.createElement("button", { className: "share-float-btn", id: "share-float-btn" }, "Share"),
|
|
91
91
|
react_1.default.createElement("div", { className: "share-modal-overlay", id: "share-modal-overlay" },
|
|
92
92
|
react_1.default.createElement("div", { className: "share-modal" },
|
|
93
|
-
react_1.default.createElement("
|
|
93
|
+
react_1.default.createElement("img", { className: "share-preview", id: "share-preview", alt: "Share preview", src: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" }),
|
|
94
94
|
react_1.default.createElement("div", { className: "share-modal-actions" },
|
|
95
95
|
react_1.default.createElement("button", { className: "share-download-btn", id: "share-download-btn" }, "Save Image"),
|
|
96
96
|
react_1.default.createElement("button", { className: "share-close-btn", id: "share-close-btn" }, "Close")))),
|
|
97
|
+
react_1.default.createElement("div", { className: "share-card", id: "share-card" },
|
|
98
|
+
react_1.default.createElement("div", { className: "share-card-header" },
|
|
99
|
+
react_1.default.createElement("div", { className: "share-card-header-left" },
|
|
100
|
+
react_1.default.createElement("div", { className: "share-card-site", id: "share-card-site" }),
|
|
101
|
+
react_1.default.createElement("div", { className: "share-card-title", id: "share-card-title" })),
|
|
102
|
+
react_1.default.createElement("div", { className: "share-card-qr" },
|
|
103
|
+
react_1.default.createElement("canvas", { id: "share-qr-canvas", width: "64", height: "64" }),
|
|
104
|
+
react_1.default.createElement("span", { className: "share-card-qr-hint" }, "Scan to read"))),
|
|
105
|
+
react_1.default.createElement("div", { className: "share-card-divider" }),
|
|
106
|
+
react_1.default.createElement("div", { className: "share-card-body", id: "share-card-body" })),
|
|
97
107
|
react_1.default.createElement("script", { id: "qrcode-lib", src: "https://cdn.jsdelivr.net/npm/qrcode-generator@1.4.4/qrcode.min.js", defer: true }),
|
|
108
|
+
react_1.default.createElement("script", { id: "html2canvas-lib", src: "https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js", defer: true }),
|
|
98
109
|
react_1.default.createElement("script", { dangerouslySetInnerHTML: {
|
|
99
110
|
__html: `
|
|
100
111
|
(function() {
|
|
101
112
|
var floatBtn = document.getElementById('share-float-btn');
|
|
102
113
|
var overlay = document.getElementById('share-modal-overlay');
|
|
103
|
-
var
|
|
114
|
+
var preview = document.getElementById('share-preview');
|
|
104
115
|
var downloadBtn = document.getElementById('share-download-btn');
|
|
105
116
|
var closeBtn = document.getElementById('share-close-btn');
|
|
106
|
-
var
|
|
117
|
+
var shareCard = document.getElementById('share-card');
|
|
118
|
+
var cardSite = document.getElementById('share-card-site');
|
|
119
|
+
var cardTitle = document.getElementById('share-card-title');
|
|
120
|
+
var cardBody = document.getElementById('share-card-body');
|
|
121
|
+
var qrCanvas = document.getElementById('share-qr-canvas');
|
|
122
|
+
var savedRange = null;
|
|
107
123
|
var articleTitle = ${JSON.stringify(title)};
|
|
108
124
|
var siteName = ${JSON.stringify(props.ctx.site.options?.site?.title || 'CZON')};
|
|
109
125
|
|
|
@@ -125,25 +141,18 @@ const ContentPage = props => {
|
|
|
125
141
|
floatBtn.style.display = 'none';
|
|
126
142
|
return;
|
|
127
143
|
}
|
|
128
|
-
|
|
144
|
+
savedRange = range.cloneRange();
|
|
129
145
|
var rect = range.getBoundingClientRect();
|
|
130
146
|
floatBtn.style.display = 'block';
|
|
131
|
-
floatBtn.style.top = (window.scrollY + rect.
|
|
147
|
+
floatBtn.style.top = (window.scrollY + rect.bottom + 6) + 'px';
|
|
132
148
|
floatBtn.style.left = (window.scrollX + rect.left + rect.width / 2 - 30) + 'px';
|
|
133
149
|
});
|
|
134
150
|
|
|
135
|
-
// Hide float button on click elsewhere
|
|
136
|
-
document.addEventListener('mousedown', function(e) {
|
|
137
|
-
if (e.target === floatBtn) return;
|
|
138
|
-
// Let selectionchange handle hiding
|
|
139
|
-
});
|
|
140
|
-
|
|
141
151
|
floatBtn.addEventListener('click', function(e) {
|
|
142
152
|
e.preventDefault();
|
|
143
153
|
e.stopPropagation();
|
|
144
|
-
if (!
|
|
145
|
-
renderShareCard(
|
|
146
|
-
overlay.classList.add('active');
|
|
154
|
+
if (!savedRange) return;
|
|
155
|
+
renderShareCard(savedRange);
|
|
147
156
|
floatBtn.style.display = 'none';
|
|
148
157
|
});
|
|
149
158
|
|
|
@@ -155,159 +164,82 @@ const ContentPage = props => {
|
|
|
155
164
|
});
|
|
156
165
|
|
|
157
166
|
downloadBtn.addEventListener('click', function() {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
a.download = 'share.png';
|
|
163
|
-
a.click();
|
|
164
|
-
URL.revokeObjectURL(url);
|
|
165
|
-
}, 'image/png');
|
|
167
|
+
var a = document.createElement('a');
|
|
168
|
+
a.href = preview.src;
|
|
169
|
+
a.download = 'share.png';
|
|
170
|
+
a.click();
|
|
166
171
|
});
|
|
167
172
|
|
|
168
|
-
function
|
|
169
|
-
|
|
170
|
-
var
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
173
|
+
function renderQR() {
|
|
174
|
+
if (typeof qrcode === 'undefined') return;
|
|
175
|
+
var size = 64;
|
|
176
|
+
var qr = qrcode(0, 'M');
|
|
177
|
+
qr.addData(window.location.href);
|
|
178
|
+
qr.make();
|
|
179
|
+
var moduleCount = qr.getModuleCount();
|
|
180
|
+
var cellSize = size / moduleCount;
|
|
181
|
+
var ctx = qrCanvas.getContext('2d');
|
|
182
|
+
ctx.clearRect(0, 0, size, size);
|
|
183
|
+
ctx.fillStyle = '#1a1a1a';
|
|
184
|
+
for (var r = 0; r < moduleCount; r++) {
|
|
185
|
+
for (var c = 0; c < moduleCount; c++) {
|
|
186
|
+
if (qr.isDark(r, c)) {
|
|
187
|
+
ctx.fillRect(c * cellSize, r * cellSize, cellSize + 0.5, cellSize + 0.5);
|
|
182
188
|
}
|
|
183
189
|
}
|
|
184
|
-
if (line) lines.push(line);
|
|
185
|
-
if (p < paragraphs.length - 1) lines.push('');
|
|
186
190
|
}
|
|
187
|
-
return lines;
|
|
188
191
|
}
|
|
189
192
|
|
|
190
|
-
function renderShareCard(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
var contentW = W - pad * 2;
|
|
195
|
-
var ctx = canvas.getContext('2d');
|
|
196
|
-
|
|
197
|
-
// Pre-calculate heights
|
|
198
|
-
ctx.font = 'bold 28px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
|
|
199
|
-
var titleLines = wrapText(ctx, articleTitle, contentW, 36);
|
|
200
|
-
var titleH = titleLines.length * 36;
|
|
201
|
-
|
|
202
|
-
ctx.font = '20px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
|
|
203
|
-
var maxTextLen = 300;
|
|
204
|
-
var displayText = text.length > maxTextLen ? text.slice(0, maxTextLen) + '...' : text;
|
|
205
|
-
var textLines = wrapText(ctx, displayText, contentW - 32, 30);
|
|
206
|
-
var textH = textLines.length * 30;
|
|
193
|
+
function renderShareCard(range) {
|
|
194
|
+
// Populate card content
|
|
195
|
+
cardSite.textContent = siteName;
|
|
196
|
+
cardTitle.textContent = articleTitle;
|
|
207
197
|
|
|
208
|
-
|
|
209
|
-
var
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
var quoteBottomPad = 24;
|
|
213
|
-
var qrTopPad = 32;
|
|
214
|
-
var qrBottomPad = 16;
|
|
215
|
-
var bottomPad = 32;
|
|
198
|
+
// Clone selected DOM fragment with rich formatting
|
|
199
|
+
var fragment = range.cloneContents();
|
|
200
|
+
cardBody.innerHTML = '';
|
|
201
|
+
cardBody.appendChild(fragment);
|
|
216
202
|
|
|
217
|
-
|
|
203
|
+
// Copy computed styles for elements that need them (e.g. KaTeX)
|
|
204
|
+
var allStyles = document.querySelectorAll('style, link[rel="stylesheet"]');
|
|
205
|
+
var styleClones = [];
|
|
206
|
+
allStyles.forEach(function(s) {
|
|
207
|
+
styleClones.push(s.cloneNode(true));
|
|
208
|
+
});
|
|
218
209
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
canvas.style.width = W + 'px';
|
|
222
|
-
canvas.style.height = H + 'px';
|
|
223
|
-
ctx.scale(dpr, dpr);
|
|
210
|
+
// Render QR code
|
|
211
|
+
renderQR();
|
|
224
212
|
|
|
225
|
-
//
|
|
226
|
-
|
|
227
|
-
ctx.beginPath();
|
|
228
|
-
ctx.roundRect(0, 0, W, H, 12);
|
|
229
|
-
ctx.fill();
|
|
230
|
-
|
|
231
|
-
var y = pad;
|
|
232
|
-
|
|
233
|
-
// Site name
|
|
234
|
-
ctx.fillStyle = '#999999';
|
|
235
|
-
ctx.font = '16px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
|
|
236
|
-
ctx.fillText(siteName, pad, y + 16);
|
|
237
|
-
y += siteNameH;
|
|
238
|
-
|
|
239
|
-
// Title
|
|
240
|
-
ctx.fillStyle = '#1a1a1a';
|
|
241
|
-
ctx.font = 'bold 28px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
|
|
242
|
-
for (var i = 0; i < titleLines.length; i++) {
|
|
243
|
-
ctx.fillText(titleLines[i], pad, y + 28);
|
|
244
|
-
y += 36;
|
|
245
|
-
}
|
|
246
|
-
y += separatorGap;
|
|
213
|
+
// Show card for html2canvas to capture
|
|
214
|
+
shareCard.classList.add('rendering');
|
|
247
215
|
|
|
248
|
-
//
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
// Quote block background
|
|
258
|
-
var quoteBlockY = y;
|
|
259
|
-
var quoteBlockH = quoteTopPad + textH + quoteBottomPad;
|
|
260
|
-
ctx.fillStyle = '#f8f9fa';
|
|
261
|
-
ctx.beginPath();
|
|
262
|
-
ctx.roundRect(pad, quoteBlockY, contentW, quoteBlockH, 8);
|
|
263
|
-
ctx.fill();
|
|
264
|
-
|
|
265
|
-
// Quote accent bar
|
|
266
|
-
ctx.fillStyle = '#007bff';
|
|
267
|
-
ctx.beginPath();
|
|
268
|
-
ctx.roundRect(pad, quoteBlockY, 4, quoteBlockH, 2);
|
|
269
|
-
ctx.fill();
|
|
270
|
-
|
|
271
|
-
// Quote text
|
|
272
|
-
y += quoteTopPad;
|
|
273
|
-
ctx.fillStyle = '#333333';
|
|
274
|
-
ctx.font = '20px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
|
|
275
|
-
for (var i = 0; i < textLines.length; i++) {
|
|
276
|
-
if (textLines[i] !== '') {
|
|
277
|
-
ctx.fillText(textLines[i], pad + 16, y + 20);
|
|
216
|
+
// Wait a frame for layout
|
|
217
|
+
requestAnimationFrame(function() {
|
|
218
|
+
// Enforce minimum 3:4 aspect ratio
|
|
219
|
+
var cardW = shareCard.offsetWidth;
|
|
220
|
+
var cardH = shareCard.offsetHeight;
|
|
221
|
+
var minH = Math.round(cardW * 4 / 3);
|
|
222
|
+
if (cardH < minH) {
|
|
223
|
+
shareCard.style.minHeight = minH + 'px';
|
|
278
224
|
}
|
|
279
|
-
y += 30;
|
|
280
|
-
}
|
|
281
|
-
y += quoteBottomPad + qrTopPad;
|
|
282
|
-
|
|
283
|
-
// QR code
|
|
284
|
-
if (typeof qrcode !== 'undefined') {
|
|
285
|
-
var qr = qrcode(0, 'M');
|
|
286
|
-
qr.addData(window.location.href);
|
|
287
|
-
qr.make();
|
|
288
|
-
var moduleCount = qr.getModuleCount();
|
|
289
|
-
var cellSize = qrSize / moduleCount;
|
|
290
|
-
var qrX = W - pad - qrSize;
|
|
291
|
-
var qrY = y;
|
|
292
225
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
226
|
+
html2canvas(shareCard, {
|
|
227
|
+
scale: 2,
|
|
228
|
+
useCORS: true,
|
|
229
|
+
backgroundColor: '#ffffff',
|
|
230
|
+
logging: false,
|
|
231
|
+
}).then(function(canvas) {
|
|
232
|
+
shareCard.classList.remove('rendering');
|
|
233
|
+
shareCard.style.minHeight = '';
|
|
296
234
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
// Hint text next to QR
|
|
307
|
-
ctx.fillStyle = '#999999';
|
|
308
|
-
ctx.font = '14px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
|
|
309
|
-
ctx.fillText('Scan to read the original', pad, y + qrSize / 2 + 5);
|
|
310
|
-
}
|
|
235
|
+
preview.src = canvas.toDataURL('image/png');
|
|
236
|
+
overlay.classList.add('active');
|
|
237
|
+
}).catch(function(err) {
|
|
238
|
+
console.error('Share card render error:', err);
|
|
239
|
+
shareCard.classList.remove('rendering');
|
|
240
|
+
shareCard.style.minHeight = '';
|
|
241
|
+
});
|
|
242
|
+
});
|
|
311
243
|
}
|
|
312
244
|
})();
|
|
313
245
|
`,
|
|
@@ -410,7 +342,7 @@ const ContentPage = props => {
|
|
|
410
342
|
|
|
411
343
|
function renderEmblaCarousels() {
|
|
412
344
|
// Detect image groups, make them carousels automatically
|
|
413
|
-
Map.groupBy(document.querySelectorAll('img'), x => x.parentNode).entries().forEach(([container, images]) => {
|
|
345
|
+
Map.groupBy(document.querySelectorAll('.content-body img'), x => x.parentNode).entries().forEach(([container, images]) => {
|
|
414
346
|
const outer = document.createElement('div');
|
|
415
347
|
outer.classList.add('embla');
|
|
416
348
|
container.appendChild(outer);
|
package/dist/ssg/style.js
CHANGED
|
@@ -424,7 +424,7 @@ html:not(.dark) body {
|
|
|
424
424
|
align-items: center;
|
|
425
425
|
gap: 16px;
|
|
426
426
|
}
|
|
427
|
-
.share-modal
|
|
427
|
+
.share-modal img.share-preview {
|
|
428
428
|
max-width: 100%;
|
|
429
429
|
height: auto;
|
|
430
430
|
border-radius: 8px;
|
|
@@ -449,5 +449,90 @@ html:not(.dark) body {
|
|
|
449
449
|
background: var(--tag-bg);
|
|
450
450
|
color: var(--tag-text);
|
|
451
451
|
}
|
|
452
|
+
|
|
453
|
+
/* Share card (off-screen DOM for html2canvas capture) */
|
|
454
|
+
.share-card {
|
|
455
|
+
display: none;
|
|
456
|
+
position: fixed;
|
|
457
|
+
left: -9999px;
|
|
458
|
+
top: 0;
|
|
459
|
+
width: 540px;
|
|
460
|
+
min-height: 720px;
|
|
461
|
+
background: #ffffff;
|
|
462
|
+
border-radius: 12px;
|
|
463
|
+
padding: 36px;
|
|
464
|
+
box-sizing: border-box;
|
|
465
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
466
|
+
color: #1a1a1a;
|
|
467
|
+
flex-direction: column;
|
|
468
|
+
pointer-events: none;
|
|
469
|
+
}
|
|
470
|
+
.share-card.rendering {
|
|
471
|
+
display: flex;
|
|
472
|
+
}
|
|
473
|
+
.share-card-header {
|
|
474
|
+
display: flex;
|
|
475
|
+
justify-content: space-between;
|
|
476
|
+
align-items: flex-start;
|
|
477
|
+
gap: 12px;
|
|
478
|
+
margin-bottom: 20px;
|
|
479
|
+
}
|
|
480
|
+
.share-card-header-left {
|
|
481
|
+
flex: 1;
|
|
482
|
+
min-width: 0;
|
|
483
|
+
}
|
|
484
|
+
.share-card-site {
|
|
485
|
+
font-size: 14px;
|
|
486
|
+
color: #999999;
|
|
487
|
+
margin-bottom: 8px;
|
|
488
|
+
}
|
|
489
|
+
.share-card-title {
|
|
490
|
+
font-size: 24px;
|
|
491
|
+
font-weight: 700;
|
|
492
|
+
color: #1a1a1a;
|
|
493
|
+
line-height: 1.3;
|
|
494
|
+
word-wrap: break-word;
|
|
495
|
+
}
|
|
496
|
+
.share-card-qr {
|
|
497
|
+
flex-shrink: 0;
|
|
498
|
+
display: flex;
|
|
499
|
+
flex-direction: column;
|
|
500
|
+
align-items: center;
|
|
501
|
+
}
|
|
502
|
+
.share-card-qr canvas {
|
|
503
|
+
display: block;
|
|
504
|
+
}
|
|
505
|
+
.share-card-qr-hint {
|
|
506
|
+
font-size: 10px;
|
|
507
|
+
color: #bbbbbb;
|
|
508
|
+
margin-top: 4px;
|
|
509
|
+
white-space: nowrap;
|
|
510
|
+
}
|
|
511
|
+
.share-card-divider {
|
|
512
|
+
height: 1px;
|
|
513
|
+
background: #e5e5e5;
|
|
514
|
+
margin-bottom: 20px;
|
|
515
|
+
}
|
|
516
|
+
.share-card-body {
|
|
517
|
+
flex: 1;
|
|
518
|
+
background: #f8f9fa;
|
|
519
|
+
border-radius: 8px;
|
|
520
|
+
padding: 20px;
|
|
521
|
+
font-size: 18px;
|
|
522
|
+
line-height: 1.8;
|
|
523
|
+
color: #333333;
|
|
524
|
+
overflow: hidden;
|
|
525
|
+
}
|
|
526
|
+
.share-card-body img {
|
|
527
|
+
max-width: 100%;
|
|
528
|
+
height: auto;
|
|
529
|
+
}
|
|
530
|
+
.share-card-body pre {
|
|
531
|
+
white-space: pre-wrap;
|
|
532
|
+
word-wrap: break-word;
|
|
533
|
+
}
|
|
534
|
+
.share-card-body strong {
|
|
535
|
+
color: #ff5722;
|
|
536
|
+
}
|
|
452
537
|
`;
|
|
453
538
|
//# sourceMappingURL=style.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isFile = void 0;
|
|
4
|
+
const promises_1 = require("fs/promises");
|
|
5
|
+
/**
|
|
6
|
+
* 检查路径是否为文件
|
|
7
|
+
* @param path 要检查的路径
|
|
8
|
+
* @returns Promise<boolean> 路径是否是文件
|
|
9
|
+
*/
|
|
10
|
+
const isFile = async (path) => {
|
|
11
|
+
return (0, promises_1.stat)(path)
|
|
12
|
+
.then(stats => stats.isFile())
|
|
13
|
+
.catch(() => false);
|
|
14
|
+
};
|
|
15
|
+
exports.isFile = isFile;
|
|
16
|
+
//# sourceMappingURL=isFile.js.map
|