From 7cdcdb44565f703b133f6673c40313dadde4a227 Mon Sep 17 00:00:00 2001 From: Nose Date: Fri, 24 Apr 2026 04:25:27 -0700 Subject: [PATCH] updated relationship display in cycle details to use inline links instead of alpha nav buttons, and added related cycle links to planet details; added element display to astrology alphabet details; updated decan range display in calendar detail panels; updated tarot card detail script to latest version; added element script to index.html --- app/tarot-database-builders.js | 22 +++- app/ui-alphabet-detail.js | 32 +++++- app/ui-calendar-data.js | 12 +- app/ui-calendar-detail-panels.js | 42 +++++-- app/ui-cube-detail.js | 112 +++++++++++++++---- app/ui-cube.js | 10 ++ app/ui-elements.js | 66 +++++++++-- app/ui-holidays-render.js | 9 +- app/ui-iching.js | 45 +++++++- app/ui-tarot-detail.js | 183 ++++++++++++++++++++++++------- app/ui-zodiac.js | 27 ++++- index.html | 22 ++-- 12 files changed, 473 insertions(+), 109 deletions(-) diff --git a/app/tarot-database-builders.js b/app/tarot-database-builders.js index 203434a..ebd698d 100644 --- a/app/tarot-database-builders.js +++ b/app/tarot-database-builders.js @@ -258,6 +258,16 @@ return sign?.name?.en || sign?.name || sign?.id || fallback || "Unknown"; } + function formatDegreeRangeLabel(startDegree, endDegree) { + const start = Number(startDegree); + const end = Number(endDegree); + if (!Number.isFinite(start) || !Number.isFinite(end)) { + return ""; + } + + return `${String(Math.trunc(start)).padStart(2, "0")}°–${String(Math.trunc(end)).padStart(2, "0")}°`; + } + function buildDecanMetadata(decan, sign) { if (!decan || !sign) { return null; @@ -268,9 +278,9 @@ return null; } - const startDegree = (index - 1) * 10; - const endDegree = startDegree + 10; - const dateRange = buildDecanDateRange(sign, index, decan); + const startDegree = (index - 1) * 10; + const endDegree = startDegree + 9; + const dateRange = buildDecanDateRange(sign, index, decan); return { decan, @@ -282,6 +292,7 @@ startDegree, endDegree, dateRange, + degreeRangeLabel: formatDegreeRangeLabel(startDegree, endDegree), normalizedCardName: normalizeMinorTarotCardName(decan.tarotMinorArcana || "") }; } @@ -566,7 +577,7 @@ return; } - const { startDegree, endDegree, dateRange, signId: metaSignId, signName, signSymbol, index } = decanMeta; + const { startDegree, endDegree, dateRange, degreeRangeLabel, signId: metaSignId, signName, signSymbol, index } = decanMeta; const ruler = planets[decan.rulerPlanetId] || null; const cardKey = canonicalCardName(cardName); @@ -591,7 +602,7 @@ createRelation( "decan", `${metaSignId}-${index}`, - `Decan ${decan.index}: ${sign.symbol || ""} ${signName} (${startDegree}°–${endDegree}°)${dateRange ? ` · ${dateRange.label}` : ""}`.trim(), + `Decan ${decan.index}: ${sign.symbol || ""} ${signName} (${degreeRangeLabel || `${startDegree}°–${endDegree}°`})${dateRange ? ` · ${dateRange.label}` : ""}`.trim(), { signId: metaSignId, signName, @@ -599,6 +610,7 @@ index, startDegree, endDegree, + degreeRangeLabel: degreeRangeLabel || null, dateStart: dateRange?.startToken || null, dateEnd: dateRange?.endToken || null, dateRange: dateRange?.label || null diff --git a/app/ui-alphabet-detail.js b/app/ui-alphabet-detail.js index 9e1a50e..960fdca 100644 --- a/app/ui-alphabet-detail.js +++ b/app/ui-alphabet-detail.js @@ -115,7 +115,7 @@ return context.card("Astrology", `
Type
Element
-
Element
${elemEmoji[id] || ""} ${context.cap(id)}
+
Element
${elemEmoji[id] || ""} ${context.inlineNavBtn(context.cap(id), "nav:elements", { "element-id": id })}
`); } @@ -127,6 +127,32 @@ `); } + function renderElementOrPlanetValue(value, context) { + const token = context.normalizeId(value); + if (!token) { + return "—"; + } + + if (context.PLANET_SYMBOLS[token]) { + return `${context.PLANET_SYMBOLS[token]} ${context.inlineNavBtn(context.cap(token), "nav:planet", { "planet-id": token })}`; + } + + if (["air", "water", "fire", "earth"].includes(token)) { + return context.inlineNavBtn(context.cap(token), "nav:elements", { "element-id": token }); + } + + return value || "—"; + } + + function renderTarotValue(value, context) { + const label = String(value || "").trim(); + if (!label) { + return "—"; + } + + return context.inlineNavBtn(label, "nav:tarot-trump", { "card-name": label }); + } + function renderHebrewDualityCard(letter, context) { const duality = context.HEBREW_DOUBLE_DUALITY[context.normalizeId(letter?.hebrewLetterId)]; if (!duality) { @@ -553,8 +579,8 @@
Name
${letter.title}
English Letters
${englishRefs.join(" / ") || "—"}
Transliteration
${letter.transliteration || "—"}
-
Element / Planet
${letter.elementOrPlanet || "—"}
-
Tarot
${letter.tarot || "—"}
+
Element / Planet
${renderElementOrPlanetValue(letter.elementOrPlanet, context)}
+
Tarot
${renderTarotValue(letter.tarot, context)}
Numerology
${letter.numerology || "—"}
Glyph Source
API asset: img/enochian (sourced from dCode set)
Position
#${letter.index} of 21
diff --git a/app/ui-calendar-data.js b/app/ui-calendar-data.js index 5398f8f..071faf2 100644 --- a/app/ui-calendar-data.js +++ b/app/ui-calendar-data.js @@ -1,6 +1,15 @@ (function () { "use strict"; + function formatDegreeLabel(value) { + const numeric = Number(value); + if (!Number.isFinite(numeric)) { + return "--"; + } + + return String(Math.trunc(numeric)).padStart(2, "0"); + } + function buildDecanWindow(context, sign, decanIndex) { const { buildSignDateBounds, addDays, formatDateLabel } = context; const bounds = buildSignDateBounds(sign); @@ -78,7 +87,7 @@ seen.add(key); const startDegree = (Number(decan.index) - 1) * 10; - const endDegree = startDegree + 10; + const endDegree = startDegree + 9; const signName = sign?.name?.en || sign?.name || signId; rows.push({ @@ -89,6 +98,7 @@ decanIndex: Number(decan.index), startDegree, endDegree, + degreeRangeLabel: `${formatDegreeLabel(startDegree)}°–${formatDegreeLabel(endDegree)}°`, startTime: window.start.getTime(), endTime: window.end.getTime(), startMonth: window.start.getMonth() + 1, diff --git a/app/ui-calendar-detail-panels.js b/app/ui-calendar-detail-panels.js index a436cd1..c4860e3 100644 --- a/app/ui-calendar-detail-panels.js +++ b/app/ui-calendar-detail-panels.js @@ -27,6 +27,26 @@ return ``; } + function buildSignInlineButton(signId, signName, signSymbol) { + if (!signId) { + return `${signSymbol ? `${signSymbol} ` : ""}${signName || "--"}`.trim(); + } + + const label = `${signSymbol ? `${signSymbol} ` : ""}${signName || signId}`.trim(); + return inlineNavButton(label, "zodiac", { "sign-id": signId }); + } + + function buildHebrewInlineButton(hebrewLetterId, label) { + if (!hebrewLetterId) { + return label || "--"; + } + + return inlineNavButton(label || hebrewLetterId, "alphabet", { + alphabet: "hebrew", + "hebrew-letter-id": hebrewLetterId + }); + } + function buildMajorArcanaRowsForMonth(context) { const { month, api, getState } = context; const currentState = getState(); @@ -142,6 +162,8 @@ ? `${row.hebrewLetterChar ? `${row.hebrewLetterChar} ` : ""}${row.hebrewLetterName || row.hebrewLetterId}` : "--"; const displayCardName = api.getDisplayTarotName(row.cardName, row.trumpNumber); + const signLabel = buildSignInlineButton(row.signId, row.signName, row.signSymbol); + const hebrewLabel = buildHebrewInlineButton(row.hebrewLetterId, label); return `
@@ -149,11 +171,12 @@ ${displayCardName}${row.trumpNumber != null ? ` · Trump ${row.trumpNumber}` : ""} ${row.rangeLabel}
-
${row.signSymbol} ${row.signName} · Hebrew: ${label}
+
${signLabel} · Hebrew: ${hebrewLabel}
Days ${inlineNavButton(row.rangeLabel, "calendar-day-range", { "range-start": row.dayStart, "range-end": row.dayEnd })} · Tarot ${inlineNavButton(displayCardName, "tarot-card", { "card-name": row.cardName, "trump-number": row.trumpNumber ?? "" })} - ${row.hebrewLetterId ? ` · Hebrew ${inlineNavButton(label, "alphabet", { alphabet: "hebrew", "hebrew-letter-id": row.hebrewLetterId })}` : ""} + ${row.hebrewLetterId ? ` · Hebrew ${hebrewLabel}` : ""} + ${row.signId ? ` · Zodiac ${signLabel}` : ""}
`; @@ -202,13 +225,14 @@ const list = rows.map((row) => { const displayCardName = api.getDisplayTarotName(row.cardName); + const signLabel = buildSignInlineButton(row.signId, row.signName, row.signSymbol); return `
- ${row.signSymbol} ${row.signName} · Decan ${row.decanIndex} - ${row.startDegree}°–${row.endDegree}° · ${row.dateRange} + ${signLabel} · Decan ${row.decanIndex} + ${row.degreeRangeLabel || `${row.startDegree}°–${row.endDegree}°`} · ${row.dateRange}
-
Tarot ${inlineNavButton(displayCardName, "tarot-card", { "card-name": row.cardName })}
+
Tarot ${inlineNavButton(displayCardName, "tarot-card", { "card-name": row.cardName })} · Zodiac ${signLabel}
`; }).join(""); @@ -291,6 +315,10 @@ const { month, api, getState, buildAssociationButtons, renderHolidaysCard } = context; const currentState = getState(); const gregorianStartDate = api.getGregorianReferenceDateForCalendarMonth(month); + const zodiacSignId = month?.associations?.zodiacSignId || findSignIdByAstrologyName(month?.zodiacSign, context); + const zodiacLabel = buildSignInlineButton(zodiacSignId, api.cap(month.zodiacSign) || "--", ""); + const hebrewLetterId = month?.associations?.hebrewLetterId || String(month?.hebrewLetterId || "").trim(); + const hebrewLabel = buildHebrewInlineButton(hebrewLetterId, month.hebrewLetter || "--"); const factsRows = [ ["Hebrew Name", month.nativeName || "--"], ["Month Order", month.leapYearOnly ? `${month.order} (leap year only)` : String(month.order)], @@ -298,10 +326,10 @@ ["Month Start (Gregorian)", api.formatGregorianReferenceDate(gregorianStartDate)], ["Days", month.daysVariant ? `${month.days}–${month.daysVariant} (varies)` : String(month.days || "--")], ["Season", month.season || "--"], - ["Zodiac Sign", api.cap(month.zodiacSign) || "--"], + ["Zodiac Sign", zodiacLabel], ["Tribe of Israel", month.tribe || "--"], ["Sense", month.sense || "--"], - ["Hebrew Letter", month.hebrewLetter || "--"] + ["Hebrew Letter", hebrewLabel] ].map(([dt, dd]) => `
${dt}
${dd}
`).join(""); const monthOrder = Number(month?.order); diff --git a/app/ui-cube-detail.js b/app/ui-cube-detail.js index 0d49039..27a7683 100644 --- a/app/ui-cube-detail.js +++ b/app/ui-cube-detail.js @@ -104,6 +104,71 @@ return list; } + function createAstrologyValue(astrology, context) { + const type = toDisplayText(astrology?.type).toLowerCase(); + const name = toDisplayText(astrology?.name); + + if (!name) { + return ""; + } + + if (type === "planet") { + return createInlineEventLink(name, "nav:planet", { + planetId: context.normalizeId(name) + }); + } + + if (type === "zodiac") { + return createInlineEventLink(name, "nav:zodiac", { + signId: context.normalizeId(name) + }); + } + + return name; + } + + function createElementValue(elementName, context) { + const label = toDisplayText(elementName); + const elementId = context.normalizeId(label); + + if (!elementId) { + return label; + } + + return createInlineEventLink(label, "nav:elements", { elementId }); + } + + function appendPathAssociationRows(rows, pathEntry, context) { + if (!Array.isArray(rows) || !pathEntry) { + return; + } + + const astrologyValue = createAstrologyValue(pathEntry?.astrology, context); + if (astrologyValue) { + rows.push({ label: "Astrology", value: astrologyValue }); + } + + const tarotCard = toDisplayText(pathEntry?.tarot?.card); + const tarotTrumpNumber = context.toFiniteNumber(pathEntry?.tarot?.trumpNumber); + if (tarotCard || tarotTrumpNumber != null) { + rows.push({ + label: "Tarot", + value: createInlineEventLink(tarotCard || `Trump ${tarotTrumpNumber}`, "nav:tarot-trump", { + cardName: tarotCard, + trumpNumber: tarotTrumpNumber + }) + }); + } + + const pathNo = context.toFiniteNumber(pathEntry?.pathNumber); + if (pathNo != null) { + rows.push({ + label: "Path", + value: createInlineEventLink(`Path ${pathNo}`, "nav:kabbalah-path", { pathNo }) + }); + } + } + function createNavButton(label, eventName, detail) { const button = document.createElement("button"); button.type = "button"; @@ -155,7 +220,7 @@ }) : centerLetterText }, - { label: "Element", value: center?.element } + { label: "Element", value: createElementValue(center?.element, context) || center?.element } ]; if (centerTarotCard || centerTrumpNo != null) { @@ -225,9 +290,8 @@ const pathNo = toFiniteNumber(connectorPath?.pathNumber); const tarotCard = toDisplayText(connectorPath?.tarot?.card); const tarotTrumpNumber = toFiniteNumber(connectorPath?.tarot?.trumpNumber); - const astrologyType = toDisplayText(connectorPath?.astrology?.type); - const astrologyName = toDisplayText(connectorPath?.astrology?.name); - const astrologySummary = [astrologyType, astrologyName].filter(Boolean).join(": "); + const astrologySummary = createAstrologyValue(connectorPath?.astrology, context) + || [toDisplayText(connectorPath?.astrology?.type), toDisplayText(connectorPath?.astrology?.name)].filter(Boolean).join(": "); elements.detailNameEl.textContent = connector?.name || "Mother Connector"; elements.detailSubEl.textContent = ["Mother Letter", letterText].filter(Boolean).join(" · ") || "Mother Letter"; @@ -329,9 +393,8 @@ const edgeLetterId = getEdgeLetterId(selectedEdge); const edgeLetter = getEdgeLetter(selectedEdge); const edgePath = getEdgePathEntry(selectedEdge); - const astrologyType = toDisplayText(edgePath?.astrology?.type); - const astrologyName = toDisplayText(edgePath?.astrology?.name); const astrologySymbol = getEdgeAstrologySymbol(selectedEdge); + const astrologyName = toDisplayText(edgePath?.astrology?.name); const astrologyText = astrologySymbol && astrologyName ? `${astrologySymbol} ${astrologyName}` : astrologySymbol || astrologyName; @@ -361,12 +424,7 @@ }, { label: "Astrology", - value: astrologyType === "zodiac" && astrologyName - ? createInlineValue([ - astrologySymbol ? `${astrologySymbol} ` : "", - createInlineEventLink(astrologyName, "nav:zodiac", { signId: normalizeId(astrologyName) }) - ]) - : astrologyText + value: createAstrologyValue(edgePath?.astrology, context) || astrologyText } ]; @@ -420,6 +478,7 @@ getWallEdgeDirections, getWallFaceLetterId, getWallFaceLetter, + getPathEntryByLetterId, getHebrewLetterName, getEdgeLetter, localDirectionOrder, @@ -458,6 +517,7 @@ bodyEl.innerHTML = ""; const wallAssociations = wall.associations || {}; + const faceLetterPath = getPathEntryByLetterId(wallFaceLetterId); const wallFaceLetterName = getHebrewLetterName(wallFaceLetterId) || toDisplayText(wallFaceLetterId); const faceLetterLabel = [wallFaceLetter, wallFaceLetterName].filter(Boolean).join(" "); const wallRows = [ @@ -478,7 +538,7 @@ }) : wallFaceLetterText }, - { label: "Element", value: wall.element }, + { label: "Element", value: createElementValue(wall.element, context) || wall.element }, { label: "Planet", value: wallAssociations.planetId @@ -497,6 +557,22 @@ } ]; + if (faceLetterPath) { + appendPathAssociationRows(wallRows, faceLetterPath, context); + } else { + const directTarotCard = toDisplayText(wallAssociations?.tarotCard || wall?.tarotCard); + const directTrumpNumber = toFiniteNumber(wallAssociations?.tarotTrumpNumber); + if (directTarotCard || directTrumpNumber != null) { + wallRows.push({ + label: "Tarot", + value: createInlineEventLink(directTarotCard || `Trump ${directTrumpNumber}`, "nav:tarot-trump", { + cardName: directTarotCard, + trumpNumber: directTrumpNumber + }) + }); + } + } + bodyEl.appendChild(createMetaCard("Wall Details", createDetailList(wallRows))); if (Array.isArray(wall.keywords) && wall.keywords.length) { @@ -612,9 +688,8 @@ ? [edgeLetter, edgeLetterName].filter(Boolean).join(" ") : ""; const edgePath = getEdgePathEntry(edge); - const astrologyType = toDisplayText(edgePath?.astrology?.type); - const astrologyName = toDisplayText(edgePath?.astrology?.name); const astrologySymbol = getEdgeAstrologySymbol(edge); + const astrologyName = toDisplayText(edgePath?.astrology?.name); const astrologyText = astrologySymbol && astrologyName ? `${astrologySymbol} ${astrologyName}` : astrologySymbol || astrologyName; @@ -655,12 +730,7 @@ }, { label: "Astrology", - value: astrologyType === "zodiac" && astrologyName - ? createInlineValue([ - astrologySymbol ? `${astrologySymbol} ` : "", - createInlineEventLink(astrologyName, "nav:zodiac", { signId: normalizeId(astrologyName) }) - ]) - : astrologyText + value: createAstrologyValue(edgePath?.astrology, context) || astrologyText } ]; diff --git a/app/ui-cube.js b/app/ui-cube.js index eba2800..4d16f02 100644 --- a/app/ui-cube.js +++ b/app/ui-cube.js @@ -735,6 +735,15 @@ return state.kabbalahPathsByLetterId.get(hebrewLetterId) || null; } + function getPathEntryByLetterId(letterId) { + const normalizedLetterId = normalizeLetterKey(letterId); + if (!normalizedLetterId) { + return null; + } + + return state.kabbalahPathsByLetterId.get(normalizedLetterId) || null; + } + const cubeMathUi = cubeMathHelpers.createCubeMathHelpers({ state, CUBE_VERTICES, @@ -940,6 +949,7 @@ getWallEdgeDirections, getConnectorById, getConnectorPathEntry, + getPathEntryByLetterId, getCubeCenterData, getCenterLetterId, getCenterLetterSymbol, diff --git a/app/ui-elements.js b/app/ui-elements.js index 7f52d72..5f377ff 100644 --- a/app/ui-elements.js +++ b/app/ui-elements.js @@ -90,6 +90,18 @@ .join(" "); } + function resolveHebrewLetterId(letterName) { + const token = normalize(letterName).replace(/[^a-z]/g, ""); + if (!token) { + return ""; + } + + if (token === "yod") return "yod"; + if (token === "vav") return "vav"; + if (token === "heh") return "he"; + return token; + } + function appendInlineParts(target, parts) { (Array.isArray(parts) ? parts : []).forEach((part) => { if (part instanceof Node) { @@ -171,6 +183,7 @@ const aceCardName = ACE_BY_ELEMENT_ID[id] || ""; const hebrewLetter = HEBREW_LETTER_CHAR_BY_ELEMENT_ID[id] || ""; const hebrewLetterName = HEBREW_LETTER_NAME_BY_ELEMENT_ID[id] || ""; + const hebrewLetterId = resolveHebrewLetterId(hebrewLetterName); const courtRank = COURT_RANK_BY_ELEMENT_ID[id] || ""; const courtCardNames = courtRank ? COURT_SUITS.map((suit) => `${courtRank} of ${suit}`) @@ -187,6 +200,7 @@ aceCardName, hebrewLetter, hebrewLetterName, + hebrewLetterId, courtRank, courtCardNames, smallCardGroups, @@ -267,16 +281,48 @@ const detailsCard = document.createElement("div"); detailsCard.className = "planet-meta-card"; - detailsCard.innerHTML = ` - Element Details -
-
Name
${entry.name}
-
Symbol
${entry.symbol || "--"}
-
Hebrew Letter
${entry.hebrewLetter || "--"}
-
Court Rank
${entry.courtRank || "--"}
-
ID
${entry.id}
-
- `; + const detailsTitle = document.createElement("strong"); + detailsTitle.textContent = "Element Details"; + + const detailsList = document.createElement("dl"); + detailsList.className = "alpha-dl"; + + function appendDetailRow(label, value) { + const term = document.createElement("dt"); + term.textContent = label; + + const detail = document.createElement("dd"); + if (value instanceof Node) { + detail.appendChild(value); + } else { + detail.textContent = String(value || "--"); + } + + detailsList.append(term, detail); + } + + appendDetailRow("Name", entry.name); + appendDetailRow("Symbol", entry.symbol || "--"); + + const hebrewLetterLabel = `${entry.hebrewLetter || ""} ${entry.hebrewLetterName || ""}`.trim() || "--"; + appendDetailRow( + "Hebrew Letter", + entry.hebrewLetterId + ? createInlineButton(hebrewLetterLabel, () => { + document.dispatchEvent(new CustomEvent("nav:alphabet", { + detail: { + alphabet: "hebrew", + hebrewLetterId: entry.hebrewLetterId + } + })); + }) + : hebrewLetterLabel + ); + + appendDetailRow("Court Rank", entry.courtRank || "--"); + appendDetailRow("ID", entry.id); + + detailsCard.append(detailsTitle, detailsList); const tarotCard = document.createElement("div"); tarotCard.className = "planet-meta-card"; diff --git a/app/ui-holidays-render.js b/app/ui-holidays-render.js index 086ffdd..b931e46 100644 --- a/app/ui-holidays-render.js +++ b/app/ui-holidays-render.js @@ -253,9 +253,9 @@ : (confidence === "exact" ? "exact" : "approximate"); const monthName = monthLabelForCalendar(holiday?.calendarId, holiday?.monthId); const holidayDate = holiday?.dateText || holiday?.date || holiday?.dateRange || "--"; - const sourceMonthLink = holiday?.monthId - ? `
Source month ${buildInlineNavButton(`${calendarLabel(holiday?.calendarId)} ${monthName}`, "calendar-month", { "calendar-id": holiday.calendarId || "", "month-id": holiday.monthId })}
` - : ""; + const sourceMonthValue = holiday?.monthId + ? buildInlineNavButton(monthName, "calendar-month", { "calendar-id": holiday.calendarId || "", "month-id": holiday.monthId }) + : monthName; return `
@@ -264,7 +264,7 @@
Source Calendar
${calendarLabel(holiday?.calendarId)}
-
Source Month
${monthName}
+
Source Month
${sourceMonthValue}
Source Date
${holidayDate}
Reference Year
${state.selectedYear}
Conversion
${confidenceLabel}
@@ -284,7 +284,6 @@
Description
${holiday?.description || "--"}
- ${sourceMonthLink}
Associations diff --git a/app/ui-iching.js b/app/ui-iching.js index b431704..72f83c6 100644 --- a/app/ui-iching.js +++ b/app/ui-iching.js @@ -95,6 +95,18 @@ return normalizePlanetInfluence(ICHING_PLANET_BY_PLANET_ID[planetId]); } + function resolvePlanetId(value) { + const normalizedValue = normalizePlanetInfluence(value); + if (!normalizedValue) { + return ""; + } + + return Object.entries(ICHING_PLANET_BY_PLANET_ID).find(([planetId, label]) => ( + normalizePlanetInfluence(planetId) === normalizedValue + || normalizePlanetInfluence(label) === normalizedValue + ))?.[0] || ""; + } + function getBinaryPattern(value, expectedLength = 0) { const raw = String(value || "").trim(); if (!raw) { @@ -437,6 +449,35 @@ }); } + function renderPlanetInfluence(entry, elements) { + if (!elements?.ichingDetailPlanetEl) { + return; + } + + clearChildren(elements.ichingDetailPlanetEl); + + const label = entry?.planetaryInfluence || "--"; + const planetId = resolvePlanetId(entry?.planetaryInfluence) + || resolvePlanetId(resolveAssociationPlanetInfluence(entry?.associations)); + + if (!planetId) { + elements.ichingDetailPlanetEl.textContent = label; + return; + } + + const button = document.createElement("button"); + button.type = "button"; + button.className = "detail-inline-link"; + button.textContent = label; + button.addEventListener("click", () => { + document.dispatchEvent(new CustomEvent("nav:planet", { + detail: { planetId } + })); + }); + + elements.ichingDetailPlanetEl.appendChild(button); + } + function renderDetail(entry, elements) { if (!entry || !elements) { return; @@ -482,9 +523,7 @@ } } - if (elements.ichingDetailPlanetEl) { - elements.ichingDetailPlanetEl.textContent = entry.planetaryInfluence || "--"; - } + renderPlanetInfluence(entry, elements); renderKeywords(entry, elements); renderTrigrams(entry, elements); diff --git a/app/ui-tarot-detail.js b/app/ui-tarot-detail.js index 4ecad2a..0e20719 100644 --- a/app/ui-tarot-detail.js +++ b/app/ui-tarot-detail.js @@ -34,6 +34,19 @@ return String(signId || "").trim().toLowerCase(); } + function formatPaddedDegreeRange(startDegree, endDegree) { + const start = Number(startDegree); + const end = Number(endDegree); + if (!Number.isFinite(start) || !Number.isFinite(end)) { + return ""; + } + + const normalizedStart = Math.trunc(start); + const normalizedEnd = Math.trunc(end) - (Math.trunc(end) - Math.trunc(start) === 10 ? 1 : 0); + + return `(${String(normalizedStart).padStart(2, "0")}°-${String(normalizedEnd).padStart(2, "0")}°)`; + } + function buildDecanSummaryRelations(relations) { const decanRelations = (relations || []).filter((relation) => relation?.type === "decan"); const signWindowRelations = (relations || []).filter((relation) => relation?.type === "signWindow"); @@ -98,9 +111,7 @@ ? String(getDisplayCardName?.(decanCardName) || decanCardName).trim() : ""; const signLabel = `${signSymbol} ${signName}`.replace(/\s+/g, " ").trim(); - const degreeLabel = Number.isFinite(startDegree) && Number.isFinite(endDegree) - ? `(${startDegree}°-${endDegree}°)` - : ""; + const degreeLabel = formatPaddedDegreeRange(startDegree, endDegree); const dateLabel = normalizeInlineDateRange(dateRange); const summaryParts = [ rulerLabel, @@ -138,9 +149,7 @@ .map((entry) => String(getDisplayCardName?.(entry?.data?.cardName) || entry?.data?.cardName || "").trim()) .filter(Boolean))]; const signLabel = `${signSymbol} ${signName}`.replace(/\s+/g, " ").trim(); - const degreeLabel = Number.isFinite(startDegree) && Number.isFinite(endDegree) - ? `(${startDegree}°-${endDegree}°)` - : ""; + const degreeLabel = formatPaddedDegreeRange(startDegree, endDegree); const dateLabel = normalizeInlineDateRange(dateRange); const summaryParts = [ cardLabels.join(", "), @@ -181,6 +190,47 @@ }); } + function createInlineButton(label, eventName, detail) { + const button = document.createElement("button"); + button.type = "button"; + button.className = "detail-inline-link"; + button.textContent = String(label || "—"); + button.addEventListener("click", () => { + document.dispatchEvent(new CustomEvent(eventName, { detail })); + }); + return button; + } + + function createInlineValue(parts) { + const inline = document.createElement("div"); + inline.className = "planet-text detail-inline-value"; + + (Array.isArray(parts) ? parts : []).forEach((part) => { + if (part instanceof Node) { + inline.appendChild(part); + return; + } + + const text = String(part || ""); + if (text) { + inline.appendChild(document.createTextNode(text)); + } + }); + + return inline; + } + + function resolvePlanetId(value) { + const token = String(value || "").trim().toLowerCase(); + if (!token) { + return ""; + } + + if (token === "sun") return "sol"; + if (token === "moon") return "luna"; + return token; + } + function collectDetailRelations(card) { const allRelations = (card.relations || []) .map((relation, index) => normalizeRelationObject(relation, index)) @@ -447,63 +497,116 @@ const letter = kabPath.hebrewLetter || {}; const fromName = kabTree.sephiroth.find((seph) => seph.number === kabPath.connects.from)?.name || kabPath.connects.from; const toName = kabTree.sephiroth.find((seph) => seph.number === kabPath.connects.to)?.name || kabPath.connects.to; - const astro = kabPath.astrology ? `${kabPath.astrology.name} (${kabPath.astrology.type})` : ""; + const astrologyType = String(kabPath.astrology?.type || "").trim().toLowerCase(); + const astrologyName = String(kabPath.astrology?.name || "").trim(); kabPathEl.innerHTML = ` - Kabbalah Tree — Path ${kabPath.pathNumber} + Kabbalah Tree
${letter.char || ""} - ${letter.transliteration || ""} — “${letter.meaning || ""}” · ${letter.letterType || ""} - ${fromName} → ${toName}${astro ? " · " + astro : ""} + +
`; - const btn = document.createElement("button"); - btn.type = "button"; - btn.className = "detail-inline-link"; - btn.textContent = `Path ${kabPath.pathNumber}`; - btn.addEventListener("click", () => { - document.dispatchEvent(new CustomEvent("tarot:view-kab-path", { - detail: { pathNumber: kabPath.pathNumber } + const pathNameEl = kabPathEl.querySelector(".tarot-kab-name"); + if (pathNameEl) { + pathNameEl.appendChild(createInlineButton(`Path ${kabPath.pathNumber}`, "nav:kabbalah-path", { + pathNo: kabPath.pathNumber })); - }); - const inline = document.createElement("div"); - inline.className = "planet-text detail-inline-value"; - inline.appendChild(document.createTextNode("Kabbalah ")); - inline.appendChild(btn); - kabPathEl.appendChild(inline); + pathNameEl.appendChild(document.createTextNode(` — ${letter.transliteration || ""}`)); + if (letter.meaning) { + pathNameEl.appendChild(document.createTextNode(` - \"${letter.meaning}\"`)); + } + if (letter.letterType) { + pathNameEl.appendChild(document.createTextNode(` - ${letter.letterType}`)); + } + } + + const connectsEl = kabPathEl.querySelector(".tarot-kab-connects"); + if (connectsEl) { + connectsEl.appendChild(createInlineButton(fromName, "nav:kabbalah-path", { + pathNo: kabPath.connects.from + })); + connectsEl.appendChild(document.createTextNode(" → ")); + connectsEl.appendChild(createInlineButton(toName, "nav:kabbalah-path", { + pathNo: kabPath.connects.to + })); + if (astrologyName) { + connectsEl.appendChild(document.createTextNode(" · ")); + if (astrologyType === "planet") { + connectsEl.appendChild(createInlineButton(astrologyName, "nav:planet", { + planetId: resolvePlanetId(astrologyName) + })); + } else if (astrologyType === "zodiac") { + connectsEl.appendChild(createInlineButton(astrologyName, "nav:zodiac", { + signId: astrologyName.toLowerCase() + })); + } else { + connectsEl.appendChild(document.createTextNode(`${astrologyName} (${astrologyType || "astrology"})`)); + } + } + } + + const letterId = String(letter.transliteration || "").trim().toLowerCase(); + if (letterId) { + kabPathEl.appendChild(createInlineValue([ + "Hebrew ", + createInlineButton(`${letter.char || ""} ${letter.transliteration || letterId}`.trim(), "nav:alphabet", { + alphabet: "hebrew", + hebrewLetterId: letterId + }) + ])); + } + kabPathEl.hidden = false; } else if (kabSeph) { const hebrewName = kabSeph.nameHebrew ? ` (${kabSeph.nameHebrew})` : ""; const translation = kabSeph.translation ? ` — ${kabSeph.translation}` : ""; const planetInfo = kabSeph.planet || ""; const tarotInfo = kabSeph.tarot ? ` · ${kabSeph.tarot}` : ""; + const resolvedPlanetId = resolvePlanetId(planetInfo); kabPathEl.innerHTML = ` - Kabbalah Tree — Sephirah ${kabSeph.number} + Kabbalah Tree
- ${kabSeph.number} + - ${kabSeph.name || ""}${hebrewName}${translation} - ${planetInfo}${tarotInfo} + +
`; - const btn = document.createElement("button"); - btn.type = "button"; - btn.className = "detail-inline-link"; - btn.textContent = `Sephirah ${kabSeph.number}`; - btn.addEventListener("click", () => { - document.dispatchEvent(new CustomEvent("tarot:view-kab-path", { - detail: { pathNumber: kabSeph.number } + const sephirahLetterEl = kabPathEl.querySelector(".tarot-kab-letter"); + if (sephirahLetterEl) { + sephirahLetterEl.appendChild(createInlineButton(`${kabSeph.number}`, "nav:kabbalah-path", { + pathNo: kabSeph.number })); - }); - const inline = document.createElement("div"); - inline.className = "planet-text detail-inline-value"; - inline.appendChild(document.createTextNode("Kabbalah ")); - inline.appendChild(btn); - kabPathEl.appendChild(inline); + } + const sephirahNameEl = kabPathEl.querySelector(".tarot-kab-name"); + if (sephirahNameEl) { + sephirahNameEl.appendChild(createInlineButton(`Sephirah ${kabSeph.number} — ${kabSeph.name || "Sephirah"}${hebrewName}${translation}`, "nav:kabbalah-path", { + pathNo: kabSeph.number + })); + } + + const sephirahConnectsEl = kabPathEl.querySelector(".tarot-kab-connects"); + if (sephirahConnectsEl) { + if (resolvedPlanetId) { + sephirahConnectsEl.appendChild(createInlineButton(planetInfo, "nav:planet", { planetId: resolvedPlanetId })); + } else if (planetInfo) { + sephirahConnectsEl.appendChild(document.createTextNode(planetInfo)); + } + + if (tarotInfo) { + if (sephirahConnectsEl.childNodes.length) { + sephirahConnectsEl.appendChild(document.createTextNode(" · ")); + } + sephirahConnectsEl.appendChild(document.createTextNode(String(kabSeph.tarot || ""))); + } + } + kabPathEl.hidden = false; } else { kabPathEl.hidden = true; diff --git a/app/ui-zodiac.js b/app/ui-zodiac.js index 1193652..1288c67 100644 --- a/app/ui-zodiac.js +++ b/app/ui-zodiac.js @@ -59,6 +59,14 @@ return String(s || "").charAt(0).toUpperCase() + String(s || "").slice(1); } + function normalizeHebrewLetterId(value) { + return String(value || "") + .trim() + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-+|-+$/g, ""); + } + function buildSearchText(sign) { return norm([ sign.name?.en, sign.meaning?.en, sign.elementId, sign.quadruplicity, @@ -142,7 +150,7 @@ const sections = []; // ── Sign Details ────────────────────────────────────────────────── - const elemBadge = `${elemStyle.emoji || ""} ${cap(sign.elementId)}`; + const elemBadge = ``; const quadBadge = `${cap(sign.quadruplicity)}`; sections.push(`
Sign Details @@ -178,13 +186,15 @@ // ── Kabbalah Path + Trump ───────────────────────────────────────── if (kabPath) { const hl = kabPath.hebrewLetter || {}; + const hebrewLetterId = normalizeHebrewLetterId(hl.transliteration); + const hebrewLetterLabel = hl.transliteration || hl.char || ""; sections.push(`
Kabbalah & Major Arcana
${hl.char || ""}
-
${hl.transliteration || ""} (${hl.meaning || ""})
+
${hebrewLetterId ? `` : hebrewLetterLabel}${hl.meaning ? ` (${hl.meaning})` : ""}
${cap(hl.letterType || "")} letter ·
@@ -203,7 +213,7 @@ const sym = PLANET_SYMBOLS[d.rulerPlanetId] || ""; return `
${ord} - ${sym} ${cap(d.rulerPlanetId)} + ${sym ? `${sym} ` : ""} @@ -249,6 +259,17 @@ document.dispatchEvent(new CustomEvent("nav:planet", { detail: { planetId: btn.dataset.planetId } })); + } else if (nav === "element") { + document.dispatchEvent(new CustomEvent("nav:elements", { + detail: { elementId: btn.dataset.elementId } + })); + } else if (nav === "alphabet") { + document.dispatchEvent(new CustomEvent("nav:alphabet", { + detail: { + alphabet: "hebrew", + hebrewLetterId: btn.dataset.hebrewLetterId + } + })); } else if (nav === "kab-path") { document.dispatchEvent(new CustomEvent("tarot:view-kab-path", { detail: { pathNumber: Number(btn.dataset.pathNumber) } diff --git a/index.html b/index.html index 834d463..55622d2 100644 --- a/index.html +++ b/index.html @@ -1191,47 +1191,47 @@ - + - + - + - + - + - + - + - + - + - + - +