From 05dd46c2f36787e71f4a3a3d7ac0febf3c6f9309 Mon Sep 17 00:00:00 2001 From: Terry Truong Date: Sat, 14 Jan 2023 14:31:14 +1100 Subject: Extend info modal date display Show combined descriptions for certain (imprecise) starts and ends. Conditionally display start and end separately. --- src/components/InfoModal.vue | 18 ++++++---- src/lib.ts | 80 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 79 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/components/InfoModal.vue b/src/components/InfoModal.vue index d2ac425..0b46be0 100644 --- a/src/components/InfoModal.vue +++ b/src/components/InfoModal.vue @@ -7,7 +7,14 @@

{{event.title}}

-

{{datesDisplayStr}}

+ +
+ {{datesDisplayStrs.length == 1 ? 'Time' : 'Start'}}: {{datesDisplayStrs[0]}} +
+
+ End: {{datesDisplayStrs[1]}} +
+
@@ -75,7 +82,7 @@ import SCollapsible from './SCollapsible.vue'; import CloseIcon from './icon/CloseIcon.vue'; import DownIcon from './icon/DownIcon.vue'; import ExternalLinkIcon from './icon/ExternalLinkIcon.vue'; -import {EventInfo, boundedDateToStr, getImagePath} from '../lib'; +import {EventInfo, eventDatesToStrings, getImagePath} from '../lib'; import {useStore} from '../store'; // Refs @@ -93,11 +100,8 @@ const emit = defineEmits(['close']); // For data display const event = computed(() => props.eventInfo.event) -const datesDisplayStr = computed(() => { - const startStr = boundedDateToStr(event.value.start, event.value.startUpper); - const endStr = event.value.end == null ? null : boundedDateToStr(event.value.end, event.value.endUpper); - return 'Start: ' + startStr + (endStr == null ? '' : ', End: ' + endStr); -}); +const datesDisplayStrs = computed( + () => eventDatesToStrings(event.value.start, event.value.startUpper, event.value.end, event.value.endUpper)); function licenseToUrl(license: string){ license = license.toLowerCase().replaceAll('-', ' '); if (license == 'cc0'){ diff --git a/src/lib.ts b/src/lib.ts index 6833520..52413bb 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -261,9 +261,9 @@ export class HistDate { } else { return `${this.year}`; // eg: 2010 } - } else { // eg: 2nd Mar 1710 BC (OS) - let bcSuffix = this.year < 0 ? ' BC' : (this.year < 1500 ? ' AD' : ''); - let calStr = this.gcal ? '' : ' (OS)'; + } else { // eg: 2nd Mar 1710 BC (O.S.) + const bcSuffix = this.year < 0 ? ' BC' : (this.year < 1500 ? ' AD' : ''); + const calStr = this.gcal ? '' : ' (O.S.)'; return `${intToOrdinal(this.day)} ${MONTH_NAMES[this.month-1]} ${Math.abs(this.year)}${bcSuffix}${calStr}`; } } @@ -312,7 +312,7 @@ export function boundedDateToStr(start: HistDate, end: HistDate | null) : string const startMatch = dateRegex.exec(startStr)!; const endMatch = dateRegex.exec(endStr)!; if (startMatch[2] == endMatch[2]){ // Same billion/million/thousand scale - let startZeros = getNumTrailingZeros(start.year); + const startZeros = getNumTrailingZeros(start.year); if (startZeros >= 4 && end.year == start.year + 10 ** startZeros - 1 || (start.year - 1) % 1e3 == 0 && end.year == start.year + 999){ return `About ${startStr}`; // Includes cases like -20_000 to -10_001 and -21999 to -21000 @@ -322,23 +322,23 @@ export function boundedDateToStr(start: HistDate, end: HistDate | null) : string return `${startMatch[1]} ${startMatch[2]} to ${endMatch[1]} ${endMatch[2]} years ago`; } } else if (moduloPositive(start.year, 1000) == 1 && end.year == start.year + 999){ // eg: 2nd millenium - let ordinal = intToOrdinal(Math.abs(start.year - 1) / 1000 + (start.year > 0 ? 1 : 0)); + const ordinal = intToOrdinal(Math.abs(start.year - 1) / 1000 + (start.year > 0 ? 1 : 0)); return ordinal + ' millenium' + (start.year < 0 ? ' BC' : ''); } else if (moduloPositive(start.year, 100) == 1 && end.year == start.year + 99){ // eg: 4th century BC - let ordinal = intToOrdinal(Math.abs(start.year - 1) / 100 + (start.year > 0 ? 1 : 0)); + const ordinal = intToOrdinal(Math.abs(start.year - 1) / 100 + (start.year > 0 ? 1 : 0)); return ordinal + ' century' + (start.year < 0 ? ' BC' : ''); } else if (start.year % 10 == 0 && end.year == start.year + 9){ // eg: 1880s return String(start.year) + 's'; } else { - const suffixes = [' BC', ' AD']; - for (let suffix of suffixes){ // eg: 1st Jan to 2nd Feb 100 AD - if (startStr.endsWith(suffix) && endStr.endsWith(suffix)){ - return startStr.slice(0, startStr.length - suffix.length) + ' to ' + endStr; - } + const bcRegex = /^(.*)( (BC|AD))$/; + const startMatch = bcRegex.exec(startStr); + const endMatch = bcRegex.exec(endStr); + if (startMatch != null && endMatch != null && startMatch[2] == endMatch[2]){ + return `${startMatch[1]} to ${endStr}`; } } } else if (start.gcal != null && end.gcal != null){ - const dateRegex = /^(\S*) (\S*) (.*)$/; // Matches day, month, and suffix + const dateRegex = /^(\S+) (\S+) (.*)$/; // Matches day, month, and suffix const startMatch = dateRegex.exec(startStr); const endMatch = dateRegex.exec(endStr); if (startMatch != null && endMatch != null && startMatch[3] == endMatch[3]){ // Same suffix @@ -354,6 +354,62 @@ export function boundedDateToStr(start: HistDate, end: HistDate | null) : string } return `${startStr} to ${endStr}`; } +export function eventDatesToStrings( + start: HistDate, startUpper: HistDate | null, end: HistDate | null, endUpper: HistDate | null) + : [string] | [string, string] { + if (end == null){ + return [boundedDateToStr(start, startUpper)]; + } + const startStr = boundedDateToStr(start, startUpper); + const endStr = boundedDateToStr(end, endUpper); + if (startStr == endStr){ + return [startStr]; + } + if (startStr.includes(' to ') || startStr.startsWith('About ') + || endStr.includes(' to ') || endStr.startsWith('About ')){ + return [startStr, endStr]; + } + let startMatch: null | string[]; + let endMatch: null | string[]; + if (start.gcal == null && end.gcal == null){ + if (startStr.endsWith(' years ago') && endStr.endsWith(' years ago')){ + const yaRegex = /^(.*) (.*) years ago$/; + startMatch = yaRegex.exec(startStr)!; + endMatch = yaRegex.exec(endStr)!; + if (startMatch[2] == endMatch[2]){ // Same billion/million/thousand scale + return [`${startMatch[1]} to ${endMatch[1]} ${startMatch[2]} years ago`]; + } else { + return [`${startMatch[1]} ${startMatch[2]} to ${endMatch[1]} ${endMatch[2]} years ago`]; + } + } + const mcRegex = /^(.*) (millenium|century( (BC|AD))?)$/; + startMatch = mcRegex.exec(startStr); + endMatch = mcRegex.exec(endStr); + if (startMatch != null && endMatch != null && startMatch[2] == endMatch[2]){ + return [`${startMatch[1]} to ${endMatch[1]} ${startMatch[2]}`]; + } + const bcRegex = /^(.*) (BC|AD)$/; + startMatch = bcRegex.exec(startStr); + endMatch = bcRegex.exec(endStr); + if (startMatch != null && endMatch != null && startMatch[2] == endMatch[2]){ + return [`${startMatch[1]} to ${endStr}`]; + } + } else if (start.gcal != null && end.gcal != null){ + const calRegex = /^(\S+ )?(\S+) (.*)$/; // Matches day (optional), month, and suffix + startMatch = calRegex.exec(startStr); + endMatch = calRegex.exec(endStr); + if (startMatch != null && endMatch != null && startMatch[3] == endMatch[3]){ // Same suffix + if (startMatch[2] == endMatch[2]){ // Same month + return [`${startMatch[1]}to ${endMatch[1]}${startMatch[2]} ${startMatch[3]}`]; + } + if (startMatch[1] == null){ + return [`${startMatch[2]} to ${endMatch[2]} ${startMatch[3]}`]; + } + return [`${startMatch[1]}${startMatch[2]} to ${endMatch[1]}${endMatch[2]} ${startMatch[3]}`]; + } + } + return [startStr, endStr]; +} // For event representation export class HistEvent { -- cgit v1.2.3