domain/converters/grammar.section.converter.ts
domain/converters/grammar.section.converter.ts is a file in Bane's Lab Site. 197 lines of code and 15 definitions.
import {
AXIS_LABEL,
CATEGORY_LABEL,
CONSTRAINTS_LABEL,
DEFAULT_VERB_LABEL,
DISTINCT_FROM_LABEL,
DOCUMENT_TYPES_TITLE,
DOCUMENT_TYPE_INTRO,
EXAMPLE_LABEL,
GROUNDS_LABEL,
KEYWORDS_KIND,
KEYWORD_INTRO,
LABEL_SEPARATOR,
LIST_SEPARATOR,
MEANING_LABEL,
MODEL_LABEL,
PRODUCTIONS_KIND,
PRODUCTION_INTRO,
PURPOSE_LABEL,
RULE_LABEL,
SLOTS_LABEL,
TEMPLATES_TITLE,
TEMPLATE_BODY_TITLE,
TEMPLATE_INTRO,
VERBS_LABEL,
} from "#configuration/strings/ontology.strings";
import {
DOCUMENT_TYPE_SECTION_ID,
KEYWORD_SECTION_PREFIX,
PAG_ANCHOR,
PRODUCTION_SECTION_PREFIX,
TEMPLATE_SECTION_ID,
} from "#core/ids/ontology.ids";
import type {
DocumentTypeView,
GrammarView,
KeywordCategoryView,
KeywordView,
ProductionGroupView,
TemplateSlotView,
TemplateView,
} from "#types/grammar.types";
import { FACE_SEPARATOR, PAG_FACE } from "@govlab/constants";
import { OPTIONAL_LABEL, REQUIRED_LABEL } from "#configuration/strings/reason.strings";
import type { Section, Subsection } from "#types/document.types";
import {
chips,
codeOf,
glossary,
labeled,
linkOf,
linkRow,
linked,
plainList,
row,
slugOf,
text,
} from "#domain/converters/ontology.converter";
import type { Block } from "#types/block.types";
import { GRAMMAR_SECTION_ICON } from "#configuration/icons/ontology.icons";
import { PAG_LANGUAGE } from "#configuration/constants/code.constants";
import type { ResolutionView } from "#types/ontology.types";
import { checkBlocks } from "#domain/converters/check.converter";
const pagRecord = function pagRecord(
anchor: string,
title: string,
blocks: readonly Block[],
resolution: ResolutionView,
): Subsection {
return {
blocks: [...blocks, ...checkBlocks(resolution, PAG_FACE + FACE_SEPARATOR + anchor)],
id: PAG_ANCHOR + anchor,
title,
};
};
const section = function section(
id: string,
title: string,
intro: string,
subsections: readonly Subsection[],
kind?: string,
): Section {
return { icon: GRAMMAR_SECTION_ICON, id, intro, subsections, title, ...(kind === undefined ? {} : { kind }) };
};
const roleRows = function roleRows(keyword: KeywordView): readonly ReturnType<typeof row>[] {
const several = keyword.roles.length > 1;
return keyword.roles.flatMap((role) => [
...(several ? [row(CATEGORY_LABEL, role.category)] : []),
row(MEANING_LABEL, role.meaning),
row(EXAMPLE_LABEL, role.example),
...linkRow(GROUNDS_LABEL, role.grounds),
]);
};
const keywordSection = function keywordSection(group: KeywordCategoryView, resolution: ResolutionView): Section {
return section(
KEYWORD_SECTION_PREFIX + slugOf(group.category),
group.category,
KEYWORD_INTRO,
group.keywords.map((keyword) =>
pagRecord(
keyword.anchor,
keyword.name,
[
glossary([
...roleRows(keyword),
...keyword.distinctFrom.map((entry) =>
row(DISTINCT_FROM_LABEL, linkOf(entry.record) + LABEL_SEPARATOR + entry.reason),
),
]),
],
resolution,
),
),
KEYWORDS_KIND,
);
};
const productionSection = function productionSection(group: ProductionGroupView, resolution: ResolutionView): Section {
return section(
PRODUCTION_SECTION_PREFIX + slugOf(group.group),
group.group,
PRODUCTION_INTRO,
group.productions.map((production) =>
pagRecord(
production.anchor,
production.lhs,
[glossary([row(RULE_LABEL, production.rhs), ...linkRow(GROUNDS_LABEL, production.grounds)])],
resolution,
),
),
PRODUCTIONS_KIND,
);
};
const documentTypeRecord = function documentTypeRecord(
documentType: DocumentTypeView,
resolution: ResolutionView,
): Subsection {
const verbs = row(VERBS_LABEL, plainList(documentType.verbs));
return pagRecord(
documentType.anchor,
documentType.type,
[
chips([
labeled(DEFAULT_VERB_LABEL, documentType.defaultVerb),
linked(MODEL_LABEL, documentType.model),
linked(AXIS_LABEL, documentType.axis),
]),
glossary([
row(PURPOSE_LABEL, documentType.purpose),
verbs,
...linkRow(GROUNDS_LABEL, documentType.grounds),
]),
],
resolution,
);
};
const slotRow = function slotRow(slot: TemplateSlotView): ReturnType<typeof row> {
const kind = slot.values.length === 0 ? slot.kind : slot.kind + LABEL_SEPARATOR + slot.values.join(LIST_SEPARATOR);
const need = slot.required ? REQUIRED_LABEL : OPTIONAL_LABEL;
return row(slot.name, `${slot.description} (${kind}${LIST_SEPARATOR}${need})`);
};
const templateRecord = function templateRecord(template: TemplateView, resolution: ResolutionView): Subsection {
const constraints = row(CONSTRAINTS_LABEL, plainList(template.constraints));
const noSlots = row(SLOTS_LABEL, plainList([]));
return pagRecord(
template.anchor,
template.title,
[
glossary([constraints]),
...(template.slots.length === 0
? [glossary([noSlots])]
: [text(SLOTS_LABEL), glossary(template.slots.map(slotRow))]),
codeOf(TEMPLATE_BODY_TITLE, template.body, PAG_LANGUAGE),
],
resolution,
);
};
export const grammarSections = function grammarSections(
grammar: GrammarView,
resolution: ResolutionView,
): readonly Section[] {
return [
...grammar.categories.map((group) => keywordSection(group, resolution)),
...grammar.groups.map((group) => productionSection(group, resolution)),
section(
DOCUMENT_TYPE_SECTION_ID,
DOCUMENT_TYPES_TITLE,
DOCUMENT_TYPE_INTRO,
grammar.documentTypes.map((documentType) => documentTypeRecord(documentType, resolution)),
),
section(
TEMPLATE_SECTION_ID,
TEMPLATES_TITLE,
TEMPLATE_INTRO,
grammar.templates.map((template) => templateRecord(template, resolution)),
),
];
};