czon 0.3.7 → 0.3.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.
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ContentPage = void 0;
7
+ const node_path_1 = require("node:path");
7
8
  const react_1 = __importDefault(require("react"));
8
9
  const ContentMeta_1 = require("./components/ContentMeta");
9
10
  const CZONFooter_1 = require("./components/CZONFooter");
@@ -20,6 +21,9 @@ const ContentPage = props => {
20
21
  const tags = frontmatter.tags || [];
21
22
  const category = props.file.category;
22
23
  const relatedContents = props.ctx.site.files.filter(f => f.category === category && f.hash !== props.file.hash);
24
+ // 查找指向当前文章的其他文章
25
+ const thisPath = (0, node_path_1.resolve)('/', props.file.path);
26
+ const referencedFiles = props.ctx.site.files.filter(f => f.links.some(link => (0, node_path_1.resolve)('/', (0, node_path_1.dirname)(f.path), link) === thisPath));
23
27
  return (react_1.default.createElement("html", { lang: props.lang, style: { background: 'black', overflow: 'hidden' } },
24
28
  react_1.default.createElement("head", null,
25
29
  react_1.default.createElement("meta", { charSet: "UTF-8" }),
@@ -40,6 +44,13 @@ const ContentPage = props => {
40
44
  const theContent = props.ctx.contents.find(c => c.lang === props.lang && c.hash === f.hash);
41
45
  return (react_1.default.createElement("li", { key: f.hash },
42
46
  react_1.default.createElement("a", { href: `${f.metadata?.slug}.html` }, theContent?.frontmatter.title)));
47
+ })))),
48
+ referencedFiles.length > 0 && (react_1.default.createElement(react_1.default.Fragment, null,
49
+ react_1.default.createElement("h2", null, "Referenced By"),
50
+ react_1.default.createElement("ul", null, referencedFiles.map(f => {
51
+ const theContent = props.ctx.contents.find(c => c.lang === props.lang && c.hash === f.hash);
52
+ return (react_1.default.createElement("li", { key: f.hash },
53
+ react_1.default.createElement("a", { href: `${f.metadata?.slug}.html` }, theContent?.frontmatter.title)));
43
54
  }))))),
