/* v7 only. Also runs on cached HTML where Vue is absent. */
(function (window, document) {
'use strict';
if (window.WitBlogRankingV7) return;
var requests = new Map();
var states = new WeakMap();
var selector = '[data-wit-blog-ranking]';
function httpUrl(value, base) {
if (typeof value !== 'string' || /[\x00-\x20\x7f\\]/.test(value)) return null;
try {
var url = new URL(value, base);
return /^(https?:)$/.test(url.protocol) && !url.username && !url.password ? url : null;
} catch (_) { return null; }
}
function config(root) {
var d = root.dataset;
var days = d.rankingDays === undefined ? 30 : Number(d.rankingDays);
if (![7, 14, 30].includes(days)) return null;
var base = httpUrl(d.rankingBase || '/_ranking_', window.location.href);
if (!/^[a-zA-Z0-9_]+$/.test(d.rankingCid || '') || !/^[a-zA-Z0-9_]+$/.test(d.rankingGid || '') || !base || base.search || base.hash) return null;
return { cid: d.rankingCid, gid: d.rankingGid, days: days,
url: base.href.replace(/\/$/, '') + '/' + encodeURIComponent(d.rankingCid) + '/' + encodeURIComponent(d.rankingGid) + '/' + days + 'd.json',
title: d.rankingTitle || '人気記事ランキング',
limit: Math.min(10, Math.max(1, parseInt(d.rankingLimit, 10) || 5)),
images: d.rankingImages !== 'false', preview: d.rankingPreview === 'true' || d.rankingComparison === 'true' };
}
function load(url) {
if (!requests.has(url)) {
var controller = new AbortController();
var timer = window.setTimeout(function () { controller.abort(); }, 8000);
var promise = window.fetch(url, { credentials: 'omit', cache: 'no-cache', signal: controller.signal })
.then(function (response) {
if (!response.ok) throw new Error('ranking fetch failed');
return response.json();
}).then(function (payload) {
if (!payload || payload.version !== 1 || !Array.isArray(payload.items)) throw new Error('invalid ranking');
return payload;
}).finally(function () { window.clearTimeout(timer); });
requests.set(url, promise);
promise.catch(function () { requests.delete(url); });
}
return requests.get(url);
}
function notice(root, text, preview) {
var element = root.querySelector('[data-ranking-notice]');
if (element) { element.textContent = text; element.hidden = !preview; }
root.hidden = !preview;
}
function render(root, settings, payload) {
if (payload.cid !== settings.cid || payload.gid !== settings.gid || (payload.periodDays || 30) !== settings.days) throw new Error('ranking target mismatch');
var list = root.querySelector('[data-ranking-list]');
var title = root.querySelector('[data-ranking-heading]');
if (!list || !title) return 0;
title.textContent = settings.title;
var period = root.querySelector('[data-ranking-period]');
if (period && payload.period) period.textContent = payload.period.start + ' 〜 ' + payload.period.end;
list.replaceChildren();
var items = payload.items.slice(0, settings.limit);
items.forEach(function (item) {
var url = item && httpUrl(item.url);
if (!url || typeof item.title !== 'string' || !Number.isInteger(item.rank) || item.rank < 1 || item.rank > 10) return;
var li = document.createElement('li');
var link = document.createElement('a');
link.href = url.href;
link.className = 'p-blog-ranking__link';
var rank = document.createElement('span');
rank.className = 'p-blog-ranking__rank';
rank.textContent = String(item.rank);
rank.setAttribute('aria-label', String(item.rank) + '位');
link.appendChild(rank);
var imageUrl = settings.images && httpUrl(item.imageUrl);
if (imageUrl) {
var img = document.createElement('img');
img.src = imageUrl.href;
img.alt = '';
img.width = 96;
img.height = 64;
img.loading = 'lazy';
img.className = 'p-blog-ranking__image';
img.addEventListener('error', function () { img.remove(); }, { once: true });
link.appendChild(img);
}
var label = document.createElement('strong');
label.className = 'p-blog-ranking__title';
label.textContent = item.title;
link.appendChild(label);
li.appendChild(link);
list.appendChild(li);
});
var message = root.querySelector('[data-ranking-notice]');
if (message) message.hidden = true;
root.hidden = list.children.length === 0;
if (root.hidden) notice(root, 'この期間に閲覧された記事はありません。', settings.preview);
return list.children.length;
}
function mount(root) {
var settings = config(root);
var signature = JSON.stringify(settings) + '|' + root.dataset.rankingPreview;
var old = states.get(root);
var list = root.querySelector('[data-ranking-list]');
if (!list) return;
if (old && old.signature === signature && (old.loading || !old.count || list.children.length === old.count)) return;
var state = { signature: signature, count: 0, loading: true };
states.set(root, state);
list.replaceChildren();
if (!settings) {
state.loading = false;
notice(root, '対象ブログまたは配信URLを設定してください。', root.dataset.rankingPreview === 'true');
return;
}
var title = root.querySelector('[data-ranking-heading]');
if (title) title.textContent = settings.title;
notice(root, 'ランキングを読み込んでいます。', settings.preview);
load(settings.url).then(function (payload) {
if (states.get(root) !== state) return;
state.count = render(root, settings, payload);
}).catch(function () {
if (states.get(root) !== state) return;
notice(root, 'ランキングを読み込めませんでした。', settings.preview);
}).finally(function () { state.loading = false; });
}
function scan() { document.querySelectorAll(selector).forEach(mount); }
window.WitBlogRankingV7 = { scan: scan };
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', scan, { once: true });
else scan();
new MutationObserver(scan).observe(document.documentElement, {
childList: true, subtree: true, attributes: true,
attributeFilter: ['data-ranking-days', 'data-ranking-comparison', 'data-ranking-cid', 'data-ranking-gid', 'data-ranking-base', 'data-ranking-title', 'data-ranking-limit', 'data-ranking-images', 'data-ranking-preview']
});
})(window, document);
/* Refresh sidebar FAQs from the same public CMS export used by the FAQ pages. */
(function (window, document) {
'use strict';
if (window.WitBlogFaqV7) return;
var requests = new Map();
var states = new WeakMap();
function load(source) {
if (!requests.has(source)) {
var controller = new AbortController();
var timer = window.setTimeout(function () { controller.abort(); }, 10000);
var request = window.fetch(source, {credentials: 'omit', cache: 'no-store', signal: controller.signal})
.then(function (response) {
if (!response.ok) throw new Error('FAQ request failed');
return response.json();
}).then(function (data) {
if (!data || data.schemaVersion !== 1 || !Array.isArray(data.items)) throw new Error('Invalid FAQ data');
return data.items;
}).finally(function () { window.clearTimeout(timer); });
requests.set(source, request);
request.catch(function () { requests.delete(source); });
}
return requests.get(source);
}
function select(items, subsidy) {
var seen = new Set();
return items.filter(function (item) {
if (!item || typeof item.id !== 'string' || !item.id || typeof item.question !== 'string' || !item.question.trim() || !Array.isArray(item.subsidies) || !item.subsidies.includes(subsidy) || seen.has(item.id)) return false;
seen.add(item.id);
return true;
}).sort(function (a, b) {
// Dedicated questions precede cross-subsidy questions; preserve CMS order within each group.
return a.subsidies.length - b.subsidies.length;
}).slice(0, 5);
}
function scan() {
document.querySelectorAll('[data-wit-faq-subsidy]').forEach(function (root) {
var subsidy = root.dataset.witFaqSubsidy;
var source = root.dataset.faqSource;
if (!['combined', 'saving'].includes(subsidy) || !source) return;
var key = source + '|' + subsidy;
if (states.get(root) === key) return;
states.set(root, key);
var list = root.querySelector('[data-faq-list]');
if (!list) return;
list.replaceChildren();
load(source).then(function (items) {
if (states.get(root) !== key) return;
select(items, subsidy).forEach(function (item) {
var li = document.createElement('li');
var link = document.createElement('a');
link.href = '/faq/answer.html?id=' + encodeURIComponent(item.id);
link.textContent = item.question;
li.appendChild(link);
list.appendChild(li);
});
root.dataset.faqState = list.children.length ? 'ready' : 'empty';
}).catch(function () {
if (states.get(root) === key) root.dataset.faqState = 'error';
// Keep the filtered FAQ index available when the public feed is unavailable.
});
});
}
window.WitBlogFaqV7 = {scan: scan};
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', scan);
else scan();
})(window, document);
/* Live projection of the existing CMS common text variables. */
(function (window, document) {
'use strict';
if (window.WitSubsidyCommon) return;
function node(tag, text, className) {
var e = document.createElement(tag); e.textContent = text;
if (className) e.className = className;
return e;
}
function render(e, value) {
var mode=e.dataset.subsidyFormat, prefix=e.dataset.subsidyPrefix;
var m=value.match(/^(\d{4}年)\s*(\d{1,2})(月)(?:(\d{1,2})(日))?(.*)$/);
e.replaceChildren();
if (mode==='hero' && /^p-(?:mono-hero|growth-hero|labor-hero|column-mv)$/.test(prefix)) {
if (m) {
e.appendChild(node('p',m[1],prefix+'__fact-year'));
var p=node('p','',prefix+'__fact-value');
p.appendChild(document.createTextNode(m[2]));p.appendChild(node('small',m[3]));
if(m[4])p.appendChild(document.createTextNode(m[4]));
p.appendChild(node('small',(m[5]||'')+m[6]));e.appendChild(p);
} else {
var fallback=node('p',value,prefix+'__support-date');e.appendChild(fallback);
}
} else if (mode==='support' && m) {
e.appendChild(document.createTextNode(m[1]+' '));
e.appendChild(node('strong',m[2]+m[3]+(m[4]||'')+(m[5]||'')));
e.appendChild(document.createTextNode(m[6]));
} else e.textContent=value;
}
async function refresh() {
var elements=Array.from(document.querySelectorAll('[data-subsidy-common]'));
if(!elements.length)return;
// Format the server-rendered common values even if the refresh is unavailable.
elements.forEach(function(e){render(e,e.textContent.trim());});
var controller=new AbortController();var timeout=window.setTimeout(function(){controller.abort();},10000);
try {
var response=await window.fetch('https://svltd2.files.cmssv.awsv.jp/_api_/subsidy-schedule.json',{cache:'no-store',credentials:'omit',signal:controller.signal});
if(!response.ok)throw new Error('Unavailable schedule');
var data=await response.json();if(data.schemaVersion!==1||!data.values)throw new Error('Invalid schedule');
elements.forEach(function(e){var value=data.values[e.dataset.subsidyCommon];if(typeof value==='string')render(e,value);});
document.documentElement.dataset.subsidyCommonState='ready';
} catch (_) {document.documentElement.dataset.subsidyCommonState='unavailable';}
finally {window.clearTimeout(timeout);}
}
window.WitSubsidyCommon={refresh:refresh};
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',refresh);else refresh();
})(window,document);