-
Notifications
You must be signed in to change notification settings - Fork 7
Module Parse Atts
src/lib/parse-atts.ts (67 行)。HTML container の data-* 属性を読み取って EmbedAttributes オブジェクトに変換するエントリ関数。
type ParseAttsParams = {
interactive?: boolean;
};
export default function parseAtts(
container: HTMLElement,
params?: ParseAttsParams,
): EmbedAttributes;(export default で関数を直接 export、parseAtts 名は import 側で付ける慣習。)
if (!container.dataset) {
container.dataset = {};
}container.dataset が undefined のときは空オブジェクトを設定する防御コード。HTMLElement.dataset は仕様上常に存在するが、jsdom やテストで mock している場合に必要。
let lang = 'auto';
if (container.dataset.lang && container.dataset.lang === 'auto') {
lang = getLang();
} else if (container.dataset.lang && container.dataset.lang === 'ja') {
lang = 'ja';
} else if (container.dataset.lang && container.dataset.lang !== 'ja') {
lang = 'en';
} else {
lang = getLang();
}意図的な if-else 連鎖:
-
data-lang="auto"→getLang()(= navigator から判定) -
data-lang="ja"→'ja' -
data-langが他の値 ("en","zh"等) →'en' - 属性なし →
getLang()
冗長性: container.dataset.lang のチェックが 3 回繰り返される。1 つの分岐で済む書き方ができそうだが、現状こうなっている。
getLang() (util.ts:122-134):
-
navigator.languages[0]を toLowerCase() -
'ja'または'ja-jp'なら'ja'、それ以外は'en'
keyring.parse(container);注: keyring.parse のシグネチャは parse(doc: Document = document) (keyring.ts:54)。引数として container を渡しているが、keyring.parse は document を受け取る関数。HTMLElement を渡しても getElementsByTagName('script') が呼べれば動くが、これは型的に怪しい (おそらくバグまたは過去の API 違いの名残)。
実用上は引数が document と同等のメソッドを持つオブジェクトであれば動く。container 自体に currentScript や getElementsByTagName が無いので、内部で fallback されているかも (要確認)。
→ 実際は container を渡しても何も起きず、keyring は前回の parse 結果 (もしくは初期 undefined) を持ち続ける可能性大。render.ts:21 で keyring.parse() (引数なし) が先に呼ばれているのが事実上の初期化。
const style = container.dataset.style || 'geolonia/basic-v2';
keyring.isGeoloniaStyle = keyring.isGeoloniaStyleCheck(style);- container の
data-styleか、なければ'geolonia/basic-v2'をデフォルトに - それを isGeoloniaStyleCheck に通して、
keyring.isGeoloniaStyleプロパティをセット
keyring.isGeoloniaStyleCheck(style) の判定ロジック詳細は Module-Keyring 参照。
return {
lat: 0,
lng: 0,
zoom: 0,
bearing: 0,
pitch: 0,
hash: 'off',
marker: 'on',
markerColor: '#E4402F',
openPopup: 'off',
customMarker: '',
customMarkerOffset: '0, 0',
gestureHandling: params.interactive === false ? 'off' : 'on',
navigationControl: params.interactive === false ? 'off' : 'on',
geolocateControl: 'off',
fullscreenControl: 'off',
scaleControl: 'off',
geoloniaControl: 'on',
geojson: '',
simpleVector: '',
cluster: 'on',
clusterColor: '#ff0000',
style: 'geolonia/basic-v2',
lang: lang,
plugin: 'off',
key: keyring.apiKey,
apiUrl: `https://api.geolonia.com/${keyring.stage}`,
stage: keyring.stage,
loader: 'on',
minZoom: '',
maxZoom: 20,
'3d': '',
...container.dataset,
};順序が重要: デフォルト値の後に ...container.dataset でスプレッド。data- 属性が指定されていれば上書き*される。
戻り値の型は宣言上 EmbedAttributes だが、戻り値リテラルには:
-
simpleVector: ''—EmbedAttributesには含まれない (型 hole、[otherKey: string]で許容) -
stage: keyring.stage— 同上
apiUrl は https://api.geolonia.com/${stage} のテンプレート展開で構築される。stage が 'v1' なら https://api.geolonia.com/v1、'dev' なら https://api.geolonia.com/dev。
parseAtts は 戻り値 + 副作用 を持つ:
-
container.datasetを空オブジェクトに初期化 (もし undefined だったら) -
keyring.parse(container)を呼ぶ (container 引数は実質無効、render.ts:21 で先に parse 済みなら no-op) -
keyring.isGeoloniaStyleをセット
書き直し時はこの副作用を意識する必要あり。
| 場所 | 用途 |
|---|---|
geolonia-map.ts:97 |
constructor 内、options 構築前 |
geolonia-map.ts:384 |
setStyle() override 内、再評価のため |
render.ts:48 |
plugin に渡す atts を取得するため |
setStyle 内の再 parseAtts は DOM の現在値を取得する目的 (data-* が外部から書き換えられている可能性に対応)。
戻り値型 EmbedAttributes (src/types.ts:3-34) に存在しないキー:
simpleVectorstage
これらは [otherKey: string]: string | number で許容されているが、型安全ではない。書き直し時は EmbedAttributes に正式追加するか、別の型として切り出す。
- lang 判定の冗長な if-else 連鎖
-
keyring.parse(container)の container 引数 (型不一致) -
simpleVector/stageの型 hole -
apiUrlとstageを両方返している (どちらが情報源か曖昧)
- lang 判定を 1 つの 3 項分岐に簡略化:
const lang = container.dataset.lang === 'ja' ? 'ja' : (container.dataset.lang && container.dataset.lang !== 'auto') ? 'en' : getLang();
-
keyring.parse(container)の引数を削除して、keyring.parse()のみ -
simpleVector/stageをEmbedAttributesに正式追加 - maps-core 側 / wrapper 側どちらに置くかは要検討 — DOM 走査するので wrapper 側だが、プログラム的利用 (params の object → atts 変換) もあるので lib 側にも一部必要