blog.git

blog

~ Personal research notes. blog.sqzer.com
git clone https://github.com/debuman/blog.git

src/lib/hangul.ts (2161B)

      1 /** Jamo, compatibility jamo, extended jamo and the precomposed syllable block. */
      2 const HANGUL = /[\u1100-\u11FF\u3130-\u318F\uA960-\uA97F\uAC00-\uD7A3\uD7B0-\uD7FF]/;
      3 
      4 /** True when any of the strings would put a Hangul glyph on the page. */
      5 export const hasHangul = (...parts: (string | null | undefined)[]): boolean =>
      6   parts.some((s) => !!s && HANGUL.test(s));
      7 
      8 /**
      9  * `lang` for a single string, returned only when it differs from the document.
     10  * Re-declaring the document language on a child makes a screen reader switch voices
     11  * for no reason, so an agreeing value is dropped.
     12  */
     13 export const langOf = (s: string, doc: 'en' | 'ko'): 'en' | 'ko' | undefined => {
     14   const l: 'en' | 'ko' = HANGUL.test(s) ? 'ko' : 'en';
     15   return l === doc ? undefined : l;
     16 };
     17 
     18 const HANGUL_ALL = new RegExp(HANGUL.source, 'g');
     19 
     20 /**
     21  * The language a post is written in: the article's lang, and the baseline satteriLang
     22  * compares passages and headings against. Both call this on the same body, so they cannot
     23  * disagree.
     24  *
     25  * It follows the body, not the title, and is measured on prose only. The label drives
     26  * leading, line breaking and speech, so it has to describe what is read. Keying off the
     27  * title would mislabel the seven Korean posts with Latin titles, VTZero and journalctl
     28  * among them; counting Hangul against every non-space character would mislabel the Korean
     29  * technical posts, whose shell transcripts and URLs swamp the prose — measured that way
     30  * sysmon lands at 0.14 and journalctl at 0.29, both plainly Korean documents. With fences
     31  * and link targets dropped and Hangul weighed against Latin letters, the corpus splits with
     32  * nothing near the line: the two English essays sit at 0.25 and 0.28, and the other 28
     33  * posts all sit at 0.49 or above.
     34  */
     35 export function docLang(md: string): 'en' | 'ko' {
     36   // Linear on any input; see the note on LINK in prose.ts.
     37   const prose = md.replace(/```[\s\S]*?```/g, '').replace(/\[[^\][]*\]\((?:[^()]|\([^()]*\))*\)/g, '');
     38   const kor = (prose.match(HANGUL_ALL) ?? []).length;
     39   const lat = (prose.match(/[A-Za-z]/g) ?? []).length;
     40   return kor / Math.max(1, kor + lat) > 0.4 ? 'ko' : 'en';
     41 }