furifont 0.1.0 → 0.1.2

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 (54) hide show
  1. package/dist/cli.d.mts +1 -0
  2. package/dist/cli.mjs +53 -0
  3. package/dist/client/200.html +1 -0
  4. package/dist/client/404.html +1 -0
  5. package/dist/client/_nuxt/AmQakyTh.js +1 -0
  6. package/dist/client/_nuxt/BDNMzG2s.js +1 -0
  7. package/dist/client/_nuxt/Bc3GUY-S.js +3 -0
  8. package/dist/client/_nuxt/Bs3Pv9Qv.js +1 -0
  9. package/dist/client/_nuxt/C4NVi0HP.js +75 -0
  10. package/dist/client/_nuxt/CC4_XjFP.js +3 -0
  11. package/dist/client/_nuxt/CEWHii-_.js +3 -0
  12. package/dist/client/_nuxt/CEo6aVYN.js +1 -0
  13. package/dist/client/_nuxt/CQTZHv-y.js +1 -0
  14. package/dist/client/_nuxt/CRzLMJPS.js +1 -0
  15. package/dist/client/_nuxt/Cg7TlFyt.js +1 -0
  16. package/dist/client/_nuxt/DA1XwGcq.js +1 -0
  17. package/dist/client/_nuxt/DGhFAXuQ.js +1 -0
  18. package/dist/client/_nuxt/DLl_pn_F.js +58 -0
  19. package/dist/client/_nuxt/DSYkQlQa.js +1 -0
  20. package/dist/client/_nuxt/DT7XmrQw.js +132 -0
  21. package/dist/client/_nuxt/DTC_KzWZ.js +79 -0
  22. package/dist/client/_nuxt/DhRy_lmV.js +1 -0
  23. package/dist/client/_nuxt/DmOlRIb5.js +2 -0
  24. package/dist/client/_nuxt/DmlUWPPW.js +3 -0
  25. package/dist/client/_nuxt/Dz56DRZ7.js +59 -0
  26. package/dist/client/_nuxt/HB7Qu17x.js +1 -0
  27. package/dist/client/_nuxt/JRbXhaR6.js +1 -0
  28. package/dist/client/_nuxt/builds/latest.json +1 -0
  29. package/dist/client/_nuxt/builds/meta/1bd12827-b513-45af-9638-872afc8faff4.json +1 -0
  30. package/dist/client/_nuxt/entry.CsCxOCYm.css +1 -0
  31. package/dist/client/_nuxt/error-404.DqUWOYf4.css +1 -0
  32. package/dist/client/_nuxt/error-500.BYTKxx4O.css +1 -0
  33. package/dist/client/_nuxt/g9q6jbAq.js +1 -0
  34. package/dist/client/_nuxt/jjE7wdAL.js +1 -0
  35. package/dist/client/_nuxt/nNFr3PcB.js +2 -0
  36. package/dist/client/_nuxt/nQF5Cd64.js +3 -0
  37. package/dist/client/_nuxt/y07Wd5I9.js +1 -0
  38. package/dist/client/customize/index.html +1 -0
  39. package/dist/client/docs/index.html +1 -0
  40. package/dist/client/favicon.svg +4 -0
  41. package/dist/client/furifont.user.js +69 -0
  42. package/dist/client/index.html +1 -0
  43. package/dist/client/logo.svg +4 -0
  44. package/dist/client/og.png +0 -0
  45. package/dist/client/okurigana.json +5339 -0
  46. package/dist/client/reference/index.html +1 -0
  47. package/dist/client/version.json +1 -0
  48. package/dist/config-BgEXAgR6.mjs +181 -0
  49. package/dist/devframe.d.mts +5 -0
  50. package/dist/devframe.mjs +24 -0
  51. package/dist/index.d.mts +162 -0
  52. package/dist/index.mjs +4 -0
  53. package/dist/studio-DLNpk_rE.mjs +137 -0
  54. package/package.json +5 -5
