#281 - Introduce new date fields and deprecate settings

This commit is contained in:
Elio Struyf
2022-03-07 11:39:57 +01:00
parent 04390b461f
commit 5644c0c381
9 changed files with 106 additions and 115 deletions
+1
View File
@@ -5,6 +5,7 @@
### ✨ Features
- [#175](https://github.com/estruyf/vscode-front-matter/issues/175): New snippet support + dashboard
- [#281](https://github.com/estruyf/vscode-front-matter/issues/281): New `isPublishDate` and `isModifiedDate` datetime field properties
### 🎨 Enhancements
+16 -3
View File
@@ -763,6 +763,16 @@
"type": "number",
"default": 0,
"description": "Limit the number of taxonomies to select. Set to 0 to allow unlimited."
},
"isPublishDate": {
"type": "boolean",
"default": false,
"description": "Specify if the field is the publish date field"
},
"isModifiedDate": {
"type": "boolean",
"default": false,
"description": "Specify if the field is the modified date field"
}
},
"additionalProperties": false,
@@ -883,7 +893,8 @@
"title": "Publishing date",
"name": "date",
"type": "datetime",
"default": "{{now}}"
"default": "{{now}}",
"isPublishDate": true
},
{
"title": "Content preview",
@@ -939,7 +950,8 @@
"frontMatter.taxonomy.dateField": {
"type": "string",
"default": "date",
"markdownDescription": "This setting is used to define the publishing date field of your articles. [Check in the docs](https://frontmatter.codes/docs/settings#frontmatter.taxonomy.datefield)"
"markdownDescription": "This setting is used to define the publishing date field of your articles. [Check in the docs](https://frontmatter.codes/docs/settings#frontmatter.taxonomy.datefield)",
"deprecationMessage": "This setting is deprecated and will be removed in the next major version. Please use the new `isPublishDate` settings instead in your content types date fields."
},
"frontMatter.taxonomy.dateFormat": {
"type": "string",
@@ -993,7 +1005,8 @@
"frontMatter.taxonomy.modifiedField": {
"type": "string",
"default": "lastmod",
"markdownDescription": "This setting is used to define the modified date field of your articles. [Check in the docs](https://frontmatter.codes/docs/settings#frontmatter.taxonomy.modifiedfield)"
"markdownDescription": "This setting is used to define the modified date field of your articles. [Check in the docs](https://frontmatter.codes/docs/settings#frontmatter.taxonomy.modifiedfield)",
"deprecationMessage": "This setting is deprecated and will be removed in the next major version. Please use the new `isModifiedDate` settings instead in your content types date fields."
},
"frontMatter.taxonomy.noPropertyValueQuotes": {
"type": "array",
+1 -1
View File
@@ -154,7 +154,7 @@ export class Article {
}
const cloneArticle = Object.assign({}, article);
const dateField = Settings.get(SETTING_MODIFIED_FIELD) as string || DefaultFields.LastModified;
const dateField = ArticleHelper.getModifiedDateField(article) || DefaultFields.LastModified;
try {
cloneArticle.data[dateField] = Article.formatDate(new Date());
return cloneArticle;
+10 -2
View File
@@ -12,8 +12,6 @@ export const SETTING_TAXONOMY_FIELD_GROUPS = "taxonomy.fieldGroups";
export const SETTING_DATE_FORMAT = "taxonomy.dateFormat";
export const SETTING_COMMA_SEPARATED_FIELDS = "taxonomy.commaSeparatedFields";
export const SETTING_TAXONOMY_CONTENT_TYPES = "taxonomy.contentTypes";
export const SETTING_DATE_FIELD = "taxonomy.dateField";
export const SETTING_MODIFIED_FIELD = "taxonomy.modifiedField";
export const SETTING_SLUG_PREFIX = "taxonomy.slugPrefix";
export const SETTING_SLUG_SUFFIX = "taxonomy.slugSuffix";
@@ -76,3 +74,13 @@ export const SETTING_SITE_BASEURL = "site.baseURL";
* @deprecated
*/
export const SETTING_CONTENT_FOLDERS = "content.folders";
/**
* @deprecated
* Use the `isPublishDate` property on the content type datetime field instead
*/
export const SETTING_DATE_FIELD = "taxonomy.dateField";
/**
* @deprecated
* Use the `isModifiedDate` property on the content type datetime field instead
*/
export const SETTING_MODIFIED_FIELD = "taxonomy.modifiedField";
+35 -3
View File
@@ -2,7 +2,7 @@ import { MarkdownFoldingProvider } from './../providers/MarkdownFoldingProvider'
import { DEFAULT_CONTENT_TYPE, DEFAULT_CONTENT_TYPE_NAME } from './../constants/ContentType';
import * as vscode from 'vscode';
import * as fs from "fs";
import { DefaultFields, SETTING_CONTENT_DEFAULT_FILETYPE, SETTING_CONTENT_PLACEHOLDERS, SETTING_CONTENT_SUPPORTED_FILETYPES, SETTING_FILE_PRESERVE_CASING, SETTING_COMMA_SEPARATED_FIELDS, SETTING_DATE_FIELD, SETTING_DATE_FORMAT, SETTING_INDENT_ARRAY, SETTING_REMOVE_QUOTES, SETTING_SITE_BASEURL, SETTING_TAXONOMY_CONTENT_TYPES, SETTING_TEMPLATES_PREFIX } from '../constants';
import { DefaultFields, SETTING_CONTENT_DEFAULT_FILETYPE, SETTING_CONTENT_PLACEHOLDERS, SETTING_CONTENT_SUPPORTED_FILETYPES, SETTING_FILE_PRESERVE_CASING, SETTING_COMMA_SEPARATED_FIELDS, SETTING_DATE_FIELD, SETTING_DATE_FORMAT, SETTING_INDENT_ARRAY, SETTING_REMOVE_QUOTES, SETTING_SITE_BASEURL, SETTING_TAXONOMY_CONTENT_TYPES, SETTING_TEMPLATES_PREFIX, SETTING_MODIFIED_FIELD } from '../constants';
import { DumpOptions } from 'js-yaml';
import { FrontMatterParser, ParsedFrontMatter } from '../parsers';
import { Extension, Logger, Settings, SlugHelper } from '.';
@@ -167,12 +167,12 @@ export class ArticleHelper {
* Get date from front matter
*/
public static getDate(article: ParsedFrontMatter | null) {
if (!article) {
if (!article || !article.data) {
return;
}
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
const dateField = Settings.get(SETTING_DATE_FIELD) as string || DefaultFields.PublishingDate;
const dateField = ArticleHelper.getPublishDateField(article) || DefaultFields.PublishingDate;
if (typeof article.data[dateField] !== "undefined") {
if (dateFormat && typeof dateFormat === "string") {
@@ -186,6 +186,38 @@ export class ArticleHelper {
return;
}
/**
* Retrieve the publishing date field name
* @param article
* @returns
*/
public static getPublishDateField(article: ParsedFrontMatter | null) {
if (!article || !article.data) {
return;
}
const articleCt = ArticleHelper.getContentType(article.data);
const pubDateField = articleCt.fields.find(f => f.isPublishDate);
return pubDateField?.name || Settings.get(SETTING_DATE_FIELD) as string || DefaultFields.PublishingDate;
}
/**
* Retrieve the publishing date field name
* @param article
* @returns
*/
public static getModifiedDateField(article: ParsedFrontMatter | null) {
if (!article || !article.data) {
return;
}
const articleCt = ArticleHelper.getContentType(article.data);
const modDateField = articleCt.fields.find(f => f.isModifiedDate);
return modDateField?.name || Settings.get(SETTING_MODIFIED_FIELD) as string || DefaultFields.PublishingDate;
}
/**
* Retrieve the content type of the current file
* @param updatedMetadata
+19 -105
View File
@@ -1,11 +1,7 @@
import { existsSync, renameSync } from "fs";
import { basename, join } from "path";
import { basename } from "path";
import { extensions, Uri, ExtensionContext, window, workspace, commands, ExtensionMode, DiagnosticCollection, languages } from "vscode";
import { Folders, WORKSPACE_PLACEHOLDER } from "../commands/Folders";
import { EXTENSION_NAME, GITHUB_LINK, SETTING_CONTENT_FOLDERS, SETTING_CONTENT_PAGE_FOLDERS, SETTING_DATE_FIELD, SETTING_MODIFIED_FIELD, SETTING_SEO_DESCRIPTION_FIELD, SETTING_TAXONOMY_CONTENT_TYPES, DEFAULT_CONTENT_TYPE_NAME, EXTENSION_BETA_ID, EXTENSION_ID, ExtensionState, DefaultFields, LocalStore, SETTING_TEMPLATES_FOLDER } from "../constants";
import { ContentType } from "../models";
import { EXTENSION_NAME, GITHUB_LINK, SETTING_DATE_FIELD, SETTING_MODIFIED_FIELD, EXTENSION_BETA_ID, EXTENSION_ID, ExtensionState } from "../constants";
import { Notifications } from "./Notifications";
import { parseWinPath } from "./parseWinPath";
import { Settings } from "./SettingsHelper";
@@ -135,115 +131,33 @@ export class Extension {
const minor = parseInt(version[1]);
const patch = parseInt(version[2]);
// Migration to version 3.1.0
if (major < 3 || (major === 3 && minor < 1)) {
const folders = Settings.get<any>(SETTING_CONTENT_FOLDERS);
if (folders && folders.length > 0) {
const workspace = Folders.getWorkspaceFolder();
const projectFolder = basename(workspace?.fsPath || "");
const paths = folders.map((folder: any) => ({
...folder,
path: `${WORKSPACE_PLACEHOLDER}${folder.fsPath.split(projectFolder).slice(1).join('')}`.split('\\').join('/')
}));
await Settings.update(SETTING_CONTENT_PAGE_FOLDERS, paths);
}
}
// Create team settings
if (Settings.hasSettings()) {
Settings.createTeamSettings();
}
// Migration to version 4.0.0
if (major < 4) {
const dateField = Settings.get<string>(SETTING_DATE_FIELD);
const lastModField = Settings.get<string>(SETTING_MODIFIED_FIELD);
const description = Settings.get<string>(SETTING_SEO_DESCRIPTION_FIELD);
const contentTypes = Settings.get<ContentType[]>(SETTING_TAXONOMY_CONTENT_TYPES);
// Migration scripts can be written here
const publishField = Settings.inspect(SETTING_DATE_FIELD);
const modifiedField = Settings.inspect(SETTING_MODIFIED_FIELD);
if (contentTypes) {
let needsUpdate = false;
let defaultContentType = contentTypes.find(ct => ct.name === DEFAULT_CONTENT_TYPE_NAME);
// Check if fields need to be changed for the default content type
if (defaultContentType) {
if (dateField && dateField !== DefaultFields.PublishingDate) {
const newDateField = defaultContentType.fields.find(f => f.name === dateField);
if (!newDateField) {
defaultContentType.fields = defaultContentType.fields.filter(f => f.name !== DefaultFields.PublishingDate);
defaultContentType.fields.push({
title: dateField,
name: dateField,
type: "datetime"
});
needsUpdate = true;
}
}
if (lastModField && lastModField !== DefaultFields.LastModified) {
const newModField = defaultContentType.fields.find(f => f.name === lastModField);
if (!newModField) {
defaultContentType.fields = defaultContentType.fields.filter(f => f.name !== DefaultFields.LastModified);
defaultContentType.fields.push({
title: lastModField,
name: lastModField,
type: "datetime"
});
needsUpdate = true;
}
}
if (description && description !== DefaultFields.Description) {
const newDescField = defaultContentType.fields.find(f => f.name === description);
if (!newDescField) {
defaultContentType.fields = defaultContentType.fields.filter(f => f.name !== DefaultFields.Description);
defaultContentType.fields.push({
title: description,
name: description,
type: "string"
});
needsUpdate = true;
}
}
if (needsUpdate) {
await Settings.update(SETTING_TAXONOMY_CONTENT_TYPES, contentTypes, true);
}
// Check for deprecation
if (publishField?.workspaceValue ||
publishField?.globalValue ||
publishField?.teamValue ||
modifiedField?.workspaceValue ||
modifiedField?.globalValue ||
modifiedField?.teamValue) {
Notifications.warning(`The "${SETTING_DATE_FIELD}" and "${SETTING_MODIFIED_FIELD}" settings have been deprecated. Please use the "isPublishDate" and "isModifiedDate" datetime field properties instead.`, "See migration guide").then(value => {
if (value === "See migration guide") {
const isProd = this.isProductionMode;
commands.executeCommand("vscode.open", Uri.parse(`https://${isProd ? '' : 'beta.'}frontmatter.codes/docs/troubleshooting#publish-and-modified-date-migration`));
}
}
});
}
// Migration to version 5
if (major <= 5) {
const isMoved = await Extension.getInstance().getState<boolean | undefined>(ExtensionState.MoveTemplatesFolder);
if (!isMoved) {
const wsFolder= Folders.getWorkspaceFolder();
if (wsFolder) {
const templateFolder = join(parseWinPath(wsFolder.fsPath), `.templates`);
if (existsSync(templateFolder)) {
window.showInformationMessage(`Would you like to move your ".templates" folder to the new ".frontmatter" folder?`, 'Yes', 'No').then(async (result) => {
if (result === "Yes") {
const newFolderPath = join(parseWinPath(wsFolder.fsPath), LocalStore.rootFolder, LocalStore.templatesFolder);
renameSync(templateFolder, newFolderPath);
commands.executeCommand(`workbench.action.reloadWindow`);
Settings.update(SETTING_TEMPLATES_FOLDER, undefined, true);
Settings.update(SETTING_TEMPLATES_FOLDER, undefined);
} else if (result === "No") {
Settings.update(SETTING_TEMPLATES_FOLDER, `.templates`, true);
}
if (result === "No" || result === "Yes") {
Extension.getInstance().setState(ExtensionState.MoveTemplatesFolder, true);
}
});
}
}
}
if (major < 7) {
// No migration needed
}
}
+19
View File
@@ -94,6 +94,21 @@ export class Settings {
});
}
/**
* Inspect a setting
* @param name
* @returns
*/
public static inspect<T>(name: string): any {
const configInpection = Settings.config.inspect<T>(name);
const settingKey = `${CONFIG_KEY}.${name}`;
return {
...configInpection,
teamValue: Settings.globalConfig[settingKey]
}
}
/**
* Retrieve a setting from global and local config
*/
@@ -162,6 +177,10 @@ export class Settings {
this.createGlobalFile(wsFolder);
}
/**
* Create the frontmatter.json file
* @param wsFolder
*/
public static createGlobalFile(wsFolder: Uri | undefined | null) {
const initialConfig = {
"$schema": `https://${Extension.getInstance().isBetaVersion() ? `beta.` : ``}frontmatter.codes/frontmatter.schema.json`
+1 -1
View File
@@ -139,7 +139,7 @@ export class PagesListener extends BaseListener {
if (article?.data.title) {
const wsFolder = Folders.getWorkspaceFolder();
const descriptionField = Settings.get(SETTING_SEO_DESCRIPTION_FIELD) as string || DefaultFields.Description;
const dateField = Settings.get(SETTING_DATE_FIELD) as string || DefaultFields.PublishingDate;
const dateField = ArticleHelper.getPublishDateField(article) || DefaultFields.PublishingDate;
const staticFolder = Settings.get<string>(SETTING_CONTENT_STATIC_FOLDER);
const page: Page = {
+4
View File
@@ -65,6 +65,10 @@ export interface Field {
fieldGroup?: string | string[];
dataType?: string | string[];
taxonomyLimit?: number;
// Date fields
isPublishDate?: boolean;
isModifiedDate?: boolean;
}
export interface DateInfo {