add iching tarot links
This commit is contained in:
@@ -873,9 +873,20 @@
|
||||
justify-items: start;
|
||||
}
|
||||
.iching-tarot-text {
|
||||
white-space: pre-line;
|
||||
white-space: normal;
|
||||
line-height: 1.4;
|
||||
font-size: 12px;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.iching-tarot-group {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
}
|
||||
.iching-tarot-group-title {
|
||||
color: #a1a1aa;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* ── Kabbalah sections ──────────────────────────────────────────────── */
|
||||
|
||||
@@ -315,6 +315,8 @@
|
||||
return;
|
||||
}
|
||||
|
||||
clearChildren(elements.ichingDetailTarotEl);
|
||||
|
||||
const upperKey = normalizeSearchValue(entry?.upperTrigram);
|
||||
const lowerKey = normalizeSearchValue(entry?.lowerTrigram);
|
||||
const upperCards = upperKey ? state.tarotByTrigramName[upperKey] || [] : [];
|
||||
@@ -325,15 +327,79 @@
|
||||
const upperLabel = upperTrigram?.element || entry?.upperTrigram || "--";
|
||||
const lowerLabel = lowerTrigram?.element || entry?.lowerTrigram || "--";
|
||||
|
||||
const lines = [];
|
||||
if (upperKey) {
|
||||
lines.push(`Upper (${upperLabel}): ${upperCards.length ? upperCards.join(", ") : "--"}`);
|
||||
}
|
||||
if (lowerKey) {
|
||||
lines.push(`Lower (${lowerLabel}): ${lowerCards.length ? lowerCards.join(", ") : "--"}`);
|
||||
function buildTarotTarget(cardName) {
|
||||
const label = String(cardName || "").trim();
|
||||
if (!label) {
|
||||
return null;
|
||||
}
|
||||
|
||||
elements.ichingDetailTarotEl.textContent = lines.length ? lines.join("\n\n") : "--";
|
||||
const trumpMatch = label.match(/^key\s*(\d{1,2})\s*:/i);
|
||||
if (trumpMatch) {
|
||||
return {
|
||||
label,
|
||||
detail: { trumpNumber: Number(trumpMatch[1]) }
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
label,
|
||||
detail: { cardName: label }
|
||||
};
|
||||
}
|
||||
|
||||
function appendTarotGroup(groupLabel, trigramLabel, cards) {
|
||||
const group = document.createElement("div");
|
||||
group.className = "iching-tarot-group";
|
||||
|
||||
const title = document.createElement("div");
|
||||
title.className = "iching-tarot-group-title";
|
||||
title.textContent = `${groupLabel} (${trigramLabel}):`;
|
||||
group.appendChild(title);
|
||||
|
||||
if (!cards.length) {
|
||||
const empty = document.createElement("div");
|
||||
empty.className = "planet-text";
|
||||
empty.textContent = "--";
|
||||
group.appendChild(empty);
|
||||
elements.ichingDetailTarotEl.appendChild(group);
|
||||
return;
|
||||
}
|
||||
|
||||
const buttonRow = document.createElement("div");
|
||||
buttonRow.className = "alpha-nav-btns";
|
||||
|
||||
cards.forEach((cardName) => {
|
||||
const target = buildTarotTarget(cardName);
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
|
||||
const button = document.createElement("button");
|
||||
button.type = "button";
|
||||
button.className = "alpha-nav-btn";
|
||||
button.textContent = `${target.label} ↗`;
|
||||
button.addEventListener("click", () => {
|
||||
document.dispatchEvent(new CustomEvent("nav:tarot-trump", {
|
||||
detail: target.detail
|
||||
}));
|
||||
});
|
||||
buttonRow.appendChild(button);
|
||||
});
|
||||
|
||||
group.appendChild(buttonRow);
|
||||
elements.ichingDetailTarotEl.appendChild(group);
|
||||
}
|
||||
|
||||
if (upperKey) {
|
||||
appendTarotGroup("Upper", upperLabel, upperCards);
|
||||
}
|
||||
if (lowerKey) {
|
||||
appendTarotGroup("Lower", lowerLabel, lowerCards);
|
||||
}
|
||||
|
||||
if (!elements.ichingDetailTarotEl.childElementCount) {
|
||||
elements.ichingDetailTarotEl.textContent = "--";
|
||||
}
|
||||
}
|
||||
|
||||
function renderCalendarMonths(entry, elements) {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
buildSmallCardRulershipRelation,
|
||||
buildSmallCardCourtLinkRelations,
|
||||
buildCubeRelationsForCard,
|
||||
buildIChingRelationsForCard,
|
||||
parseMonthDayToken,
|
||||
createRelationListItem,
|
||||
findSephirahForMinorCard
|
||||
@@ -131,6 +132,7 @@
|
||||
const smallCardCourtLinkRelations = buildSmallCardCourtLinkRelations(card, dedupedRelations);
|
||||
const mergedCourtDateRelations = [...courtDateRelations, ...smallCardCourtLinkRelations];
|
||||
const cubeRelations = buildCubeRelationsForCard(card);
|
||||
const iChingRelations = buildIChingRelationsForCard(card);
|
||||
const monthRelations = (getMonthRefsByCardId().get(card.id) || []).map((month, index) => {
|
||||
const dateRange = String(month?.dateRange || "").trim();
|
||||
const context = String(month?.context || "").trim();
|
||||
@@ -229,6 +231,7 @@
|
||||
renderStaticRelationGroup(elements.tarotDetailCourtDateEl, elements.tarotMetaCourtDateCardEl, mergedCourtDateRelations);
|
||||
renderStaticRelationGroup(elements.tarotDetailHebrewEl, elements.tarotMetaHebrewCardEl, hebrewRelations);
|
||||
renderStaticRelationGroup(elements.tarotDetailCubeEl, elements.tarotMetaCubeCardEl, cubeRelations);
|
||||
renderStaticRelationGroup(elements.tarotDetailIChingEl, elements.tarotMetaIChingCardEl, iChingRelations);
|
||||
renderStaticRelationGroup(elements.tarotDetailCalendarEl, elements.tarotMetaCalendarCardEl, mergedMonthRelations);
|
||||
|
||||
const kabPathEl = elements.tarotKabPathEl;
|
||||
|
||||
@@ -190,6 +190,17 @@
|
||||
label: `Open ${d.name || monthId} in Calendar`
|
||||
};
|
||||
}
|
||||
if (t === "ichingHexagram") {
|
||||
const hexagramNumber = Number(d.hexagramNumber || relation?.id);
|
||||
if (!Number.isFinite(hexagramNumber)) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
event: "nav:iching",
|
||||
detail: { hexagramNumber },
|
||||
label: `Open Hexagram ${hexagramNumber} in I Ching`
|
||||
};
|
||||
}
|
||||
if (t === "cubeFace") {
|
||||
const wallId = d.wallId || relation?.id;
|
||||
if (!wallId) {
|
||||
|
||||
@@ -102,6 +102,8 @@
|
||||
return String(value || "")
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/^key\s+\d+\s*:\s*/g, "")
|
||||
.replace(/\b(pentacles?|coins?)\b/g, "disks")
|
||||
.replace(/\s+/g, " ");
|
||||
}
|
||||
|
||||
@@ -114,6 +116,14 @@
|
||||
}
|
||||
|
||||
function resolveTarotTrumpNumber(cardName) {
|
||||
const rawKey = String(cardName || "")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
const keyMatch = rawKey.match(/\bkey\s*(\d{1,2})\b/);
|
||||
if (keyMatch) {
|
||||
return Number(keyMatch[1]);
|
||||
}
|
||||
|
||||
const key = normalizeTarotName(cardName);
|
||||
if (!key) {
|
||||
return null;
|
||||
@@ -724,11 +734,86 @@
|
||||
];
|
||||
}
|
||||
|
||||
function buildIChingRelationsForCard(card, referenceData) {
|
||||
const iChing = referenceData?.iChing;
|
||||
const hexagrams = Array.isArray(iChing?.hexagrams) ? iChing.hexagrams : [];
|
||||
const trigrams = Array.isArray(iChing?.trigrams) ? iChing.trigrams : [];
|
||||
const correspondences = Array.isArray(iChing?.correspondences?.tarotToTrigram)
|
||||
? iChing.correspondences.tarotToTrigram
|
||||
: [];
|
||||
|
||||
if (!card || !hexagrams.length || !correspondences.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const trigramByKey = new Map(
|
||||
trigrams
|
||||
.map((trigram) => [normalizeRelationId(trigram?.name), trigram])
|
||||
.filter(([key]) => Boolean(key))
|
||||
);
|
||||
|
||||
const matchedTrigramKeys = [...new Set(
|
||||
correspondences
|
||||
.filter((row) => cardMatchesTarotAssociation(card, row?.tarot))
|
||||
.map((row) => normalizeRelationId(row?.trigram))
|
||||
.filter(Boolean)
|
||||
)];
|
||||
|
||||
if (!matchedTrigramKeys.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const relations = [];
|
||||
|
||||
hexagrams.forEach((hexagram) => {
|
||||
const positionsByTrigram = new Map();
|
||||
const upperKey = normalizeRelationId(hexagram?.upperTrigram);
|
||||
const lowerKey = normalizeRelationId(hexagram?.lowerTrigram);
|
||||
|
||||
if (matchedTrigramKeys.includes(upperKey)) {
|
||||
positionsByTrigram.set(upperKey, ["upper"]);
|
||||
}
|
||||
if (matchedTrigramKeys.includes(lowerKey)) {
|
||||
const existing = positionsByTrigram.get(lowerKey) || [];
|
||||
positionsByTrigram.set(lowerKey, [...existing, "lower"]);
|
||||
}
|
||||
|
||||
positionsByTrigram.forEach((positions, trigramKey) => {
|
||||
const trigram = trigramByKey.get(trigramKey) || null;
|
||||
const sideLabel = positions.length === 2
|
||||
? "Upper + Lower"
|
||||
: positions[0] === "upper"
|
||||
? "Upper"
|
||||
: "Lower";
|
||||
const trigramLabel = trigram?.element || trigram?.name || hexagram?.upperTrigram || hexagram?.lowerTrigram || "Trigram";
|
||||
|
||||
relations.push({
|
||||
type: "ichingHexagram",
|
||||
id: String(hexagram?.number || ""),
|
||||
label: `Hexagram ${hexagram.number}: ${hexagram.name || "--"} · ${sideLabel} ${trigramLabel}`,
|
||||
data: {
|
||||
hexagramNumber: Number(hexagram?.number),
|
||||
name: hexagram?.name || "",
|
||||
upperTrigram: hexagram?.upperTrigram || "",
|
||||
lowerTrigram: hexagram?.lowerTrigram || "",
|
||||
trigramName: trigram?.name || "",
|
||||
trigramElement: trigram?.element || "",
|
||||
positions: positions.join(",")
|
||||
},
|
||||
__key: `ichingHexagram|${hexagram?.number}|${trigramKey}|${positions.join(",")}`
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return relations.sort((left, right) => Number(left?.data?.hexagramNumber || 999) - Number(right?.data?.hexagramNumber || 999));
|
||||
}
|
||||
|
||||
window.TarotRelationsUi = {
|
||||
buildCourtCardByDecanId,
|
||||
buildSmallCardCourtLinkRelations,
|
||||
buildMonthReferencesByCard,
|
||||
buildCubeRelationsForCard,
|
||||
buildIChingRelationsForCard,
|
||||
parseMonthDayToken
|
||||
};
|
||||
})();
|
||||
@@ -236,6 +236,7 @@
|
||||
tarotMetaCourtDateCardEl: document.getElementById("tarot-meta-courtdate-card"),
|
||||
tarotMetaHebrewCardEl: document.getElementById("tarot-meta-hebrew-card"),
|
||||
tarotMetaCubeCardEl: document.getElementById("tarot-meta-cube-card"),
|
||||
tarotMetaIChingCardEl: document.getElementById("tarot-meta-iching-card"),
|
||||
tarotMetaCalendarCardEl: document.getElementById("tarot-meta-calendar-card"),
|
||||
tarotDetailPlanetEl: document.getElementById("tarot-detail-planet"),
|
||||
tarotDetailElementEl: document.getElementById("tarot-detail-element"),
|
||||
@@ -244,6 +245,7 @@
|
||||
tarotDetailCourtDateEl: document.getElementById("tarot-detail-courtdate"),
|
||||
tarotDetailHebrewEl: document.getElementById("tarot-detail-hebrew"),
|
||||
tarotDetailCubeEl: document.getElementById("tarot-detail-cube"),
|
||||
tarotDetailIChingEl: document.getElementById("tarot-detail-iching"),
|
||||
tarotDetailCalendarEl: document.getElementById("tarot-detail-calendar"),
|
||||
tarotKabPathEl: document.getElementById("tarot-kab-path"),
|
||||
tarotHouseOfCardsEl: document.getElementById("tarot-house-of-cards")
|
||||
@@ -303,6 +305,7 @@
|
||||
buildSmallCardRulershipRelation,
|
||||
buildSmallCardCourtLinkRelations,
|
||||
buildCubeRelationsForCard,
|
||||
buildIChingRelationsForCard,
|
||||
parseMonthDayToken,
|
||||
createRelationListItem,
|
||||
findSephirahForMinorCard
|
||||
@@ -513,6 +516,13 @@
|
||||
return tarotRelationsUi.buildCubeRelationsForCard(card, state.magickDataset);
|
||||
}
|
||||
|
||||
function buildIChingRelationsForCard(card) {
|
||||
if (typeof tarotRelationsUi.buildIChingRelationsForCard !== "function") {
|
||||
return [];
|
||||
}
|
||||
return tarotRelationsUi.buildIChingRelationsForCard(card, state.referenceData);
|
||||
}
|
||||
|
||||
// Returns nav dispatch config for relations that have a corresponding section,
|
||||
// null for informational-only relations.
|
||||
function getRelationNavTarget(relation) {
|
||||
|
||||
@@ -244,6 +244,10 @@
|
||||
<strong>Cube of Space</strong>
|
||||
<ul id="tarot-detail-cube" class="tarot-relations"></ul>
|
||||
</div>
|
||||
<div id="tarot-meta-iching-card" class="tarot-meta-card" hidden>
|
||||
<strong>I Ching</strong>
|
||||
<ul id="tarot-detail-iching" class="tarot-relations"></ul>
|
||||
</div>
|
||||
<div id="tarot-meta-calendar-card" class="tarot-meta-card" hidden>
|
||||
<strong>Calendar Months</strong>
|
||||
<ul id="tarot-detail-calendar" class="tarot-relations"></ul>
|
||||
@@ -392,7 +396,7 @@
|
||||
</div>
|
||||
<div class="planet-meta-card">
|
||||
<strong>Tarot Correspondences</strong>
|
||||
<p id="iching-detail-tarot" class="planet-text iching-tarot-text">--</p>
|
||||
<div id="iching-detail-tarot" class="planet-text iching-tarot-text">--</div>
|
||||
</div>
|
||||
<div class="planet-meta-card">
|
||||
<strong>Calendar Months</strong>
|
||||
|
||||
Reference in New Issue
Block a user