From 8f17782a5f2adbafd031b269195879eb7f79e05f Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Thu, 23 Nov 2023 11:16:48 -0400 Subject: data, content: extract external link parsing into nicer interface --- src/data/things/language.js | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'src/data/things/language.js') diff --git a/src/data/things/language.js b/src/data/things/language.js index 646eb6d1..185488e2 100644 --- a/src/data/things/language.js +++ b/src/data/things/language.js @@ -1,5 +1,11 @@ -import {Tag} from '#html'; import {isLanguageCode} from '#validators'; +import {Tag} from '#html'; + +import { + getExternalLinkStringsFromDescriptors, + isExternalLinkSpec, + isExternalLinkStyle, +} from '#external-links'; import { externalFunction, @@ -72,6 +78,13 @@ export class Language extends Thing { update: {validate: (t) => typeof t === 'object'}, }, + // List of descriptors for providing to external link utilities when using + // language.formatExternalLink - refer to util/external-links.js for info. + externalLinkSpec: { + flags: {update: true, expose: true}, + update: {validate: isExternalLinkSpec}, + }, + // Update only escapeHTML: externalFunction(), @@ -299,6 +312,25 @@ export class Language extends Thing { : duration; } + formatExternalLink(url, {style = 'normal'} = {}) { + if (!this.externalLinkSpec) { + throw new TypeError(`externalLinkSpec unavailable`); + } + + if (style !== 'all') { + isExternalLinkStyle(style); + } + + const results = + getExternalLinkStringsFromDescriptors(url, this.externalLinkSpec, this); + + if (style === 'all') { + return results; + } else { + return results[style]; + } + } + formatIndex(value) { this.assertIntlAvailable('intl_pluralOrdinal'); return this.formatString('count.index.' + this.intl_pluralOrdinal.select(value), {index: value}); -- cgit 1.3.0-6-gf8a5 From cf08893d48db6f8082a176f54d0d92cb82716b3a Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Thu, 23 Nov 2023 18:50:59 -0400 Subject: external-links: general support for page-contextual formatting --- src/data/things/language.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/data/things/language.js') diff --git a/src/data/things/language.js b/src/data/things/language.js index 185488e2..f83b4218 100644 --- a/src/data/things/language.js +++ b/src/data/things/language.js @@ -3,6 +3,7 @@ import {Tag} from '#html'; import { getExternalLinkStringsFromDescriptors, + isExternalLinkContext, isExternalLinkSpec, isExternalLinkStyle, } from '#external-links'; @@ -312,17 +313,22 @@ export class Language extends Thing { : duration; } - formatExternalLink(url, {style = 'normal'} = {}) { + formatExternalLink(url, { + style = 'normal', + context = 'generic', + } = {}) { if (!this.externalLinkSpec) { throw new TypeError(`externalLinkSpec unavailable`); } - if (style !== 'all') { - isExternalLinkStyle(style); - } + if (style !== 'all') isExternalLinkStyle(style); + isExternalLinkContext(context); const results = - getExternalLinkStringsFromDescriptors(url, this.externalLinkSpec, this); + getExternalLinkStringsFromDescriptors(url, this.externalLinkSpec, { + language: this, + context, + }); if (style === 'all') { return results; -- cgit 1.3.0-6-gf8a5 From ba6c4e043b3364481ac3beff1e2a141d1bfcf6fb Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Thu, 23 Nov 2023 20:47:34 -0400 Subject: external-links: cleaner per-style logic --- src/data/things/language.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/data/things/language.js') diff --git a/src/data/things/language.js b/src/data/things/language.js index f83b4218..70481299 100644 --- a/src/data/things/language.js +++ b/src/data/things/language.js @@ -2,6 +2,7 @@ import {isLanguageCode} from '#validators'; import {Tag} from '#html'; import { + getExternalLinkStringOfStyleFromDescriptors, getExternalLinkStringsFromDescriptors, isExternalLinkContext, isExternalLinkSpec, @@ -321,20 +322,19 @@ export class Language extends Thing { throw new TypeError(`externalLinkSpec unavailable`); } - if (style !== 'all') isExternalLinkStyle(style); isExternalLinkContext(context); - const results = - getExternalLinkStringsFromDescriptors(url, this.externalLinkSpec, { + if (style === 'all') { + return getExternalLinkStringsFromDescriptors(url, this.externalLinkSpec, { language: this, context, }); - - if (style === 'all') { - return results; - } else { - return results[style]; } + + return getExternalLinkStringOfStyleFromDescriptors(url, style, this.externalLinkSpec, { + language: this, + context, + }); } formatIndex(value) { -- cgit 1.3.0-6-gf8a5 From 8238f11469c64e6a2a735ca43a70e2a665ef63f1 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Sun, 26 Nov 2023 17:32:54 -0400 Subject: data: minor fixes caught by eslint --- src/data/things/language.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/data/things/language.js') diff --git a/src/data/things/language.js b/src/data/things/language.js index 70481299..d8af9620 100644 --- a/src/data/things/language.js +++ b/src/data/things/language.js @@ -331,6 +331,8 @@ export class Language extends Thing { }); } + isExternalLinkStyle(style); + return getExternalLinkStringOfStyleFromDescriptors(url, style, this.externalLinkSpec, { language: this, context, -- cgit 1.3.0-6-gf8a5 From 017be69511d1d3638fa834ffb1300fbbb9a187b7 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Wed, 29 Nov 2023 21:41:16 -0400 Subject: data: language: formatDateDuration, formatRelativeDate Also related counting functions. --- src/data/things/language.js | 108 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) (limited to 'src/data/things/language.js') diff --git a/src/data/things/language.js b/src/data/things/language.js index d8af9620..fa529a8e 100644 --- a/src/data/things/language.js +++ b/src/data/things/language.js @@ -1,3 +1,5 @@ +import { Temporal, toTemporalInstant } from '@js-temporal/polyfill'; + import {isLanguageCode} from '#validators'; import {Tag} from '#html'; @@ -284,6 +286,108 @@ export class Language extends Thing { return this.intl_date.formatRange(startDate, endDate); } + formatDateDuration({ + years: numYears = 0, + months: numMonths = 0, + days: numDays = 0, + approximate = false, + }) { + let basis; + + const years = this.countYears(numYears, {unit: true}); + const months = this.countMonths(numMonths, {unit: true}); + const days = this.countDays(numDays, {unit: true}); + + if (numYears && numMonths && numDays) + basis = this.formatString('count.dateDuration.yearsMonthsDays', {years, months, days}); + else if (numYears && numMonths) + basis = this.formatString('count.dateDuration.yearsMonths', {years, months}); + else if (numYears && numDays) + basis = this.formatString('count.dateDuration.yearsDays', {years, days}); + else if (numYears) + basis = this.formatString('count.dateDuration.years', {years}); + else if (numMonths && numDays) + basis = this.formatString('count.dateDuration.monthsDays', {months, days}); + else if (numMonths) + basis = this.formatzString('count.dateDuration.months', {months}); + else if (numDays) + basis = this.formatString('count.dateDuration.days', {days}); + else + return this.formatString('count.dateDuration.zero'); + + if (approximate) { + return this.formatString('count.dateDuration.approximate', { + duration: basis, + }); + } else { + return basis; + } + } + + formatRelativeDate(currentDate, referenceDate, { + considerRoundingDays = false, + approximate = true, + absolute = true, + } = {}) { + const currentInstant = toTemporalInstant.apply(currentDate); + const referenceInstant = toTemporalInstant.apply(referenceDate); + + const comparison = + Temporal.Instant.compare(currentInstant, referenceInstant); + + if (comparison === 0) { + return this.formatString('count.dateDuration.same'); + } + + const currentTDZ = currentInstant.toZonedDateTimeISO('Etc/UTC'); + const referenceTDZ = referenceInstant.toZonedDateTimeISO('Etc/UTC'); + + const earlierTDZ = (comparison === -1 ? currentTDZ : referenceTDZ); + const laterTDZ = (comparison === 1 ? currentTDZ : referenceTDZ); + + const {years, months, days} = + laterTDZ.since(earlierTDZ, { + largestUnit: 'year', + smallestUnit: + (considerRoundingDays + ? (laterTDZ.since(earlierTDZ, { + largestUnit: 'year', + smallestUnit: 'day', + }).years + ? 'month' + : 'day') + : 'day'), + roundingMode: 'halfCeil', + }); + + const duration = + this.formatDateDuration({ + years, months, days, + approximate: false, + }); + + const relative = + this.formatString( + 'count.dateDuration', + (approximate + ? (comparison === -1 + ? 'approximateEarlier' + : 'approximateLater') + : (comparison === -1 + ? 'earlier' + : 'later')), + {duration}); + + if (absolute) { + return this.formatString('count.dateDuration.relativeAbsolute', { + relative, + absolute: this.formatDate(currentDate), + }); + } else { + return relative; + } + } + formatDuration(secTotal, {approximate = false, unit = false} = {}) { if (secTotal === 0) { return this.formatString('count.duration.missing'); @@ -442,7 +546,11 @@ Object.assign(Language.prototype, { countCommentaryEntries: countHelper('commentaryEntries', 'entries'), countContributions: countHelper('contributions'), countCoverArts: countHelper('coverArts'), + countDays: countHelper('days'), + countMonths: countHelper('months'), countTimesReferenced: countHelper('timesReferenced'), countTimesUsed: countHelper('timesUsed'), countTracks: countHelper('tracks'), + countWeeks: countHelper('weeks'), + countYears: countHelper('years'), }); -- cgit 1.3.0-6-gf8a5 From 168efd0f2685fa00259fffc9f26c7f6a30a61991 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Wed, 29 Nov 2023 22:29:26 -0400 Subject: data: language: don't approximate same date in formatRelativeDate --- src/data/things/language.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/data/things/language.js') diff --git a/src/data/things/language.js b/src/data/things/language.js index fa529a8e..80a34575 100644 --- a/src/data/things/language.js +++ b/src/data/things/language.js @@ -369,7 +369,7 @@ export class Language extends Thing { const relative = this.formatString( 'count.dateDuration', - (approximate + (approximate && (years || months || days) ? (comparison === -1 ? 'approximateEarlier' : 'approximateLater') -- cgit 1.3.0-6-gf8a5