From 97518ca3c386b87c326d77cbbda9f9d066657cbc Mon Sep 17 00:00:00 2001 From: Frank Zimmer Date: Wed, 31 May 2023 22:42:04 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=9D=20Adds=20collaboration=20associate?= =?UTF-8?q?d=20with=20author=20in=20frontmatter=20(#343)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/friendly-gifts-bake.md | 6 +++++ .../src/frontmatter/frontmatter.spec.ts | 1 + .../myst-frontmatter/src/frontmatter/types.ts | 1 + .../src/frontmatter/validators.ts | 11 +++++++++ packages/myst-templates/src/frontmatter.ts | 24 ++++++++++++++++++- packages/myst-templates/src/types.ts | 9 +++++-- 6 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 .changeset/friendly-gifts-bake.md diff --git a/.changeset/friendly-gifts-bake.md b/.changeset/friendly-gifts-bake.md new file mode 100644 index 000000000..d998bd4c9 --- /dev/null +++ b/.changeset/friendly-gifts-bake.md @@ -0,0 +1,6 @@ +--- +'myst-frontmatter': patch +'myst-templates': patch +--- + +Add collaborations list to myst-frontmatter diff --git a/packages/myst-frontmatter/src/frontmatter/frontmatter.spec.ts b/packages/myst-frontmatter/src/frontmatter/frontmatter.spec.ts index d618f29b3..fc8bfbc14 100644 --- a/packages/myst-frontmatter/src/frontmatter/frontmatter.spec.ts +++ b/packages/myst-frontmatter/src/frontmatter/frontmatter.spec.ts @@ -34,6 +34,7 @@ const TEST_AUTHOR: Author = { email: 'test@example.com', roles: ['Software', 'Validation'], affiliations: ['example university'], + collaborations: ['example collaboration'], twitter: '@test', github: 'test', website: 'https://example.com', diff --git a/packages/myst-frontmatter/src/frontmatter/types.ts b/packages/myst-frontmatter/src/frontmatter/types.ts index f92d0f712..8cd30bed3 100644 --- a/packages/myst-frontmatter/src/frontmatter/types.ts +++ b/packages/myst-frontmatter/src/frontmatter/types.ts @@ -11,6 +11,7 @@ export interface Author { email?: string; roles?: AuthorRoles[]; affiliations?: string[]; + collaborations?: string[]; twitter?: string; github?: string; website?: string; diff --git a/packages/myst-frontmatter/src/frontmatter/validators.ts b/packages/myst-frontmatter/src/frontmatter/validators.ts index ca11911a5..4dfcfa676 100644 --- a/packages/myst-frontmatter/src/frontmatter/validators.ts +++ b/packages/myst-frontmatter/src/frontmatter/validators.ts @@ -104,6 +104,7 @@ const AUTHOR_KEYS = [ 'email', 'roles', 'affiliations', + 'collaborations', 'twitter', 'github', 'website', @@ -275,6 +276,16 @@ export function validateAuthor(input: any, opts: ValidationOptions) { return validateString(aff, affiliationsOpts)?.trim(); }); } + if (defined(value.collaborations)) { + const collaborationsOpts = incrementOptions('collaborations', opts); + let collaborations = value.collaborations; + if (typeof collaborations === 'string') { + collaborations = collaborations.split(';'); + } + output.collaborations = validateList(collaborations, collaborationsOpts, (col) => { + return validateString(col, collaborationsOpts)?.trim(); + }); + } if (defined(value.twitter)) { output.twitter = validateString(value.twitter, incrementOptions('twitter', opts)); } diff --git a/packages/myst-templates/src/frontmatter.ts b/packages/myst-templates/src/frontmatter.ts index 6bd4bd77b..d477c7cfc 100644 --- a/packages/myst-templates/src/frontmatter.ts +++ b/packages/myst-templates/src/frontmatter.ts @@ -17,11 +17,16 @@ function undefinedIfEmpty(array?: T[]): T[] | undefined { function addIndicesToAuthors( authors: Author[], affiliationList: RendererDoc['affiliations'], + collaborationList: RendererDoc['collaborations'], ): RendererAuthor[] { const affiliationLookup: Record = {}; affiliationList.forEach((affil) => { affiliationLookup[affil.value] = affil; }); + const collaborationLookup: Record = {}; + collaborationList.forEach((col) => { + collaborationLookup[col.value] = col; + }); let correspondingIndex = 0; return authors.map((auth, index) => { let corresponding: ValueAndIndex | undefined; @@ -39,6 +44,13 @@ function addIndicesToAuthors( // Affiliations are explicitly undefined if length === 0 affiliations = undefined; } + let collaborations = auth.collaborations?.map((value) => { + return { ...collaborationLookup[value] }; + }); + if (!collaborations || collaborations.length === 0) { + // Affiliations are explicitly undefined if length === 0 + collaborations = undefined; + } const [givenName, ...surnameParts] = auth.name?.split(' ') || ['', '']; const surname = surnameParts.join(' '); return { @@ -46,6 +58,7 @@ function addIndicesToAuthors( ...indexAndLetter(index), corresponding, affiliations, + collaborations, given_name: givenName, surname, }; @@ -59,9 +72,17 @@ function affiliationsFromAuthors(authors: Author[]): ValueAndIndex[] { }); } +function collaborationsFromAuthors(authors: Author[]): ValueAndIndex[] { + const allCollaborations = authors.map((auth) => auth.collaborations || []).flat(); + return [...new Set(allCollaborations)].map((value, index) => { + return { value, ...indexAndLetter(index) }; + }); +} + export function extendFrontmatter(frontmatter: PageFrontmatter): RendererDoc { const datetime = frontmatter.date ? new Date(frontmatter.date) : new Date(); const affiliations = affiliationsFromAuthors(frontmatter.authors || []); + const collaborations = collaborationsFromAuthors(frontmatter.authors || []); const doc: RendererDoc = { ...frontmatter, date: { @@ -69,8 +90,9 @@ export function extendFrontmatter(frontmatter: PageFrontmatter): RendererDoc { month: String(datetime.getMonth() + 1), year: String(datetime.getFullYear()), }, - authors: addIndicesToAuthors(frontmatter.authors || [], affiliations), + authors: addIndicesToAuthors(frontmatter.authors || [], affiliations, collaborations), affiliations, + collaborations, bibliography: undefinedIfEmpty(frontmatter.bibliography), }; return doc; diff --git a/packages/myst-templates/src/types.ts b/packages/myst-templates/src/types.ts index d4f7fedef..82aaa2347 100644 --- a/packages/myst-templates/src/types.ts +++ b/packages/myst-templates/src/types.ts @@ -13,8 +13,12 @@ export type ValueAndIndex = { letter: string; }; -export type RendererAuthor = Omit & { +export type RendererAuthor = Omit< + Author, + 'affiliations' | 'collaborations' | 'corresponding' | 'orcid' +> & { affiliations?: ValueAndIndex[]; + collaborations?: ValueAndIndex[]; corresponding?: ValueAndIndex; orcid?: string; index: number; @@ -31,9 +35,10 @@ export type RendererDoc = Omit & { }; authors: RendererAuthor[]; affiliations: ValueAndIndex[]; + collaborations: ValueAndIndex[]; }; -export const RENDERER_DOC_KEYS = ['affiliations'].concat(PAGE_FRONTMATTER_KEYS); +export const RENDERER_DOC_KEYS = ['affiliations', 'collaborations'].concat(PAGE_FRONTMATTER_KEYS); export type TemplatePartDefinition = { id: string;