mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-03-28 17:42:40 +01:00
Merge branch 'estruyf:dev' into dev
This commit is contained in:
14
.github/ISSUE_TEMPLATE/bug_report.md
vendored
14
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -12,6 +12,7 @@ A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
@@ -23,16 +24,11 @@ A clear and concise description of what you expected to happen.
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
**Device:**
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
- OS: [e.g. iOS]
|
||||
- Front Matter CMS Version [e.g. 10.2.0]
|
||||
- Browser [e.g. chrome, safari]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
||||
8
.vscode/launch.json
vendored
8
.vscode/launch.json
vendored
@@ -10,7 +10,9 @@
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}", "--disable-extension=eliostruyf.vscode-front-matter"
|
||||
],
|
||||
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
|
||||
"preLaunchTask": "npm: build:ext"
|
||||
},
|
||||
@@ -19,7 +21,9 @@
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}", "--disable-extension=eliostruyf.vscode-front-matter"
|
||||
],
|
||||
"outFiles": ["${workspaceFolder}/dist/**/*.js"]
|
||||
}
|
||||
]
|
||||
|
||||
10
.vscode/settings.json
vendored
10
.vscode/settings.json
vendored
@@ -1,5 +1,15 @@
|
||||
// Place your settings in this file to overwrite default and user settings.
|
||||
{
|
||||
"commitHelper.messages": [
|
||||
{
|
||||
"type": "👨💻 apps",
|
||||
"values": ["#search", "#profile"]
|
||||
},
|
||||
{
|
||||
"type": "⚙️ tasks",
|
||||
"values": ["#build", "#deploy", "#skip"]
|
||||
}
|
||||
],
|
||||
"workbench.colorCustomizations": {
|
||||
"titleBar.activeBackground": "#15c2cb",
|
||||
"titleBar.inactiveBackground": "#44ffd299",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Change Log
|
||||
|
||||
## [10.2.0] - 2024-xx-xx
|
||||
## [10.2.0] - 2024-06-12 - [Release notes](https://beta.frontmatter.codes/updates/v10.2.0)
|
||||
|
||||
### ✨ New features
|
||||
|
||||
@@ -9,15 +9,15 @@
|
||||
### 🎨 Enhancements
|
||||
|
||||
- [#441](https://github.com/estruyf/vscode-front-matter/issues/441): Show input descriptions for snippet and data forms
|
||||
- [#442](https://github.com/estruyf/vscode-front-matter/issues/442): Hide sidebar on data view when data file is selecte + show dropdown of data files
|
||||
- [#442](https://github.com/estruyf/vscode-front-matter/issues/442): Hide sidebar on data view when data file is selected + show dropdown of data files
|
||||
- [#788](https://github.com/estruyf/vscode-front-matter/issues/788): Show a warning on setting update when it exists in an extended configuration
|
||||
- [#798](https://github.com/estruyf/vscode-front-matter/issues/798): Changed dialog to slide-over for the snippet forms
|
||||
- [#799](https://github.com/estruyf/vscode-front-matter/issues/799): Added `frontMatter.logging` setting to define the logging output. Options are `info`, `warn`, `error`, and `verbose`. Default is `info`.
|
||||
- [#799](https://github.com/estruyf/vscode-front-matter/issues/799): Added `frontMatter.logging` setting to define the logging output. Options are `info`, `warn`, `error`, and `verbose`. The default is `info`.
|
||||
- [#800](https://github.com/estruyf/vscode-front-matter/issues/800): Add colors for the Front Matter CMS output
|
||||
- [#808](https://github.com/estruyf/vscode-front-matter/issues/808): Add support to generate field groups and `block` fields in content type generation
|
||||
- [#810](https://github.com/estruyf/vscode-front-matter/issues/810): Update the tab title based on the view
|
||||
- [#811](https://github.com/estruyf/vscode-front-matter/issues/811): Added `panel.gitActions` view mode option to hide the Git actions in the panel
|
||||
- [#812](https://github.com/estruyf/vscode-front-matter/issues/812): Added the `{{locale}}` placeholder which can be used in the `previewPath` property
|
||||
- [#812](https://github.com/estruyf/vscode-front-matter/issues/812): Added the `{{locale}}` placeholder, which can be used in the `previewPath` property
|
||||
|
||||
### ⚡️ Optimizations
|
||||
|
||||
|
||||
@@ -1176,7 +1176,7 @@
|
||||
"scope": "Site preview"
|
||||
},
|
||||
"frontMatter.preview.trailingSlash": {
|
||||
"type": "string",
|
||||
"type": "boolean",
|
||||
"default": "",
|
||||
"markdownDescription": "%setting.frontMatter.preview.trailingSlash.markdownDescription%",
|
||||
"scope": "Site preview"
|
||||
|
||||
@@ -27,6 +27,7 @@ import { CustomPlaceholder, Field } from '../models';
|
||||
import { format } from 'date-fns';
|
||||
import {
|
||||
ArticleHelper,
|
||||
Logger,
|
||||
Settings,
|
||||
SlugHelper,
|
||||
processArticlePlaceholdersFromData,
|
||||
@@ -133,6 +134,7 @@ export class Article {
|
||||
private static async setLastModifiedDateInner(
|
||||
document: TextDocument
|
||||
): Promise<ParsedFrontMatter | undefined> {
|
||||
Logger.verbose(`Article:setLastModifiedDateInner:Start`);
|
||||
const article = ArticleHelper.getFrontMatterFromDocument(document);
|
||||
|
||||
// Only set the date, if there is already front matter set
|
||||
@@ -142,9 +144,16 @@ export class Article {
|
||||
|
||||
const cloneArticle = Object.assign({}, article);
|
||||
const dateField = await ArticleHelper.getModifiedDateField(article);
|
||||
Logger.verbose(`Article:setLastModifiedDateInner:DateField - ${JSON.stringify(dateField)}`);
|
||||
|
||||
try {
|
||||
const fieldName = dateField?.name || DefaultFields.LastModified;
|
||||
cloneArticle.data[fieldName] = Article.formatDate(new Date(), dateField?.dateFormat);
|
||||
const fieldValue = Article.formatDate(new Date(), dateField?.dateFormat);
|
||||
cloneArticle.data[fieldName] = fieldValue;
|
||||
Logger.verbose(
|
||||
`Article:setLastModifiedDateInner:DateField name - ${fieldName} - value - ${fieldValue}`
|
||||
);
|
||||
Logger.verbose(`Article:setLastModifiedDateInner:End`);
|
||||
return cloneArticle;
|
||||
} catch (e: unknown) {
|
||||
Notifications.error(
|
||||
@@ -352,7 +361,7 @@ export class Article {
|
||||
const autoUpdate = Settings.get(SETTING_AUTO_UPDATE_DATE);
|
||||
|
||||
// Is article located in one of the content folders
|
||||
const folders = await Folders.get();
|
||||
const folders = Folders.getCached();
|
||||
const documentPath = parseWinPath(document.fileName);
|
||||
const folder = folders.find((f) => documentPath.startsWith(f.path));
|
||||
if (!folder) {
|
||||
@@ -371,11 +380,16 @@ export class Article {
|
||||
public static formatDate(dateValue: Date, fieldDateFormat?: string): string {
|
||||
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
|
||||
|
||||
Logger.verbose(`Article:formatDate:Start`);
|
||||
|
||||
if (fieldDateFormat) {
|
||||
Logger.verbose(`Article:formatDate:FieldDateFormat - ${fieldDateFormat}`);
|
||||
return format(dateValue, DateHelper.formatUpdate(fieldDateFormat) as string);
|
||||
} else if (dateFormat && typeof dateFormat === 'string') {
|
||||
Logger.verbose(`Article:formatDate:DateFormat - ${dateFormat}`);
|
||||
return format(dateValue, DateHelper.formatUpdate(dateFormat) as string);
|
||||
} else {
|
||||
Logger.verbose(`Article:formatDate:toISOString - ${dateValue}`);
|
||||
return typeof dateValue.toISOString === 'function'
|
||||
? dateValue.toISOString()
|
||||
: dateValue?.toString();
|
||||
|
||||
@@ -33,7 +33,10 @@ export class Diagnostics {
|
||||
|
||||
const fileTypes = Diagnostics.getFileTypes();
|
||||
|
||||
const logging = `# Front Matter CMS - Diagnostics
|
||||
const logging = `# ${Extension.getInstance().displayName} - Diagnostics
|
||||
|
||||
Beta: \`${Extension.getInstance().isBetaVersion()}\`
|
||||
Version: \`${Extension.getInstance().version}\`
|
||||
|
||||
## Project name
|
||||
|
||||
|
||||
@@ -448,6 +448,14 @@ export class Folders {
|
||||
return Folders._folders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cached folder settings
|
||||
* @returns {ContentFolder[]} - The cached folder settings
|
||||
*/
|
||||
public static getCached(): ContentFolder[] {
|
||||
return Folders._folders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the folder settings
|
||||
* @param folders
|
||||
|
||||
@@ -13,7 +13,6 @@ import { join, parse } from 'path';
|
||||
import { commands, env, Uri, ViewColumn, window, WebviewPanel, extensions } from 'vscode';
|
||||
import {
|
||||
ArticleHelper,
|
||||
DateHelper,
|
||||
Extension,
|
||||
parseWinPath,
|
||||
processI18nPlaceholders,
|
||||
@@ -21,10 +20,10 @@ import {
|
||||
processFmPlaceholders,
|
||||
processPathPlaceholders,
|
||||
Settings,
|
||||
Telemetry
|
||||
Telemetry,
|
||||
processDateTimePlaceholders
|
||||
} from '../helpers';
|
||||
import { ContentFolder, ContentType, PreviewSettings } from '../models';
|
||||
import { format } from 'date-fns';
|
||||
import { Article } from '.';
|
||||
import { WebviewHelper } from '@estruyf/vscode';
|
||||
import { Folders } from './Folders';
|
||||
@@ -33,6 +32,7 @@ import { getLocalizationFile } from '../utils/getLocalizationFile';
|
||||
import * as l10n from '@vscode/l10n';
|
||||
import { LocalizationKey } from '../localization';
|
||||
import { joinUrl } from '../utils';
|
||||
import { i18n } from './i18n';
|
||||
|
||||
export class Preview {
|
||||
public static filePath: string | undefined = undefined;
|
||||
@@ -250,9 +250,7 @@ export class Preview {
|
||||
// Check if there is a pathname defined on content folder level
|
||||
const folders = await Folders.get();
|
||||
if (folders.length > 0) {
|
||||
const foldersWithPath = folders.filter((folder) => folder.previewPath);
|
||||
|
||||
for (const folder of foldersWithPath) {
|
||||
for (const folder of folders) {
|
||||
const folderPath = parseWinPath(folder.path);
|
||||
if (filePath.startsWith(folderPath)) {
|
||||
if (!selectedFolder || selectedFolder.path.length < folderPath.length) {
|
||||
@@ -298,6 +296,11 @@ export class Preview {
|
||||
slug = Article.getSlug();
|
||||
}
|
||||
|
||||
const locale = await i18n.getLocale(filePath);
|
||||
if (locale && locale.path === slug) {
|
||||
slug = '';
|
||||
}
|
||||
|
||||
if (pathname) {
|
||||
// Known placeholders
|
||||
const dateFormat = Settings.get(SETTING_DATE_FORMAT) as string;
|
||||
@@ -336,10 +339,8 @@ export class Preview {
|
||||
|
||||
try {
|
||||
const articleDate = await ArticleHelper.getDate(article);
|
||||
slug = join(
|
||||
format(articleDate || new Date(), DateHelper.formatUpdate(pathname) as string),
|
||||
slug
|
||||
);
|
||||
pathname = processDateTimePlaceholders(pathname, dateFormat, articleDate);
|
||||
slug = join(pathname, slug);
|
||||
} catch (error) {
|
||||
slug = join(pathname, slug);
|
||||
}
|
||||
|
||||
12
src/constants/DefaultFeatureFlags.ts
Normal file
12
src/constants/DefaultFeatureFlags.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { FEATURE_FLAG } from './Features';
|
||||
|
||||
export const DEFAULT_PANEL_FEATURE_FLAGS = Object.values(FEATURE_FLAG.panel).filter(
|
||||
(v) => v !== FEATURE_FLAG.panel.globalSettings
|
||||
);
|
||||
|
||||
export const DEFAULT_DASHBOARD_FEATURE_FLAGS = [
|
||||
FEATURE_FLAG.dashboard.data.view,
|
||||
FEATURE_FLAG.dashboard.taxonomy.view,
|
||||
FEATURE_FLAG.dashboard.snippets.view,
|
||||
FEATURE_FLAG.dashboard.snippets.manage
|
||||
];
|
||||
@@ -9,6 +9,7 @@ import { Tab } from './Tab';
|
||||
import * as l10n from '@vscode/l10n';
|
||||
import { LocalizationKey } from '../../../localization';
|
||||
import { PageIcon } from '../../../panelWebView/components/Icons';
|
||||
import { DEFAULT_DASHBOARD_FEATURE_FLAGS } from '../../../constants/DefaultFeatureFlags';
|
||||
|
||||
export interface ITabsProps {
|
||||
onNavigate: (navigationType: NavigationType) => void;
|
||||
@@ -19,12 +20,6 @@ export const Tabs: React.FunctionComponent<ITabsProps> = ({
|
||||
}: React.PropsWithChildren<ITabsProps>) => {
|
||||
const mode = useRecoilValue(ModeAtom);
|
||||
|
||||
const allDashboardVIews = [
|
||||
FEATURE_FLAG.dashboard.snippets.view,
|
||||
FEATURE_FLAG.dashboard.data.view,
|
||||
FEATURE_FLAG.dashboard.taxonomy.view
|
||||
];
|
||||
|
||||
return (
|
||||
<ul
|
||||
className="flex items-center justify-start h-full space-x-4"
|
||||
@@ -43,7 +38,7 @@ export const Tabs: React.FunctionComponent<ITabsProps> = ({
|
||||
<span>{l10n.t(LocalizationKey.dashboardHeaderTabsMedia)}</span>
|
||||
</Tab>
|
||||
</li>
|
||||
<FeatureFlag features={mode?.features || [...allDashboardVIews]} flag={FEATURE_FLAG.dashboard.snippets.view}>
|
||||
<FeatureFlag features={mode?.features || DEFAULT_DASHBOARD_FEATURE_FLAGS} flag={FEATURE_FLAG.dashboard.snippets.view}>
|
||||
<li role="presentation">
|
||||
<Tab navigationType={NavigationType.Snippets} onNavigate={onNavigate}>
|
||||
<ScissorsIcon className={`h-4 w-auto mr-2`} />
|
||||
@@ -51,7 +46,7 @@ export const Tabs: React.FunctionComponent<ITabsProps> = ({
|
||||
</Tab>
|
||||
</li>
|
||||
</FeatureFlag>
|
||||
<FeatureFlag features={mode?.features || [...allDashboardVIews]} flag={FEATURE_FLAG.dashboard.data.view}>
|
||||
<FeatureFlag features={mode?.features || DEFAULT_DASHBOARD_FEATURE_FLAGS} flag={FEATURE_FLAG.dashboard.data.view}>
|
||||
<li role="presentation">
|
||||
<Tab navigationType={NavigationType.Data} onNavigate={onNavigate}>
|
||||
<CircleStackIcon className={`h-4 w-auto mr-2`} />
|
||||
@@ -59,7 +54,7 @@ export const Tabs: React.FunctionComponent<ITabsProps> = ({
|
||||
</Tab>
|
||||
</li>
|
||||
</FeatureFlag>
|
||||
<FeatureFlag features={mode?.features || [...allDashboardVIews]} flag={FEATURE_FLAG.dashboard.taxonomy.view}>
|
||||
<FeatureFlag features={mode?.features || DEFAULT_DASHBOARD_FEATURE_FLAGS} flag={FEATURE_FLAG.dashboard.taxonomy.view}>
|
||||
<li role="presentation">
|
||||
<Tab navigationType={NavigationType.Taxonomy} onNavigate={onNavigate}>
|
||||
<TagIcon className={`h-4 w-auto mr-2`} />
|
||||
|
||||
@@ -19,6 +19,7 @@ import { LocalizationKey } from '../../../localization';
|
||||
import { FooterActions } from './FooterActions';
|
||||
import { ItemMenu } from './ItemMenu';
|
||||
import { SlideOver } from '../Modals/SlideOver';
|
||||
import { DEFAULT_DASHBOARD_FEATURE_FLAGS } from '../../../constants/DefaultFeatureFlags';
|
||||
|
||||
export interface IItemProps {
|
||||
snippetKey: string;
|
||||
@@ -163,7 +164,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
|
||||
</h2>
|
||||
|
||||
<FeatureFlag
|
||||
features={mode?.features || []}
|
||||
features={mode?.features || DEFAULT_DASHBOARD_FEATURE_FLAGS}
|
||||
flag={FEATURE_FLAG.dashboard.snippets.manage}
|
||||
alternative={
|
||||
<ItemMenu
|
||||
@@ -190,7 +191,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
|
||||
</div>
|
||||
|
||||
<FeatureFlag
|
||||
features={mode?.features || []}
|
||||
features={mode?.features || DEFAULT_DASHBOARD_FEATURE_FLAGS}
|
||||
flag={FEATURE_FLAG.dashboard.snippets.manage}
|
||||
alternative={
|
||||
<FooterActions
|
||||
|
||||
@@ -18,6 +18,7 @@ import * as l10n from '@vscode/l10n';
|
||||
import { LocalizationKey } from '../../../localization';
|
||||
import { List } from '../Media/List';
|
||||
import { SlideOver } from '../Modals/SlideOver';
|
||||
import { DEFAULT_DASHBOARD_FEATURE_FLAGS } from '../../../constants/DefaultFeatureFlags';
|
||||
|
||||
export interface ISnippetsProps { }
|
||||
|
||||
@@ -96,7 +97,9 @@ export const Snippets: React.FunctionComponent<ISnippetsProps> = (
|
||||
return (
|
||||
<PageLayout
|
||||
header={
|
||||
<FeatureFlag features={mode?.features || []} flag={FEATURE_FLAG.dashboard.snippets.manage}>
|
||||
<FeatureFlag
|
||||
features={mode?.features || DEFAULT_DASHBOARD_FEATURE_FLAGS}
|
||||
flag={FEATURE_FLAG.dashboard.snippets.manage}>
|
||||
<div
|
||||
className={`py-3 px-4 flex items-center justify-between border-b border-[var(--frontmatter-border)]`}
|
||||
aria-label={l10n.t(LocalizationKey.dashboardSnippetsViewSnippetsAriaLabel)}
|
||||
|
||||
@@ -166,7 +166,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
-100
|
||||
);
|
||||
fmStatusBarItem.command = COMMAND_NAME.dashboard;
|
||||
fmStatusBarItem.text = `$(fm-logo)`;
|
||||
fmStatusBarItem.text = `$(fm-logo) ${extension.getVersion().installedVersion}`;
|
||||
fmStatusBarItem.tooltip = EXTENSION_NAME;
|
||||
fmStatusBarItem.show();
|
||||
|
||||
|
||||
@@ -44,7 +44,8 @@ import {
|
||||
SETTING_PROJECTS,
|
||||
SETTING_TAXONOMY_TAGS,
|
||||
SETTING_TAXONOMY_CATEGORIES,
|
||||
SETTING_CONTENT_FILTERS
|
||||
SETTING_CONTENT_FILTERS,
|
||||
SETTING_CONTENT_I18N
|
||||
} from '../constants';
|
||||
import { Folders } from '../commands/Folders';
|
||||
import { join, basename, dirname, parse } from 'path';
|
||||
@@ -992,6 +993,10 @@ ${JSON.stringify(value, null, 2)}`,
|
||||
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_PROJECTS)) {
|
||||
Settings.updateGlobalConfigArraySetting(SETTING_PROJECTS, 'name', configJson);
|
||||
}
|
||||
// i18n
|
||||
else if (Settings.isEqualOrStartsWith(relSettingName, SETTING_CONTENT_I18N)) {
|
||||
Settings.updateGlobalConfigArraySetting(SETTING_CONTENT_I18N, 'locale', configJson);
|
||||
}
|
||||
// Snippets
|
||||
else if (
|
||||
Settings.isEqualOrStartsWith(relSettingName, SETTING_CONTENT_SNIPPETS) &&
|
||||
|
||||
@@ -32,6 +32,7 @@ export * from './isValidFile';
|
||||
export * from './openFileInEditor';
|
||||
export * from './parseWinPath';
|
||||
export * from './processArticlePlaceholders';
|
||||
export * from './processDateTimePlaceholders';
|
||||
export * from './processFmPlaceholders';
|
||||
export * from './processI18nPlaceholders';
|
||||
export * from './processPathPlaceholders';
|
||||
|
||||
43
src/helpers/processDateTimePlaceholders.ts
Normal file
43
src/helpers/processDateTimePlaceholders.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { format } from 'date-fns';
|
||||
import { DateHelper } from './DateHelper';
|
||||
|
||||
/**
|
||||
* Replace the datetime placeholders
|
||||
* @param value
|
||||
* @param dateFormat
|
||||
* @param articleDate
|
||||
* @returns
|
||||
*/
|
||||
export const processDateTimePlaceholders = (
|
||||
value: string,
|
||||
dateFormat?: string,
|
||||
articleDate?: Date
|
||||
) => {
|
||||
if (value && typeof value === 'string') {
|
||||
if (value.includes(`{{date|`)) {
|
||||
const regex = /{{date\|[^}]*}}/g;
|
||||
const matches = value.match(regex);
|
||||
if (matches) {
|
||||
for (const match of matches) {
|
||||
const placeholderParts = match.split('|');
|
||||
if (placeholderParts.length > 1) {
|
||||
let dateFormat = placeholderParts[1].trim().replace('}}', '');
|
||||
|
||||
if (dateFormat) {
|
||||
if (dateFormat && typeof dateFormat === 'string') {
|
||||
value = value.replace(
|
||||
match,
|
||||
format(articleDate || new Date(), DateHelper.formatUpdate(dateFormat) as string)
|
||||
);
|
||||
} else {
|
||||
value = value.replace(match, (articleDate || new Date()).toISOString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
@@ -4,10 +4,10 @@ import { DateHelper } from './DateHelper';
|
||||
/**
|
||||
* Replace the time placeholders
|
||||
* @param value
|
||||
* @param title
|
||||
* @param dateFormat
|
||||
* @returns
|
||||
*/
|
||||
export const processTimePlaceholders = (value: string, dateFormat?: string) => {
|
||||
export const processTimePlaceholders = (value: string, dateFormat?: string, articleDate?: Date) => {
|
||||
if (value && typeof value === 'string') {
|
||||
if (value.includes('{{now}}')) {
|
||||
const regex = new RegExp('{{now}}', 'g');
|
||||
@@ -15,46 +15,46 @@ export const processTimePlaceholders = (value: string, dateFormat?: string) => {
|
||||
if (dateFormat && typeof dateFormat === 'string') {
|
||||
value = value.replace(
|
||||
regex,
|
||||
format(new Date(), DateHelper.formatUpdate(dateFormat) as string)
|
||||
format(articleDate || new Date(), DateHelper.formatUpdate(dateFormat) as string)
|
||||
);
|
||||
} else {
|
||||
value = value.replace(regex, new Date().toISOString());
|
||||
value = value.replace(regex, (articleDate || new Date()).toISOString());
|
||||
}
|
||||
}
|
||||
|
||||
if (value.includes('{{year}}')) {
|
||||
const regex = new RegExp('{{year}}', 'g');
|
||||
value = value.replace(regex, format(new Date(), 'yyyy'));
|
||||
value = value.replace(regex, format(articleDate || new Date(), 'yyyy'));
|
||||
}
|
||||
|
||||
if (value.includes('{{month}}')) {
|
||||
const regex = new RegExp('{{month}}', 'g');
|
||||
value = value.replace(regex, format(new Date(), 'MM'));
|
||||
value = value.replace(regex, format(articleDate || new Date(), 'MM'));
|
||||
}
|
||||
|
||||
if (value.includes('{{day}}')) {
|
||||
const regex = new RegExp('{{day}}', 'g');
|
||||
value = value.replace(regex, format(new Date(), 'dd'));
|
||||
value = value.replace(regex, format(articleDate || new Date(), 'dd'));
|
||||
}
|
||||
|
||||
if (value.includes('{{hour12}}')) {
|
||||
const regex = new RegExp('{{hour12}}', 'g');
|
||||
value = value.replace(regex, format(new Date(), 'hh'));
|
||||
value = value.replace(regex, format(articleDate || new Date(), 'hh'));
|
||||
}
|
||||
|
||||
if (value.includes('{{hour24}}')) {
|
||||
const regex = new RegExp('{{hour24}}', 'g');
|
||||
value = value.replace(regex, format(new Date(), 'HH'));
|
||||
value = value.replace(regex, format(articleDate || new Date(), 'HH'));
|
||||
}
|
||||
|
||||
if (value.includes('{{ampm}}')) {
|
||||
const regex = new RegExp('{{ampm}}', 'g');
|
||||
value = value.replace(regex, format(new Date(), 'aaa'));
|
||||
value = value.replace(regex, format(articleDate || new Date(), 'aaa'));
|
||||
}
|
||||
|
||||
if (value.includes('{{minute}}')) {
|
||||
const regex = new RegExp('{{minute}}', 'g');
|
||||
value = value.replace(regex, format(new Date(), 'mm'));
|
||||
value = value.replace(regex, format(articleDate || new Date(), 'mm'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ export class PagesListener extends BaseListener {
|
||||
// Optimize the list of recently changed files
|
||||
DataListener.getFoldersAndFiles(doc.uri);
|
||||
// Trigger the metadata update
|
||||
this.watcherExec(doc.uri);
|
||||
this.watcherExec(doc.uri, 'save');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -103,9 +103,9 @@ export class PagesListener extends BaseListener {
|
||||
false,
|
||||
false
|
||||
);
|
||||
watcher.onDidCreate(async (uri: Uri) => this.watcherExec(uri));
|
||||
watcher.onDidChange(async (uri: Uri) => this.watcherExec(uri));
|
||||
watcher.onDidDelete(async (uri: Uri) => this.watcherExec(uri));
|
||||
watcher.onDidCreate(async (uri: Uri) => this.watcherExec(uri, 'create'));
|
||||
watcher.onDidChange(async (uri: Uri) => this.watcherExec(uri, 'change'));
|
||||
watcher.onDidDelete(async (uri: Uri) => this.watcherExec(uri, 'delete'));
|
||||
this.watchers[folderUri.fsPath] = watcher;
|
||||
}
|
||||
}
|
||||
@@ -162,10 +162,10 @@ export class PagesListener extends BaseListener {
|
||||
* Watcher for processing page updates
|
||||
* @param file
|
||||
*/
|
||||
private static async watcherExec(file: Uri) {
|
||||
private static async watcherExec(file: Uri, type?: 'create' | 'change' | 'delete' | 'save') {
|
||||
const progressFile = async (file: Uri) => {
|
||||
const ext = Extension.getInstance();
|
||||
Logger.info(`File watcher execution for: ${file.fsPath}`);
|
||||
Logger.info(`File watcher execution for (${type}): ${file.fsPath}`);
|
||||
|
||||
const pageIdx = this.lastPages.findIndex((p) => p.fmFilePath === file.fsPath);
|
||||
if (pageIdx !== -1) {
|
||||
|
||||
@@ -17,6 +17,7 @@ import { usePrevious } from './hooks/usePrevious';
|
||||
import * as l10n from '@vscode/l10n';
|
||||
import { LocalizationKey } from '../localization';
|
||||
import { InitializeAction } from './components/InitializeAction';
|
||||
import { DEFAULT_PANEL_FEATURE_FLAGS } from '../constants/DefaultFeatureFlags';
|
||||
|
||||
export interface IViewPanelProps { }
|
||||
|
||||
@@ -37,10 +38,6 @@ export const ViewPanel: React.FunctionComponent<IViewPanelProps> = (
|
||||
const prevMediaSelection = usePrevious(mediaSelecting);
|
||||
const [scrollY, setScrollY] = useState(0);
|
||||
|
||||
const allPanelValues = useMemo(() => {
|
||||
return Object.values(FEATURE_FLAG.panel).filter(v => v !== FEATURE_FLAG.panel.globalSettings)
|
||||
}, [FEATURE_FLAG.panel]);
|
||||
|
||||
const scollListener = useCallback((e: Event) => {
|
||||
if (!mediaSelecting) {
|
||||
setScrollY(window.scrollY);
|
||||
@@ -48,7 +45,7 @@ export const ViewPanel: React.FunctionComponent<IViewPanelProps> = (
|
||||
}, [mediaSelecting]);
|
||||
|
||||
const isSomethingShown = useMemo(() => {
|
||||
const panelModeValues = (mode?.features || [...allPanelValues]).filter(v => v.startsWith('panel.'));
|
||||
const panelModeValues = (mode?.features || DEFAULT_PANEL_FEATURE_FLAGS).filter(v => v.startsWith('panel.'));
|
||||
|
||||
if (panelModeValues.length === 0) {
|
||||
return false;
|
||||
@@ -125,19 +122,19 @@ export const ViewPanel: React.FunctionComponent<IViewPanelProps> = (
|
||||
<InitializeAction settings={settings} />
|
||||
|
||||
<div className={`ext_actions`}>
|
||||
<FeatureFlag features={mode?.features || [...allPanelValues]} flag={FEATURE_FLAG.panel.gitActions}>
|
||||
<FeatureFlag features={mode?.features || DEFAULT_PANEL_FEATURE_FLAGS} flag={FEATURE_FLAG.panel.gitActions}>
|
||||
<GitAction settings={settings} />
|
||||
</FeatureFlag>
|
||||
|
||||
{!loading && (<CustomView metadata={metadata} />)}
|
||||
|
||||
<FeatureFlag features={mode?.features || [...allPanelValues]} flag={FEATURE_FLAG.panel.globalSettings}>
|
||||
<FeatureFlag features={mode?.features || DEFAULT_PANEL_FEATURE_FLAGS} flag={FEATURE_FLAG.panel.globalSettings}>
|
||||
<GlobalSettings settings={settings} isBase={!metadata} />
|
||||
</FeatureFlag>
|
||||
|
||||
{
|
||||
!loading && metadata && settings && settings.seo && (
|
||||
<FeatureFlag features={mode?.features || [...allPanelValues]} flag={FEATURE_FLAG.panel.seo}>
|
||||
<FeatureFlag features={mode?.features || DEFAULT_PANEL_FEATURE_FLAGS} flag={FEATURE_FLAG.panel.seo}>
|
||||
<SeoStatus
|
||||
seo={settings.seo}
|
||||
data={metadata}
|
||||
@@ -149,7 +146,7 @@ export const ViewPanel: React.FunctionComponent<IViewPanelProps> = (
|
||||
}
|
||||
|
||||
{!loading && settings && (
|
||||
<FeatureFlag features={mode?.features || [...allPanelValues]} flag={FEATURE_FLAG.panel.actions}>
|
||||
<FeatureFlag features={mode?.features || DEFAULT_PANEL_FEATURE_FLAGS} flag={FEATURE_FLAG.panel.actions}>
|
||||
<Actions
|
||||
metadata={metadata}
|
||||
settings={settings}
|
||||
@@ -159,23 +156,23 @@ export const ViewPanel: React.FunctionComponent<IViewPanelProps> = (
|
||||
|
||||
{
|
||||
!loading && metadata && (
|
||||
<FeatureFlag features={mode?.features || [...allPanelValues]} flag={FEATURE_FLAG.panel.metadata}>
|
||||
<FeatureFlag features={mode?.features || DEFAULT_PANEL_FEATURE_FLAGS} flag={FEATURE_FLAG.panel.metadata}>
|
||||
<Metadata
|
||||
settings={settings}
|
||||
metadata={metadata}
|
||||
focusElm={focusElm}
|
||||
unsetFocus={unsetFocus}
|
||||
features={mode?.features || [...allPanelValues]}
|
||||
features={mode?.features || DEFAULT_PANEL_FEATURE_FLAGS}
|
||||
/>
|
||||
</FeatureFlag>
|
||||
)
|
||||
}
|
||||
|
||||
<FeatureFlag features={mode?.features || [...allPanelValues]} flag={FEATURE_FLAG.panel.recentlyModified}>
|
||||
<FeatureFlag features={mode?.features || DEFAULT_PANEL_FEATURE_FLAGS} flag={FEATURE_FLAG.panel.recentlyModified}>
|
||||
<FolderAndFiles data={folderAndFiles} isBase={!metadata} />
|
||||
</FeatureFlag>
|
||||
|
||||
<FeatureFlag features={mode?.features || [...allPanelValues]} flag={FEATURE_FLAG.panel.otherActions}>
|
||||
<FeatureFlag features={mode?.features || DEFAULT_PANEL_FEATURE_FLAGS} flag={FEATURE_FLAG.panel.otherActions}>
|
||||
<OtherActions settings={settings} isFile={!!metadata} isBase={!metadata} />
|
||||
</FeatureFlag>
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { FEATURE_FLAG, GeneralCommands } from '../../constants';
|
||||
import { Messenger } from '@estruyf/vscode/dist/client';
|
||||
import * as l10n from '@vscode/l10n';
|
||||
import { LocalizationKey } from '../../localization';
|
||||
import { DEFAULT_PANEL_FEATURE_FLAGS } from '../../constants/DefaultFeatureFlags';
|
||||
|
||||
export interface IMetadata {
|
||||
[prop: string]: string[] | string | null | IMetadata;
|
||||
@@ -95,7 +96,7 @@ const Metadata: React.FunctionComponent<IMetadataProps> = ({
|
||||
id={`tags`}
|
||||
title={`${l10n.t(LocalizationKey.panelMetadataTitle)}${contentType?.name ? ` (${contentType?.name})` : ""}`}
|
||||
className={`inherit z-20`}>
|
||||
<FeatureFlag features={features || []} flag={FEATURE_FLAG.panel.contentType}>
|
||||
<FeatureFlag features={features || DEFAULT_PANEL_FEATURE_FLAGS} flag={FEATURE_FLAG.panel.contentType}>
|
||||
<ContentTypeValidator fields={contentType?.fields || []} metadata={metadata} />
|
||||
</FeatureFlag>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user