PageSourceSearch

https://seokbinyoon96.github.io/script/publications.js?v=bibtex-1

js seokbinyoon96.github.io collected 2026-10-03 08:15:05 UTC 3,569 bytes, 82 lines download raw bytes

1/* BibTeX -> the existing publication card data. No generated JSON to maintain. */
2(function (root) {
3  function text(value = "") {
4    return String(value)
5      .replace(/\\(?:textit|textbf|emph|textrm|textnormal)\s*\{([^{}]*)\}/g, "$1")
6      .replace(/\\([&%_#$])/g, "$1")
7      .replace(/\\(?:LaTeX|TeX)\b/g, (s) => s.slice(1))
8      .replace(/[{}]/g, "")
9      .replace(/\s+/g, " ").trim();
10  }
11
12  // Split only outside braces, so a braced organization name remains one author.
13  function splitAuthors(value) {
14    const result = [];
15    let depth = 0, start = 0;
16    for (let i = 0; i < value.length; i++) {
17      if (value[i] === "\\") { i++; continue; }
18      if (value[i] === "{") depth++;
19      if (value[i] === "}") depth--;
20      const separator = depth === 0 && value.slice(i).match(/^\s+and\s+/i);
21      if (separator) {
22        result.push(value.slice(start, i));
23        i += separator[0].length - 1;
24        start = i + 1;
25      }
26    }
27    result.push(value.slice(start));
28    return result.filter((name) => name.trim()).map((name) => {
29      const trimmed = name.trim();
30      if (trimmed.startsWith("{") && trimmed.endsWith("}")) return text(trimmed);
31      const parts = trimmed.split(",").map(text);
32      return parts.length === 1 ? parts[0]
33        : parts.length === 2 ? `${parts[1]} ${parts[0]}`
34        : `${parts[2]} ${parts[0]}, ${parts[1]}`;
35    });
36  }
37
38  function httpURL(value) {
39    try {
40      const url = new URL(value);
41      return ["https:", "http:"].includes(url.protocol) ? url.href : "";
42    } catch { return ""; }
43  }
44
45  function parse(source, authorProfiles = {}) {
46    const keys = new Set();
47    return root.bibtexParse.toJSON(source).filter((entry) => entry.entryTags).map((entry) => {
48      const f = Object.fromEntries(Object.entries(entry.entryTags).map(([k, v]) => [k.toLowerCase(), v]));
49      const id = entry.citationKey;
50      if (!id || keys.has(id)) throw new Error(`Missing or duplicate BibTeX key: ${id}`);
51      keys.add(id);
52      if (!f.title || !f.author || !/^\d{4}$/.test(text(f.year))) {
53        throw new Error(`${id}: title, author and a four-digit year are required`);
54      }
55      const doi = text(f.doi).replace(/^(?:https?:\/\/(?:dx\.)?doi\.org\/|doi:\s*)/i, "");
56      if (doi && !/^10\.\d{4,9}\/\S+$/i.test(doi)) throw new Error(`${id}: invalid DOI`);
57      const href = doi ? `https://doi.org/${doi}` : httpURL(text(f.url));
58      const venue = [text(f.journal || f.booktitle), text(f.volume), text(f.pages).replace(/--/g, "–")]
59        .filter(Boolean).join(", ");
60      return {
61        id, title: text(f.title), year: Number(text(f.year)), venue,
62        authors: splitAuthors(f.author).map((name) => {
63          const profile = Object.hasOwn(authorProfiles, name) ? authorProfiles[name] : {};
64          return { name, ...(profile.me ? { me: true } : {}),
65            ...(httpURL(profile.url) ? { url: httpURL(profile.url) } : {}) };
66        }),
67        image: text(f.image), category: text(f.category), summary: text(f.abstract),
68        notes: f.award ? text(f.award).split(/\s*;\s*/).filter(Boolean) : [],
69        links: href ? [{ label: doi ? "doi" : "paper", url: href }] : [],
70      };
71    });
72  }
73
74  async function load(path) {
75    const [bib, authors] = await Promise.all([
76      fetch(path, { cache: "no-cache" }), fetch("data/authors.json", { cache: "no-cache" }),
77    ]);
78    if (!bib.ok || !authors.ok) throw new Error("Could not load publication data");
79    return parse(await bib.text(), await authors.json());
80  }
81  root.PublicationData = { parse, load };
82})(globalThis);

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.