@@ -0,0 +1,3 @@
1
+ import{C as e,Ct as t,D as n,E as r,Gt as i,Kt as a,M as o,P as s,Y as c,Z as l,_ as u,bt as d,et as f,j as p,lt as m,mt as h,o as g,ot as _,vt as v,w as y,wt as b}from"./DmlUWPPW.js";import{lt as x}from"./Cg7TlFyt.js";import{a as S,c as C,d as w,f as T,i as E,l as D,m as O,n as k,p as A,r as j,s as ee,u as M}from"./CEWHii-_.js";import{n as N,t as P}from"./g9q6jbAq.js";import{t as F}from"./BDNMzG2s.js";import{t as I}from"#entry";import{n as L,r as R,t as z}from"./AmQakyTh.js";import{a as B,i as V,n as H,o as U,r as te,s as ne,t as W}from"./C4NVi0HP.js";var G=Object.assign(s({__name:`UiTypeGrid`,props:{size:{}},setup(t){let r=e(()=>{let e=Math.round(P.baseline*t.size),n=n=>`${Math.round(e+(n-P.baseline)*t.size)}px`,r=e=>`transparent ${n(e)}, var(--ff-line) ${n(e)} calc(${n(e)} + 1px), transparent calc(${n(e)} + 1px)`,{emTop:i,emBottom:a}=P;return{backgroundImage:[`linear-gradient(${[i,a].map(r).join(`, `)})`,`linear-gradient(90deg, var(--ff-line) 1px, transparent 1px)`].join(`, `),backgroundSize:`100% ${t.size*N}px, ${t.size}px 100%`,backgroundPosition:`100vmax 100vmax`}});return(e,t)=>(l(),n(`div`,{"aria-hidden":`true`,class:`pointer-events-none absolute -inset-[100vmax] -z-1`,style:i(b(r))},null,4))}}),{__name:`UiTypeGrid`});function K(e){let t=new Map,n=/(?<!\p{sc=Han})\p{sc=Han}+(?=\p{sc=Hiragana})/gu,r=n=>{if(!t.has(n)){let r=new Map;for(let[t,i]of Object.entries(e.pairs[n]??{}))for(let e of i)r.set(e,t||null);t.set(n,r.size?{reading:r,longest:Math.max(...[...r.keys()].map(e=>e.length))}:void 0)}return t.get(n)},i=(t,n)=>{let r=t.length>[...t][0].length,i=(r?e.words[t]?.map(e=>[...e.matchAll(/\[([^\]]*)\]/g)].map(e=>e[1]).join(``)):e.readings[t])?.indexOf(n)??-1;return i>=+!!r&&i<15&&e.lone[t]!==n?i+1:0};return{find:e=>{let t=[];for(let{0:a,index:o}of e.matchAll(n)){let n=r(a),s=e.slice(o+a.length,o+a.length+(n?.longest??0)),c;for(let e=s.length;e>0&&c===void 0;e--)c=n?.reading.get(s.slice(0,e));let l=c?i(a,c):0;c&&l&&t.push({at:o,length:a.length,reading:c,salt:l})}return t},saltOf:i}}var q=new Map;function J(e,t){let n=q.get(e);return n||(n=(t?t(e):fetch(e).then(t=>t.ok?t.text():Promise.reject(Error(e)))).then(JSON.parse),n.catch(()=>q.delete(e)),q.set(e,n)),n}async function Y({readings:e,pairs:t,fetchText:n}){try{let[r,i]=await Promise.all([J(e,n),J(t,n)]);return r.salt===!0?K({pairs:i,readings:r.kanji,words:r.words,lone:r.lone}):void 0}catch{return}}function X(e){let n=g().app.baseURL,r=d();async function i(){let i=t(e),a=await Y({readings:`${n}${w(i,`ivs.json`)}`,pairs:`${n}okurigana.json`});i.stem===t(e).stem&&(r.value=a)}return c(i),_(()=>t(e).stem,i),{reader:r}}var Z={class:`grid lg:grid-cols-2`},re={class:`flex flex-col gap-8 border-base px-6 py-16 lg:border-r lg:py-24`},ie={class:`display hero-title font-semibold`},ae={class:`max-w-[46ch] text-[15px] leading-relaxed color-muted`},oe={class:`flex flex-wrap gap-3`},se={class:`relative isolate flex flex-col justify-center gap-4 overflow-hidden border-t border-base px-6 py-12 lg:border-t-0`},ce={class:`relative`},le={key:0,class:`label no-ruby absolute right-3 bottom-3 border border-base bg-base px-2 py-1`},ue={class:`label absolute bottom-4 left-4 border border-base bg-base px-2 py-1`},Q=44,de=Object.assign(s({__name:`DemoHero`,emits:[`download`],setup(t,{emit:i}){let s=i,c=v(U[0].text),u=e(()=>U.find(e=>e.text===c.value)?.author),{family:d,ruby:f,okurigana:g}=I(),{reader:_}=X(d);return(e,t)=>{let i=W,v=G,x=L;return l(),n(`div`,Z,[y(`div`,re,[t[4]||=y(`span`,{class:`label`},`振り仮名 / furigana`,-1),y(`h1`,ie,[p(a(e.$t(`hero.title1`)),1),t[3]||=y(`br`,null,null,-1),p(a(e.$t(`hero.title2`)),1)]),y(`p`,ae,a(e.$t(`hero.body`)),1),y(`div`,oe,[o(i,{variant:`solid`,icon:`i-ph-download-simple`,onClick:t[0]||=e=>s(`download`)},{default:m(()=>[p(a(e.$t(`hero.download`)),1)]),_:1}),o(i,{to:`/customize`,icon:`i-ph-sliders-horizontal`},{default:m(()=>[p(a(e.$t(`hero.build`)),1)]),_:1})])]),y(`div`,se,[o(i,{icon:`i-ph-shuffle`,class:`absolute right-3 top-3 w-9 bg-base px-0`,"aria-label":e.$t(`shuffle`),title:e.$t(`shuffle`),onClick:t[1]||=t=>c.value=(`otherSample`in e?e.otherSample:b(ne))(b(c)).text},null,8,[`aria-label`,`title`]),y(`div`,ce,[o(v,{size:Q}),o(x,{text:b(c),"onUpdate:text":t[2]||=e=>h(c)?c.value=e:null,family:b(d).family,ruby:b(f),size:Q,okurigana:b(g)?b(_):void 0},null,8,[`text`,`family`,`ruby`,`okurigana`])]),b(u)?(l(),n(`span`,le,`⁄ `+a(b(u)),1)):r(``,!0),y(`span`,ue,a(b(d).family)+` Regular / `+a(Q)+`px`,1)])])}}}),{__name:`DemoHero`}),fe={class:`grid lg:grid-cols-[340px_1fr]`},pe={class:`flex flex-col gap-5 border-b border-base p-6 lg:border-b-0 lg:border-r`},me={class:`flex flex-col gap-1.5`},he={class:`text-xs leading-relaxed color-muted`},ge={class:`flex min-w-0 flex-col`},_e={class:`min-h-72 flex-1 px-6 py-8`},ve={class:`flex items-center gap-3 border-t border-base px-6 py-3`},ye={class:`text-xs color-muted`},be=Object.assign(s({__name:`DemoPlayground`,setup(e){let t=v(`今日は日本語の勉強をします。
2
+ 明日は東京の大学へ行きます。
3
+ 私は毎朝新聞を読みます。桜が咲きました。`),{face:r,script:i,ruby:s,okurigana:c,family:u,faces:d,scripts:f}=I(),{reader:g}=X(u),_=v(30),x=v(400),{copied:C,copy:w}=R();return(e,v)=>{let T=V,D=B,O=te,k=H,A=L,j=W;return l(),n(`div`,fe,[y(`div`,pe,[o(D,{label:e.$t(`playground.script`)},{default:m(()=>[o(T,{modelValue:b(i),"onUpdate:modelValue":v[0]||=e=>h(i)?i.value=e:null,label:e.$t(`playground.script`),options:b(f)},null,8,[`modelValue`,`label`,`options`])]),_:1},8,[`label`]),o(D,{label:e.$t(`playground.face`)},{default:m(()=>[o(T,{modelValue:b(r),"onUpdate:modelValue":v[1]||=e=>h(r)?r.value=e:null,label:e.$t(`playground.face`),options:b(d)},null,8,[`modelValue`,`label`,`options`])]),_:1},8,[`label`]),o(D,{label:e.$t(`playground.size`,{size:b(_)})},{default:m(()=>[o(O,{modelValue:b(_),"onUpdate:modelValue":v[2]||=e=>h(_)?_.value=e:null,min:16,max:64},null,8,[`modelValue`])]),_:1},8,[`label`]),o(D,{label:e.$t(`playground.weight`,{weight:b(x)})},{default:m(()=>[o(O,{modelValue:b(x),"onUpdate:modelValue":v[3]||=e=>h(x)?x.value=e:null,min:`MIN_WEIGHT`in e?e.MIN_WEIGHT:b(S),max:`MAX_WEIGHT`in e?e.MAX_WEIGHT:b(E),step:10},null,8,[`modelValue`,`min`,`max`])]),_:1},8,[`label`]),o(k,{modelValue:b(s),"onUpdate:modelValue":v[4]||=e=>h(s)?s.value=e:null},{default:m(()=>[p(a(e.$t(`playground.ruby`)),1)]),_:1},8,[`modelValue`]),y(`div`,me,[o(k,{modelValue:b(c),"onUpdate:modelValue":v[5]||=e=>h(c)?c.value=e:null},{default:m(()=>[p(a(e.$t(`playground.okurigana`)),1)]),_:1},8,[`modelValue`]),y(`p`,he,a(e.$t(`playground.okuriganaHint`)),1)])]),y(`div`,ge,[y(`div`,_e,[o(A,{text:b(t),"onUpdate:text":v[6]||=e=>h(t)?t.value=e:null,family:b(u).family,ruby:b(s),size:b(_),weight:b(x),okurigana:b(c)?b(g):void 0},null,8,[`text`,`family`,`ruby`,`size`,`weight`,`okurigana`])]),y(`div`,ve,[y(`div`,ye,a(e.$t(`playground.textHint`)),1),v[8]||=y(`div`,{class:`flex-auto`},null,-1),o(j,{variant:`ghost`,icon:b(C)?`i-ph-check`:`i-ph-copy`,onClick:v[7]||=e=>b(w)(b(t))},{default:m(()=>[p(a(b(C)?e.$t(`copied`):e.$t(`playground.copy`)),1)]),_:1},8,[`icon`])])])])}}}),{__name:`DemoPlayground`}),xe={class:`overflow-hidden`},Se={class:`-mb-px -mr-px grid sm:grid-cols-2 lg:grid-cols-3`},Ce={class:`font-mono text-xs color-muted`},we={class:`text-base font-semibold tracking-tight`},Te={class:`text-sm leading-relaxed color-muted`},Ee=Object.assign(s({__name:`DemoHowItWorks`,setup(e){let t=[`build`,`ligatures`,`longest`,`bare`,`okurigana`];return(e,r)=>(l(),n(`div`,xe,[y(`ol`,Se,[(l(),n(u,null,f(t,(t,n)=>y(`li`,{key:t,class:`flex flex-col gap-3 border-b border-r border-base p-8`},[y(`span`,Ce,a(String(n+1).padStart(2,`0`)),1),y(`h3`,we,a(e.$t(`how.${t}.title`)),1),y(`p`,Te,a(e.$t(`how.${t}.body`)),1)])),64))])]))}}),{__name:`DemoHowItWorks`}),De={class:`grid sm:grid-cols-[1fr_2fr] overflow-hidden`},Oe={class:`flex flex-col gap-4 border-b border-base p-6 sm:border-b-0 sm:border-r`},ke={class:`text-sm leading-relaxed color-muted`},Ae={class:`grid grid-cols-2 lg:grid-cols-5 -mb-px -mr-px`},je={class:`label`},Me=[`onClick`],Ne=Object.assign(s({__name:`DemoSelectors`,setup(e){let t=e=>String.fromCodePoint(917984+e),r=[{label:`selectors.default`,text:`市場`,code:`市場`},{label:`selectors.reading2`,text:`市${t(2)}場`,code:`市\\u{E01E2}場`},{label:`selectors.default`,text:`今日`,code:`今日`},{label:`selectors.reading2`,text:`今${t(2)}日`,code:`今\\u{E01E2}日`},{label:`selectors.none`,text:`今${t(0)}日`,code:`今\\u{E01E0}日`}],{copied:i,copy:s}=R(),{family:c,ruby:d}=I();return(e,t)=>{let h=W,g=L;return l(),n(`div`,De,[y(`div`,Oe,[y(`p`,ke,a(e.$t(`selectors.body`)),1),o(h,{to:`/reference`,icon:`i-ph-list-magnifying-glass`,class:`self-start`},{default:m(()=>[p(a(e.$t(`selectors.lookUp`)),1)]),_:1})]),y(`ul`,Ae,[(l(),n(u,null,f(r,t=>y(`li`,{key:t.code,class:`flex flex-col gap-2 border-b border-r border-base p-4 last:border-r-0`},[o(g,{text:t.text,family:b(c).family,ruby:b(d),size:36},null,8,[`text`,`family`,`ruby`]),y(`span`,je,a(e.$t(t.label)),1),y(`button`,{type:`button`,class:`focus-ring self-start font-mono text-xs color-muted hover:color-base`,onClick:e=>b(s)(t.text)},a(b(i)===t.text?e.$t(`copied`):t.code),9,Me)])),64))])])}}}),{__name:`DemoSelectors`}),Pe={},Fe={class:`grid lg:grid-cols-[5fr_4fr]`},Ie={class:`w-full border-b border-base text-sm lg:border-b-0 lg:border-r`},Le={class:`border-b border-base text-left`},Re={class:`label px-6 py-3 font-normal`},ze={class:`label px-3 py-3 font-normal`},Be={class:`label px-3 py-3 font-normal`},Ve={class:`px-6 py-3 font-medium`},He={class:`px-3 py-3 color-muted`},Ue={class:`px-3 py-3`},We={class:`flex gap-3 font-mono text-xs`},Ge=[`href`],Ke={class:`flex gap-3 font-mono text-xs`},qe=[`href`],Je={class:`flex flex-col gap-4 p-6`},Ye={class:`text-sm color-muted`},Xe={class:`text-sm color-muted`};function Ze(e,t){let r=W;return l(),n(`div`,Fe,[y(`table`,Ie,[y(`thead`,null,[y(`tr`,Le,[y(`th`,Re,a(e.$t(`downloads.family`)),1),y(`th`,ze,a(e.$t(`downloads.ruby`)),1),y(`th`,Be,a(e.$t(`downloads.variable`)),1),(l(!0),n(u,null,f(`WEIGHTS`in e?e.WEIGHTS:b(M),e=>(l(),n(`th`,{key:e.style,class:`label px-3 py-3 font-normal`},a(e.style),1))),128))])]),y(`tbody`,null,[(l(!0),n(u,null,f(`FAMILIES`in e?e.FAMILIES:b(j),t=>(l(),n(`tr`,{key:t.stem,class:`border-b border-base last:border-b-0`},[y(`td`,Ve,a(t.family),1),y(`td`,He,a(e.$t(`scripts.${t.script}`)),1),y(`td`,Ue,[y(`span`,We,[(l(),n(u,null,f([`ttf`,`woff2`],n=>y(`a`,{key:n,href:(`releaseUrl`in e?e.releaseUrl:b(T))(`${t.stem}VF.${n}`),class:`focus-ring underline underline-offset-3 hover:color-muted`},a(n),9,Ge)),64))])]),(l(!0),n(u,null,f(`WEIGHTS`in e?e.WEIGHTS:b(M),r=>(l(),n(`td`,{key:r.style,class:`px-3 py-3`},[y(`span`,Ke,[(l(),n(u,null,f([`otf`,`woff2`],n=>y(`a`,{key:n,href:(`releaseUrl`in e?e.releaseUrl:b(T))(`${t.stem}-${r.style}.${n}`),class:`focus-ring underline underline-offset-3 hover:color-muted`},a(n),9,qe)),64))])]))),128))]))),128))])]),y(`div`,Je,[y(`p`,Ye,a(e.$t(`downloads.formats`)),1),o(r,{href:(`releaseUrl`in e?e.releaseUrl:b(T))(`Furifont.zip`),icon:`i-ph-download-simple`,class:`self-start`},{default:m(()=>[p(a(e.$t(`downloads.all`)),1)]),_:1},8,[`href`]),y(`p`,Xe,a(e.$t(`downloads.buildOwn`)),1),o(r,{to:`/customize`,icon:`i-ph-sliders-horizontal`,class:`self-start`},{default:m(()=>[p(a(e.$t(`nav.customize`)),1)]),_:1})])])}var Qe=Object.assign(F(Pe,[[`render`,Ze]]),{__name:`DemoDownloads`}),$e='var Furifont=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let t={fonts:[{family:`Furifont Sans`,base:`Source Han Sans JP`,face:`sans`,rubyScript:`hiragana`},{family:`Furifont Sans Romaji`,base:`Source Han Sans JP`,face:`sans`,rubyScript:`hepburn`},{family:`Furifont Serif`,base:`Source Han Serif JP`,face:`serif`,rubyScript:`hiragana`},{family:`Furifont Serif Romaji`,base:`Source Han Serif JP`,face:`serif`,rubyScript:`hepburn`}],weights:[{style:`Regular`,weight:400}],variable:{style:`VF`,weights:[250,900]},options:{}},n={base:12290,selector:65024},r=`U+2E80-2FDF,U+3000-30FF,U+3190-319F,U+31F0-31FF,U+3400-4DBF,U+4E00-9FFF,U+F900-FAFF,U+FE00-FE0F,U+FF00-FFEF,U+20000-3FFFF,U+E0100-E01EF`,i=/[\\p{sc=Han}\\p{sc=Hiragana}\\p{sc=Katakana}]/u;function a(e){return(e.match(/\\s*(?:"(?:[^"\\\\]|\\\\.)*"|\'(?:[^\'\\\\]|\\\\.)*\'|[^,]+)/g)??[]).map(e=>e.trim()).filter(Boolean)}function o(e){return e.replace(/^(["\'])(.*)\\1$/,`$2`)}let s=/mono|courier|consol|menlo|monaco|等幅/i;function c(e){let t=e.map(o);return t.some(e=>e===`monospace`||e===`ui-monospace`)||s.test(t[0]??``)}async function l({family:e,url:n,fetchFont:i}){let a=(t,n=`400`)=>new FontFace(e,t,{unicodeRange:r,weight:n}).load().catch(()=>void 0),o=await Promise.all(t.weights.map(({style:t,weight:n})=>a(`local("${e} ${t}")${n===400?`,local("${e}")`:``}`,String(n)))),s=t.variable.weights.join(` `),c=o.some(Boolean)?o:[await(i?i(n).then(e=>a(e,s),()=>void 0):a(`url("${n}")`,s))];for(let e of c)e&&document.fonts.add(e);return c.some(Boolean)}function u(e){let t=/* @__PURE__ */ new Map,n=/(?<!\\p{sc=Han})\\p{sc=Han}+(?=\\p{sc=Hiragana})/gu,r=n=>{if(!t.has(n)){let r=/* @__PURE__ */ new Map;for(let[t,i]of Object.entries(e.pairs[n]??{}))for(let e of i)r.set(e,t||null);t.set(n,r.size?{reading:r,longest:Math.max(...[...r.keys()].map(e=>e.length))}:void 0)}return t.get(n)},i=(t,n)=>{let r=t.length>[...t][0].length,i=(r?e.words[t]?.map(e=>[...e.matchAll(/\\[([^\\]]*)\\]/g)].map(e=>e[1]).join(``)):e.readings[t])?.indexOf(n)??-1;return i>=+!!r&&i<15&&e.lone[t]!==n?i+1:0};return{find:e=>{let t=[];for(let{0:a,index:o}of e.matchAll(n)){let n=r(a),s=e.slice(o+a.length,o+a.length+(n?.longest??0)),c;for(let e=s.length;e>0&&c===void 0;e--)c=n?.reading.get(s.slice(0,e));let l=c?i(a,c):0;c&&l&&t.push({at:o,length:a.length,reading:c,salt:l})}return t},saltOf:i}}let d=/* @__PURE__ */ new Map;function f(e,t){let n=d.get(e);return n||(n=(t?t(e):fetch(e).then(t=>t.ok?t.text():Promise.reject(Error(e)))).then(JSON.parse),n.catch(()=>d.delete(e)),d.set(e,n)),n}async function p({readings:e,pairs:t,fetchText:n}){try{let[r,i]=await Promise.all([f(e,n),f(t,n)]);return r.salt===!0?u({pairs:i,readings:r.kanji,words:r.words,lone:r.lone}):void 0}catch{return}}function m(e,t){return{href:new URL(`/#downloads`,e).href,text:t.download}}function h(e,t,n){document.querySelector(`furifont-toast`)?.remove();let r=document.createElement(`furifont-toast`),i=r.attachShadow({mode:`open`}),a=new CSSStyleSheet;a.replaceSync(`:host{all:initial}div{position:fixed;z-index:2147483647;right:16px;bottom:16px;display:flex;gap:16px;align-items:start;max-width:360px;padding:12px 16px;border:1px solid #fafafa2b;background:#0a0a0a;color:#fafafa;font:14px/1.5 system-ui,sans-serif}p{margin:0}a{color:inherit;margin-right:12px}button{padding:0;border:0;background:none;color:inherit;font:inherit;cursor:pointer}`),i.adoptedStyleSheets=[a];let o=document.createElement(`p`);o.append(e,` `,...t.map(({href:e,text:t})=>Object.assign(document.createElement(`a`),{href:e,target:`_blank`,rel:`noopener`,textContent:t})));let s=Object.assign(document.createElement(`button`),{ariaLabel:n,textContent:`×`,onclick:()=>r.remove()}),c=Object.assign(document.createElement(`div`),{role:`alert`});c.append(o,s),i.append(c),document.body.append(r),setTimeout(()=>r.remove(),1e4)}function g(e){let[t=0,n=0,r=0]=e.split(`.`).map(Number);return t*1e3+n*100+r}function _(e){let t=document.createElement(`canvas`).getContext(`2d`);return t.font=`1000px "${e}"`,Math.round(t.measureText(String.fromCodePoint(n.base,n.selector)).width)-2e3}async function v({family:e,url:t,toast:n},r){let i=new URL(`/version.json`,t).href,a;try{a=g(JSON.parse(await(r.fetchText?r.fetchText(i):fetch(i).then(e=>e.text()))).version)}catch{return}let o=[...g(r.version)<a?[r]:[],..._(e)<a?[m(t,n)]:[]];o.length&&h(n.outdated,o,n.close)}function y(e){let t=[];for(let n of e.filter(e=>e.isConnected)){let e=document.createTreeWalker(n,NodeFilter.SHOW_TEXT);for(let n=e.currentNode;n;n=e.nextNode())n.nodeType===Node.TEXT_NODE&&n.parentElement&&t.push(n)}return t}function b(e){let t=new Set(y(e).filter(e=>i.test(e.nodeValue??``)).map(e=>e.parentElement));for(let n of e){if(n.nodeType!==Node.ELEMENT_NODE)continue;let e=n;e.matches(`input,textarea`)&&t.add(e);for(let n of e.querySelectorAll(`input,textarea`))t.add(n)}return t}function x(e){let t=new CSSStyleSheet,n=[],r,i=0,s=()=>{for(let e of document.querySelectorAll(`[data-furifont-reading]`)){let t=r?r.saltOf(e.textContent??``,e.dataset.furifontReading):0;t?e.dataset.furifontSalt=String(t):delete e.dataset.furifontSalt}},l=e=>{if(!r)return;let t=y(e).filter(e=>/\\p{sc=Han}\\p{sc=Hiragana}/u.test(e.nodeValue??``)&&!e.parentElement.closest(`script,style,textarea,noscript,[contenteditable]:not([contenteditable=false]),[data-furifont-reading]`));for(let e of t)for(let{at:t,length:n,reading:i,salt:a}of r.find(e.nodeValue??``).reverse()){let r=t?e.splitText(t):e;r.length>n&&r.splitText(n);let o=document.createElement(`span`);o.dataset.furifontReading=i,o.dataset.furifontSalt=String(a),r.replaceWith(o),o.append(r)}},u={dispose:()=>{},sheet:t,family:e,restyle:()=>{let e=Array.from({length:15},(e,t)=>`[data-furifont-salt="${t+1}"]{font-feature-settings:"salt" ${t+1}!important}`).join(``),r=n.map((e,t)=>`[data-furifont="${t}"]{font-family:"${u.family}",${e}!important}`).join(``);t.replaceSync(`${r}[data-furifont-tight]{line-height:normal!important}${e}`)},okurigana:e=>{let n=++i;r=void 0,s(),e&&!t.disabled&&p(e).then(e=>{n===i&&e&&(r=e,s(),l([document.body]))})}},d=e=>{let t=[...b(e)].filter(e=>!e.hasAttribute(`data-furifont`)).map(e=>{let{fontFamily:t,lineHeight:n,fontSize:r}=getComputedStyle(e),i=a(t);return o(i[0]??``)===u.family&&i.shift(),{element:e,stack:i,tight:Number.parseFloat(n)<1.6*Number.parseFloat(r)}}).filter(({stack:e})=>e.length&&!c(e)),r=n.length;for(let{element:e,stack:r,tight:i}of t){let t=r.join(`,`),a=n.includes(t)?n.indexOf(t):n.push(t)-1;e.setAttribute(`data-furifont`,String(a)),i&&e.setAttribute(`data-furifont-tight`,``)}n.length>r&&u.restyle()},f=new MutationObserver(e=>{let t=e.flatMap(e=>e.type===`characterData`?[e.target]:[...e.addedNodes]);d(t),l(t)});return u.dispose=()=>{f.disconnect(),i++,r=void 0,document.adoptedStyleSheets=document.adoptedStyleSheets.filter(e=>e!==t);for(let e of document.querySelectorAll(`[data-furifont],[data-furifont-tight]`))e.removeAttribute(`data-furifont`),e.removeAttribute(`data-furifont-tight`);for(let e of document.querySelectorAll(`[data-furifont-reading]`))e.replaceWith(...e.childNodes);window.furifont===u&&delete window.furifont},window.furifont=u,document.adoptedStyleSheets=[...document.adoptedStyleSheets,t],d([document.body]),f.observe(document.body,{childList:!0,characterData:!0,subtree:!0}),u}async function S(e){let{family:t,url:n,toast:r,okurigana:i,update:a}=e,o=window.furifont;o?.family===t?(o.sheet.disabled=!o.sheet.disabled,o.sheet.disabled||o.okurigana(i)):(o??=x(t),o.family=t,o.restyle(),o.sheet.disabled=!1,await l(e)?(o.okurigana(i),a&&await v(e,a)):(o.sheet.disabled=!0,o.family=``,h(r.message,[m(n,r)],r.close)))}return e.JAPANESE=i,e.UNICODE_RANGE=r,e.createOkuriganaReader=u,e.isMonospace=c,e.loadFurifont=l,e.loadOkuriganaReader=p,e.parseFontStack=a,e.showToast=h,e.toggleFurifont=S,e})({});',et={class:`grid lg:grid-cols-[340px_1fr]`},tt={class:`flex flex-col gap-5 border-b border-base p-6 lg:border-b-0 lg:border-r`},$={class:`text-sm leading-relaxed color-muted`},nt={class:`flex flex-col gap-1.5`},rt={class:`text-xs leading-relaxed color-muted`},it={class:`grid sm:grid-cols-2`},at={class:`flex flex-col gap-3 border-b border-base p-6 sm:border-b-0 sm:border-r`},ot={class:`label`},st=[`href`],ct={class:`text-sm leading-relaxed color-muted`},lt={class:`flex flex-col gap-3 p-6`},ut={class:`label`},dt={class:`text-sm leading-relaxed color-muted`},ft=Object.assign(s({__name:`DemoAnyPage`,setup(t){let{t:r}=k(),{face:i,script:s,okurigana:c,family:u,faces:d,scripts:f}=I(),_=e(()=>{let e={family:u.value.family,url:A(u.value),toast:{message:r(`anyPage.toast.message`),download:r(`anyPage.toast.download`),close:r(`anyPage.toast.close`),outdated:r(`anyPage.toast.outdated`)},okurigana:c.value?{readings:O(u.value),pairs:C}:void 0,update:{version:D,href:`${ee}/#any-page`,text:r(`anyPage.toast.bookmarklet`)}};return`javascript:${encodeURIComponent(`void (()=>{${$e};Furifont.toggleFurifont(${JSON.stringify(e)})})()`)}`}),v=`${g().app.baseURL}furifont.user.js`;return(e,t)=>{let r=V,g=B,x=H,S=W;return l(),n(`div`,et,[y(`div`,tt,[y(`p`,$,a(e.$t(`anyPage.body`)),1),o(g,{label:e.$t(`playground.script`)},{default:m(()=>[o(r,{modelValue:b(s),"onUpdate:modelValue":t[0]||=e=>h(s)?s.value=e:null,label:e.$t(`playground.script`),options:b(f)},null,8,[`modelValue`,`label`,`options`])]),_:1},8,[`label`]),o(g,{label:e.$t(`playground.face`)},{default:m(()=>[o(r,{modelValue:b(i),"onUpdate:modelValue":t[1]||=e=>h(i)?i.value=e:null,label:e.$t(`playground.face`),options:b(d)},null,8,[`modelValue`,`label`,`options`])]),_:1},8,[`label`]),y(`div`,nt,[o(x,{modelValue:b(c),"onUpdate:modelValue":t[2]||=e=>h(c)?c.value=e:null},{default:m(()=>[p(a(e.$t(`anyPage.okurigana`)),1)]),_:1},8,[`modelValue`]),y(`p`,rt,a(e.$t(`anyPage.okuriganaHint`)),1)])]),y(`div`,it,[y(`div`,at,[y(`span`,ot,a(e.$t(`anyPage.bookmarklet`)),1),y(`a`,{href:b(_),class:`btn-solid focus-ring self-start`},[t[3]||=y(`span`,{class:`i-ph-bookmark-simple`},null,-1),p(` `+a(b(u).family),1)],8,st),y(`p`,ct,a(e.$t(`anyPage.bookmarkletHint`)),1)]),y(`div`,lt,[y(`span`,ut,a(e.$t(`anyPage.userscript`)),1),o(S,{href:v,icon:`i-ph-puzzle-piece`,class:`self-start`},{default:m(()=>[p(a(e.$t(`anyPage.install`)),1)]),_:1}),y(`p`,dt,a(e.$t(`anyPage.userscriptHint`)),1)])])])}}}),{__name:`DemoAnyPage`}),pt={class:`flex items-center gap-2 border-t border-base px-6 py-3 text-center text-xs color-muted bg-amber:5`},mt=s({__name:`index`,setup(e){function t(){document.getElementById(`downloads`)?.scrollIntoView({behavior:`smooth`})}let r=x();return c(()=>{r.hash&&document.getElementById(r.hash.slice(1))?.scrollIntoView({behavior:`smooth`})}),(e,r)=>{let i=de,s=be,c=z,u=Ee,d=Ne,f=Qe,h=ft;return l(),n(`div`,null,[o(i,{onDownload:t}),o(c,{index:`01`,title:e.$t(`sections.try`)},{default:m(()=>[o(s)]),_:1},8,[`title`]),o(c,{index:`02`,title:e.$t(`sections.how`)},{default:m(()=>[o(u)]),_:1},8,[`title`]),o(c,{index:`03`,title:e.$t(`sections.selectors`)},{default:m(()=>[o(d)]),_:1},8,[`title`]),y(`p`,pt,[r[0]||=y(`span`,{class:`i-ph-warning shrink-0 text-base text-amber`,"aria-hidden":`true`},null,-1),p(` `+a(e.$t(`notice`)),1)]),o(c,{id:`downloads`,index:`04`,title:e.$t(`sections.download`)},{default:m(()=>[o(f)]),_:1},8,[`title`]),o(c,{id:`any-page`,index:`05`,title:e.$t(`sections.anyPage`)},{default:m(()=>[o(h)]),_:1},8,[`title`])])}}});export{mt as default};
@@ -0,0 +1 @@
1
+ function e(e,...t){return typeof e==`function`?e(...t):e}var t=Error.captureStackTrace,n=class e extends Error{name;code;docs;fix;sources;data;get why(){return this.message}constructor(n,r=e){super(n.why,{cause:n.cause}),this.code=this.name=n.code,this.fix=n.fix,this.docs=n.docs,this.sources=n.sources,this.data=n.data,t?.(this,r)}toJSON(){return{name:this.name,why:this.why,fix:this.fix,docs:this.docs,sources:this.sources,cause:this.cause,data:this.data,stack:this.stack}}};function r(e,t){return typeof e==`string`?`${e}/${t.toLowerCase()}`:e?.(t)}function i(t){let i=t.reporters??[],a={},{docsBase:o}=t;for(let s of Object.keys(t.codes)){let c=t.codes[s],l=c.docs===!1?void 0:c.docs||r(o,s),u=(t={},r={})=>{let a=new n({code:s,why:e(c.why,t),fix:e(c.fix,t),docs:l,cause:t.cause,sources:t.sources,data:e(c.data,t)},u);for(let e of i)e(a,r);return a};a[s]=u}return a}function a(e={}){let{docsBase:t,reporters:i=[]}=e;return new Proxy({},{get(e,a){if(typeof a!=`string`)return;let o=(e={},s={})=>{let c=r(t,a),l=new n({code:a,why:c??``,docs:c,cause:e.cause,sources:e.sources},o);for(let e of i)e(l,s);return l};return o}})}export{a as n,i as t};
@@ -0,0 +1 @@
1
+ <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Furifont: furigana built into the font</title><script type="importmap">{"imports":{"#entry":"/_nuxt/CC4_XjFP.js"}}</script><link rel="stylesheet" href="/_nuxt/entry.CsCxOCYm.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/_nuxt/CC4_XjFP.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/y07Wd5I9.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/DmlUWPPW.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/DmOlRIb5.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/Cg7TlFyt.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/CRzLMJPS.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/CEWHii-_.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/BDNMzG2s.js"><script type="module" src="/_nuxt/CC4_XjFP.js" crossorigin></script><link rel="prefetch" as="script" crossorigin href="/_nuxt/DLl_pn_F.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/Dz56DRZ7.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/DT7XmrQw.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/jjE7wdAL.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/Bs3Pv9Qv.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/DA1XwGcq.js"><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-404.DqUWOYf4.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/CEo6aVYN.js"><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-500.BYTKxx4O.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/DhRy_lmV.js"><meta name="description" content="A Japanese font that shows furigana by itself."><meta property="og:type" content="website"><meta property="og:url" content="https://furifont.antfu.me"><meta property="og:title" content="Furifont: furigana built into the font"><meta property="og:description" content="A Japanese font that shows furigana by itself."><meta property="og:image" content="https://furifont.antfu.me/og.png"><meta property="og:image:width" content="2400"><meta property="og:image:height" content="1260"><meta property="og:image:alt" content="Furifont: furigana built into the font"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Furifont: furigana built into the font"><meta name="twitter:description" content="A Japanese font that shows furigana by itself."><meta name="twitter:image" content="https://furifont.antfu.me/og.png"><link rel="icon" type="image/svg+xml" href="favicon.svg"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{devCustomizeBase:"/__furifont/"},app:{baseURL:"/",buildId:"1bd12827-b513-45af-9638-872afc8faff4",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1792041185168,false]</script></body></html>
@@ -0,0 +1 @@
1
+ <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Furifont: furigana built into the font</title><script type="importmap">{"imports":{"#entry":"/_nuxt/CC4_XjFP.js"}}</script><link rel="stylesheet" href="/_nuxt/entry.CsCxOCYm.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/_nuxt/CC4_XjFP.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/y07Wd5I9.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/DmlUWPPW.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/DmOlRIb5.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/Cg7TlFyt.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/CRzLMJPS.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/CEWHii-_.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/BDNMzG2s.js"><script type="module" src="/_nuxt/CC4_XjFP.js" crossorigin></script><link rel="prefetch" as="script" crossorigin href="/_nuxt/DLl_pn_F.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/Dz56DRZ7.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/DT7XmrQw.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/jjE7wdAL.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/Bs3Pv9Qv.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/DA1XwGcq.js"><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-404.DqUWOYf4.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/CEo6aVYN.js"><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-500.BYTKxx4O.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/DhRy_lmV.js"><meta name="description" content="A Japanese font that shows furigana by itself."><meta property="og:type" content="website"><meta property="og:url" content="https://furifont.antfu.me"><meta property="og:title" content="Furifont: furigana built into the font"><meta property="og:description" content="A Japanese font that shows furigana by itself."><meta property="og:image" content="https://furifont.antfu.me/og.png"><meta property="og:image:width" content="2400"><meta property="og:image:height" content="1260"><meta property="og:image:alt" content="Furifont: furigana built into the font"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Furifont: furigana built into the font"><meta name="twitter:description" content="A Japanese font that shows furigana by itself."><meta name="twitter:image" content="https://furifont.antfu.me/og.png"><link rel="icon" type="image/svg+xml" href="favicon.svg"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{devCustomizeBase:"/__furifont/"},app:{baseURL:"/",buildId:"1bd12827-b513-45af-9638-872afc8faff4",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1792041185169,false]</script></body></html>
@@ -0,0 +1,4 @@
1
+ <svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <rect width="200" height="200" fill="black"/>
3
+ <path d="M100.475 116.282C101.89 115.363 103.269 114.408 104.613 113.417C105.957 112.356 107.018 111.508 107.796 110.871C106.31 109.598 104.294 108.218 101.748 106.733C99.2016 105.248 96.4784 103.762 93.5783 102.277C90.6782 100.791 87.8842 99.5182 85.1963 98.4572L90.0769 92.3034C92.7648 93.4351 95.7357 94.8144 98.9894 96.4413C102.243 97.9975 105.391 99.6243 108.432 101.322C111.545 103.02 114.162 104.646 116.284 106.203L118.194 111.72C117.628 112.215 116.814 112.887 115.753 113.736C114.763 114.514 113.667 115.363 112.464 116.282C111.332 117.131 110.165 118.015 108.963 118.935C107.831 119.783 106.77 120.562 105.78 121.269L100.475 116.282ZM79.9974 166.998C82.6853 167.706 85.3731 168.272 88.061 168.696C90.7489 169.12 93.7551 169.333 97.0796 169.333C98.7065 169.333 100.333 169.085 101.96 168.59C103.658 168.095 105.037 167.211 106.098 165.937C107.23 164.593 107.796 162.79 107.796 160.526C107.796 158.687 107.371 156.777 106.523 154.797C105.674 152.745 104.577 150.694 103.233 148.643C101.89 146.592 100.404 144.611 98.7772 142.701C97.2211 140.721 95.7003 138.917 94.2149 137.29C93.0831 136.017 91.7746 134.673 90.2891 133.258C88.8037 131.844 87.283 130.535 85.7268 129.333L91.9868 123.815C93.3307 125.159 94.6393 126.539 95.9125 127.953C97.2564 129.297 98.565 130.677 99.8382 132.091C103.163 135.486 106.098 138.846 108.645 142.171C111.191 145.425 113.172 148.643 114.586 151.826C116.001 155.009 116.708 158.227 116.708 161.481C116.708 164.664 116.107 167.317 114.905 169.439C113.773 171.561 112.287 173.188 110.448 174.319C108.609 175.451 106.629 176.229 104.507 176.654C102.385 177.149 100.369 177.396 98.4589 177.396C95.1344 177.396 92.0221 177.219 89.122 176.866C86.2219 176.583 83.5694 176.194 81.1645 175.699L79.9974 166.998ZM141.218 170.924C140.439 168.378 139.414 165.619 138.141 162.648C136.938 159.607 135.523 156.565 133.897 153.524C132.34 150.411 130.678 147.476 128.91 144.717C127.142 141.888 125.338 139.448 123.499 137.396L130.395 133.471C132.234 135.663 134.073 138.174 135.913 141.004C137.752 143.762 139.52 146.698 141.218 149.81C142.915 152.852 144.436 155.822 145.78 158.723C147.124 161.623 148.22 164.24 149.069 166.574L141.218 170.924ZM83.4987 150.234C81.5181 152.356 79.0778 154.691 76.1777 157.237C73.2776 159.784 70.13 162.33 66.7348 164.876C63.3395 167.423 59.9089 169.722 56.443 171.773L51.4562 164.664C53.649 163.462 55.9832 162.047 58.4589 160.42C61.0053 158.723 63.5164 156.919 65.9921 155.009C68.5385 153.099 70.8727 151.189 72.9947 149.28C75.1875 147.299 77.0619 145.495 78.6181 143.868L83.4987 150.234Z" fill="white"/>
4
+ </svg>
@@ -0,0 +1,69 @@
1
+ // ==UserScript==
2
+ // @name Furifont
3
+ // @namespace https://furifont.antfu.me
4
+ // @version 0.1.2
5
+ // @description Furigana on any page: Furifont turns on by itself on Japanese pages, and the menu switches family, turns it off, or turns okurigana readings (来る, 来ない) off.
6
+ // @homepageURL https://furifont.antfu.me
7
+ // @downloadURL https://furifont.antfu.me/furifont.user.js
8
+ // @match *://*/*
9
+ // @run-at document-idle
10
+ // @noframes
11
+ // @grant GM_getValue
12
+ // @grant GM_setValue
13
+ // @grant GM_registerMenuCommand
14
+ // @grant GM_xmlhttpRequest
15
+ // @connect furifont.antfu.me
16
+ // ==/UserScript==
17
+
18
+ (() => {
19
+ var Furifont=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let t={fonts:[{family:`Furifont Sans`,base:`Source Han Sans JP`,face:`sans`,rubyScript:`hiragana`},{family:`Furifont Sans Romaji`,base:`Source Han Sans JP`,face:`sans`,rubyScript:`hepburn`},{family:`Furifont Serif`,base:`Source Han Serif JP`,face:`serif`,rubyScript:`hiragana`},{family:`Furifont Serif Romaji`,base:`Source Han Serif JP`,face:`serif`,rubyScript:`hepburn`}],weights:[{style:`Regular`,weight:400}],variable:{style:`VF`,weights:[250,900]},options:{}},n={base:12290,selector:65024},r=`U+2E80-2FDF,U+3000-30FF,U+3190-319F,U+31F0-31FF,U+3400-4DBF,U+4E00-9FFF,U+F900-FAFF,U+FE00-FE0F,U+FF00-FFEF,U+20000-3FFFF,U+E0100-E01EF`,i=/[\p{sc=Han}\p{sc=Hiragana}\p{sc=Katakana}]/u;function a(e){return(e.match(/\s*(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|[^,]+)/g)??[]).map(e=>e.trim()).filter(Boolean)}function o(e){return e.replace(/^(["'])(.*)\1$/,`$2`)}let s=/mono|courier|consol|menlo|monaco|等幅/i;function c(e){let t=e.map(o);return t.some(e=>e===`monospace`||e===`ui-monospace`)||s.test(t[0]??``)}async function l({family:e,url:n,fetchFont:i}){let a=(t,n=`400`)=>new FontFace(e,t,{unicodeRange:r,weight:n}).load().catch(()=>void 0),o=await Promise.all(t.weights.map(({style:t,weight:n})=>a(`local("${e} ${t}")${n===400?`,local("${e}")`:``}`,String(n)))),s=t.variable.weights.join(` `),c=o.some(Boolean)?o:[await(i?i(n).then(e=>a(e,s),()=>void 0):a(`url("${n}")`,s))];for(let e of c)e&&document.fonts.add(e);return c.some(Boolean)}function u(e){let t=/* @__PURE__ */ new Map,n=/(?<!\p{sc=Han})\p{sc=Han}+(?=\p{sc=Hiragana})/gu,r=n=>{if(!t.has(n)){let r=/* @__PURE__ */ new Map;for(let[t,i]of Object.entries(e.pairs[n]??{}))for(let e of i)r.set(e,t||null);t.set(n,r.size?{reading:r,longest:Math.max(...[...r.keys()].map(e=>e.length))}:void 0)}return t.get(n)},i=(t,n)=>{let r=t.length>[...t][0].length,i=(r?e.words[t]?.map(e=>[...e.matchAll(/\[([^\]]*)\]/g)].map(e=>e[1]).join(``)):e.readings[t])?.indexOf(n)??-1;return i>=+!!r&&i<15&&e.lone[t]!==n?i+1:0};return{find:e=>{let t=[];for(let{0:a,index:o}of e.matchAll(n)){let n=r(a),s=e.slice(o+a.length,o+a.length+(n?.longest??0)),c;for(let e=s.length;e>0&&c===void 0;e--)c=n?.reading.get(s.slice(0,e));let l=c?i(a,c):0;c&&l&&t.push({at:o,length:a.length,reading:c,salt:l})}return t},saltOf:i}}let d=/* @__PURE__ */ new Map;function f(e,t){let n=d.get(e);return n||(n=(t?t(e):fetch(e).then(t=>t.ok?t.text():Promise.reject(Error(e)))).then(JSON.parse),n.catch(()=>d.delete(e)),d.set(e,n)),n}async function p({readings:e,pairs:t,fetchText:n}){try{let[r,i]=await Promise.all([f(e,n),f(t,n)]);return r.salt===!0?u({pairs:i,readings:r.kanji,words:r.words,lone:r.lone}):void 0}catch{return}}function m(e,t){return{href:new URL(`/#downloads`,e).href,text:t.download}}function h(e,t,n){document.querySelector(`furifont-toast`)?.remove();let r=document.createElement(`furifont-toast`),i=r.attachShadow({mode:`open`}),a=new CSSStyleSheet;a.replaceSync(`:host{all:initial}div{position:fixed;z-index:2147483647;right:16px;bottom:16px;display:flex;gap:16px;align-items:start;max-width:360px;padding:12px 16px;border:1px solid #fafafa2b;background:#0a0a0a;color:#fafafa;font:14px/1.5 system-ui,sans-serif}p{margin:0}a{color:inherit;margin-right:12px}button{padding:0;border:0;background:none;color:inherit;font:inherit;cursor:pointer}`),i.adoptedStyleSheets=[a];let o=document.createElement(`p`);o.append(e,` `,...t.map(({href:e,text:t})=>Object.assign(document.createElement(`a`),{href:e,target:`_blank`,rel:`noopener`,textContent:t})));let s=Object.assign(document.createElement(`button`),{ariaLabel:n,textContent:`×`,onclick:()=>r.remove()}),c=Object.assign(document.createElement(`div`),{role:`alert`});c.append(o,s),i.append(c),document.body.append(r),setTimeout(()=>r.remove(),1e4)}function g(e){let[t=0,n=0,r=0]=e.split(`.`).map(Number);return t*1e3+n*100+r}function _(e){let t=document.createElement(`canvas`).getContext(`2d`);return t.font=`1000px "${e}"`,Math.round(t.measureText(String.fromCodePoint(n.base,n.selector)).width)-2e3}async function v({family:e,url:t,toast:n},r){let i=new URL(`/version.json`,t).href,a;try{a=g(JSON.parse(await(r.fetchText?r.fetchText(i):fetch(i).then(e=>e.text()))).version)}catch{return}let o=[...g(r.version)<a?[r]:[],..._(e)<a?[m(t,n)]:[]];o.length&&h(n.outdated,o,n.close)}function y(e){let t=[];for(let n of e.filter(e=>e.isConnected)){let e=document.createTreeWalker(n,NodeFilter.SHOW_TEXT);for(let n=e.currentNode;n;n=e.nextNode())n.nodeType===Node.TEXT_NODE&&n.parentElement&&t.push(n)}return t}function b(e){let t=new Set(y(e).filter(e=>i.test(e.nodeValue??``)).map(e=>e.parentElement));for(let n of e){if(n.nodeType!==Node.ELEMENT_NODE)continue;let e=n;e.matches(`input,textarea`)&&t.add(e);for(let n of e.querySelectorAll(`input,textarea`))t.add(n)}return t}function x(e){let t=new CSSStyleSheet,n=[],r,i=0,s=()=>{for(let e of document.querySelectorAll(`[data-furifont-reading]`)){let t=r?r.saltOf(e.textContent??``,e.dataset.furifontReading):0;t?e.dataset.furifontSalt=String(t):delete e.dataset.furifontSalt}},l=e=>{if(!r)return;let t=y(e).filter(e=>/\p{sc=Han}\p{sc=Hiragana}/u.test(e.nodeValue??``)&&!e.parentElement.closest(`script,style,textarea,noscript,[contenteditable]:not([contenteditable=false]),[data-furifont-reading]`));for(let e of t)for(let{at:t,length:n,reading:i,salt:a}of r.find(e.nodeValue??``).reverse()){let r=t?e.splitText(t):e;r.length>n&&r.splitText(n);let o=document.createElement(`span`);o.dataset.furifontReading=i,o.dataset.furifontSalt=String(a),r.replaceWith(o),o.append(r)}},u={dispose:()=>{},sheet:t,family:e,restyle:()=>{let e=Array.from({length:15},(e,t)=>`[data-furifont-salt="${t+1}"]{font-feature-settings:"salt" ${t+1}!important}`).join(``),r=n.map((e,t)=>`[data-furifont="${t}"]{font-family:"${u.family}",${e}!important}`).join(``);t.replaceSync(`${r}[data-furifont-tight]{line-height:normal!important}${e}`)},okurigana:e=>{let n=++i;r=void 0,s(),e&&!t.disabled&&p(e).then(e=>{n===i&&e&&(r=e,s(),l([document.body]))})}},d=e=>{let t=[...b(e)].filter(e=>!e.hasAttribute(`data-furifont`)).map(e=>{let{fontFamily:t,lineHeight:n,fontSize:r}=getComputedStyle(e),i=a(t);return o(i[0]??``)===u.family&&i.shift(),{element:e,stack:i,tight:Number.parseFloat(n)<1.6*Number.parseFloat(r)}}).filter(({stack:e})=>e.length&&!c(e)),r=n.length;for(let{element:e,stack:r,tight:i}of t){let t=r.join(`,`),a=n.includes(t)?n.indexOf(t):n.push(t)-1;e.setAttribute(`data-furifont`,String(a)),i&&e.setAttribute(`data-furifont-tight`,``)}n.length>r&&u.restyle()},f=new MutationObserver(e=>{let t=e.flatMap(e=>e.type===`characterData`?[e.target]:[...e.addedNodes]);d(t),l(t)});return u.dispose=()=>{f.disconnect(),i++,r=void 0,document.adoptedStyleSheets=document.adoptedStyleSheets.filter(e=>e!==t);for(let e of document.querySelectorAll(`[data-furifont],[data-furifont-tight]`))e.removeAttribute(`data-furifont`),e.removeAttribute(`data-furifont-tight`);for(let e of document.querySelectorAll(`[data-furifont-reading]`))e.replaceWith(...e.childNodes);window.furifont===u&&delete window.furifont},window.furifont=u,document.adoptedStyleSheets=[...document.adoptedStyleSheets,t],d([document.body]),f.observe(document.body,{childList:!0,characterData:!0,subtree:!0}),u}async function S(e){let{family:t,url:n,toast:r,okurigana:i,update:a}=e,o=window.furifont;o?.family===t?(o.sheet.disabled=!o.sheet.disabled,o.sheet.disabled||o.okurigana(i)):(o??=x(t),o.family=t,o.restyle(),o.sheet.disabled=!1,await l(e)?(o.okurigana(i),a&&await v(e,a)):(o.sheet.disabled=!0,o.family=``,h(r.message,[m(n,r)],r.close)))}return e.JAPANESE=i,e.UNICODE_RANGE=r,e.createOkuriganaReader=u,e.isMonospace=c,e.loadFurifont=l,e.loadOkuriganaReader=p,e.parseFontStack=a,e.showToast=h,e.toggleFurifont=S,e})({});
20
+ ;(function start(manager, toggle, fonts, pairs, script, toasts, menus, detect) {
21
+ var _a;
22
+ const locale = detect(navigator.languages);
23
+ const toast = toasts[locale];
24
+ const menu = menus[locale];
25
+ const fetchBytes = (url, responseType) => new Promise((resolve, reject) => manager.xmlHttpRequest({ url, responseType, onload: (r) => resolve(r.response), onerror: reject }));
26
+ const fetchFont = (url) => fetchBytes(url, "arraybuffer");
27
+ const fetchText = (url) => fetchBytes(url, "text");
28
+ const update = () => {
29
+ if (Date.now() - Number(manager.getValue("checked", "0")) < 864e5)
30
+ return void 0;
31
+ manager.setValue("checked", String(Date.now()));
32
+ return { ...script, text: toast.userscript, fetchText };
33
+ };
34
+ let okurigana = manager.getValue("okurigana", "on") !== "off";
35
+ const options = ({ family, url, readings }) => ({ family, url, toast, fetchFont, okurigana: okurigana ? { readings, pairs, fetchText } : void 0 });
36
+ const saved = (_a = fonts.find((f) => f.family === manager.getValue("family", ""))) != null ? _a : fonts[0];
37
+ for (const font of fonts) {
38
+ manager.registerMenuCommand(font.family, () => {
39
+ manager.setValue("family", font.family);
40
+ toggle({ ...options(font), update: update() });
41
+ });
42
+ }
43
+ const registerOkurigana = () => manager.registerMenuCommand(okurigana ? menu.okuriganaOn : menu.okuriganaOff, () => {
44
+ var _a2;
45
+ okurigana = !okurigana;
46
+ manager.setValue("okurigana", okurigana ? "on" : "off");
47
+ const font = fonts.find((f) => {
48
+ var _a3;
49
+ return f.family === ((_a3 = window.furifont) == null ? void 0 : _a3.family);
50
+ });
51
+ if (font)
52
+ (_a2 = window.furifont) == null ? void 0 : _a2.okurigana(options(font).okurigana);
53
+ registerOkurigana();
54
+ }, { id: "okurigana", autoClose: false });
55
+ registerOkurigana();
56
+ if (/^ja(?:-|$)/i.test(document.documentElement.lang))
57
+ toggle({ ...options(saved), update: update() });
58
+ })({ getValue: GM_getValue, setValue: GM_setValue, registerMenuCommand: GM_registerMenuCommand, xmlHttpRequest: GM_xmlhttpRequest }, Furifont.toggleFurifont, [{"family":"Furifont Sans","url":"https://furifont.antfu.me/fonts/FurifontSansVF.woff2?v=0.1.2","readings":"https://furifont.antfu.me/fonts/FurifontSansVF.ivs.json?v=0.1.2"},{"family":"Furifont Sans Romaji","url":"https://furifont.antfu.me/fonts/FurifontSansRomajiVF.woff2?v=0.1.2","readings":"https://furifont.antfu.me/fonts/FurifontSansRomajiVF.ivs.json?v=0.1.2"},{"family":"Furifont Serif","url":"https://furifont.antfu.me/fonts/FurifontSerifVF.woff2?v=0.1.2","readings":"https://furifont.antfu.me/fonts/FurifontSerifVF.ivs.json?v=0.1.2"},{"family":"Furifont Serif Romaji","url":"https://furifont.antfu.me/fonts/FurifontSerifRomajiVF.woff2?v=0.1.2","readings":"https://furifont.antfu.me/fonts/FurifontSerifRomajiVF.ivs.json?v=0.1.2"}], "https://furifont.antfu.me/okurigana.json", {"version":"0.1.2","href":"https://furifont.antfu.me/furifont.user.js"}, {"en":{"message":"Furifont could not load its font on this page. Some sites, such as X and GitHub, do not let fonts load from other sites. On those sites, you must install Furifont on your computer.","download":"Download the fonts","close":"Close","outdated":"A newer version of Furifont is out.","userscript":"Update the userscript","bookmarklet":"Get the new bookmarklet"},"ja":{"message":"このページでは Furifont のフォントを読み込めませんでした。X や GitHub のように、他のサイトのフォントを読み込めないサイトがあります。そのようなサイトでは、パソコンに Furifont をインストールする必要があります。","download":"フォントをダウンロード","close":"閉じる","outdated":"Furifont の新しいバージョンがあります。","userscript":"ユーザースクリプトを更新","bookmarklet":"新しいブックマークレットを入手"},"zh-Hans":{"message":"Furifont 无法在此页面加载字体。有些网站(如 X 和 GitHub)不允许加载其他网站的字体。在这些网站上,需要在电脑上安装 Furifont。","download":"下载字体","close":"关闭","outdated":"Furifont 有新版本了。","userscript":"更新用户脚本","bookmarklet":"获取新的书签小工具"},"zh-Hant":{"message":"Furifont 無法在此頁面載入字型。有些網站(如 X 和 GitHub)不允許載入其他網站的字型。在這些網站上,需要在電腦上安裝 Furifont。","download":"下載字型","close":"關閉","outdated":"Furifont 有新版本了。","userscript":"更新使用者腳本","bookmarklet":"取得新的書籤小工具"}}, {"en":{"okuriganaOn":"Okurigana readings: on","okuriganaOff":"Okurigana readings: off"},"ja":{"okuriganaOn":"送り仮名の読み:オン","okuriganaOff":"送り仮名の読み:オフ"},"zh-Hans":{"okuriganaOn":"送假名读音:开","okuriganaOff":"送假名读音:关"},"zh-Hant":{"okuriganaOn":"送假名讀音:開","okuriganaOff":"送假名讀音:關"}}, function detectLocale(languages) {
59
+ for (const tag of languages.map((l) => l.toLowerCase())) {
60
+ if (tag.startsWith("zh"))
61
+ return /-(?:tw|hk|mo|hant)\b/.test(tag) ? "zh-Hant" : "zh-Hans";
62
+ if (tag.startsWith("ja"))
63
+ return "ja";
64
+ if (tag.startsWith("en"))
65
+ return "en";
66
+ }
67
+ return "en";
68
+ })
69
+ })()
@@ -0,0 +1 @@
1
+ <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Furifont: furigana built into the font</title><script type="importmap">{"imports":{"#entry":"/_nuxt/CC4_XjFP.js"}}</script><link rel="stylesheet" href="/_nuxt/entry.CsCxOCYm.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/_nuxt/CC4_XjFP.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/y07Wd5I9.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/DmlUWPPW.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/DmOlRIb5.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/Cg7TlFyt.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/CRzLMJPS.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/CEWHii-_.js"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/BDNMzG2s.js"><script type="module" src="/_nuxt/CC4_XjFP.js" crossorigin></script><link rel="prefetch" as="script" crossorigin href="/_nuxt/DLl_pn_F.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/Dz56DRZ7.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/DT7XmrQw.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/jjE7wdAL.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/Bs3Pv9Qv.js"><link rel="prefetch" as="script" crossorigin href="/_nuxt/DA1XwGcq.js"><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-404.DqUWOYf4.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/CEo6aVYN.js"><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-500.BYTKxx4O.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/DhRy_lmV.js"><meta name="description" content="A Japanese font that shows furigana by itself."><meta property="og:type" content="website"><meta property="og:url" content="https://furifont.antfu.me"><meta property="og:title" content="Furifont: furigana built into the font"><meta property="og:description" content="A Japanese font that shows furigana by itself."><meta property="og:image" content="https://furifont.antfu.me/og.png"><meta property="og:image:width" content="2400"><meta property="og:image:height" content="1260"><meta property="og:image:alt" content="Furifont: furigana built into the font"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Furifont: furigana built into the font"><meta name="twitter:description" content="A Japanese font that shows furigana by itself."><meta name="twitter:image" content="https://furifont.antfu.me/og.png"><link rel="icon" type="image/svg+xml" href="favicon.svg"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{devCustomizeBase:"/__furifont/"},app:{baseURL:"/",buildId:"1bd12827-b513-45af-9638-872afc8faff4",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1792041185170,false]</script></body></html>
@@ -0,0 +1,4 @@
1
+ <svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <rect width="200" height="200" fill="black"/>
3
+ <path d="M100.475 116.282C101.89 115.363 103.269 114.408 104.613 113.417C105.957 112.356 107.018 111.508 107.796 110.871C106.31 109.598 104.294 108.218 101.748 106.733C99.2016 105.248 96.4784 103.762 93.5783 102.277C90.6782 100.791 87.8842 99.5182 85.1963 98.4572L90.0769 92.3034C92.7648 93.4351 95.7357 94.8144 98.9894 96.4413C102.243 97.9975 105.391 99.6243 108.432 101.322C111.545 103.02 114.162 104.646 116.284 106.203L118.194 111.72C117.628 112.215 116.814 112.887 115.753 113.736C114.763 114.514 113.667 115.363 112.464 116.282C111.332 117.131 110.165 118.015 108.963 118.935C107.831 119.783 106.77 120.562 105.78 121.269L100.475 116.282ZM79.9974 166.998C82.6853 167.706 85.3731 168.272 88.061 168.696C90.7489 169.12 93.7551 169.333 97.0796 169.333C98.7065 169.333 100.333 169.085 101.96 168.59C103.658 168.095 105.037 167.211 106.098 165.937C107.23 164.593 107.796 162.79 107.796 160.526C107.796 158.687 107.371 156.777 106.523 154.797C105.674 152.745 104.577 150.694 103.233 148.643C101.89 146.592 100.404 144.611 98.7772 142.701C97.2211 140.721 95.7003 138.917 94.2149 137.29C93.0831 136.017 91.7746 134.673 90.2891 133.258C88.8037 131.844 87.283 130.535 85.7268 129.333L91.9868 123.815C93.3307 125.159 94.6393 126.539 95.9125 127.953C97.2564 129.297 98.565 130.677 99.8382 132.091C103.163 135.486 106.098 138.846 108.645 142.171C111.191 145.425 113.172 148.643 114.586 151.826C116.001 155.009 116.708 158.227 116.708 161.481C116.708 164.664 116.107 167.317 114.905 169.439C113.773 171.561 112.287 173.188 110.448 174.319C108.609 175.451 106.629 176.229 104.507 176.654C102.385 177.149 100.369 177.396 98.4589 177.396C95.1344 177.396 92.0221 177.219 89.122 176.866C86.2219 176.583 83.5694 176.194 81.1645 175.699L79.9974 166.998ZM141.218 170.924C140.439 168.378 139.414 165.619 138.141 162.648C136.938 159.607 135.523 156.565 133.897 153.524C132.34 150.411 130.678 147.476 128.91 144.717C127.142 141.888 125.338 139.448 123.499 137.396L130.395 133.471C132.234 135.663 134.073 138.174 135.913 141.004C137.752 143.762 139.52 146.698 141.218 149.81C142.915 152.852 144.436 155.822 145.78 158.723C147.124 161.623 148.22 164.24 149.069 166.574L141.218 170.924ZM83.4987 150.234C81.5181 152.356 79.0778 154.691 76.1777 157.237C73.2776 159.784 70.13 162.33 66.7348 164.876C63.3395 167.423 59.9089 169.722 56.443 171.773L51.4562 164.664C53.649 163.462 55.9832 162.047 58.4589 160.42C61.0053 158.723 63.5164 156.919 65.9921 155.009C68.5385 153.099 70.8727 151.189 72.9947 149.28C75.1875 147.299 77.0619 145.495 78.6181 143.868L83.4987 150.234Z" fill="white"/>
4
+ </svg>
Binary file