29 lines
3.3 KiB
JavaScript
29 lines
3.3 KiB
JavaScript
(function initCompatibilityGuidance(root, factory) {
|
|
const api = factory();
|
|
if (typeof module === 'object' && module.exports) module.exports = api;
|
|
if (root) root.chimeraCompatibilityGuidance = api;
|
|
})(typeof window !== 'undefined' ? window : null, function compatibilityGuidanceFactory() {
|
|
'use strict';
|
|
const STATES = new Set(['compatible', 'incompatible', 'workaround', 'conflict', 'unknown']);
|
|
const esc = value => String(value ?? '').replace(/[&<>"']/g, character => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[character]);
|
|
const tr = (key, fallback) => typeof window !== 'undefined' && window.t?.(key) && window.t(key) !== key ? window.t(key) : fallback;
|
|
function normalize(value = {}) { const state = STATES.has(value.state) ? value.state : 'unknown'; return { state, blocking: value.blocking === true, rationale: Array.isArray(value.rationale) ? value.rationale : [], workarounds: Array.isArray(value.workarounds) ? value.workarounds : [] }; }
|
|
function markup(value) {
|
|
const guidance = normalize(value);
|
|
const labels = { compatible: 'Compatible', incompatible: 'Incompatible', workaround: 'Workaround available', conflict: 'Conflicting evidence', unknown: 'Compatibility unknown' };
|
|
const rationale = guidance.rationale.map(item => `<li><strong>${esc(item.explanation)}</strong><span>${esc(item.providerId)} / ${esc(item.revision)} / ${esc(item.confidence)} confidence</span><a href="${esc(item.sourceUrl)}" target="_blank" rel="noreferrer">${esc(tr('compatibilityGuidance.inspectSource', 'Inspect source'))}</a></li>`).join('');
|
|
const workarounds = guidance.workarounds.map(item => `<li>${esc(item.explanation)} <small>${esc(item.providerId)} / ${esc(item.revision)}</small></li>`).join('');
|
|
const detail = guidance.state === 'unknown' ? tr('compatibilityGuidance.unknownDetail', 'No applicable evidence is cached for this exact context.') : guidance.state === 'conflict' ? tr('compatibilityGuidance.conflictDetail', 'Sources disagree. Chimera does not resolve this automatically.') : guidance.blocking ? tr('compatibilityGuidance.blockingDetail', 'Blocked by critical, high-confidence, non-conflicting evidence.') : tr('compatibilityGuidance.informationalDetail', 'Guidance is informational unless the evidence meets the blocking policy.');
|
|
return `<article class="compatibility-guidance state-${guidance.state}" data-compatibility-state="${guidance.state}" role="status"><header><strong>${esc(tr(`compatibilityGuidance.state.${guidance.state}`, labels[guidance.state]))}</strong>${guidance.blocking ? `<span>${esc(tr('compatibilityGuidance.blocked', 'Blocked'))}</span>` : ''}</header><p>${esc(detail)}</p>${rationale ? `<ul class="compatibility-rationale">${rationale}</ul>` : ''}${workarounds ? `<details><summary>${esc(tr('compatibilityGuidance.workarounds', 'Safe workaround guidance'))}</summary><ul>${workarounds}</ul></details>` : ''}</article>`;
|
|
}
|
|
async function load(host, context) {
|
|
if (!host || typeof window === 'undefined') return null;
|
|
let guidance;
|
|
try { guidance = await window.pork.compatibilityGuidance(context); } catch (_) { guidance = { state: 'unknown', unknownReason: 'unavailable' }; }
|
|
host.querySelector('.compatibility-guidance')?.remove();
|
|
host.insertAdjacentHTML('beforeend', markup(guidance));
|
|
return guidance;
|
|
}
|
|
return Object.freeze({ normalize, markup, load });
|
|
});
|