hexo-theme-gnix 1.1.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.
Files changed (143) hide show
  1. package/README.md +106 -0
  2. package/include/hexo/filter/locals.js +109 -0
  3. package/include/hexo/generator/categories.js +12 -0
  4. package/include/hexo/generator/category.js +52 -0
  5. package/include/hexo/generator/insight.js +50 -0
  6. package/include/hexo/generator/manifest.js +23 -0
  7. package/include/hexo/generator/tags.js +12 -0
  8. package/include/hexo/helper/cdn.js +21 -0
  9. package/include/hexo/helper/page.js +27 -0
  10. package/include/hexo/view.js +40 -0
  11. package/include/register.js +11 -0
  12. package/include/util/common.js +33 -0
  13. package/languages/en.yml +47 -0
  14. package/languages/fr.yml +46 -0
  15. package/languages/ja.yml +46 -0
  16. package/languages/zh-CN.yml +47 -0
  17. package/languages/zh-TW.yml +47 -0
  18. package/layout/archive.jsx +118 -0
  19. package/layout/categories.jsx +137 -0
  20. package/layout/category.jsx +38 -0
  21. package/layout/comment/disqus.jsx +79 -0
  22. package/layout/comment/disqusjs.jsx +127 -0
  23. package/layout/comment/giscus.jsx +193 -0
  24. package/layout/comment/gitalk.jsx +141 -0
  25. package/layout/comment/twikoo.jsx +63 -0
  26. package/layout/comment/utterances.jsx +86 -0
  27. package/layout/comment/valine.jsx +143 -0
  28. package/layout/comment/waline.jsx +156 -0
  29. package/layout/common/article.jsx +131 -0
  30. package/layout/common/article_cover.jsx +33 -0
  31. package/layout/common/article_media.jsx +34 -0
  32. package/layout/common/comment.jsx +38 -0
  33. package/layout/common/footer.jsx +228 -0
  34. package/layout/common/head.jsx +242 -0
  35. package/layout/common/navbar.jsx +219 -0
  36. package/layout/common/plugins.jsx +39 -0
  37. package/layout/common/scripts.jsx +49 -0
  38. package/layout/common/search.jsx +22 -0
  39. package/layout/common/theme_selector.jsx +79 -0
  40. package/layout/common/toc.jsx +53 -0
  41. package/layout/index.jsx +29 -0
  42. package/layout/layout.jsx +34 -0
  43. package/layout/misc/article_licensing.jsx +114 -0
  44. package/layout/misc/meta.jsx +61 -0
  45. package/layout/misc/open_graph.jsx +164 -0
  46. package/layout/misc/paginator.jsx +90 -0
  47. package/layout/misc/structured_data.jsx +110 -0
  48. package/layout/misc/web_app.jsx +106 -0
  49. package/layout/page.jsx +12 -0
  50. package/layout/plugin/bing_webmaster.jsx +47 -0
  51. package/layout/plugin/busuanzi.jsx +40 -0
  52. package/layout/plugin/clarity.jsx +22 -0
  53. package/layout/plugin/cookie_consent.jsx +136 -0
  54. package/layout/plugin/google_analytics.jsx +66 -0
  55. package/layout/plugin/google_tag_mamager.jsx +41 -0
  56. package/layout/plugin/netlify.jsx +39 -0
  57. package/layout/plugin/pjax.jsx +20 -0
  58. package/layout/plugin/statcounter.jsx +69 -0
  59. package/layout/plugin/twitter_conversion_tracking.jsx +51 -0
  60. package/layout/post.jsx +16 -0
  61. package/layout/search/insight.jsx +53 -0
  62. package/layout/tag.jsx +29 -0
  63. package/layout/tags.jsx +55 -0
  64. package/package.json +42 -0
  65. package/scripts/index.js +1 -0
  66. package/source/css/callout_blocks.css +204 -0
  67. package/source/css/default.css +1590 -0
  68. package/source/css/font/woff2/Futura-Book.woff2 +0 -0
  69. package/source/css/font/woff2/Paris2024-Variable.woff2 +0 -0
  70. package/source/css/font/woff2/doto.woff2 +0 -0
  71. package/source/css/optional/chinese.css +17 -0
  72. package/source/css/responsive/desktop.css +164 -0
  73. package/source/css/responsive/mobile.css +46 -0
  74. package/source/css/responsive/tablet.css +46 -0
  75. package/source/css/responsive/touch.css +254 -0
  76. package/source/css/shiki/shiki.min.css +1 -0
  77. package/source/css/twikoo.css +2143 -0
  78. package/source/img/avatar.webp +0 -0
  79. package/source/img/background.webp +0 -0
  80. package/source/img/favicon.svg +6 -0
  81. package/source/img/logo.svg +9 -0
  82. package/source/img/og_image.png +0 -0
  83. package/source/js/busuanzi.js +46 -0
  84. package/source/js/host/cookieconsent/3.1.1/build/cookieconsent.min.css +6 -0
  85. package/source/js/host/cookieconsent/3.1.1/build/cookieconsent.min.js +1 -0
  86. package/source/js/host/iconify-icon/3.0.2/iconify-icon.min.js +12 -0
  87. package/source/js/host/medium-zoom/dist/medium-zoom.min.js +2 -0
  88. package/source/js/host/mermaid/mermaid.min.js +2811 -0
  89. package/source/js/host/pjax/0.2.8/pjax.min.js +1 -0
  90. package/source/js/host/twikoo/1.6.41/dist/twikoo.all.min.js +2 -0
  91. package/source/js/insight.js +330 -0
  92. package/source/js/instant-page.min.js +1 -0
  93. package/source/js/live2d_Asoul/Model/Ava/Ava.4096/texture_00.webp +0 -0
  94. package/source/js/live2d_Asoul/Model/Ava/Ava.moc3 +0 -0
  95. package/source/js/live2d_Asoul/Model/Ava/Ava.model3.json +323 -0
  96. package/source/js/live2d_Asoul/Model/Ava/Ava.physics3.json +1225 -0
  97. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_idle.motion3.json +1 -0
  98. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_shake01.motion3.json +1 -0
  99. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_shake02.motion3.json +1 -0
  100. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap01.motion3.json +1 -0
  101. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap02.motion3.json +1 -0
  102. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap03.motion3.json +1 -0
  103. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap04.motion3.json +1 -0
  104. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap05.motion3.json +1 -0
  105. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap06.motion3.json +1 -0
  106. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap07.motion3.json +1 -0
  107. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap08.motion3.json +1 -0
  108. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap09.motion3.json +1 -0
  109. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap10.motion3.json +1 -0
  110. package/source/js/live2d_Asoul/Model/Ava/motions/Ava_tap11.motion3.json +1 -0
  111. package/source/js/live2d_Asoul/Model/Ava/raw.ex.json +16 -0
  112. package/source/js/live2d_Asoul/Model/Ava/raw.model3.json +321 -0
  113. package/source/js/live2d_Asoul/Model/Diana/Diana.4096/texture_00.webp +0 -0
  114. package/source/js/live2d_Asoul/Model/Diana/Diana.moc3 +0 -0
  115. package/source/js/live2d_Asoul/Model/Diana/Diana.model3.json +212 -0
  116. package/source/js/live2d_Asoul/Model/Diana/Diana.physics3.json +764 -0
  117. package/source/js/live2d_Asoul/Model/Diana/motions/Diana_idle.motion3.json +1 -0
  118. package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap01.motion3.json +1 -0
  119. package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap02.motion3.json +1 -0
  120. package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap03.motion3.json +1 -0
  121. package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap04.motion3.json +1 -0
  122. package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap05.motion3.json +1 -0
  123. package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap06.motion3.json +1 -0
  124. package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap07.motion3.json +1 -0
  125. package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap08.motion3.json +1 -0
  126. package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap09.motion3.json +1 -0
  127. package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap10.motion3.json +1 -0
  128. package/source/js/live2d_Asoul/Model/Diana/motions/Diana_tap11.motion3.json +1 -0
  129. package/source/js/live2d_Asoul/Model/Diana/raw.ex.json +16 -0
  130. package/source/js/live2d_Asoul/Model/Diana/raw.model3.json +210 -0
  131. package/source/js/live2d_Asoul/TweenLite.js +12 -0
  132. package/source/js/live2d_Asoul/cubism4.min.js +2 -0
  133. package/source/js/live2d_Asoul/live2dcubismcore.min.js +9 -0
  134. package/source/js/live2d_Asoul/load.js +231 -0
  135. package/source/js/live2d_Asoul/pio.css +161 -0
  136. package/source/js/live2d_Asoul/pio.js +296 -0
  137. package/source/js/live2d_Asoul/pio_sdk4.js +149 -0
  138. package/source/js/live2d_Asoul/pixi.min.js +9 -0
  139. package/source/js/main.js +218 -0
  140. package/source/js/pjax.js +29 -0
  141. package/source/js/shiki/shiki.js +191 -0
  142. package/source/js/theme-selector.js +206 -0
  143. package/util/cache.js +47 -0
