Skip to content

Commit

Permalink
Add name and description template metadata attributes
Browse files Browse the repository at this point in the history
These are displayed in the template picker
  • Loading branch information
movermeyer committed May 30, 2021
1 parent 05941b1 commit ec767a2
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 8 deletions.
97 changes: 90 additions & 7 deletions packages/foam-vscode/src/features/create-from-template.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {
window,
commands,
ExtensionContext,
workspace,
QuickPickItem,
SnippetString,
Uri,
window,
workspace,
} from 'vscode';
import * as path from 'path';
import { FoamFeature } from '../types';
Expand All @@ -31,7 +32,13 @@ export class UserCancelledOperation extends Error {

const knownFoamVariables = new Set(['FOAM_TITLE']);

const defaultTemplateDefaultText: string = '# ${FOAM_TITLE}'; // eslint-disable-line no-template-curly-in-string
const defaultTemplateDefaultText: string = `---
foam_template:
name: New Note
description: Foam's default new note template
---
# \${FOAM_TITLE}
`;
const defaultTemplateUri = Uri.joinPath(templatesDir, 'new-note.md');

const templateContent = `# \${1:$TM_FILENAME_BASE}
Expand All @@ -53,9 +60,24 @@ For a full list of features see [the VS Code snippets page](https://code.visuals
2. create a note from this template by running the \`Foam: Create New Note From Template\` command
`;

async function getTemplates(): Promise<string[]> {
async function templateMetadata(
templateUri: Uri
): Promise<Map<string, string>> {
const contents = await workspace.fs
.readFile(templateUri)
.then(bytes => bytes.toString());
let templateMetadata: Map<string, string>,
_templateWithFoamFrontmatterRemoved: string;
[
templateMetadata,
_templateWithFoamFrontmatterRemoved,
] = extractFoamTemplateFrontmatterMetadata(contents);
return templateMetadata;
}

async function getTemplates(): Promise<Uri[]> {
const templates = await workspace.findFiles('.foam/templates/**.md');
return templates.map(template => path.basename(template.path));
return templates;
}

async function offerToCreateTemplate(): Promise<void> {
Expand Down Expand Up @@ -155,12 +177,71 @@ export function substituteFoamVariables(
return templateText;
}

function sortTemplatesMetadata(
t1: Map<string, string>,
t2: Map<string, string>
) {
// Sort by name's existence, then name, then path

if (t1.get('name') === undefined && t2.get('name') !== undefined) {
return 1;
}

if (t1.get('name') !== undefined && t2.get('name') === undefined) {
return -1;
}

const pathSortOrder = t1
.get('templatePath')
.localeCompare(t2.get('templatePath'));

if (t1.get('name') === undefined && t2.get('name') === undefined) {
return pathSortOrder;
}

const nameSortOrder = t1.get('name').localeCompare(t2.get('name'));

return nameSortOrder || pathSortOrder;
}

async function askUserForTemplate() {
const templates = await getTemplates();
if (templates.length === 0) {
return offerToCreateTemplate();
}
return await window.showQuickPick(templates, {

const templatesMetadata = (
await Promise.all(
templates.map(async templateUri => {
const metadata = await templateMetadata(templateUri);
metadata.set('templatePath', path.basename(templateUri.path));
return metadata;
})
)
).sort(sortTemplatesMetadata);

const items: QuickPickItem[] = await Promise.all(
templatesMetadata.map(metadata => {
const label = metadata.get('name') || metadata.get('templatePath');
const description = metadata.get('name')
? metadata.get('templatePath')
: null;
const detail = metadata.get('description');
const item = {
label: label,
description: description,
detail: detail,
};
Object.keys(item).forEach(key => {
if (!item[key]) {
delete item[key];
}
});
return item;
})
);

return await window.showQuickPick(items, {
placeHolder: 'Select a template to use.',
});
}
Expand Down Expand Up @@ -301,7 +382,9 @@ async function createNoteFromTemplate(
if (selectedTemplate === undefined) {
return;
}
templateFilename = selectedTemplate as string;
templateFilename =
(selectedTemplate as QuickPickItem).description ||
(selectedTemplate as QuickPickItem).label;
const templateUri = Uri.joinPath(templatesDir, templateFilename);
const templateText = await workspace.fs
.readFile(templateUri)
Expand Down
14 changes: 14 additions & 0 deletions packages/foam-vscode/src/utils/template-frontmatter-parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ foo: bar
test('Returns the `foam_template` metadata when it is used in its own frontmatter block', () => {
const input = `---
foam_template:
name: My Note Template
description: This is my note template
filepath: journal/$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE_$FOAM_TITLE.md
---
Expand All @@ -76,6 +78,8 @@ foam_template:
`;

const expectedMetadata = new Map<string, string>();
expectedMetadata.set('name', 'My Note Template');
expectedMetadata.set('description', 'This is my note template');
expectedMetadata.set(
'filepath',
'journal/$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE_$FOAM_TITLE.md'
Expand All @@ -89,6 +93,8 @@ foam_template:
const input = `---
foam_template:
filepath: journal/$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE_$FOAM_TITLE.md
description: This is my note template
name: My Note Template
---
---
Expand Down Expand Up @@ -116,6 +122,8 @@ more_metadata: *info
`;

const expectedMetadata = new Map<string, string>();
expectedMetadata.set('name', 'My Note Template');
expectedMetadata.set('description', 'This is my note template');
expectedMetadata.set(
'filepath',
'journal/$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE_$FOAM_TITLE.md'
Expand All @@ -129,7 +137,9 @@ more_metadata: *info
const input = `---
foo: bar
foam_template:
name: My Note Template
filepath: journal/$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE_$FOAM_TITLE.md
description: This is my note template
# A YAML comment
metadata: &info
title: The Gentlemen
Expand All @@ -151,6 +161,8 @@ more_metadata: *info
# $FOAM_TITLE`;

const expectedMetadata = new Map<string, string>();
expectedMetadata.set('name', 'My Note Template');
expectedMetadata.set('description', 'This is my note template');
expectedMetadata.set(
'filepath',
'journal/$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE_$FOAM_TITLE.md'
Expand All @@ -166,7 +178,9 @@ describe('removeFoamMetadata', () => {
const input = `---
foo: bar
foam_template: &foam_template # A YAML comment
description: This is my note template
filepath: journal/$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE_$FOAM_TITLE.md # A YAML comment
name: My Note Template
# A YAML comment
metadata: &info
title: The Gentlemen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,8 @@ export function extractFoamTemplateFrontmatterMetadata(
}

export function removeFoamMetadata(contents: string) {
return contents.replace(/^\s*foam_template:.*?\n\s*filepath:.*\n/gm, '');
return contents.replace(
/^\s*foam_template:.*?\n(?:\s*(?:filepath|name|description):.*\n)+/gm,
''
);
}

0 comments on commit ec767a2

Please sign in to comment.