PageSourceSearch

https://www.hamienet.com/assets/bilingual-CBk-npe4.js

js hamienet.com collected 2026-10-02 05:01:09 UTC 8,764 bytes, 215 lines download raw bytes

1function detectScriptType(text) {
2  if (!text) return null;
3  if (/[가-힣\u1100-\u11FF\u3130-\u318F\uA960-\uA97F\uAC00-\uD7AF\uD7B0-\uD7FF]/.test(text)) return "ko";
4  if (/[ぁ-んァ-ヶー\u3040-\u309F\u30A0-\u30FF\u31F0-\u31FF\uFF65-\uFF9F]/.test(text)) return "ja";
5  if (/[ऀ-ॿ\u0900-\u097F]/.test(text)) return "hi";
6  if (/[؀-ۿ\u0600-\u06FF\u0750-\u077F]/.test(text)) return "ar";
7  if (/[Ѐ-ӿ\u0400-\u04FF]/.test(text)) return "ru";
8  if (/[ก-๛\u0E00-\u0E7F]/.test(text)) return "th";
9  if (/[Ͱ-Ͽ\u0370-\u03FF]/.test(text)) return "el";
10  if (/[֐-׿\u0590-\u05FF]/.test(text)) return "he";
11  if (/[一-龥\u4E00-\u9FFF\u3400-\u4DBF]/.test(text)) return "zh";
12  if (/[a-zA-Z]/.test(text)) return "latin";
13  return null;
14}
15function getScriptBadge(scriptType) {
16  switch (scriptType) {
17    case "ko":
18      return "KR";
19    case "ja":
20      return "JP";
21    case "zh":
22      return "CN";
23    case "hi":
24      return "IN";
25    case "ru":
26      return "RU";
27    case "ar":
28      return "AR";
29    case "th":
30      return "TH";
31    case "el":
32      return "GR";
33    case "he":
34      return "IL";
35    default:
36      return null;
37  }
38}
39function parseMultilingualData(rawStr) {
40  if (!rawStr) return null;
41  if (typeof rawStr === "object") return rawStr;
42  if (typeof rawStr === "string" && (rawStr.startsWith("{") || rawStr.startsWith("["))) {
43    try {
44      return JSON.parse(rawStr);
45    } catch {
46      return null;
47    }
48  }
49  return null;
50}
51function extractBilingualPairFromText(text) {
52  if (!text) return { title: text, native: null, romanized: null };
53  const parenMatch = text.match(/^(.+?)\s*\(([^)]+)\)\s*$/);
54  if (parenMatch) {
55    const part1 = parenMatch[1].trim();
56    const part2 = parenMatch[2].trim();
57    const isYear = /^\d{4}(?:[-–—/]\d{2,4})?$/.test(part2);
58    if (!isYear) {
59      const script1 = detectScriptType(part1);
60      const script2 = detectScriptType(part2);
61      if (script1 && script1 !== "latin" && script2 === "latin") {
62        return { title: part1, native: part1, romanized: part2 };
63      } else if (script1 === "latin" && script2 && script2 !== "latin") {
64        return { title: part1, native: part2, romanized: part1 };
65      }
66    }
67  }
68  const slashMatch = text.match(/^(.+?)\s*[/|•]\s*(.+)$/);
69  if (slashMatch) {
70    const part1 = slashMatch[1].trim();
71    const part2 = slashMatch[2].trim();
72    const script1 = detectScriptType(part1);
73    const script2 = detectScriptType(part2);
74    if (script1 && script1 !== "latin" && script2 === "latin") {
75      return { title: part2, native: part1, romanized: part2 };
76    } else if (script1 === "latin" && script2 && script2 !== "latin") {
77      return { title: part1, native: part2, romanized: part1 };
78    }
79  }
80  const script = detectScriptType(text);
81  if (script && script !== "latin") {
82    return { title: text, native: text, romanized: null };
83  }
84  return { title: text, native: null, romanized: text };
85}
86function getBilingualData(primaryTitle, rawSubtitleOrDetails, currentLang = "en") {
87  const lang = (currentLang || "en").toLowerCase();
88  const langPrefix = lang.split("-")[0];
89  const parsed = parseMultilingualData(rawSubtitleOrDetails);
90  const textPair = extractBilingualPairFromText(primaryTitle || "");
91  let titleDict = null;
92  let extraSubtitle = null;
93  if (parsed && typeof parsed === "object") {
94    if (parsed.title && typeof parsed.title === "object") {
95      titleDict = parsed.title;
96    } else if (parsed.translations && typeof parsed.translations === "object") {
97      titleDict = parsed.translations;
98    } else if (parsed.ja || parsed.ko || parsed.en || parsed["zh-CN"] || parsed.zh || parsed.hi || parsed.ru || parsed.fr || parsed.es || parsed.it || parsed.de) {
99      const pScript = detectScriptType(primaryTitle);
100      const isNonLatin = pScript && pScript !== "latin";
101      const normPrimary = (primaryTitle || "").toLowerCase().trim();
102      const matchesPrimary = Object.values(parsed).some((v) => typeof v === "string" && v.toLowerCase().trim() === normPrimary);
103      if (isNonLatin || matchesPrimary) {
104        titleDict = parsed;
105      } else {
106        extraSubtitle = parsed[lang] || parsed[langPrefix] || parsed.en || parsed.ja || null;
107      }
108    }
109    if (parsed.subtitle) {
110      if (typeof parsed.subtitle === "string") {
111        extraSubtitle = parsed.subtitle;
112      } else if (typeof parsed.subtitle === "object") {
113        extraSubtitle = parsed.subtitle[lang] || parsed.subtitle[langPrefix] || parsed.subtitle.en || null;
114      }
115    }
116  }
117  let nativeTitle = null;
118  let romanizedTitle = textPair.romanized;
119  let nativeScript = null;
120  const primaryScript = detectScriptType(primaryTitle);
121  if (primaryScript && primaryScript !== "latin") {
122    nativeScript = primaryScript;
123    nativeTitle = primaryTitle;
124  }
125  if (!nativeTitle && textPair.native) {
126    nativeTitle = textPair.native;
127    nativeScript = detectScriptType(textPair.native);
128  }
129  if (!nativeTitle && titleDict) {
130    const lowerTitle = (primaryTitle || "").toLowerCase();
131    const isKoreanOrigin = lowerTitle.includes("k-pop") || lowerTitle.includes("korean");
132    const isJapaneseOrigin = lowerTitle.includes("ghibli") || lowerTitle.includes("anime") || lowerTitle.includes("j-pop") || lowerTitle.includes("japanese") || lowerTitle.includes("vocaloid") || lowerTitle.includes("touhou");
133    const isChineseOrigin = lowerTitle.includes("c-pop") || lowerTitle.includes("mandopop") || lowerTitle.includes("cantopop") || lowerTitle.includes("chinese");
134    const isRussianOrigin = lowerTitle.includes("russian");
135    const isArabicOrigin = lowerTitle.includes("arabic");
136    if (isKoreanOrigin && titleDict.ko && detectScriptType(titleDict.ko) === "ko") {
137      nativeTitle = titleDict.ko;
138      nativeScript = "ko";
139    } else if (isJapaneseOrigin && titleDict.ja && detectScriptType(titleDict.ja) === "ja") {
140      nativeTitle = titleDict.ja;
141      nativeScript = "ja";
142    } else if (isChineseOrigin && (titleDict["zh-CN"] || titleDict["zh-TW"] || titleDict.zh)) {
143      nativeTitle = titleDict["zh-CN"] || titleDict["zh-TW"] || titleDict.zh || null;
144      nativeScript = "zh";
145    } else if (isRussianOrigin && titleDict.ru && detectScriptType(titleDict.ru) === "ru") {
146      nativeTitle = titleDict.ru;
147      nativeScript = "ru";
148    } else if (isArabicOrigin && titleDict.ar && detectScriptType(titleDict.ar) === "ar") {
149      nativeTitle = titleDict.ar;
150      nativeScript = "ar";
151    }
152  }
153  if (titleDict && titleDict.en) {
154    romanizedTitle = titleDict.en;
155  }
156  if (!romanizedTitle) {
157    if (textPair.romanized) romanizedTitle = textPair.romanized;
158    else if (detectScriptType(primaryTitle) === "latin") romanizedTitle = primaryTitle;
159  }
160  let mainTitle = primaryTitle || "";
161  let subTitle = null;
162  if (titleDict && (titleDict[lang] || titleDict[langPrefix])) {
163    mainTitle = titleDict[lang] || titleDict[langPrefix] || primaryTitle;
164    if (nativeTitle && mainTitle !== nativeTitle) {
165      subTitle = nativeTitle;
166    } else if (romanizedTitle && mainTitle !== romanizedTitle) {
167      subTitle = romanizedTitle;
168    } else if (extraSubtitle) {
169      subTitle = extraSubtitle;
170    }
171  } else if (nativeScript && (lang === nativeScript || langPrefix === nativeScript)) {
172    mainTitle = nativeTitle || primaryTitle;
173    subTitle = romanizedTitle && romanizedTitle !== mainTitle ? romanizedTitle : extraSubtitle;
174  } else {
175    mainTitle = romanizedTitle || primaryTitle;
176    if (nativeTitle && nativeTitle !== mainTitle) {
177      subTitle = nativeTitle;
178    } else if (extraSubtitle) {
179      subTitle = extraSubtitle;
180    } else if (typeof rawSubtitleOrDetails === "string" && !rawSubtitleOrDetails.trim().startsWith("{") && !rawSubtitleOrDetails.trim().startsWith("[")) {
181      subTitle = rawSubtitleOrDetails;
182    }
183  }
184  if (subTitle && typeof subTitle === "string" && (subTitle.trim().startsWith("{") || subTitle.trim().startsWith("["))) {
185    subTitle = null;
186  }
187  let hoverTooltip = mainTitle;
188  if (nativeTitle && nativeTitle !== mainTitle) {
189    hoverTooltip = `${nativeTitle} (${mainTitle})`;
190  } else if (romanizedTitle && romanizedTitle !== mainTitle) {
191    hoverTooltip = `${romanizedTitle} (${mainTitle})`;
192  }
193  let altText = mainTitle;
194  if (nativeTitle && nativeTitle !== mainTitle) {
195    altText = `${mainTitle} (${nativeTitle})`;
196  }
197  const nativeBadge = getScriptBadge(nativeScript);
198  return {
199    mainTitle,
200    subTitle,
201    nativeTitle,
202    romanizedTitle,
203    hoverTooltip,
204    altText,
205    nativeScriptType: nativeScript,
206    nativeBadge
207  };
208}
209function getBilingualTitle(primaryTitle, rawSubtitleOrDetails, currentLang = "en") {
210  return getBilingualData(primaryTitle, rawSubtitleOrDetails, currentLang);
211}
212export {
213  getBilingualTitle as g,
214  parseMultilingualData as p
215};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.