Skip to content
This repository has been archived by the owner on Aug 27, 2024. It is now read-only.

JSON import and object casting to TS model #46

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions examples/style.csl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# this is a flatter model, relying more heavily on parameters
title: APA
options:
dateFormatting:
month: short # all are optional, and set reasonable defaults
sort:
- key: author
order: ascending
Expand All @@ -11,16 +13,13 @@ options:
group:
# be explicit about grouping, which is core logic
- key: author
# not sure on details here yet, but basic idea is disambiguation
# is related to grouping
disambiguate:
addNames: all-with-initials
- key: year
disambiguate:
addYearSuffix: true
# pave the way for multilingual support
localization:
scope: global
disambiguate:
addNames: all-with-initials
addYearSuffix: true
# again: put this on a parameter
substitute:
author:
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
"start:ci": "node ./build/esbuild.js --run",
"start:prod": "node ./build/esbuild.js --watch --run"
},
"prettier": "./.prettierrc.json",
"types": "./types/index.d.ts",
"dependencies": {},
"devDependencies": {
"@es-exec/esbuild-plugin-start": "^0.0.4",
"@types/node": "^18.14.1",
"class-transformer": "^0.5.1",
"edtf": "^4.4.1",
"esbuild": "^0.17.10",
"minimist": "^1.2.8",
"rome": "^12.0.0",
Expand All @@ -28,6 +28,7 @@
"typescript-json-schema": "^0.56.0"
},
"dependencies": {
"yaml": "^2.2.2"
"yaml": "^2.2.2",
"edtf": "^4.4.1"
}
}
3 changes: 3 additions & 0 deletions rome.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@
"rules": {
"recommended": true
}
},
"files": {
"ignore": ["symlink/**/*.ts"]
}
}
43 changes: 39 additions & 4 deletions src/bibliography.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,47 @@
import { Type } from "class-transformer";
import { Reference } from "./reference";

