Skip to content
niryuu edited this page May 25, 2026 · 1 revision

parse-atts.ts — data-* 属性パース

src/lib/parse-atts.ts (67 行)。HTML container の data-* 属性を読み取って EmbedAttributes オブジェクトに変換するエントリ関数。

公開 API

type ParseAttsParams = {
  interactive?: boolean;
};

export default function parseAtts(
  container: HTMLElement,
  params?: ParseAttsParams,
): EmbedAttributes;

(export default で関数を直接 export、parseAtts 名は import 側で付ける慣習。)

フロー (parse-atts.ts:11-67)

1. dataset 防御 (parse-atts.ts:12-14)

if (!container.dataset) {
  container.dataset = {};
}

container.dataset が undefined のときは空オブジェクトを設定する防御コード。HTMLElement.dataset は仕様上常に存在するが、jsdom やテストで mock している場合に必要。

2. lang 判定 (parse-atts.ts:16-25)

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'

3. keyring 初期化 (parse-atts.ts:27)

keyring.parse(container);

: keyring.parse のシグネチャは parse(doc: Document = document) (keyring.ts:54)。引数として container を渡しているが、keyring.parse は document を受け取る関数。HTMLElement を渡しても getElementsByTagName('script') が呼べれば動くが、これは型的に怪しい (おそらくバグまたは過去の API 違いの名残)。

実用上は引数が document と同等のメソッドを持つオブジェクトであれば動く。container 自体に currentScriptgetElementsByTagName が無いので、内部で fallback されているかも (要確認)。

→ 実際は container を渡しても何も起きず、keyring は前回の parse 結果 (もしくは初期 undefined) を持ち続ける可能性大。render.ts:21keyring.parse() (引数なし) が先に呼ばれているのが事実上の初期化。

4. isGeoloniaStyle セット (parse-atts.ts:30-31)

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 参照。

5. 戻り値 (parse-atts.ts:33-66)

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 — 同上

apiUrlhttps://api.geolonia.com/${stage} のテンプレート展開で構築される。stage が 'v1' なら https://api.geolonia.com/v1'dev' なら https://api.geolonia.com/dev

副作用一覧

parseAtts戻り値 + 副作用 を持つ:

  1. container.dataset を空オブジェクトに初期化 (もし undefined だったら)
  2. keyring.parse(container) を呼ぶ (container 引数は実質無効、render.ts:21 で先に parse 済みなら no-op)
  3. keyring.isGeoloniaStyle をセット

書き直し時はこの副作用を意識する必要あり。

呼び出し元

場所 用途
geolonia-map.ts:97 constructor 内、options 構築前
geolonia-map.ts:384 setStyle() override 内、再評価のため
render.ts:48 plugin に渡す atts を取得するため

setStyle 内の再 parseAtts は DOM の現在値を取得する目的 (data-* が外部から書き換えられている可能性に対応)。

戻り値の型 vs 実体の食い違い

戻り値型 EmbedAttributes (src/types.ts:3-34) に存在しないキー:

  • simpleVector
  • stage

これらは [otherKey: string]: string | number で許容されているが、型安全ではない。書き直し時は EmbedAttributes に正式追加するか、別の型として切り出す。

怪しい点 (詳細は Suspicious-Logic)

  • lang 判定の冗長な if-else 連鎖
  • keyring.parse(container) の container 引数 (型不一致)
  • simpleVector / stage の型 hole
  • apiUrlstage を両方返している (どちらが情報源か曖昧)

書き直し時の指針

  • 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 / stageEmbedAttributes に正式追加
  • maps-core 側 / wrapper 側どちらに置くかは要検討 — DOM 走査するので wrapper 側だが、プログラム的利用 (params の object → atts 変換) もあるので lib 側にも一部必要

Clone this wiki locally