@@ -0,0 +1,330 @@
1
+ // biome-ignore lint/correctness/noUnusedVariables: Called in other files
2
+ function loadInsight(config, translation) {
3
+ const main = document.querySelector(".searchbox");
4
+ if (!main) return;
5
+
6
+ const input = main.querySelector(".searchbox-input");
7
+ const container = main.querySelector(".searchbox-body");
8
+
9
+ // 状态管理
10
+ let dataset = null; // 缓存 JSON 数据
11
+ let isLoading = false; // 加载锁
12
+ let searchTimer = null; // 防抖定时器
13
+
14
+ // 辅助:创建 DOM
15
+ function createElement(tag, className, text) {
16
+ const el = document.createElement(tag);
17
+ if (className) el.className = className;
18
+ if (text) el.textContent = text;
19
+ return el;
20
+ }
21
+
22
+ function section(title) {
23
+ const sectionEl = createElement("section", "searchbox-result-section");
24
+ const header = createElement("header", "", title);
25
+ sectionEl.appendChild(header);
26
+ return sectionEl;
27
+ }
28
+
29
+ // --- 核心逻辑优化区 ---
30
+
31
+ // 优化点:合并 ranges 的逻辑保持不变,这是高亮的核心算法
32
+ function merge(ranges) {
33
+ let last;
34
+ const result = [];
35
+ ranges.forEach((r) => {
36
+ if (!last || r[0] > last[1]) {
37
+ result.push((last = r));
38
+ } else if (r[1] > last[1]) {
39
+ last[1] = r[1];
40
+ }
41
+ });
42
+ return result;
43
+ }
44
+
45
+ function findAndHighlight(text, matches, maxlen) {
46
+ if (!Array.isArray(matches) || !matches.length || !text) {
47
+ return maxlen ? text.slice(0, maxlen) : text;
48
+ }
49
+ const testText = text.toLowerCase();
50
+
51
+ // 性能优化:直接搜索索引,不再 map 后 filter
52
+ const indices = [];
53
+ for (const match of matches) {
54
+ const index = testText.indexOf(match.toLowerCase());
55
+ if (match && index !== -1) {
56
+ indices.push([index, index + match.length]);
57
+ }
58
+ }
59
+
60
+ // 排序
61
+ indices.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
62
+
63
+ if (!indices.length) return maxlen ? text.slice(0, maxlen) : text;
64
+
65
+ let result = "";
66
+ let last = 0;
67
+ const ranges = merge(indices);
68
+ const sumRange = [ranges[0][0], ranges[ranges.length - 1][1]];
69
+
70
+ if (maxlen && maxlen < sumRange[1]) {
71
+ last = sumRange[0];
72
+ }
73
+
74
+ for (let i = 0; i < ranges.length; i++) {
75
+ const range = ranges[i];
76
+ result += text.slice(last, Math.min(range[0], sumRange[0] + maxlen));
77
+ if (maxlen && range[0] >= sumRange[0] + maxlen) break;
78
+
79
+ result += `<em>${text.slice(range[0], range[1])}</em>`;
80
+ last = range[1];
81
+
82
+ if (i === ranges.length - 1) {
83
+ if (maxlen) {
84
+ result += text.slice(range[1], Math.min(text.length, sumRange[0] + maxlen + 1));
85
+ } else {
86
+ result += text.slice(range[1]);
87
+ }
88
+ }
89
+ }
90
+ return result;
91
+ }
92
+
93
+ function searchItem(title, preview, url) {
94
+ title = title || translation.untitled;
95
+ return `<a class="searchbox-result-item" href="${url}">
96
+ <span class="searchbox-result-content">
97
+ <span class="searchbox-result-title">${title}</span>
98
+ ${preview ? `<span class="searchbox-result-preview">${preview}</span>` : ""}
99
+ </span>
100
+ </a>`;
101
+ }
102
+
103
+ function sectionFactory(keywords, type, array) {
104
+ if (array.length === 0) return null;
105
+ const sectionTitle = translation[type.toLowerCase()];
106
+
107
+ // 优化点:使用 DocumentFragment 并不完全适用这里因为我们返回的是 element
108
+ // 但我们可以用 map + join 一次性生成 HTML 字符串
109
+ const isPostOrPage = type === "POSTS" || type === "PAGES";
110
+
111
+ const itemsHTML = array.map(item => {
112
+ if (isPostOrPage) {
113
+ const title = findAndHighlight(item.title, keywords);
114
+ const text = findAndHighlight(item.text, keywords, 100);
115
+ return searchItem(title, text, item.link);
116
+ } else {
117
+ // Categories / Tags
118
+ const name = findAndHighlight(item.name, keywords);
119
+ return searchItem(name, null, item.link);
120
+ }
121
+ }).join("");
122
+
123
+ const sectionEl = section(sectionTitle);
124
+ sectionEl.insertAdjacentHTML("beforeend", itemsHTML);
125
+ return sectionEl;
126
+ }
127
+
128
+ function parseKeywords(keywords) {
129
+ return keywords.split(" ").filter((k) => !!k).map((k) => k.toLowerCase());
130
+ }
131
+
132
+ function search(json, keywordsStr) {
133
+ const keywords = parseKeywords(keywordsStr);
134
+ if (keywords.length === 0) return {};
135
+
136
+ // 把keywords中的特殊字符转义, 将转移后的关键词编译为正则表达式(忽略大小写,全局,多行)
137
+ // 后续在文章内容匹配时使用
138
+ const keywordRegexes = keywords.map(k => new RegExp(k.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), "img"));
139
+
140
+ const calculateWeight = (obj, fields, weights) => {
141
+ let value = 0;
142
+
143
+ // 检查所有关键词
144
+ for (let i = 0; i < keywords.length; i++) {
145
+ const keyword = keywords[i];
146
+ const regex = keywordRegexes[i];
147
+ let keywordInFields = false;
148
+
149
+ for (let j = 0; j < fields.length; j++) {
150
+ const field = fields[j];
151
+ if (!obj[field]) continue;
152
+
153
+ // 1. 快速检查:如果都不包含这个词,直接跳过正则
154
+ if (obj[field].toLowerCase().indexOf(keyword) === -1) continue;
155
+
156
+ // 2. 权重计算
157
+ const matches = obj[field].match(regex);
158
+ if (matches) {
159
+ value += matches.length * weights[j];
160
+ keywordInFields = true;
161
+ }
162
+ }
163
+
164
+ // 如果这个关键词在任何字段都没出现,那这个对象就不符合“包含所有关键词”的逻辑
165
+ // 原逻辑是 filter 必须包含所有关键词,这里保持一致
166
+ if (!keywordInFields) return 0;
167
+ }
168
+ return value;
169
+ };
170
+
171
+ // 通用搜索器
172
+ const executeSearch = (list, fields, weights) => {
173
+ const results = [];
174
+ for (const item of list) {
175
+ const w = calculateWeight(item, fields, weights);
176
+ if (w > 0) {
177
+ results.push({ item, weight: w });
178
+ }
179
+ }
180
+ // 排序并取 Top 5
181
+ return results
182
+ .sort((a, b) => b.weight - a.weight)
183
+ .map(r => r.item)
184
+ .slice(0, 5);
185
+ };
186
+
187
+ return {
188
+ posts: executeSearch(json.posts, ["title", "text"], [3, 1]),
189
+ pages: executeSearch(json.pages, ["title", "text"], [3, 1]),
190
+ categories: executeSearch(json.categories, ["name", "slug"], [1, 1]),
191
+ tags: executeSearch(json.tags, ["name", "slug"], [1, 1]),
192
+ };
193
+ }
194
+
195
+ function searchResultToDOM(keywords, searchResult) {
196
+ container.innerHTML = "";
197
+ const fragment = document.createDocumentFragment(); // 使用 Fragment 减少重排
198
+
199
+ for (const key in searchResult) {
200
+ const sectionNode = sectionFactory(
201
+ parseKeywords(keywords),
202
+ key.toUpperCase(),
203
+ searchResult[key]
204
+ );
205
+ if (sectionNode) {
206
+ fragment.appendChild(sectionNode);
207
+ }
208
+ }
209
+ container.appendChild(fragment);
210
+ }
211
+
212
+ function scrollTo(item) {
213
+ if (!item) return;
214
+ const wrapperHeight = container.clientHeight;
215
+ const itemTop = item.offsetTop;
216
+ const itemHeight = item.clientHeight;
217
+ const scrollTop = container.scrollTop;
218
+ if (itemTop + itemHeight > scrollTop + wrapperHeight) {
219
+ container.scrollTop = itemTop + itemHeight - wrapperHeight;
220
+ }
221
+ if (itemTop < scrollTop) {
222
+ container.scrollTop = itemTop;
223
+ }
224
+ }
225
+
226
+ function selectItemByDiff(value) {
227
+ const items = Array.from(container.querySelectorAll(".searchbox-result-item"));
228
+ if (items.length === 0) return;
229
+
230
+ // 查找 active 索引
231
+ const prevPosition = items.findIndex(item => item.classList.contains("active"));
232
+
233
+ const nextPosition = (items.length + prevPosition + value) % items.length;
234
+ const finalPosition = nextPosition < 0 ? nextPosition + items.length : nextPosition;
235
+
236
+ if (prevPosition !== -1) items[prevPosition].classList.remove("active");
237
+
238
+ const nextItem = items[finalPosition];
239
+ nextItem.classList.add("active");
240
+ scrollTo(nextItem);
241
+ }
242
+
243
+ // --- 数据加载与事件 ---
244
+
245
+ // 优化点:提取 Fetch 逻辑,支持 Lazy Load
246
+ function fetchData() {
247
+ if (dataset || isLoading) return;
248
+ isLoading = true;
249
+
250
+ fetch(config.contentUrl)
251
+ .then((response) => response.json())
252
+ .then((json) => {
253
+ dataset = json;
254
+ isLoading = false;
255
+ // 如果加载完之后输入框里有字,立即触发一次搜索
256
+ if (input.value.trim()) {
257
+ input.dispatchEvent(new Event("input"));
258
+ }
259
+ })
260
+ .catch((err) => {
261
+ console.error("Insight Search: Failed to load content.json", err);
262
+ isLoading = false;
263
+ });
264
+ }
265
+
266
+ // 监听输入
267
+ input.addEventListener("input", function () {
268
+ const keywords = this.value;
269
+
270
+ // 清除上一次的定时器
271
+ if (searchTimer) clearTimeout(searchTimer);
272
+
273
+ if (!dataset) {
274
+ fetchData(); // 兜底,防止万一没加载
275
+ return;
276
+ }
277
+
278
+ // 优化点:防抖 (Debounce) 300ms
279
+ searchTimer = setTimeout(() => {
280
+ searchResultToDOM(keywords, search(dataset, keywords));
281
+ }, 200);
282
+ });
283
+
284
+ main.addEventListener("focusout", (e) => {
285
+ if (main.contains(e.relatedTarget)) {
286
+ return;
287
+ }
288
+ // 当焦点移出 searchbox 时,关闭搜索框
289
+ main.classList.remove("show");
290
+ });
291
+
292
+ // 监听打开搜索框的点击事件
293
+ document.addEventListener("click", (e) => {
294
+ if (e.target.closest(".navbar-main .search")) {
295
+ main.classList.add("show");
296
+ const inp = main.querySelector(".searchbox-input");
297
+ if (inp) inp.focus();
298
+
299
+ // 优化点:Lazy Load - 打开时再请求数据
300
+ fetchData();
301
+ }
302
+ });
303
+
304
+
305
+ document.addEventListener("keydown", (e) => {
306
+ if (!main.classList.contains("show")) return;
307
+ switch (e.key) {
308
+ case "ArrowUp":
309
+ selectItemByDiff(-1);
310
+ break;
311
+ case "ArrowDown":
312
+ selectItemByDiff(1);
313
+ break;
314
+ case "Enter": {
315
+ const activeItem = container.querySelector(".searchbox-result-item.active");
316
+ if (activeItem) location.href = activeItem.getAttribute("href");
317
+ break;
318
+ }
319
+ }
320
+ });
321
+
322
+ document.addEventListener("touchstart", () => { touch = true; });
323
+ document.addEventListener("touchmove", () => { touch = false; });
324
+
325
+ // 处理 location.hash 自动打开的情况
326
+ if (location.hash.trim() === "#insight-search") {
327
+ main.classList.add("show");
328
+ fetchData();
329
+ }
330
+ }
@@ -0,0 +1 @@
1
+ /*! instant.page v5.2.0 - (C) 2019-2023 Alexandre Dieulot - https://instant.page/license */let t,e,n,o,i,a=null,s=65,c=new Set;const r=1111;function d(e){o=performance.now();const t=e.target.closest("a");m(t)&&p(t.href,"high")}function u(e){if(performance.now()-o<r)return;if(!("closest"in e.target))return;const t=e.target.closest("a");m(t)&&(t.addEventListener("mouseout",f,{passive:!0}),i=setTimeout(()=>{p(t.href,"high"),i=0[0]},s))}function l(e){const t=e.target.closest("a");m(t)&&p(t.href,"high")}function f(e){e.relatedTarget&&e.target.closest("a")==e.relatedTarget.closest("a")||i&&(clearTimeout(i),i=0[0])}function h(e){if(performance.now()-o<r)return;const t=e.target.closest("a");if(e.which>1||e.metaKey||e.ctrlKey)return;if(!t)return;t.addEventListener("click",function(e){1337!=e.detail&&e.preventDefault()},{capture:!0,passive:!1,once:!0});const n=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1,detail:1337});t.dispatchEvent(n)}function m(s){if(s&&s.href&&(!n||"instant"in s.dataset)){if(s.origin!=location.origin&&(!(e||"instant"in s.dataset)||!a))return;if(["http:","https:"].includes(s.protocol)&&("http:"!=s.protocol||"https:"!=location.protocol)&&(t||!s.search||"instant"in s.dataset)&&!(s.hash&&s.pathname+s.search==location.pathname+location.search||"noInstant"in s.dataset))return!0}}function p(e,t="auto"){if(c.has(e))return;const n=document.createElement("link");n.rel="prefetch",n.href=e,n.fetchPriority=t,n.as="document",document.head.appendChild(n),c.add(e)}!function(){if(!document.createElement("link").relList.supports("prefetch"))return;const v="instantVaryAccept"in document.body.dataset||"Shopify"in window,r=navigator.userAgent.indexOf("Chrome/");if(r>-1&&(a=parseInt(navigator.userAgent.substring(r+"Chrome/".length))),v&&a&&a<110)return;const c="instantMousedownShortcut"in document.body.dataset;t="instantAllowQueryString"in document.body.dataset,e="instantAllowExternalLinks"in document.body.dataset,n="instantWhitelist"in document.body.dataset;const o={capture:!0,passive:!0};let f=!1,g=!1,i=!1;if("instantIntensity"in document.body.dataset){const e=document.body.dataset.instantIntensity;if(e.startsWith("mousedown"))f=!0,"mousedown-only"==e&&(g=!0);else if(e.startsWith("viewport")){const t=navigator.connection&&navigator.connection.saveData,n=navigator.connection&&navigator.connection.effectiveType&&navigator.connection.effectiveType.includes("2g");t||n||("viewport"==e?document.documentElement.clientWidth*document.documentElement.clientHeight<45e4&&(i=!0):"viewport-all"==e&&(i=!0))}else{const t=parseInt(e);isNaN(t)||(s=t)}}if(g||document.addEventListener("touchstart",d,o),f?c||document.addEventListener("mousedown",l,o):document.addEventListener("mouseover",u,o),c&&document.addEventListener("mousedown",h,o),i){let e=window.requestIdleCallback;e||(e=e=>{e()}),e(function(){const e=new IntersectionObserver(t=>{t.forEach(t=>{if(t.isIntersecting){const n=t.target;e.unobserve(n),p(n.href)}})});document.querySelectorAll("a").forEach(t=>{m(t)&&e.observe(t)})},{timeout:1500})}}()
@@ -0,0 +1,323 @@
1
+ {
2
+ "Version": 3,
3
+ "Bounds": {
4
+ "Width": 9.772043,
5
+ "Height": 11.08606,
6
+ "CenterX": 0.1069689,
7
+ "CenterY": -1.404058
8
+ },
9
+ "FileReferences": {
10
+ "Moc": "Ava.moc3",
11
+ "Textures": [
12
+ "Ava.4096/texture_00.webp"
13
+ ],
14
+ "Physics": "Ava.physics3.json",
15
+ "PhysicsV2": {
16
+ "File": "Ava.physics3.json"
17
+ },
18
+ "Motions": {
19
+ "Idle": [{
20
+ "Name": "待机",
21
+ "File": "motions/Ava_idle.motion3.json"
22
+ }],
23
+ "Shake": [{
24
+ "Name": "晕",
25
+ "File": "motions/Ava_shake01.motion3.json",
26
+ "Text": "啊呜...",
27
+ "TextDuration": 2000
28
+ }, {
29
+ "File": "motions/Ava_shake02.motion3.json"
30
+ }],
31
+ "Tap左手": [{
32
+ "Name": "吉他",
33
+ "File": "motions/Ava_tap01.motion3.json",
34
+ "Text": "可爱的鸽子鸽子~我喜欢你~",
35
+ "TextDelay": 1200,
36
+ "TextDuration": 5600
37
+ }],
38
+ "Tap右手": [{
39
+ "Name": "游戏",
40
+ "File": "motions/Ava_tap02.motion3.json",
41
+ "Text": "来陪我玩游戏!",
42
+ "TextDelay": 600,
43
+ "TextDuration": 2500
44
+ }],
45
+ "Tap腰": [{
46
+ "Name": "傲娇",
47
+ "File": "motions/Ava_tap03.motion3.json",
48
+ "Text": "哼,才不是傲娇大小姐",
49
+ "TextDelay": 500,
50
+ "TextDuration": 3000
51
+ }],
52
+ "Tap中间刘海": [{
53
+ "Name": "害羞",
54
+ "File": "motions/Ava_tap04.motion3.json",
55
+ "Text": "好...好兄弟之间喜欢很正常啦",
56
+ "TextDelay": 1500,
57
+ "TextDuration": 3000
58
+ }, {
59
+ "Name": "害羞2",
60
+ "File": "motions/Ava_tap04.motion3.json",
61
+ "Text": "也...也不是不可以",
62
+ "TextDelay": 2000,
63
+ "TextDuration": 3000
64
+ }],
65
+ "Tap嘴": [{
66
+ "Name": "傲娇",
67
+ "File": "motions/Ava_tap03.motion3.json",
68
+ "Text": "什么傲娇啦,我才没有",
69
+ "TextDelay": 500,
70
+ "TextDuration": 2200
71
+ }],
72
+ "Tap胸口项链": [{
73
+ "Name": "笑",
74
+ "File": "motions/Ava_tap05.motion3.json"
75
+ }],
76
+ "Tap脖子": [{
77
+ "Name": "监督",
78
+ "File": "motions/Ava_tap06.motion3.json",
79
+ "Text": "嗯?老戳我干嘛,快去干正事啦 ",
80
+ "TextDelay": 550,
81
+ "TextDuration": 4000
82
+ }],
83
+ "Tap 右边头饰小花": [{
84
+ "Name": "懒羊羊",
85
+ "File": "motions/Ava_tap07.motion3.json",
86
+ "Text": "顶晚人...顶晚人在哪里...",
87
+ "TextDelay": 800,
88
+ "TextDuration": 6000
89
+ }],
90
+ "Tap右头饰": [{
91
+ "Name": "猫",
92
+ "File": "motions/Ava_tap08.motion3.json",
93
+ "Text": "neko panch!",
94
+ "TextDelay": 500,
95
+ "TextDuration": 2000
96
+ }],
97
+ "Tap右眼": [{
98
+ "Name": "惊讶",
99
+ "File": "motions/Ava_tap09.motion3.json",
100
+ "Text": "啊",
101
+ "TextDelay": 200,
102
+ "TextDuration": 1000
103
+ }],
104
+ "Tap左眼": [{
105
+ "Name": "墨镜",
106
+ "File": "motions/Ava_tap10.motion3.json",
107
+ "Text": "嗯哼~我超帅的",
108
+ "TextDelay": 700,
109
+ "TextDuration": 2000
110
+ }],
111
+ "Tap右马尾 ": [{
112
+ "Name": "水母",
113
+ "File": "motions/Ava_tap11.motion3.json"
114
+ }],
115
+ "Tap左马尾": [{
116
+ "Name": "><",
117
+ "File": "motions/Ava_shake02.motion3.json",
118
+ "Text": "头发摸乱了啦~",
119
+ "TextDelay": 500,
120
+ "TextDuration": 2000
121
+ }],
122
+ "Tap右手臂": [{
123
+ "File": "motions/Ava_tap06.motion3.json",
124
+ "Text": "嗯?老戳我干嘛,快去干正事啦 ",
125
+ "TextDelay": 550,
126
+ "TextDuration": 4000
127
+ }],
128
+ "Tap左中马尾": [{
129
+ "File": "motions/Ava_tap11.motion3.json"
130
+ }]
131
+ }
132
+ },
133
+ "Controllers": {
134
+ "ParamHit": {},
135
+ "ParamLoop": {},
136
+ "KeyTrigger": {},
137
+ "EyeBlink": {
138
+ "MinInterval": 500,
139
+ "MaxInterval": 6000,
140
+ "Items": [{
141
+ "Id": "ParamEyeLOpen",
142
+ "Min": 0.0,
143
+ "Max": 1.0,
144
+ "BlendMode": 2,
145
+ "Input": 0
146
+ }, {
147
+ "Id": "ParamEyeROpen",
148
+ "Min": 0.0,
149
+ "Max": 1.0,
150
+ "BlendMode": 2,
151
+ "Input": 0
152
+ }, {
153
+ "Id": "Param7",
154
+ "Min": 0.0,
155
+ "Max": 1.0,
156
+ "BlendMode": 2,
157
+ "Input": 0
158
+ }, {
159
+ "Id": "Param8",
160
+ "Min": 0.0,
161
+ "Max": 1.0,
162
+ "BlendMode": 2,
163
+ "Input": 0
164
+ }],
165
+ "Enabled": true
166
+ },
167
+ "LipSync": {
168
+ "Gain": 5.0
169
+ },
170
+ "MouseTracking": {
171
+ "SmoothTime": 0.15,
172
+ "Items": [{
173
+ "Id": "ParamAngleX",
174
+ "Min": -30.0,
175
+ "Max": 30.0,
176
+ "DefaultValue": 0.0,
177
+ "Weight": 0.359834284,
178
+ "BlendMode": 1,
179
+ "Input": 1
180
+ }, {
181
+ "Id": "ParamAngleY",
182
+ "Min": -30.0,
183
+ "Max": 30.0,
184
+ "DefaultValue": 0.0,
185
+ "Weight": 0.3398514,
186
+ "BlendMode": 1,
187
+ "Axis": 1,
188
+ "Input": 2
189
+ }, {
190
+ "Id": "ParamAngleZ",
191
+ "Min": -15.0,
192
+ "Max": 15.0,
193
+ "DefaultValue": 0.0,
194
+ "Weight": 0.199971348,
195
+ "BlendMode": 1,
196
+ "Axis": 2,
197
+ "Input": 1
198
+ }, {
199
+ "Id": "ParamBodyAngleX",
200
+ "Min": -10.0,
201
+ "Max": 10.0,
202
+ "DefaultValue": 0.0,
203
+ "Weight": 0.376962453,
204
+ "BlendMode": 1,
205
+ "Input": 1
206
+ }, {
207
+ "Id": "ParamBodyAngleZ",
208
+ "Min": -10.0,
209
+ "Max": 10.0,
210
+ "DefaultValue": 0.0,
211
+ "Weight": 0.365543664,
212
+ "BlendMode": 1,
213
+ "Axis": 2,
214
+ "Input": 1
215
+ }, {
216
+ "Id": "Param46",
217
+ "Min": -30.0,
218
+ "Max": 30.0,
219
+ "DefaultValue": 0.0,
220
+ "Weight": 0.411218822,
221
+ "BlendMode": 1,
222
+ "Axis": 1,
223
+ "Input": 2
224
+ }, {
225
+ "Id": "ParamEyeBallX",
226
+ "Min": -1.0,
227
+ "Max": 1.0,
228
+ "DefaultValue": 0.0,
229
+ "BlendMode": 1,
230
+ "Input": 1
231
+ }, {
232
+ "Id": "ParamEyeBallY",
233
+ "Min": -1.0,
234
+ "Max": 1.0,
235
+ "DefaultValue": 0.0,
236
+ "BlendMode": 1,
237
+ "Axis": 1,
238
+ "Input": 2
239
+ }],
240
+ "Enabled": true
241
+ },
242
+ "AutoBreath": {
243
+ "Enabled": true
244
+ },
245
+ "ExtraMotion": {
246
+ "Enabled": true
247
+ },
248
+ "Accelerometer": {
249
+ "Enabled": true
250
+ },
251
+ "Microphone": {},
252
+ "Transform": {},
253
+ "FaceTracking": {
254
+ "Enabled": true
255
+ },
256
+ "ParamValue": {},
257
+ "PartOpacity": {
258
+ "Items": [{
259
+ "Name": "猫耳",
260
+ "Ids": ["Part23", "weiba_Skinning"]
261
+ }, {
262
+ "Name": "墨镜",
263
+ "Ids": ["Part26"]
264
+ }],
265
+ "Enabled": true
266
+ },
267
+ "ArtmeshOpacity": {},
268
+ "ArtmeshColor": {},
269
+ "ArtmeshCulling": {
270
+ "DefaultMode": 0
271
+ },
272
+ "IntimacySystem": {}
273
+ },
274
+ "HitAreas": [{
275
+ "Name": "左手",
276
+ "Id": "ArtMesh2"
277
+ }, {
278
+ "Name": "右手",
279
+ "Id": "ArtMesh87"
280
+ }, {
281
+ "Name": "腰",
282
+ "Id": "yao"
283
+ }, {
284
+ "Name": "中间刘海",
285
+ "Id": "ArtMesh26"
286
+ }, {
287
+ "Name": "嘴",
288
+ "Id": "ArtMesh35"
289
+ }, {
290
+ "Name": "胸口项链",
291
+ "Id": "ArtMesh45"
292
+ }, {
293
+ "Name": "脖子",
294
+ "Id": "ArtMesh52"
295
+ }, {
296
+ "Name": " 右边头饰小花",
297
+ "Id": "hua2"
298
+ }, {
299
+ "Name": "右头饰",
300
+ "Id": "ArtMesh19"
301
+ }, {
302
+ "Name": "右眼",
303
+ "Id": "qiu"
304
+ }, {
305
+ "Name": "左眼",
306
+ "Id": "ArtMesh42"
307
+ }, {
308
+ "Name": "右马尾 ",
309
+ "Id": "R8"
310
+ }, {
311
+ "Name": "左马尾",
312
+ "Id": "L4"
313
+ }, {
314
+ "Name": "右手臂",
315
+ "Id": "ArtMesh48"
316
+ }, {
317
+ "Name": "左中马尾",
318
+ "Id": "L6"
319
+ }],
320
+ "Options": {
321
+ "TexFixed": true
322
+ }
323
+ }