[FEATURE]: accept font data (a URL or the bytes) for export and text measurement
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 45/100
- issue の種類
- 機能追加
- 明瞭さ
- おおむね明確
- 活発さ
- 活発
- 技術スタック
- javascript
調査の方向性
まず、plotly-basic と plotly-cartesian における既存のフォント読み込み動作と、full bundle および maplibre-gl にすでに存在する FontFace 関連の loader を確認します。最初にサポートする入力形式を決定し、その後、測定前にフォントを登録し、エクスポートされた SVG に埋め込む方法を定義します。完了条件は、指定されたフォントバイトまたは URL がレイアウト測定に影響し、期待される SVG フォントデータを生成し、読み込みに失敗した場合でもハングしないことです。
索引モデルが issue の本文から書いたものです。
説明
Description
We want charts to render with a font that isn't installed on the machine doing the rendering - Kaleido in a container, in our case. This all started in https://github.com/plotly/Kaleido/issues/464 but @camdecoster has pointed me here and I found a similar issue - #4885, but we then concluded it would make sense to create a narrower one, so here it is.
The request is a way to hand plotly.js a font, as either a URL or the raw bytes, and have it do two things with whichever it gets: register the face
before it measures text, and inline @font-face with base64 into the exported SVG.
Why should this feature be added?
Well, people are still hitting #4885 that has been open since 2020. I just tried with plotly.py 7.1.0 (plotly.js 4.1.1) and a font that isn't installed on my machine:
fig.update_layout(font=dict(family="Fira Sans Condensed"))
fig.write_image("out.svg")
and the resulting SVG names that family 7 times but carries no @font-face and no base64anywhere. The name travels, but the bytes don't.
It's two bugs though, not one. The other is WilliamMayor's 2023 comment in the same thread - the font also isn't loaded when plotly.js measures text, so ticks, margins and legends get sized on some kind of "fallback" and the layout is wrong before anything is exported. Taking the font as input could fix both, I believe, because both come from it not being in the page.
I saw @alexcjohnson proposing a cheaper alternative in #4885 - to read the @font-face rules already active in the document instead of having users declare fonts. I tested that: with a plain <link> to fonts.googleapis.com, cssRules throws SecurityError, and it's only readable when the link carries crossorigin="anonymous" (at least in the one browser and the one Google family we've checked).
Mocks/Designs
Rough, and I'm not attached to the naming:
Plotly.newPlot(gd, data, layout, {
fonts: [
// a google fonts css url - the same string that's already in the <link>
{family: 'Open Sans', url: 'https://fonts.googleapis.com/css2?family=Open+Sans'},
// a direct font file, nothing to parse
{family: 'Open Sans', weight: 700, url: '/static/OpenSans-Bold.woff2'},
// or the bytes, for offline and headless
{family: 'Open Sans', weight: 700, data: arrayBufferOrBase64}
]
})
The first form is the convenient one and it's the only one that needs extra work: a Google Fonts URL returns CSS rather than a font, so something has to read the src out of that CSS and fetch the file it points at. The other two skip that step - the second is already a font file, the third is already bytes. So the CSS reading could come later, or never, and the feature still works.
Notes
My motivation is Kaleido, which has no user CSS and no network, so it would pass bytes. The same option would cover a browser user passing the Google Fonts URL they already have in their <link>.
In case it comes up: I've grep'ed the latest plotly.js bundle and maplibre-gl does this already, and it's in the tree, but I don't think chart text can borrow it. Its loader is wired into maplibre's own style system, and plotly-basic and plotly-cartesian contain 0 FontFace - only the full bundle has it - so depending on it would put a map renderer in every build.
One case I'd leave out on purpose: pulling the bytes of a font that's only installed on the system. No browser API exposes them, so those users would have to supply the file.
One question we would need to agree on: how much of the URL side is needed? The bytes form needs no network at all, so it could land on its own. A direct .woff2 URL adds a fetch, which would need a timeout and a warn-and-continue fallback so it can never hang a render. A Google Fonts CSS URL (which would add reading the src out of that CSS) looks a bit more complicated - from what I saw, google splits one family across several @font-face blocks, one per script, each pointing at a different file, so taking just the first gets you Latin and drops Cyrillic or Greek without saying anything.
- 主要言語
- JavaScript
- スター
- 18.3k
- フォーク
- 2k
- 平均マージ
- 2日 10時間
- マージ済み PR(30日)
- 30
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
plotly/plotly.js のほかの issue
-
chore P3 plotly-internal size: 3 task
難易度 2/5 1〜3時間 初心者へのやさしさ 77/100
-
bug P2 size: 1
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
-
chore P1 plotly-internal size: 1 task
難易度 1/5 1時間未満 初心者へのやさしさ 82/100
-
chore P3 plotly-internal size: 1 task
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
plotly/plotly.js の issue をすべて見る
似ている issue
-
bug customer-eng Durable Agents Inngest status: needs triage
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
-
optimization optimization:agents-md-curator
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
githubnext/gh-aw-cao#13475 ·
-
[BUG]: "Clear All" in Settings doesn't clear the saved analysis, old data comes back after reload オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
AOSSIE-Org/OrgExplorer#253 · コメント 1 件 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
oxc-project/oxc#26944 ·
-
ai-observability bug team/ai-observability
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100