/**
* A bibliography is a collection of references.
*
* It is the input of a citation processor.
*
* @examples
* {
* "title": "My Bibliography",
* "description": "A collection of references.",
* "references": [
* {
* "id": "doe1",
* "type": "book",
* "title": "The Title",
* "author": [
* {
* "family": "Doe",
* "given": "Jane"
* }
* ],
* "issued": "2023"
* }
* ]
*}
*/
export class Bibliography {
/**
* The title of the bibliography.
*/
title?: string;
/**
* The description of the bibliography.
*/
description?: string;

/**
* The references array.
*
* @items.minimum 1
*/
@Type(() => Reference)
references: Reference[];

constructor(title?: string, description?: string) {
Expand All @@ -14,8 +53,4 @@ export class Bibliography {
addReference(reference: Reference): void {
this.references.push(reference);
}

addReferences(references: Reference[]): void {
this.references = this.references.concat(references);
}
}
39 changes: 39 additions & 0 deletions src/contributor.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
export abstract class Agent {
constructor(public name: string) {}

getSortName(): string {
return `${this.name}`;
}
}

export class Person extends Agent {
givenName: string;
familyName: string;
constructor(name: string, gname: string, fname: string) {
super(name);
this.givenName = gname;
this.familyName = fname;
}

public override getSortName() {
return `${this.familyName}, ${this.givenName}`;
}
}

export class Organization extends Agent {}

const p1 = new Person("Jane Doe", "Jane", "Doe");
const a1 = new Organization("United Nations");

function contributorKind(x: Person | Organization) {
// x is type Person or Organization here
if (x instanceof Person) {
// x is type Person here
x.familyName;
} else {
x.name;
}
}

contributorKind(p1);

// contributor modeling needs more thought in general

export type Contributor = Person | Organization;
Expand Down
6 changes: 2 additions & 4 deletions src/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,7 @@ function groupReferences(
function getSortKey(sort: SortType, reference: Reference): string {
switch (sort.key) {
case "author":
if (reference.author !== undefined) {
return reference.author[0].getSortName();
}
return reference.author?.[0]?.getSortName(); // TODO add Contributors class with methods for all names
case "year":
return reference.issued;
case "as-cited":
Expand All @@ -155,7 +153,7 @@ function getSortKey(sort: SortType, reference: Reference): string {
}

// TODO write a function that returns the position of a reference in a list of cited references
function citedReferencePosition(citedRef: CiteRef): number {
function citedReferencePosition(_citedRef: CiteRef): number {
return 1; // placeholder
}

Expand Down
40 changes: 33 additions & 7 deletions src/reference.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Typescript model for a CSL Reference
import "reflect-metadata";
import { Type } from "class-transformer";
import { Organization, Person, Agent } from "./contributor";

import { Contributor } from "./contributor";

//export type Contributor = Person | Org;
// Types

/**
Expand Down Expand Up @@ -33,13 +35,37 @@ export type TitleString = string; // plain or Djot?
export interface TitleStructured {
full?: TitleString;
main: TitleString;
sub: TitleString[];
sub?: TitleString[];
}

export interface Reference {
export class Reference {
id: ID;
type: ReferenceType;
author?: Contributor[]; // fix
title?: Title | Title[]; // REVIEW is this too much flexibility?
issued: CSLDate;

@Type(() => Agent, {
discriminator: {
property: 'kind',
subTypes: [
{ value: Organization, name: 'organization' },
{ value: Person, name: 'person' },
],
},
})
author: (Organization | Person)[];
title?: Title;
issued: string;

constructor(
id: ID,
type: ReferenceType,
issued: string,
author: (Organization | Person)[],
title?: Title,
) {
this.id = id;
this.type = type;
this.author = author;
this.title = title;
this.issued = issued;
}
}
56 changes: 55 additions & 1 deletion src/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ export interface OptionGroup {
* Localization configuration.
*/
localization?: Localization;
/**
* Date formatting configuration.
*/
dateFormatting?: DateFormatting;
}

/**
Expand Down Expand Up @@ -255,10 +259,60 @@ export interface Substitution {
author: SubstitutionType[];
}

/**
* Date formatting configuration.
*/
export interface DateFormatting {
// REVIEW not sure on details ATM
// the model is a subset of JS Intl.DateTimeFormatOptions
/**
* @default long
*/
date?: DateStyle;
/**
* @default long
*/
time?: TimeStyle;
/**
* @default numeric
*/
year?: YearStyle;
/**
* @default long
*/
month?: MonthStyle;
}

type DateStyle =
| "full" // 'Thursday, April 27, 2023'
| "long" // 'April 27, 2023'
| "medium" // 'Apr 27, 2023'
| "short"; // '4/27/23'

type YearStyle =
// The representation of the year. Possible values are:
| "numeric" // (e.g., 2012)
| "2-digit"; // (e.g., 12)

type TimeStyle =
| "full" // '8:04:49 AM Eastern Daylight Time'
| "long" // '8:04:49 AM EDT'
| "medium" // '8:04:49 AM'
| "short"; // '8:04 AM'

type MonthStyle =
// The representation of the month. Possible values are:
| "numeric" // (e.g., 3)
| "2-digit" // (e.g., 03)
| "long" // (e.g., March)
| "short" // (e.g., Mar)
| "narrow"; // (e.g., M).

/**
* A CSL Style.
*/
export interface Style {

export class Style {
/**
* The human-readable name of the style.
*/
Expand Down
21 changes: 16 additions & 5 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,25 @@
"target": "es2022",
"module": "es2022",
"moduleResolution": "node",
"lib": ["dom", "es2022"],
"lib": [
"dom",
"es2022"
],
"experimentalDecorators": true,
"noUnusedLocals": true,
"removeComments": true,
"strict": true,
"typeRoots": ["node_modules/@types"],
"useDefineForClassFields": false
"skipLibCheck": true,
"outDir": "lib",
"declaration": true,
"declarationDir": "types",
"isolatedModules": true,
// "allowImportingTsExtensions": true,
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules"
]
}
17 changes: 7 additions & 10 deletions typedoc.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
{
"entryPoints": [
"./src/citation.ts",
"./src/bibliography.ts",
"./src/style.ts",
"./src/locator.ts",
"./src/reference.ts"
],
"umlClassDiagram": {
"arrowColor": "gray"
}
"entryPoints": [
"./src/citation.ts", "./src/bibliography.ts", "./src/style.ts",
"./src/locator.ts", "./src/reference.ts"
],
"umlClassDiagram": {
"arrowColor": "gray"
}
}