hexo-theme-gnix 8.0.0 → 10.0.0
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/README.md +4 -2
- package/include/hexo/feed.js +6 -5
- package/include/hexo/filter.js +25 -1
- package/include/hexo/generator/archive.js +116 -0
- package/include/hexo/generator/home.js +64 -0
- package/include/hexo/generator/index.js +82 -0
- package/include/hexo/generator/md_generator.js +87 -0
- package/include/hexo/generator/page.js +55 -0
- package/include/hexo/generator/tag.js +84 -0
- package/include/hexo/helper.js +38 -0
- package/include/hexo/i18n.js +183 -0
- package/include/util/article_font.js +132 -0
- package/include/util/i18n.js +280 -0
- package/include/util/theme.js +84 -0
- package/languages/en.yml +28 -0
- package/languages/zh-CN.yml +28 -0
- package/layout/archive.jsx +131 -127
- package/layout/common/article.jsx +316 -34
- package/layout/common/article_info.jsx +339 -0
- package/layout/common/article_media.jsx +11 -4
- package/layout/common/comment.jsx +15 -7
- package/layout/common/footer.jsx +6 -5
- package/layout/common/head.jsx +122 -33
- package/layout/common/navbar.jsx +195 -65
- package/layout/common/theme_selector.jsx +16 -14
- package/layout/layout.jsx +43 -5
- package/layout/misc/open_graph.jsx +162 -66
- package/layout/misc/paginator.jsx +2 -8
- package/layout/plugin/cookie_consent.jsx +252 -53
- package/layout/plugin/swup.jsx +1 -1
- package/layout/search/insight.jsx +1 -1
- package/layout/tag.jsx +3 -2
- package/layout/tags.jsx +81 -73
- package/package.json +5 -5
- package/scripts/index.js +1 -0
- package/source/css/archive.css +225 -180
- package/source/css/default.css +1223 -126
- package/source/css/responsive.css +426 -0
- package/source/css/shiki/shiki.css +12 -2081
- package/source/css/tags.css +183 -0
- package/source/css/twikoo.css +1053 -1049
- package/source/img/favicon.svg +1 -6
- package/source/img/og_image.webp +0 -0
- package/source/js/article-font-utils.js +99 -0
- package/source/js/busuanzi.js +91 -24
- package/source/js/components/chat.js +169 -50
- package/source/js/components/image-carousel.js +152 -108
- package/source/js/components/sidenote.js +210 -0
- package/source/js/components/text-image-section.js +78 -90
- package/source/js/components/theme-stacked.js +65 -33
- package/source/js/components/tree.js +30 -16
- package/source/js/decrypt.js +7 -2
- package/source/js/main.js +428 -5
- package/source/js/swup.js +39 -0
- package/source/js/theme-selector.js +26 -16
- package/include/hexo/generator.js +0 -53
- package/layout/misc/article_licensing.jsx +0 -99
- package/source/css/responsive/desktop.css +0 -36
- package/source/css/responsive/mobile.css +0 -38
- package/source/css/responsive/tablet.css +0 -43
- package/source/css/responsive/touch.css +0 -155
- package/source/img/logo.svg +0 -9
- package/source/js/archive-breadcrumb.js +0 -132
- package/source/js/host/cookieconsent/3.1.1/build/cookieconsent.min.css +0 -6
- package/source/js/host/cookieconsent/3.1.1/build/cookieconsent.min.js +0 -1
- package/source/js/swup.bundle.js +0 -1
package/source/img/favicon.svg
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
<svg
|
|
2
|
-
xmlns="http://www.w3.org/2000/svg" version="1.1" width="256" height="256" viewbox="0 0 949 256">
|
|
3
|
-
<path fill="#2366d1" d="M110.85125168440814 128L221.70250336881628 192L110.85125168440814 256L0 192Z"/>
|
|
4
|
-
<path fill="#609dff" d="M110.85125168440814 64L221.70250336881628 128L110.85125168440814 192L0 128Z"/>
|
|
5
|
-
<path fill="#a4c7ff" d="M110.85125168440814 0L221.70250336881628 64L110.85125168440814 128L0 64Z"/>
|
|
6
|
-
</svg>
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 256 256"> <circle fill="#0821A8" cx="128" cy="128" r="128" /> </svg>
|
package/source/img/og_image.webp
CHANGED
|
Binary file
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
function normalizeCustomFontImport(value) {
|
|
3
|
+
if (typeof value !== "string") return null;
|
|
4
|
+
|
|
5
|
+
var href = value.trim();
|
|
6
|
+
if (!href || /[\s<>"']/.test(href) || /^javascript:/i.test(href)) return null;
|
|
7
|
+
if (!/^(https?:)?\/\//i.test(href) && href.charAt(0) !== "/") return null;
|
|
8
|
+
|
|
9
|
+
return href;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function normalizeCustomFontFamily(value) {
|
|
13
|
+
if (typeof value !== "string") return null;
|
|
14
|
+
|
|
15
|
+
var family = value.trim();
|
|
16
|
+
if (!family || /[{};<>]/.test(family)) return null;
|
|
17
|
+
|
|
18
|
+
return family;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function normalizeCustomFonts(value, familyOptions, importLimit) {
|
|
22
|
+
var customFonts = value && typeof value === "object" ? value : {};
|
|
23
|
+
var sourceFamilies = customFonts.families && typeof customFonts.families === "object" ? customFonts.families : {};
|
|
24
|
+
var importSource = customFonts.imports;
|
|
25
|
+
var importValues = Array.isArray(importSource) ? importSource : typeof importSource === "string" ? importSource.split(/\r?\n/) : [];
|
|
26
|
+
var imports = [];
|
|
27
|
+
var families = {};
|
|
28
|
+
var limit = Number(importLimit);
|
|
29
|
+
|
|
30
|
+
if (!Number.isFinite(limit) || limit < 1) limit = 6;
|
|
31
|
+
|
|
32
|
+
importValues.forEach((item) => {
|
|
33
|
+
var href = normalizeCustomFontImport(item);
|
|
34
|
+
if (href && imports.indexOf(href) === -1 && imports.length < limit) {
|
|
35
|
+
imports.push(href);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
Object.keys(familyOptions || {}).forEach((key) => {
|
|
40
|
+
var family = normalizeCustomFontFamily(sourceFamilies[key]);
|
|
41
|
+
if (family) families[key] = family;
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
imports: imports,
|
|
46
|
+
families: families,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function applyCustomFontImports(imports, selector) {
|
|
51
|
+
var signature = Array.isArray(imports) ? imports.join("\n") : "";
|
|
52
|
+
var sel = selector || 'link[data-gnix-custom-font="true"]';
|
|
53
|
+
var currentLinks = [];
|
|
54
|
+
|
|
55
|
+
if (typeof document !== "undefined") {
|
|
56
|
+
currentLinks = Array.prototype.slice.call(document.querySelectorAll(sel));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
var currentHrefs = currentLinks.map((link) => link.getAttribute("href") || link.href);
|
|
60
|
+
|
|
61
|
+
if (signature === applyCustomFontImports._signature && currentHrefs.length === (imports ? imports.length : 0) && (!imports || imports.every((href) => currentHrefs.indexOf(href) !== -1))) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
currentLinks.forEach((link) => {
|
|
66
|
+
link.remove();
|
|
67
|
+
});
|
|
68
|
+
applyCustomFontImports._signature = signature;
|
|
69
|
+
|
|
70
|
+
if (!document || !document.head || !Array.isArray(imports)) return;
|
|
71
|
+
|
|
72
|
+
imports.forEach((href, index) => {
|
|
73
|
+
var link = document.createElement("link");
|
|
74
|
+
link.rel = "stylesheet";
|
|
75
|
+
link.href = href;
|
|
76
|
+
link.setAttribute("data-gnix-custom-font", "true");
|
|
77
|
+
link.setAttribute("data-gnix-custom-font-index", String(index));
|
|
78
|
+
document.head.appendChild(link);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function applyCustomFontFamilies(html, families, familyOptions) {
|
|
83
|
+
Object.keys(familyOptions || {}).forEach((key) => {
|
|
84
|
+
if (families?.[key]) {
|
|
85
|
+
html.style.setProperty(familyOptions[key], families[key]);
|
|
86
|
+
} else {
|
|
87
|
+
html.style.removeProperty(familyOptions[key]);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
window.__GNIX_ARTICLE_FONT_UTILS__ = {
|
|
93
|
+
normalizeCustomFontImport: normalizeCustomFontImport,
|
|
94
|
+
normalizeCustomFontFamily: normalizeCustomFontFamily,
|
|
95
|
+
normalizeCustomFonts: normalizeCustomFonts,
|
|
96
|
+
applyCustomFontImports: applyCustomFontImports,
|
|
97
|
+
applyCustomFontFamilies: applyCustomFontFamilies,
|
|
98
|
+
};
|
|
99
|
+
})();
|
package/source/js/busuanzi.js
CHANGED
|
@@ -1,33 +1,100 @@
|
|
|
1
1
|
!(() => {
|
|
2
2
|
const TYPES = ["site_pv", "site_uv", "page_pv", "page_uv"];
|
|
3
|
+
const PAGE_TYPES = ["page_pv", "page_uv"];
|
|
3
4
|
const STORAGE_KEY = "bsz-id";
|
|
5
|
+
const API = "https://bsz.dusays.com:9001/api";
|
|
4
6
|
const BASE = { site_pv: 12801, site_uv: 2450 };
|
|
5
7
|
|
|
8
|
+
const getPagePathVariants = () => {
|
|
9
|
+
const path = location.pathname || "/";
|
|
10
|
+
let base = path;
|
|
11
|
+
|
|
12
|
+
if (path.endsWith("/index.html")) {
|
|
13
|
+
base = path.slice(0, -"/index.html".length) || "/";
|
|
14
|
+
} else if (path !== "/" && path.endsWith("/")) {
|
|
15
|
+
base = path.slice(0, -1);
|
|
16
|
+
} else if (/\/[^/]+\.[^/]+$/.test(path)) {
|
|
17
|
+
return [path];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (base === "/") return ["/", "/index.html"];
|
|
21
|
+
return [base, `${base}/`, `${base}/index.html`];
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const toReferer = (path) => `${location.origin}${path}`;
|
|
25
|
+
|
|
26
|
+
const unique = (values) => [...new Set(values)];
|
|
27
|
+
|
|
28
|
+
const request = (method, referer) =>
|
|
29
|
+
new Promise((resolve, reject) => {
|
|
30
|
+
const xhr = new XMLHttpRequest();
|
|
31
|
+
xhr.open(method, API, true);
|
|
32
|
+
|
|
33
|
+
const token = localStorage.getItem(STORAGE_KEY);
|
|
34
|
+
token && xhr.setRequestHeader("Authorization", `Bearer ${token}`);
|
|
35
|
+
xhr.setRequestHeader("x-bsz-referer", referer);
|
|
36
|
+
|
|
37
|
+
xhr.onload = () => {
|
|
38
|
+
if (xhr.status !== 200) {
|
|
39
|
+
reject(new Error(`Busuanzi responded with ${xhr.status}`));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let response;
|
|
44
|
+
try {
|
|
45
|
+
response = JSON.parse(xhr.responseText);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
reject(error);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const { success, data } = response;
|
|
52
|
+
if (!success) {
|
|
53
|
+
reject(new Error("Busuanzi request failed"));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const newToken = xhr.getResponseHeader("Set-Bsz-Identity");
|
|
58
|
+
if (newToken) localStorage.setItem(STORAGE_KEY, newToken);
|
|
59
|
+
|
|
60
|
+
resolve(data || {});
|
|
61
|
+
};
|
|
62
|
+
xhr.onerror = () => reject(new Error("Busuanzi request failed"));
|
|
63
|
+
xhr.send();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const render = (data) => {
|
|
67
|
+
TYPES.forEach((type) => {
|
|
68
|
+
const el = document.getElementById(`busuanzi_${type}`);
|
|
69
|
+
if (el) el.innerHTML = (BASE[type] || 0) + (data[type] || 0);
|
|
70
|
+
|
|
71
|
+
const container = document.getElementById(`busuanzi_container_${type}`);
|
|
72
|
+
if (container) container.style.display = "inline";
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
6
76
|
const update = () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (newToken) localStorage.setItem(STORAGE_KEY, newToken);
|
|
29
|
-
};
|
|
30
|
-
xhr.send();
|
|
77
|
+
request("POST", location.href)
|
|
78
|
+
.then((data) => {
|
|
79
|
+
const currentPath = location.pathname || "/";
|
|
80
|
+
const referers = unique(getPagePathVariants().map(toReferer)).filter((referer) => new URL(referer).pathname !== currentPath);
|
|
81
|
+
if (!referers.length) return data;
|
|
82
|
+
|
|
83
|
+
return Promise.all(referers.map((referer) => request("GET", referer).catch(() => null))).then((results) => {
|
|
84
|
+
const merged = { ...data };
|
|
85
|
+
|
|
86
|
+
results.forEach((result) => {
|
|
87
|
+
if (!result) return;
|
|
88
|
+
PAGE_TYPES.forEach((type) => {
|
|
89
|
+
merged[type] = (merged[type] || 0) + (result[type] || 0);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return merged;
|
|
94
|
+
});
|
|
95
|
+
})
|
|
96
|
+
.then(render)
|
|
97
|
+
.catch(() => {});
|
|
31
98
|
};
|
|
32
99
|
|
|
33
100
|
update();
|
|
@@ -24,74 +24,77 @@
|
|
|
24
24
|
const CHAT_STYLES = `
|
|
25
25
|
:host {
|
|
26
26
|
display: block;
|
|
27
|
-
font-family: var(--font-sans, sans-serif);
|
|
27
|
+
font-family: var(--article-font-family, var(--font-sans-serif, system-ui, sans-serif));
|
|
28
|
+
color: var(--text, #cdd6f4);
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
.chat-container {
|
|
31
32
|
display: flex;
|
|
32
33
|
flex-direction: column;
|
|
33
|
-
gap:
|
|
34
|
-
padding:
|
|
35
|
-
|
|
36
|
-
border-radius: 12px;
|
|
37
|
-
max-height: 500px;
|
|
34
|
+
gap: 22px;
|
|
35
|
+
padding: 4px 0;
|
|
36
|
+
max-height: 640px;
|
|
38
37
|
overflow-y: auto;
|
|
39
|
-
|
|
40
|
-
-
|
|
38
|
+
overscroll-behavior: contain;
|
|
39
|
+
scrollbar-width: thin;
|
|
40
|
+
scrollbar-color: hsl(from var(--text, #cdd6f4) h s l / 0.18) transparent;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
.chat-container::-webkit-scrollbar {
|
|
44
|
-
|
|
43
|
+
.chat-container::-webkit-scrollbar { width: 6px; }
|
|
44
|
+
.chat-container::-webkit-scrollbar-thumb {
|
|
45
|
+
background: hsl(from var(--text, #cdd6f4) h s l / 0.18);
|
|
46
|
+
border-radius: 3px;
|
|
45
47
|
}
|
|
48
|
+
.chat-container::-webkit-scrollbar-track { background: transparent; }
|
|
46
49
|
|
|
47
50
|
.chat-message {
|
|
48
|
-
display:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
display: grid;
|
|
52
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
53
|
+
grid-template-areas:
|
|
54
|
+
"avatar header"
|
|
55
|
+
"avatar bubble";
|
|
56
|
+
column-gap: 12px;
|
|
57
|
+
row-gap: 6px;
|
|
58
|
+
align-items: start;
|
|
51
59
|
}
|
|
52
60
|
|
|
53
61
|
.chat-message.is-me {
|
|
54
|
-
|
|
62
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
63
|
+
grid-template-areas:
|
|
64
|
+
"header avatar"
|
|
65
|
+
"bubble avatar";
|
|
55
66
|
}
|
|
56
67
|
|
|
57
|
-
.avatar
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
.avatar,
|
|
69
|
+
.avatar-placeholder {
|
|
70
|
+
grid-area: avatar;
|
|
71
|
+
width: 36px;
|
|
72
|
+
height: 36px;
|
|
60
73
|
border-radius: 50%;
|
|
61
|
-
|
|
62
|
-
flex-shrink: 0;
|
|
74
|
+
align-self: start;
|
|
63
75
|
}
|
|
64
76
|
|
|
77
|
+
.avatar { object-fit: cover; }
|
|
78
|
+
|
|
65
79
|
.avatar-placeholder {
|
|
66
|
-
width: 40px;
|
|
67
|
-
height: 40px;
|
|
68
|
-
border-radius: 50%;
|
|
69
80
|
display: flex;
|
|
70
81
|
align-items: center;
|
|
71
82
|
justify-content: center;
|
|
72
|
-
font-size:
|
|
83
|
+
font-size: 14px;
|
|
73
84
|
font-weight: 600;
|
|
74
85
|
color: var(--text, #cdd6f4);
|
|
75
|
-
flex-shrink: 0;
|
|
76
86
|
background: var(--surface1, #45475a);
|
|
77
87
|
}
|
|
78
88
|
|
|
79
|
-
.message-content {
|
|
80
|
-
display: flex;
|
|
81
|
-
flex-direction: column;
|
|
82
|
-
gap: 4px;
|
|
83
|
-
max-width: 70%;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.chat-message.is-me .message-content {
|
|
87
|
-
align-items: flex-end;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
89
|
.message-header {
|
|
90
|
+
grid-area: header;
|
|
91
91
|
display: flex;
|
|
92
|
-
align-items:
|
|
92
|
+
align-items: baseline;
|
|
93
93
|
gap: 8px;
|
|
94
|
+
padding: 2px 4px 0;
|
|
94
95
|
font-size: 12px;
|
|
96
|
+
line-height: 1;
|
|
97
|
+
min-width: 0;
|
|
95
98
|
}
|
|
96
99
|
|
|
97
100
|
.chat-message.is-me .message-header {
|
|
@@ -101,39 +104,114 @@ const CHAT_STYLES = `
|
|
|
101
104
|
.sender-name {
|
|
102
105
|
font-weight: 600;
|
|
103
106
|
color: var(--subtext1, #bac2de);
|
|
107
|
+
letter-spacing: 0.01em;
|
|
108
|
+
overflow: hidden;
|
|
109
|
+
text-overflow: ellipsis;
|
|
110
|
+
white-space: nowrap;
|
|
104
111
|
}
|
|
105
112
|
|
|
106
113
|
.timestamp {
|
|
107
114
|
color: var(--subtext0, #a6adc8);
|
|
108
115
|
font-size: 11px;
|
|
116
|
+
font-variant-numeric: tabular-nums;
|
|
117
|
+
white-space: nowrap;
|
|
109
118
|
}
|
|
110
119
|
|
|
111
120
|
.message-bubble {
|
|
121
|
+
grid-area: bubble;
|
|
122
|
+
max-width: min(620px, 100%);
|
|
123
|
+
justify-self: start;
|
|
112
124
|
padding: 10px 14px;
|
|
113
|
-
border-radius:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
125
|
+
border-radius: 14px;
|
|
126
|
+
border-top-left-radius: 4px;
|
|
127
|
+
background: var(--surface0, #313244);
|
|
128
|
+
color: inherit;
|
|
117
129
|
font-size: 14px;
|
|
118
|
-
|
|
130
|
+
line-height: 1.65;
|
|
131
|
+
overflow-wrap: anywhere;
|
|
132
|
+
word-break: break-word;
|
|
119
133
|
}
|
|
120
134
|
|
|
121
135
|
.chat-message.is-me .message-bubble {
|
|
136
|
+
justify-self: end;
|
|
122
137
|
background: var(--blue, #89b4fa);
|
|
123
138
|
color: var(--base, #1e1e2e);
|
|
139
|
+
border-radius: 14px;
|
|
140
|
+
border-top-right-radius: 4px;
|
|
124
141
|
}
|
|
125
142
|
|
|
143
|
+
.message-bubble > :first-child { margin-top: 0; }
|
|
144
|
+
.message-bubble > :last-child { margin-bottom: 0; }
|
|
145
|
+
|
|
146
|
+
.message-bubble p { margin: 0 0 8px; }
|
|
147
|
+
|
|
148
|
+
.message-bubble ul,
|
|
149
|
+
.message-bubble ol {
|
|
150
|
+
margin: 6px 0;
|
|
151
|
+
padding-left: 22px;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.message-bubble li { margin: 4px 0; }
|
|
155
|
+
.message-bubble li::marker { color: hsl(from currentColor h s l / 0.55); }
|
|
156
|
+
|
|
126
157
|
.message-bubble a {
|
|
127
158
|
color: var(--blue, #89b4fa);
|
|
128
159
|
text-decoration: underline;
|
|
160
|
+
text-underline-offset: 2px;
|
|
161
|
+
text-decoration-thickness: 1px;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.chat-message.is-me .message-bubble a {
|
|
165
|
+
color: inherit;
|
|
166
|
+
text-decoration-color: hsl(from currentColor h s l / 0.4);
|
|
129
167
|
}
|
|
130
168
|
|
|
131
169
|
.message-bubble code {
|
|
132
170
|
font-family: var(--font-mono, 'Maple Mono', 'Fira Code', monospace);
|
|
133
|
-
font-size:
|
|
134
|
-
|
|
135
|
-
padding: 2px 6px;
|
|
171
|
+
font-size: 0.875em;
|
|
172
|
+
padding: 1px 6px;
|
|
136
173
|
border-radius: 4px;
|
|
174
|
+
background: hsl(from var(--mantle, #181825) h s l / 0.55);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.chat-message.is-me .message-bubble code {
|
|
178
|
+
background: hsl(from var(--base, #1e1e2e) h s l / 0.18);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.message-bubble hr {
|
|
182
|
+
margin: 12px 0;
|
|
183
|
+
border: 0;
|
|
184
|
+
height: 1px;
|
|
185
|
+
background: hsl(from currentColor h s l / 0.12);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.message-bubble kbd {
|
|
189
|
+
display: inline-block;
|
|
190
|
+
padding: 1px 6px;
|
|
191
|
+
font-family: var(--font-mono, monospace);
|
|
192
|
+
font-size: 0.78em;
|
|
193
|
+
border: 1px solid hsl(from currentColor h s l / 0.3);
|
|
194
|
+
border-radius: 4px;
|
|
195
|
+
background: hsl(from currentColor h s l / 0.05);
|
|
196
|
+
vertical-align: baseline;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.message-bubble strong { font-weight: 600; }
|
|
200
|
+
|
|
201
|
+
.message-bubble .chat-heading {
|
|
202
|
+
display: block;
|
|
203
|
+
margin: 14px 0 6px;
|
|
204
|
+
font-size: 15px;
|
|
205
|
+
font-weight: 700;
|
|
206
|
+
letter-spacing: 0.01em;
|
|
207
|
+
line-height: 1.4;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.message-bubble .chat-heading:first-child { margin-top: 0; }
|
|
211
|
+
|
|
212
|
+
.message-bubble .chat-heading code {
|
|
213
|
+
font-size: 13px;
|
|
214
|
+
padding: 1px 5px;
|
|
137
215
|
}
|
|
138
216
|
|
|
139
217
|
.empty-state {
|
|
@@ -141,6 +219,49 @@ const CHAT_STYLES = `
|
|
|
141
219
|
padding: 40px 20px;
|
|
142
220
|
color: var(--subtext0, #a6adc8);
|
|
143
221
|
}
|
|
222
|
+
|
|
223
|
+
@media (max-width: 640px) {
|
|
224
|
+
.chat-container {
|
|
225
|
+
gap: 16px;
|
|
226
|
+
max-height: 75vh;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.chat-message {
|
|
230
|
+
grid-template-areas:
|
|
231
|
+
"avatar header"
|
|
232
|
+
"bubble bubble";
|
|
233
|
+
column-gap: 8px;
|
|
234
|
+
row-gap: 4px;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.chat-message.is-me {
|
|
238
|
+
grid-template-areas:
|
|
239
|
+
"header avatar"
|
|
240
|
+
"bubble bubble";
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.avatar,
|
|
244
|
+
.avatar-placeholder {
|
|
245
|
+
width: 26px;
|
|
246
|
+
height: 26px;
|
|
247
|
+
align-self: center;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.avatar-placeholder { font-size: 11px; }
|
|
251
|
+
|
|
252
|
+
.message-header {
|
|
253
|
+
align-items: center;
|
|
254
|
+
padding-top: 0;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.message-bubble,
|
|
258
|
+
.chat-message.is-me .message-bubble {
|
|
259
|
+
max-width: 100%;
|
|
260
|
+
justify-self: stretch;
|
|
261
|
+
border-radius: 12px;
|
|
262
|
+
padding: 9px 12px;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
144
265
|
`;
|
|
145
266
|
|
|
146
267
|
class Chat extends HTMLElement {
|
|
@@ -195,13 +316,11 @@ class Chat extends HTMLElement {
|
|
|
195
316
|
return `
|
|
196
317
|
<div class="chat-message ${msg.isMe ? "is-me" : ""}">
|
|
197
318
|
${avatarHTML}
|
|
198
|
-
<div class="message-
|
|
199
|
-
<
|
|
200
|
-
|
|
201
|
-
<span class="timestamp">${msg.timestamp}</span>
|
|
202
|
-
</div>
|
|
203
|
-
<div class="message-bubble">${msg.content}</div>
|
|
319
|
+
<div class="message-header">
|
|
320
|
+
<span class="sender-name">${msg.name}</span>
|
|
321
|
+
<span class="timestamp">${msg.timestamp}</span>
|
|
204
322
|
</div>
|
|
323
|
+
<div class="message-bubble">${msg.content}</div>
|
|
205
324
|
</div>
|
|
206
325
|
`;
|
|
207
326
|
}
|