work on events
This commit is contained in:
parent
2dd300f4dc
commit
7297f9cd7a
@ -5,12 +5,13 @@ import { BuildState } from './state';
|
|||||||
import { mkdirp, write_text } from '../fs';
|
import { mkdirp, write_text } from '../fs';
|
||||||
import { CalendarConfig, RSSConfig } from '../conf';
|
import { CalendarConfig, RSSConfig } from '../conf';
|
||||||
import { render_theme_css_properties } from '../themes';
|
import { render_theme_css_properties } from '../themes';
|
||||||
import { load_partials, FrontMatter, Context, load_layout, render_template } from '../template';
|
import { load_partials, FrontMatter, Context, load_layout, render_template, EventFrontmatter } from '../template';
|
||||||
import { render_markdown_to_html, render_markdown_to_html_inline_sync } from '@doc-utils/markdown2html';
|
import { render_markdown_to_html, render_markdown_to_html_inline_sync } from '@doc-utils/markdown2html';
|
||||||
import { RSSEntry } from './rss';
|
import { RSSEntry } from './rss';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { EventEntry } from './icalendar';
|
import { EventEntry } from './icalendar';
|
||||||
import { as_context_time, as_html_time, from_iso } from '../time';
|
import { as_context_time, as_html_time, from_iso } from '../time';
|
||||||
|
import { FileMetadata } from '../metadata';
|
||||||
|
|
||||||
export interface OutFileURL {
|
export interface OutFileURL {
|
||||||
base_url: string;
|
base_url: string;
|
||||||
@ -82,31 +83,42 @@ export async function build_partials(state: BuildState) {
|
|||||||
Object.assign(state.partials, state.extras);
|
Object.assign(state.partials, state.extras);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mustache_context(state: BuildState, page_url: string, frontmatter?: FrontMatter) : Context {
|
export function mustache_context(state: BuildState, page_url: string, metadata: FileMetadata, frontmatter?: FrontMatter) : Context {
|
||||||
let event: Context['event'] = {
|
let event: Context['event'];
|
||||||
start: null,
|
|
||||||
end: null,
|
|
||||||
zone: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (frontmatter?.event) {
|
if (frontmatter?.event) {
|
||||||
const start = from_iso(frontmatter.event.start, frontmatter.event.zone);
|
event = Array.isArray(frontmatter.event)
|
||||||
event.start = as_context_time(start);
|
? frontmatter.event.map(to_context_event)
|
||||||
|
: to_context_event(frontmatter.event);
|
||||||
|
|
||||||
const end = from_iso(frontmatter.event.end, frontmatter.event.zone);
|
function to_context_event(event_fm: EventFrontmatter) {
|
||||||
event.end = as_context_time(end);
|
const start = from_iso(event_fm.start, event_fm.time_zone);
|
||||||
|
const end = from_iso(event_fm.end, event_fm.time_zone);
|
||||||
|
|
||||||
event.zone = frontmatter.event.zone;
|
return {
|
||||||
|
start: as_context_time(start),
|
||||||
|
end: as_context_time(end),
|
||||||
|
time_zone: event_fm.time_zone,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const has_been_updated = metadata.first_seen_time !== metadata.last_updated_time;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
env: state.env,
|
env: state.env,
|
||||||
page: frontmatter,
|
page: frontmatter,
|
||||||
base_url: state.conf.base_url,
|
base_url: state.conf.base_url,
|
||||||
page_url: page_url,
|
page_url: page_url,
|
||||||
|
page_published: as_context_time(from_iso(metadata.first_seen_time), 'dt-published'),
|
||||||
|
page_updated: has_been_updated ? as_context_time(from_iso(metadata.last_updated_time), 'dt-updated') : null,
|
||||||
site_title: state.conf.title,
|
site_title: state.conf.title,
|
||||||
author: get_author(state, frontmatter),
|
author: get_author(state, frontmatter),
|
||||||
event: event,
|
event: event,
|
||||||
|
event_series: Array.isArray(event) && {
|
||||||
|
start: event[0].start,
|
||||||
|
end: event[event.length - 1].end,
|
||||||
|
},
|
||||||
build_time: state.build_time,
|
build_time: state.build_time,
|
||||||
icons: icons,
|
icons: icons,
|
||||||
rss_feeds: state.conf.rss || [ ],
|
rss_feeds: state.conf.rss || [ ],
|
||||||
@ -127,7 +139,7 @@ export function mustache_context(state: BuildState, page_url: string, frontmatte
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function render_page(state: BuildState, in_file: string, out_file: string, out_url: OutFileURL, text: string, render_as_markdown: boolean, frontmatter?: any) {
|
export async function render_page(state: BuildState, in_file: string, out_file: string, out_url: OutFileURL, text: string, render_as_markdown: boolean, hash: string, frontmatter?: any) {
|
||||||
if (render_as_markdown) {
|
if (render_as_markdown) {
|
||||||
const opts = Object.assign({ }, state.conf.markdown, {
|
const opts = Object.assign({ }, state.conf.markdown, {
|
||||||
base_url: out_url.abs_url
|
base_url: out_url.abs_url
|
||||||
@ -147,11 +159,21 @@ export async function render_page(state: BuildState, in_file: string, out_file:
|
|||||||
layout = state.layouts[layout_file];
|
layout = state.layouts[layout_file];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hash_matches = file_hash_matches(state, in_file, hash);
|
||||||
|
const rel_in_file = in_file.slice(state.conf.input.root.length);
|
||||||
|
const old_metadata = state.old_metadata?.files?.[rel_in_file];
|
||||||
|
const new_metadata = hash_matches ? structuredClone(old_metadata) : {
|
||||||
|
first_seen_time: old_metadata?.first_seen_time || state.build_time.iso,
|
||||||
|
last_build_hash: hash,
|
||||||
|
last_updated_time: state.build_time.iso,
|
||||||
|
};
|
||||||
|
|
||||||
const tags = state.conf.templates?.tags;
|
const tags = state.conf.templates?.tags;
|
||||||
const context = mustache_context(state, out_url.abs_url, frontmatter);
|
const context = mustache_context(state, out_url.abs_url, new_metadata, frontmatter);
|
||||||
const rendered = render_template(text, context, layout, structuredClone(state.partials), tags);
|
const rendered = render_template(text, context, layout, structuredClone(state.partials), tags);
|
||||||
await write_text(out_file, rendered);
|
await write_text(out_file, rendered);
|
||||||
|
|
||||||
|
state.new_metadata.files[rel_in_file] = new_metadata;
|
||||||
handle_page_side_effects(state, in_file, out_file, out_url, text, frontmatter);
|
handle_page_side_effects(state, in_file, out_file, out_url, text, frontmatter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,16 +252,30 @@ function handle_event(state: BuildState, in_file: string, out_url: OutFileURL, f
|
|||||||
const author_or_authors = get_author(state, frontmatter);
|
const author_or_authors = get_author(state, frontmatter);
|
||||||
const author = Array.isArray(author_or_authors) ? author_or_authors[0] : author_or_authors;
|
const author = Array.isArray(author_or_authors) ? author_or_authors[0] : author_or_authors;
|
||||||
|
|
||||||
|
if (Array.isArray(frontmatter.event)) {
|
||||||
|
state.event_series.push({
|
||||||
|
url: out_url.abs_url,
|
||||||
|
in_file: in_file,
|
||||||
|
title: frontmatter.title,
|
||||||
|
description: frontmatter.description,
|
||||||
|
author_name: author?.name,
|
||||||
|
author_email: author?.email,
|
||||||
|
entries: frontmatter.event.slice(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
state.events.push({
|
state.events.push({
|
||||||
url: out_url.abs_url,
|
url: out_url.abs_url,
|
||||||
in_file: in_file,
|
in_file: in_file,
|
||||||
title: frontmatter.title,
|
title: frontmatter.event.title || frontmatter.title,
|
||||||
description: frontmatter.description,
|
description: frontmatter.description,
|
||||||
author_name: author?.name,
|
author_name: author?.name,
|
||||||
author_email: author?.email,
|
author_email: author?.email,
|
||||||
start_time: frontmatter.event?.start,
|
start: frontmatter.event.start,
|
||||||
end_time: frontmatter.event?.end,
|
end: frontmatter.event.end,
|
||||||
time_zone: frontmatter.event?.zone,
|
time_zone: frontmatter.event.time_zone,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,6 +283,12 @@ function handle_calendar(state: BuildState, cal_conf: CalendarConfig, entries: E
|
|||||||
const author_or_authors = get_author(state, frontmatter);
|
const author_or_authors = get_author(state, frontmatter);
|
||||||
const author = Array.isArray(author_or_authors) ? author_or_authors[0] : author_or_authors;
|
const author = Array.isArray(author_or_authors) ? author_or_authors[0] : author_or_authors;
|
||||||
|
|
||||||
|
if (Array.isArray(frontmatter.event)) {
|
||||||
|
// todo: add each event to the calendar
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
entries.push({
|
entries.push({
|
||||||
url: out_url.abs_url,
|
url: out_url.abs_url,
|
||||||
in_file: in_file,
|
in_file: in_file,
|
||||||
@ -254,9 +296,9 @@ function handle_calendar(state: BuildState, cal_conf: CalendarConfig, entries: E
|
|||||||
description: frontmatter.description,
|
description: frontmatter.description,
|
||||||
author_name: author?.name,
|
author_name: author?.name,
|
||||||
author_email: author?.email,
|
author_email: author?.email,
|
||||||
start_time: frontmatter.event?.start,
|
start: frontmatter.event?.start,
|
||||||
end_time: frontmatter.event?.end,
|
end: frontmatter.event?.end,
|
||||||
time_zone: frontmatter.event?.zone,
|
time_zone: frontmatter.event?.time_zone,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,20 +337,6 @@ export function skip_file(state: BuildState, in_file: string, out_file: string,
|
|||||||
handle_page_side_effects(state, in_file, out_file, out_url, frontmatter);
|
handle_page_side_effects(state, in_file, out_file, out_url, frontmatter);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function copy_metadata(state: BuildState, in_file: string) {
|
|
||||||
in_file = in_file.slice(state.conf.input.root.length);
|
|
||||||
state.new_metadata.files[in_file] = structuredClone(state.old_metadata?.files?.[in_file]);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function update_metadata(state: BuildState, in_file: string, hash: string) {
|
|
||||||
in_file = in_file.slice(state.conf.input.root.length);
|
|
||||||
state.new_metadata.files[in_file] = {
|
|
||||||
first_seen_time: state.old_metadata?.files?.[in_file]?.first_seen_time || state.build_time.iso,
|
|
||||||
last_build_hash: hash,
|
|
||||||
last_updated_time: state.build_time.iso,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function get_author(state: BuildState, frontmatter?: FrontMatter) {
|
export function get_author(state: BuildState, frontmatter?: FrontMatter) {
|
||||||
if (! frontmatter?.author) {
|
if (! frontmatter?.author) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -2,11 +2,28 @@
|
|||||||
import { write_text } from '../fs';
|
import { write_text } from '../fs';
|
||||||
import { BuildState } from './state';
|
import { BuildState } from './state';
|
||||||
import { map_input_file_to_output_file } from './helpers';
|
import { map_input_file_to_output_file } from './helpers';
|
||||||
import { parseICS, CalendarComponent } from 'ical';
|
// import { parseICS, CalendarComponent } from 'ical';
|
||||||
import create_calendar, { ICalEventData, ICalCalendarData } from 'ical-generator';
|
import create_calendar, { ICalEventData, ICalCalendarData } from 'ical-generator';
|
||||||
|
import { FrontMatterLocation } from '../template';
|
||||||
|
|
||||||
export type { ICalEventData, ICalCalendarData, ICalAttendeeData, ICalAttendeeStatus } from 'ical-generator';
|
export type { ICalEventData, ICalCalendarData, ICalAttendeeData, ICalAttendeeStatus } from 'ical-generator';
|
||||||
|
|
||||||
|
export interface EventSeries {
|
||||||
|
url: string;
|
||||||
|
in_file: string;
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
author_name?: string;
|
||||||
|
author_email?: string;
|
||||||
|
entries: {
|
||||||
|
title?: string;
|
||||||
|
start?: string;
|
||||||
|
end?: string;
|
||||||
|
time_zone?: `${string}/${string}`;
|
||||||
|
location?: FrontMatterLocation;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface EventEntry {
|
export interface EventEntry {
|
||||||
url: string;
|
url: string;
|
||||||
in_file: string;
|
in_file: string;
|
||||||
@ -14,9 +31,10 @@ export interface EventEntry {
|
|||||||
description?: string;
|
description?: string;
|
||||||
author_name?: string;
|
author_name?: string;
|
||||||
author_email?: string;
|
author_email?: string;
|
||||||
start_time?: string;
|
start?: string;
|
||||||
end_time?: string;
|
end?: string;
|
||||||
time_zone?: `${string}/${string}`;
|
time_zone?: `${string}/${string}`;
|
||||||
|
location?: FrontMatterLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function write_events_and_calendars_if_needed(state: BuildState) {
|
export async function write_events_and_calendars_if_needed(state: BuildState) {
|
||||||
@ -36,6 +54,39 @@ export async function write_events_and_calendars_if_needed(state: BuildState) {
|
|||||||
const out_file = await map_input_file_to_output_file(state, entry.in_file, [ '.html', '.md', '.markdown' ], '.ics');
|
const out_file = await map_input_file_to_output_file(state, entry.in_file, [ '.html', '.md', '.markdown' ], '.ics');
|
||||||
await write_text(out_file, calendar);
|
await write_text(out_file, calendar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const series of state.event_series) {
|
||||||
|
const events = series.entries.map((event) => {
|
||||||
|
return icalendar_event(state, {
|
||||||
|
url: series.url,
|
||||||
|
in_file: series.in_file,
|
||||||
|
title: event.title || series.title,
|
||||||
|
description: series.description,
|
||||||
|
author_name: series.author_name,
|
||||||
|
author_email: series.author_email,
|
||||||
|
start: event.start,
|
||||||
|
end: event.end,
|
||||||
|
time_zone: event.time_zone,
|
||||||
|
location: event.location,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const cal_data: ICalCalendarData = {
|
||||||
|
name: series.title,
|
||||||
|
description: series.description,
|
||||||
|
url: series.url,
|
||||||
|
prodId: {
|
||||||
|
company: 'jbrumond.me',
|
||||||
|
product: 'docs2website',
|
||||||
|
language: 'EN',
|
||||||
|
},
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
|
||||||
|
const calendar = create_icalendar(cal_data, events);
|
||||||
|
const out_file = await map_input_file_to_output_file(state, series.in_file, [ '.html', '.md', '.markdown' ], '.ics');
|
||||||
|
await write_text(out_file, calendar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.conf.calendars) {
|
if (state.conf.calendars) {
|
||||||
@ -62,16 +113,16 @@ export async function write_events_and_calendars_if_needed(state: BuildState) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parse_icalendar(contents: string) {
|
// export function parse_icalendar(contents: string) {
|
||||||
const parsed = parseICS(contents);
|
// const parsed = parseICS(contents);
|
||||||
const calendar: CalendarComponent[] = [ ];
|
// const calendar: CalendarComponent[] = [ ];
|
||||||
|
|
||||||
for (const data of Object.values(parsed)) {
|
// for (const data of Object.values(parsed)) {
|
||||||
calendar.push(data);
|
// calendar.push(data);
|
||||||
}
|
// }
|
||||||
|
|
||||||
return calendar;
|
// return calendar;
|
||||||
}
|
// }
|
||||||
|
|
||||||
export function create_icalendar(cal: ICalCalendarData, events: ICalEventData | ICalEventData[]) {
|
export function create_icalendar(cal: ICalCalendarData, events: ICalEventData | ICalEventData[]) {
|
||||||
const calendar = create_calendar(cal);
|
const calendar = create_calendar(cal);
|
||||||
@ -97,8 +148,8 @@ export function icalendar_event(state: BuildState, entry: EventEntry) : ICalEven
|
|||||||
id: entry.url,
|
id: entry.url,
|
||||||
summary: entry.title,
|
summary: entry.title,
|
||||||
description: entry.description || void 0,
|
description: entry.description || void 0,
|
||||||
start: entry.start_time,
|
start: entry.start,
|
||||||
end: entry.end_time,
|
end: entry.end,
|
||||||
url: entry.url,
|
url: entry.url,
|
||||||
timezone: entry.time_zone,
|
timezone: entry.time_zone,
|
||||||
created: metadata.first_seen_time,
|
created: metadata.first_seen_time,
|
||||||
@ -107,6 +158,7 @@ export function icalendar_event(state: BuildState, entry: EventEntry) : ICalEven
|
|||||||
name: entry.author_name || 'Unknown',
|
name: entry.author_name || 'Unknown',
|
||||||
email: entry.author_email,
|
email: entry.author_email,
|
||||||
},
|
},
|
||||||
|
location: format_location(entry.location),
|
||||||
// attendees: post.mentions.flatMap((mention) : ICalAttendeeData | ICalAttendeeData[] => {
|
// attendees: post.mentions.flatMap((mention) : ICalAttendeeData | ICalAttendeeData[] => {
|
||||||
// if (mention.is_rsvp && mention.is_reply_to_this) {
|
// if (mention.is_rsvp && mention.is_reply_to_this) {
|
||||||
// const ext = mention.external as ExternalEntry;
|
// const ext = mention.external as ExternalEntry;
|
||||||
@ -129,3 +181,29 @@ export function icalendar_event(state: BuildState, entry: EventEntry) : ICalEven
|
|||||||
// }),
|
// }),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function format_location(loc: FrontMatterLocation) {
|
||||||
|
if (! loc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loc.description) {
|
||||||
|
if (loc.address) {
|
||||||
|
return `${loc.description} (${loc.address})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loc.lat && loc.long) {
|
||||||
|
return `${loc.description} [${loc.lat}, ${loc.long}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return loc.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loc.address) {
|
||||||
|
return loc.address;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loc.lat && loc.long) {
|
||||||
|
return `[${loc.lat}, ${loc.long}]`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -61,6 +61,7 @@ export async function build_docs_project(conf: Config) {
|
|||||||
rss: [ ],
|
rss: [ ],
|
||||||
sitemap: [ ],
|
sitemap: [ ],
|
||||||
events: [ ],
|
events: [ ],
|
||||||
|
event_series: [ ],
|
||||||
calendars: [ ],
|
calendars: [ ],
|
||||||
build_time: as_context_time(now),
|
build_time: as_context_time(now),
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@ import { BuildState } from './state';
|
|||||||
import { read_json, write_text, read_yaml } from '../fs';
|
import { read_json, write_text, read_yaml } from '../fs';
|
||||||
import { build_markdown_from_json_schema } from '@doc-utils/jsonschema2markdown';
|
import { build_markdown_from_json_schema } from '@doc-utils/jsonschema2markdown';
|
||||||
import { stringify as to_yaml } from 'yaml';
|
import { stringify as to_yaml } from 'yaml';
|
||||||
import { build_partials, copy_metadata, file_hash_matches, map_input_file_to_output_file, map_output_file_to_url, render_page, skip_file, update_metadata } from './helpers';
|
import { build_partials, map_input_file_to_output_file, map_output_file_to_url, render_page } from './helpers';
|
||||||
|
|
||||||
export async function render_json_schema_files(state: BuildState) {
|
export async function render_json_schema_files(state: BuildState) {
|
||||||
const promises: Promise<any>[] = [ ];
|
const promises: Promise<any>[] = [ ];
|
||||||
@ -124,14 +124,8 @@ export async function render_json_schema(state: BuildState, schema: unknown, in_
|
|||||||
}
|
}
|
||||||
|
|
||||||
promises.push(
|
promises.push(
|
||||||
render_page(state, in_file, out_file, out_url, markdown, true, frontmatter)
|
render_page(state, in_file, out_file, out_url, markdown, true, hash, frontmatter)
|
||||||
);
|
);
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
|
|
||||||
if (file_hash_matches(state, in_file, hash)) {
|
|
||||||
return copy_metadata(state, in_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
update_metadata(state, in_file, hash);
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { glob } from 'glob';
|
import { glob } from 'glob';
|
||||||
import { read_text } from '../fs';
|
import { read_text } from '../fs';
|
||||||
import { BuildState } from './state';
|
import { BuildState } from './state';
|
||||||
import { build_partials, copy_metadata, file_hash_matches, map_input_file_to_output_file, map_output_file_to_url, render_page, skip_file, update_metadata } from './helpers';
|
import { build_partials, map_input_file_to_output_file, map_output_file_to_url, render_page } from './helpers';
|
||||||
|
|
||||||
export async function render_markdown_files(state: BuildState) {
|
export async function render_markdown_files(state: BuildState) {
|
||||||
const promises: Promise<any>[] = [ ];
|
const promises: Promise<any>[] = [ ];
|
||||||
@ -39,11 +39,5 @@ export async function render_markdown_file(state: BuildState, in_file: string) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await render_page(state, in_file, out_file, out_url, text, true, frontmatter);
|
await render_page(state, in_file, out_file, out_url, text, true, hash, frontmatter);
|
||||||
|
|
||||||
if (file_hash_matches(state, in_file, hash)) {
|
|
||||||
return copy_metadata(state, in_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
update_metadata(state, in_file, hash);
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { glob } from 'glob';
|
import { glob } from 'glob';
|
||||||
import { read_text } from '../fs';
|
import { read_text } from '../fs';
|
||||||
import { BuildState } from './state';
|
import { BuildState } from './state';
|
||||||
import { build_partials, copy_metadata, file_hash_matches, map_input_file_to_output_file, map_output_file_to_url, render_page, skip_file, update_metadata } from './helpers';
|
import { build_partials, map_input_file_to_output_file, map_output_file_to_url, render_page } from './helpers';
|
||||||
|
|
||||||
export async function render_text_file_templates(state: BuildState) {
|
export async function render_text_file_templates(state: BuildState) {
|
||||||
const promises: Promise<any>[] = [ ];
|
const promises: Promise<any>[] = [ ];
|
||||||
@ -39,11 +39,5 @@ export async function render_text_file_template(state: BuildState, in_file: stri
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await render_page(state, in_file, out_file, out_url, text, false, frontmatter);
|
await render_page(state, in_file, out_file, out_url, text, false, hash, frontmatter);
|
||||||
|
|
||||||
if (file_hash_matches(state, in_file, hash)) {
|
|
||||||
return copy_metadata(state, in_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
update_metadata(state, in_file, hash);
|
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import type { Metadata } from '../metadata';
|
|||||||
import type { ColorTheme } from '@doc-utils/color-themes';
|
import type { ColorTheme } from '@doc-utils/color-themes';
|
||||||
import type { SitemapEntry } from './sitemap';
|
import type { SitemapEntry } from './sitemap';
|
||||||
import { RSSEntry } from './rss';
|
import { RSSEntry } from './rss';
|
||||||
import { EventEntry } from './icalendar';
|
import { EventEntry, EventSeries } from './icalendar';
|
||||||
import { ContextTime } from '../template';
|
import { ContextTime } from '../template';
|
||||||
|
|
||||||
export interface BuildState {
|
export interface BuildState {
|
||||||
@ -22,6 +22,7 @@ export interface BuildState {
|
|||||||
rss: RSSEntry[][];
|
rss: RSSEntry[][];
|
||||||
sitemap: SitemapEntry[];
|
sitemap: SitemapEntry[];
|
||||||
events: EventEntry[];
|
events: EventEntry[];
|
||||||
|
event_series: EventSeries[];
|
||||||
calendars: EventEntry[][];
|
calendars: EventEntry[][];
|
||||||
build_time: ContextTime;
|
build_time: ContextTime;
|
||||||
}
|
}
|
||||||
|
@ -8,19 +8,20 @@ import { load_from_dir } from './fs';
|
|||||||
import { ColorTheme } from '@doc-utils/color-themes';
|
import { ColorTheme } from '@doc-utils/color-themes';
|
||||||
import { ThemeGroups } from './build-files';
|
import { ThemeGroups } from './build-files';
|
||||||
import { ChangeFreq } from './build-files/sitemap';
|
import { ChangeFreq } from './build-files/sitemap';
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
|
|
||||||
export interface Context {
|
export interface Context {
|
||||||
env?: Record<string, string>;
|
env?: Record<string, string>;
|
||||||
page?: FrontMatter;
|
page?: FrontMatter;
|
||||||
base_url: string;
|
base_url: string;
|
||||||
page_url: string;
|
page_url: string;
|
||||||
|
page_published: ContextTime;
|
||||||
|
page_updated: ContextTime;
|
||||||
site_title: string;
|
site_title: string;
|
||||||
author: AuthorConfig | AuthorConfig[];
|
author: AuthorConfig | AuthorConfig[];
|
||||||
event?: {
|
event?: ContextEvent | ContextEvent[];
|
||||||
start: ContextTime;
|
event_series?: {
|
||||||
end: ContextTime;
|
start?: ContextTime;
|
||||||
zone: `${string}/${string}`;
|
end?: ContextTime;
|
||||||
};
|
};
|
||||||
icons: Record<string, string>;
|
icons: Record<string, string>;
|
||||||
themes: ColorTheme[];
|
themes: ColorTheme[];
|
||||||
@ -39,6 +40,22 @@ export interface ContextTime {
|
|||||||
html: string;
|
html: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ContextEvent {
|
||||||
|
title?: string;
|
||||||
|
start?: ContextTime;
|
||||||
|
end?: ContextTime;
|
||||||
|
time_zone?: `${string}/${string}`;
|
||||||
|
location?: ContextLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ContextLocation {
|
||||||
|
description?: string;
|
||||||
|
lat?: string;
|
||||||
|
long?: string;
|
||||||
|
// todo: represent this better?
|
||||||
|
address?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface FrontMatter {
|
export interface FrontMatter {
|
||||||
skip?: boolean;
|
skip?: boolean;
|
||||||
layout?: string;
|
layout?: string;
|
||||||
@ -48,23 +65,33 @@ export interface FrontMatter {
|
|||||||
author?: string | string[];
|
author?: string | string[];
|
||||||
rss?: RSSFrontmatter;
|
rss?: RSSFrontmatter;
|
||||||
sitemap?: SitemapFrontmatter;
|
sitemap?: SitemapFrontmatter;
|
||||||
event?: EventFrontmatter;
|
event?: EventFrontmatter | EventFrontmatter[];
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SitemapFrontmatter {
|
export interface SitemapFrontmatter {
|
||||||
skip?: boolean;
|
skip?: boolean;
|
||||||
change_freq?: ChangeFreq;
|
change_freq?: ChangeFreq;
|
||||||
priority?: number;
|
priority?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EventFrontmatter {
|
export interface EventFrontmatter {
|
||||||
|
title?: string;
|
||||||
start?: string;
|
start?: string;
|
||||||
end?: string;
|
end?: string;
|
||||||
zone?: `${string}/${string}`;
|
time_zone?: `${string}/${string}`;
|
||||||
|
location?: FrontMatterLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RSSFrontmatter {
|
export interface FrontMatterLocation {
|
||||||
|
description?: string;
|
||||||
|
lat?: string;
|
||||||
|
long?: string;
|
||||||
|
// todo: represent this better?
|
||||||
|
address?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RSSFrontmatter {
|
||||||
skip?: boolean;
|
skip?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,20 +13,20 @@ export function from_iso(time: string, zone?: string) {
|
|||||||
: DateTime.fromISO(time);
|
: DateTime.fromISO(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function as_html_time(time: DateTime, lang?: string, config?: Intl.DateTimeFormatOptions) {
|
export function as_html_time(time: DateTime, classname = '', lang?: string, config?: Intl.DateTimeFormatOptions) {
|
||||||
if (lang && config) {
|
if (lang && config) {
|
||||||
const formatter = new Intl.DateTimeFormat(lang, config);
|
const formatter = new Intl.DateTimeFormat(lang, config);
|
||||||
const formatted = formatter.format(new Date(time.toISO()));
|
const formatted = formatter.format(new Date(time.toISO()));
|
||||||
return `<time datetime="${time.toISO()}">${formatted}</time>`;
|
return `<time datetime="${time.toISO()}">${formatted}</time>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `<time datetime="${time.toISO()}">${time.toRFC2822()}</time>`;
|
return `<time class="${classname}" datetime="${time.toISO()}">${time.toRFC2822()}</time>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function as_context_time(time: DateTime, lang?: string, config?: Intl.DateTimeFormatOptions) {
|
export function as_context_time(time: DateTime, classname = '', lang?: string, config?: Intl.DateTimeFormatOptions) {
|
||||||
return {
|
return {
|
||||||
iso: time.toISO(),
|
iso: time.toISO(),
|
||||||
rfc2822: time.toRFC2822(),
|
rfc2822: time.toRFC2822(),
|
||||||
html: as_html_time(time, lang, config),
|
html: as_html_time(time, classname, lang, config),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user