Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

馃彿 Parts selection is case-insensitive #1025

Merged
merged 2 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cool-windows-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"myst-common": patch
---

Allow parts mapping to be case insensitive.
6 changes: 6 additions & 0 deletions .changeset/tough-parrots-give.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"myst-common": patch
"myst-cli": patch
---

Case insensitivity in parts, and allow spaces when picking up JATS titles.
4 changes: 2 additions & 2 deletions docs/document-parts.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Parts allow you to specify special parts of your document, like abs

Document parts allow you to add metadata to your documents with specific components of your page, for example, abstract, dedication, or acknowledgments. Many templates put these in specific places.

There are three ways that you can define parts of a document: (1) in your page frontmatter; (2) implicitly using a section heading; and (3) on a block using a `part` or `tag` annotation.
There are three ways that you can define parts of a document: (1) in your page frontmatter; (2) implicitly using a section heading; and (3) on a block using a `part` or `tag` annotation. These are all based on a part name, which is case insensitive.

## Parts in Frontmatter

Expand Down Expand Up @@ -76,7 +76,7 @@ Complete this using a header as usual:
This is my abstract!
```

Note that frontmatter parts and explicitly tagged cells/blocks will take precedence over this method.
Note that frontmatter parts and explicitly tagged cells/blocks will take precedence over this method. Themes may choose to only pick up a subset of implicit parts, for example, only an `Abstract` and not `Summary` as summary section can be used in other contexts.

## In a Jupyter Notebook cells and blocks

Expand Down
2 changes: 1 addition & 1 deletion docs/frontmatter.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ The following table lists the available frontmatter fields, a brief description
- object for customizing content numbering (see [](#numbering))
- page can override project
* - `parts`
- a dictionary of arbitrary content parts, not part of the main article, for example `abstract`, `data_availability`
- a dictionary of arbitrary content parts, not part of the main article, for example `abstract`, `data_availability` see [](./document-parts.md).
- page only
* - `options`
- a dictionary of arbitrary options validated and consumed by templates, for example, during site or PDF build
Expand Down
9 changes: 7 additions & 2 deletions packages/myst-cli/src/build/jats/single.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,20 @@ export async function runJatsExport(
abstractParts: [
{ part: 'abstract' },
{
part: ['plain-language-summary', 'plain-language-abstract', 'summary'],
part: [
'plain-language-summary',
'plain-language-abstract',
'summary',
'plain language summary',
],
type: 'plain-language-summary',
title: 'Plain Language Summary',
},
{ part: 'keypoints', type: 'key-points', title: 'Key Points' },
],
backSections: [
{
part: ['data-availability', 'data_availability', 'availability'],
part: ['data-availability', 'data_availability', 'availability', 'data availability'],
type: 'data-availability',
title: 'Data Availability',
},
Expand Down
8 changes: 4 additions & 4 deletions packages/myst-common/src/extractParts.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,25 +100,25 @@ describe('extractPart', () => {
],
});
});
it('extract parts (with lists)', async () => {
it('extract parts (with lists and case insensitivity)', async () => {
expect(
extractPart(
{
type: 'root',
children: [
{
type: 'block' as any,
data: { tags: ['tagged_part'] },
data: { tags: ['TAGGED_part'] },
children: [{ type: 'text', value: 'untagged content' }],
},
{
type: 'block' as any,
data: { tags: ['other_tag', 'test_part'] },
data: { tags: ['other_tag', 'TEST_PART'] },
children: [{ type: 'text', value: 'also tagged content' }],
},
],
},
['test_part', 'tagged_part'],
['test_part', 'TAGGED_PART'],
{ removePartData: false },
),
).toEqual({
Expand Down
19 changes: 10 additions & 9 deletions packages/myst-common/src/extractParts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function coercePart(part?: string | string[]): string[] {
// Prevent an undefined, null or empty part comparison
return [];
}
return typeof part === 'string' ? [part] : part;
return typeof part === 'string' ? [part.toLowerCase()] : part.map((s) => s.toLowerCase());
}

/**
Expand All @@ -20,13 +20,12 @@ export function selectBlockParts(tree: GenericParent, part?: string | string[]):
const parts = coercePart(part);
if (parts.length === 0) return [];
const blockParts = selectAll('block', tree).filter((block) => {
const blockTags: string[] = (
block.data?.tags && Array.isArray(block.data.tags) ? block.data.tags : []
).map((tag) => tag?.toLowerCase());
const blockPart = (block.data?.part as string)?.toLowerCase();
return parts
.map((p) => {
return (
block.data?.part === p ||
(block.data?.tags && Array.isArray(block.data.tags) && block.data.tags.includes(p))
);
})
.map((p) => blockPart === p || blockTags.includes(p))
.reduce((a, b) => a || b, false);
});
return blockParts as Block[];
Expand Down Expand Up @@ -138,9 +137,11 @@ export function extractPart(
if (
block.data.tags &&
Array.isArray(block.data.tags) &&
block.data.tags.reduce((a, t) => a || partStrings.includes(t), false)
block.data.tags.reduce((a, t) => a || partStrings.includes(t.toLowerCase()), false)
) {
block.data.tags = block.data.tags.filter((tag) => !partStrings.includes(tag)) as string[];
block.data.tags = block.data.tags.filter(
(tag) => !partStrings.includes(tag.toLowerCase()),
) as string[];
if ((block.data.tags as string[]).length === 0) {
delete block.data.tags;
}
Expand Down