// 静的HTML側（<script>/<style> の外）のテキストノードと属性を抽出する。
import fs from 'fs';
const src = fs.readFileSync('app/game/index.html', 'utf8');

// script/style/svg の範囲をマスクする
const masked = [];
{
  const re = /<(script|style|svg)\b[\s\S]*?<\/\1>/g;
  let m;
  while ((m = re.exec(src))) masked.push([m.index, m.index + m[0].length]);
}
const inMask = i => masked.some(([a, b]) => i >= a && i < b);

const items = [];   // {start,end,text,kind}

// 1) テキストノード: > ... <
{
  const re = />([^<>]+)</g;
  let m;
  while ((m = re.exec(src))) {
    const s = m[1];
    if (inMask(m.index)) continue;
    if (!/[A-Za-z]{2}/.test(s)) continue;
    const trimmed = s.trim();
    if (!trimmed || !/[A-Za-z]{2}/.test(trimmed)) continue;
    const lead = s.length - s.trimStart().length;
    items.push({ start: m.index + 1 + lead, end: m.index + 1 + lead + trimmed.length, text: trimmed, kind: 'text' });
  }
}
// 2) 属性: data-help / data-helptitle / aria-label / title / placeholder
{
  const re = /\b(data-help|data-helptitle|aria-label|title|placeholder)="([^"]*)"/g;
  let m;
  while ((m = re.exec(src))) {
    if (inMask(m.index)) continue;
    const v = m[2];
    if (!/[A-Za-z]{2}/.test(v)) continue;
    const off = m.index + m[1].length + 2;
    items.push({ start: off, end: off + v.length, text: v, kind: m[1] });
  }
}

const uniq = [...new Set(items.map(i => i.text))];
console.log('html items:', items.length, 'unique:', uniq.length,
  'chars:', uniq.reduce((a, s) => a + s.length, 0));
fs.writeFileSync('out-html.json', JSON.stringify(uniq.sort((a, b) => b.length - a.length), null, 1));
fs.writeFileSync('out-html-items.json', JSON.stringify(items, null, 1));