44
55
  react_1.default.createElement("footer", { className: "footer" },
45
56
  react_1.default.createElement(LanguageSwitcher_1.LanguageSwitcher, { ctx: props.ctx, lang: props.lang, file: props.file }),
@@ -7,6 +7,63 @@ exports.LanguageSwitch = void 0;
7
7
  const node_path_1 = require("node:path");
8
8
  const react_1 = __importDefault(require("react"));
9
9
  const languages_1 = require("../../languages");
10
+ const style = `
11
+ /* LanguageSwitch dropdown styles - Pure CSS version */
12
+ .language-switch-container {
13
+ position: relative;
14
+ display: inline-block;
15
+ }
16
+
17
+ .language-switch-trigger {
18
+ transition: all 0.2s ease;
19
+ }
20
+
21
+ .language-switch-trigger:hover {
22
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
23
+ }
24
+
25
+ .language-switch-icon {
26
+ transition: transform 0.2s ease;
27
+ }
28
+
29
+ .language-switch-dropdown {
30
+ max-width: 80vw;
31
+ inset-inline-start: auto;
32
+ inset-inline-end: 0;
33
+ margin-inline-start: 0;
34
+ margin-inline-end: 0;
35
+
36
+ opacity: 0;
37
+ visibility: hidden;
38
+ transform: translateY(-10px);
39
+ transition:
40
+ opacity 0.2s ease,
41
+ visibility 0.2s ease,
42
+ transform 0.2s ease;
43
+ }
44
+ #language-switch-toggle:checked ~ .language-switch-dropdown {
45
+ opacity: 1;
46
+ visibility: visible;
47
+ transform: translateY(0);
48
+ }
49
+ #language-switch-toggle:checked ~ .language-switch-trigger .language-switch-icon {
50
+ transform: rotate(180deg);
51
+ }
52
+
53
+ .language-switch-option {
54
+ transition: all 0.15s ease;
55
+ }
56
+
57
+ .language-switch-option:hover {
58
+ transform: translateY(-1px);
59
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
60
+ }
61
+
62
+ .language-switch-option:focus {
63
+ outline: 2px solid #3b82f6;
64
+ outline-offset: 2px;
65
+ }
66
+ `;
10
67
  const LanguageSwitch = props => {
11
68
  // 获取当前语言名称
12
69
  const currentLangName = languages_1.LANGUAGE_NAMES[props.lang] || props.lang;
@@ -18,13 +75,15 @@ const LanguageSwitch = props => {
18
75
  return (0, node_path_1.join)('..', lang, target);
19
76
  };
20
77
  return (react_1.default.createElement("div", { className: "language-switch-container relative inline-block" },
21
- react_1.default.createElement("button", { type: "button", className: "language-switch-trigger px-4 py-2 border border-gray-300 rounded-md flex items-center gap-2 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors", "aria-label": `Language switcher. Current language: ${currentLangName}`, "aria-haspopup": "true", "aria-expanded": "false", "aria-controls": "language-dropdown" },
78
+ react_1.default.createElement("style", null, style),
79
+ react_1.default.createElement("input", { id: "language-switch-toggle", type: "checkbox", className: "hidden", "aria-hidden": "true" }),
80
+ react_1.default.createElement("label", { htmlFor: "language-switch-toggle", className: "language-switch-trigger px-4 py-2 border border-gray-300 rounded-md flex items-center gap-2 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors", "aria-label": `Language switcher. Current language: ${currentLangName}`, "aria-haspopup": "true", "aria-expanded": "false", "aria-controls": "language-dropdown" },
22
81
  react_1.default.createElement("span", { className: "text-sm font-medium" }, currentLangName),
23
82
  react_1.default.createElement("svg", { className: "language-switch-icon w-4 h-4 transition-transform", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true" },
24
83
  react_1.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }))),
25
84
  react_1.default.createElement("div", { id: "language-dropdown", className: "language-switch-dropdown absolute top-full mt-1 w-96 md:w-2xl lg:w-3xl max-h-96 overflow-y-auto bg-white border border-gray-300 rounded-md shadow-lg z-50", role: "menu", "aria-label": "Available languages" },
26
85
  react_1.default.createElement("div", { className: "p-4" },
27
- react_1.default.createElement("div", { className: "language-switch-grid grid grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-2" }, languages.map(lang => {
86
+ react_1.default.createElement("div", { className: "language-switch-grid grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-2" }, languages.map(lang => {
28
87
  const langName = languages_1.LANGUAGE_NAMES[lang] || lang;
29
88
  const isActive = lang === props.lang;
30
89
  return (react_1.default.createElement("a", { key: lang, href: getLanguageLink(lang), className: `
package/dist/ssg/style.js CHANGED
@@ -301,140 +301,6 @@ exports.style = `
301
301
  margin: 0 auto;
302
302
  }
303
303
 
304
- /* LanguageSwitch dropdown styles - Pure CSS version */
305
- .language-switch-container {
306
- position: relative;
307
- display: inline-block;
308
- }
309
-
310
- .language-switch-trigger {
311
- transition: all 0.2s ease;
312
- }
313
-
314
- .language-switch-trigger:hover {
315
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
316
- }
317
-
318
- .language-switch-trigger:focus {
319
- outline: 2px solid #3b82f6;
320
- outline-offset: 2px;
321
- }
322
-
323
- .language-switch-icon {
324
- transition: transform 0.2s ease;
325
- }
326
-
327
- .language-switch-option {
328
- transition: all 0.15s ease;
329
- }
330
-
331
- .language-switch-option:hover {
332
- transform: translateY(-1px);
333
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
334
- }
335
-
336
- .language-switch-option:focus {
337
- outline: 2px solid #3b82f6;
338
- outline-offset: 2px;
339
- }
340
-
341
- /* Pure CSS dropdown using :focus-within */
342
- .language-switch-dropdown {
343
- opacity: 0;
344
- visibility: hidden;
345
- transform: translateY(-10px);
346
- transition: opacity 0.2s ease, visibility 0.2s ease, transform 0.2s ease;
347
- }
348
-
349
- .language-switch-container:focus-within .language-switch-dropdown {
350
- opacity: 1;
351
- visibility: visible;
352
- transform: translateY(0);
353
- }
354
-
355
- .language-switch-container:focus-within .language-switch-icon {
356
- transform: rotate(180deg);
357
- }
358
-
359
- /* Ensure dropdown stays visible when focusing inside it */
360
- .language-switch-dropdown:focus-within {
361
- opacity: 1;
362
- visibility: visible;
363
- transform: translateY(0);
364
- }
365
-
366
- .language-switch-dropdown {
367
- max-width: 80vw;
368
- inset-inline-start: auto;
369
- inset-inline-end: 0;
370
- margin-inline-start: 0;
371
- margin-inline-end: 0;
372
- }
373
-
374
-
375
- /* Mobile responsiveness for language dropdown */
376
- @media (max-width: 768px) {
377
- .language-switch-trigger {
378
- padding: 0.5rem 0.75rem;
379
- font-size: 0.875rem;
380
- }
381
-
382
-
383
- .language-switch-option {
384
- padding: 0.5rem 0.75rem;
385
- font-size: 0.8125rem;
386
- }
387
-
388
- .language-switch-grid {
389
- grid-template-columns: repeat(2, 1fr);
390
- }
391
- }
392
-
393
- @media (max-width: 480px) {
394
- .language-switch-grid {
395
- grid-template-columns: 1fr;
396
- }
397
- }
398
-
399
- /* Scrollbar styling for dropdown */
400
- .language-switch-dropdown::-webkit-scrollbar {
401
- width: 8px;
402
- }
403
-
404
- .language-switch-dropdown::-webkit-scrollbar-track {
405
- background: #f1f1f1;
406
- border-radius: 4px;
407
- }
408
-
409
- .language-switch-dropdown::-webkit-scrollbar-thumb {
410
- background: #c1c1c1;
411
- border-radius: 4px;
412
- }
413
-
414
- .language-switch-dropdown::-webkit-scrollbar-thumb:hover {
415
- background: #a8a8a8;
416
- }
417
-
418
- /* Browser compatibility fallback for :focus-within */
419
- @supports not selector(:focus-within) {
420
- .language-switch-dropdown {
421
- display: none;
422
- }
423
-
424
- .language-switch-container:hover .language-switch-dropdown,
425
- .language-switch-container:focus .language-switch-dropdown {
426
- display: block;
427
- opacity: 1;
428
- visibility: visible;
429
- transform: translateY(0);
430
- }
431
-
432
- .language-switch-container:hover .language-switch-icon,
433
- .language-switch-container:focus .language-switch-icon {
434
- transform: rotate(180deg);
435
- }
436
- }
437
-
438
304
  .embla {
439
305
  overflow: hidden;
440
306
  }
@@ -445,5 +311,5 @@ exports.style = `
445
311
  flex: 0 0 100%;
446
312
  min-width: 0;
447
313
  }
448
- `;
314
+ `;
449
315
  //# sourceMappingURL=style.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "czon",
3
- "version": "0.3.7",
3
+ "version": "0.3.9",
4
4
  "description": "CZone - AI enhanced Markdown content engine",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",