Compare commits

..

16 Commits

Author SHA1 Message Date
Elio Struyf
f1f0e0ab58 Merge pull request #886 from estruyf/beta
PR for v10.6.0
2024-11-06 11:06:01 +01:00
Elio Struyf
5f7f847ff8 Merge branch 'beta' of github.com:estruyf/vscode-front-matter into beta 2024-11-06 10:54:36 +01:00
Elio Struyf
2c4dbeb1eb update changelog 2024-11-06 10:54:32 +01:00
Elio Struyf
17164df11f Update fuse options 2024-11-04 19:37:00 +01:00
Elio Struyf
228c46084d Update categories 2024-11-04 18:39:47 +01:00
Elio Struyf
e838f18abc Remove unused ref 2024-11-04 13:42:36 +01:00
Elio Struyf
3d6359bc2e Issue: Content relationship field type is fetching forever #885 2024-11-04 13:20:18 +01:00
Elio Struyf
57b710cc61 Enhancement: hide WYSIWYG actions in git diff mode #884 2024-11-04 11:23:19 +01:00
Elio Struyf
7796d52ff9 Fix beta version 2024-10-28 16:25:49 +01:00
Elio Struyf
f8f539be0d #862 - evaluate the node command 2024-10-28 15:07:35 +01:00
Elio Struyf
fc96c8922c Feedback: Enum/Select in schema fields #859 2024-10-28 14:41:50 +01:00
Elio Struyf
c84af8493b Enhancement: dynamic evaluation of commands #882 2024-10-28 10:40:49 +01:00
Elio Struyf
6f288ff757 #879 Fix for auto updating last modified date on save 2024-10-24 14:25:34 +02:00
Elio Struyf
0e04e687fa #878 - Enhanced select all logic 2024-10-24 12:05:07 +02:00
Elio Struyf
cec3cbee3a Update changelog 2024-10-23 17:54:43 +02:00
Elio Struyf
c6f40194b4 Refactor snippet type display logic #867 2024-10-23 17:53:27 +02:00
20 changed files with 237 additions and 147 deletions

View File

@@ -1,5 +1,20 @@
# Change Log
## [10.6.0] - 2024-11-06 - [Release notes](https://beta.frontmatter.codes/updates/v10.6.0)
### 🎨 Enhancements
- [#878](https://github.com/estruyf/vscode-front-matter/issues/878): Allow the `select all` button to work on other pages when there is a selection present
- [#882](https://github.com/estruyf/vscode-front-matter/issues/882): Dynamic evaluation of the `node` executable path
- [#884](https://github.com/estruyf/vscode-front-matter/issues/884): Hide WYSIWYG actions when the file is in git diff mode
### 🐞 Fixes
- [#859](https://github.com/estruyf/vscode-front-matter/issues/859): Fix label in the data view dropdown field
- [#876](https://github.com/estruyf/vscode-front-matter/issues/876): Fix snippet type on the snippet card
- [#879](https://github.com/estruyf/vscode-front-matter/issues/879): Fix for auto updating last modified date on save
- [#885](https://github.com/estruyf/vscode-front-matter/issues/885): Fix content relationship for none i18n content
## [10.5.1] - 2024-10-23
### 🎨 Enhancements

View File

@@ -3,7 +3,7 @@
"displayName": "Front Matter CMS",
"description": "Front Matter is a CMS that runs within Visual Studio Code. It gives you the power and control of a full-blown CMS while also providing you the flexibility and speed of the static site generator of your choice like: Hugo, Jekyll, Docusaurus, NextJs, Gatsby, and many more...",
"icon": "assets/frontmatter-teal-128x128.png",
"version": "10.5.1",
"version": "10.6.0",
"preview": false,
"publisher": "eliostruyf",
"galleryBanner": {
@@ -31,7 +31,7 @@
"l10n": "./l10n",
"categories": [
"AI",
"Other"
"Visualization"
],
"keywords": [
"Front Matter",
@@ -2421,32 +2421,32 @@
"editor/title": [{
"command": "frontMatter.markup.heading",
"group": "navigation@-133",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg && activeEditor == 'workbench.editors.files.textFileEditor'"
},
{
"command": "frontMatter.markup.bold",
"group": "navigation@-132",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg && activeEditor == 'workbench.editors.files.textFileEditor'"
},
{
"command": "frontMatter.markup.italic",
"group": "navigation@-131",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg && activeEditor == 'workbench.editors.files.textFileEditor'"
},
{
"command": "frontMatter.markup.hyperlink",
"group": "navigation@-130",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg && activeEditor == 'workbench.editors.files.textFileEditor'"
},
{
"command": "frontMatter.insertSnippet",
"group": "navigation@-129",
"when": "frontMatter:file:isValid == true && frontMatter:dashboard:snippets:enabled"
"when": "frontMatter:file:isValid == true && frontMatter:dashboard:snippets:enabled && activeEditor == 'workbench.editors.files.textFileEditor'"
},
{
"command": "frontMatter.insertMedia",
"group": "navigation@-128",
"when": "frontMatter:file:isValid == true"
"when": "frontMatter:file:isValid == true && activeEditor == 'workbench.editors.files.textFileEditor'"
},
{
"command": "frontMatter.i18n.createOrOpen",
@@ -2456,37 +2456,37 @@
{
"command": "frontMatter.markup.options",
"group": "navigation@-126",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg && activeEditor == 'workbench.editors.files.textFileEditor'"
},
{
"command": "frontMatter.markup.orderedlist",
"group": "1_markup@1",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg && activeEditor == 'workbench.editors.files.textFileEditor'"
},
{
"command": "frontMatter.markup.unorderedlist",
"group": "1_markup@2",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg && activeEditor == 'workbench.editors.files.textFileEditor'"
},
{
"command": "frontMatter.markup.tasklist",
"group": "1_markup@3",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg && activeEditor == 'workbench.editors.files.textFileEditor'"
},
{
"command": "frontMatter.markup.code",
"group": "1_markup@4",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg && activeEditor == 'workbench.editors.files.textFileEditor'"
},
{
"command": "frontMatter.markup.codeblock",
"group": "1_markup@5",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg && activeEditor == 'workbench.editors.files.textFileEditor'"
},
{
"command": "frontMatter.markup.blockquote",
"group": "1_markup@6",
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg && activeEditor == 'workbench.editors.files.textFileEditor'"
},
{
"command": "frontMatter.dashboard",

View File

@@ -52,7 +52,7 @@ export class Article {
*
* @param subscriptions - The array of subscriptions to register the commands with.
*/
public static async registerCommands(subscriptions: unknown[]) {
public static registerCommands(subscriptions: unknown[]) {
subscriptions.push(
commands.registerCommand(COMMAND_NAME.setLastModifiedDate, Article.setLastModifiedDate)
);
@@ -66,6 +66,15 @@ export class Article {
subscriptions.push(commands.registerCommand(COMMAND_NAME.insertSnippet, Article.insertSnippet));
}
/**
* Registers event listeners for the Article class.
*
* @param subscriptions - An array to which the event listener will be added.
*/
public static registerListeners(subscriptions: unknown[]) {
subscriptions.push(workspace.onWillSaveTextDocument(Article.autoUpdate));
}
/**
* Sets the article date
*/
@@ -369,15 +378,15 @@ export class Article {
* Article auto updater
* @param event
*/
public static async autoUpdate(event: TextDocumentWillSaveEvent) {
public static autoUpdate(event: TextDocumentWillSaveEvent) {
const document = event.document;
if (document && ArticleHelper.isSupportedFile(document)) {
const autoUpdate = Settings.get(SETTING_AUTO_UPDATE_DATE);
// Is article located in one of the content folders
const folders = await Folders.getCachedOrFresh();
const folders = Folders.getCached();
const documentPath = parseWinPath(document.fileName);
const folder = folders.find((f) => documentPath.startsWith(f.path));
const folder = folders?.find((f) => documentPath.startsWith(f.path));
if (!folder) {
return;
}

View File

@@ -42,6 +42,7 @@ function Select({
...props
}: SelectFieldProps) {
const multiple = fieldType === Array;
return (
<div className="autoform__select_field" {...filterDOMProps(props)}>
<LabelField label={label} id={id} required={required} />
@@ -84,11 +85,12 @@ function Select({
}}
ref={inputRef}
value={value ?? ''}
className='text-[var(--vscode-foreground)] bg-[var(--vscode-list-activeSelectionBackground)] rounded-[2px] active:border-transparent disabled:opacity-40 disabled:cursor-not-allowed focus:outline-none'
style={{ width: '100%', padding: '0.5rem' }}
>
{(!!placeholder || !required || value === undefined) && !multiple && (
{(!required || value === undefined) && !multiple && (
<option value="" disabled={required} hidden={required}>
{placeholder || label}
{""}
</option>
)}

View File

@@ -25,6 +25,9 @@ export const ItemSelection: React.FunctionComponent<IItemSelectionProps> = ({
<div className={`${cssNames} group-hover:block`}>
<VSCodeCheckbox
className={show ? "" : " shadow-[0_0_3px_var(--frontmatter-border-preserve)]"}
onClick={(e) => {
e.stopPropagation();
}}
onChange={() => {
onMultiSelect(filePath);
}}

View File

@@ -4,8 +4,7 @@ import { CommandLineIcon, PencilIcon, TrashIcon, ChevronDownIcon, XMarkIcon, Eye
import { useRecoilState, useRecoilValue } from 'recoil';
import { MultiSelectedItemsAtom, PagedItems, SelectedItemActionAtom, SelectedMediaFolderSelector, SettingsSelector } from '../../state';
import { ActionsBarItem } from './ActionsBarItem';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
import { LocalizationKey, localize } from '../../../localization';
import { Alert } from '../Modals/Alert';
import { messageHandler } from '@estruyf/vscode/dist/client';
import { DashboardMessage } from '../../DashboardMessage';
@@ -68,8 +67,14 @@ export const ActionsBar: React.FunctionComponent<IActionsBarProps> = ({
}, [selectedFiles]);
const selectAllItems = React.useCallback(() => {
setSelectedFiles([...pagedItems]);
}, [pagedItems]);
const allSelected = [...selectedFiles, ...pagedItems];
setSelectedFiles(Array.from(new Set(allSelected)));
}, [selectedFiles, pagedItems]);
const hasAllItemsSelectedOnPage = React.useMemo(() => {
const selectedItemsOnPage = selectedFiles.filter((file) => pagedItems.includes(file));
return selectedItemsOnPage.length >= pagedItems.length;
}, [selectedFiles, pagedItems]);
const languageActions = React.useMemo(() => {
const actions: React.ReactNode[] = [];
@@ -92,7 +97,7 @@ export const ActionsBar: React.FunctionComponent<IActionsBarProps> = ({
})
}}>
<LanguageIcon className={`mr-2 h-4 w-4`} aria-hidden={true} />
<span>{l10n.t(LocalizationKey.commonTranslate)}</span>
<span>{localize(LocalizationKey.commonTranslate)}</span>
</ActionsBarItem>
)
@@ -107,7 +112,7 @@ export const ActionsBar: React.FunctionComponent<IActionsBarProps> = ({
className='flex items-center text-[var(--vscode-tab-inactiveForeground)] hover:text-[var(--vscode-tab-activeForeground)]'
>
<LanguageIcon className="mr-2 h-4 w-4" aria-hidden={true} />
<span>{l10n.t(LocalizationKey.commonLanguages)}</span>
<span>{localize(LocalizationKey.commonLanguages)}</span>
<ChevronDownIcon className="ml-2 h-4 w-4" aria-hidden={true} />
</DropdownMenuTrigger>
@@ -163,7 +168,7 @@ export const ActionsBar: React.FunctionComponent<IActionsBarProps> = ({
disabled={selectedFiles.length === 0}
>
<CommandLineIcon className="mr-2 h-4 w-4" aria-hidden={true} />
<span>{l10n.t(LocalizationKey.commonScripts)}</span>
<span>{localize(LocalizationKey.commonScripts)}</span>
<ChevronDownIcon className="ml-2 h-4 w-4" aria-hidden={true} />
</DropdownMenuTrigger>
@@ -197,10 +202,10 @@ export const ActionsBar: React.FunctionComponent<IActionsBarProps> = ({
<ActionsBarItem
disabled={selectedFiles.length === 0 || selectedFiles.length > 1}
onClick={viewFile}
title={l10n.t(LocalizationKey.commonView)}
title={localize(LocalizationKey.commonView)}
>
<EyeIcon className="w-4 h-4 mr-2" aria-hidden="true" />
<span>{l10n.t(LocalizationKey.commonView)}</span>
<span>{localize(LocalizationKey.commonView)}</span>
</ActionsBarItem>
{
@@ -211,10 +216,10 @@ export const ActionsBar: React.FunctionComponent<IActionsBarProps> = ({
messageHandler.send(DashboardMessage.rename, selectedFiles[0]);
setSelectedFiles([]);
}}
title={l10n.t(LocalizationKey.commonRename)}
title={localize(LocalizationKey.commonRename)}
>
<RenameIcon className="w-4 h-4 mr-2" aria-hidden="true" />
<span>{l10n.t(LocalizationKey.commonRename)}</span>
<span>{localize(LocalizationKey.commonRename)}</span>
</ActionsBarItem>
)
}
@@ -228,10 +233,10 @@ export const ActionsBar: React.FunctionComponent<IActionsBarProps> = ({
path: selectedFiles[0],
action: 'edit'
})}
title={l10n.t(LocalizationKey.commonEdit)}
title={localize(LocalizationKey.commonEdit)}
>
<PencilIcon className="w-4 h-4 mr-2" aria-hidden="true" />
<span>{l10n.t(LocalizationKey.commonEdit)}</span>
<span>{localize(LocalizationKey.commonEdit)}</span>
</ActionsBarItem>
</>
)
@@ -245,10 +250,10 @@ export const ActionsBar: React.FunctionComponent<IActionsBarProps> = ({
className='hover:text-[var(--vscode-statusBarItem-errorBackground)]'
disabled={selectedFiles.length === 0}
onClick={() => setShowAlert(true)}
title={l10n.t(LocalizationKey.commonDelete)}
title={localize(LocalizationKey.commonDelete)}
>
<TrashIcon className="w-4 h-4 mr-2" aria-hidden="true" />
<span>{l10n.t(LocalizationKey.commonDelete)}</span>
<span>{localize(LocalizationKey.commonDelete)}</span>
</ActionsBarItem>
</div>
@@ -258,33 +263,33 @@ export const ActionsBar: React.FunctionComponent<IActionsBarProps> = ({
<ActionsBarItem
className='flex items-center hover:text-[var(--vscode-statusBarItem-warningBackground)]'
onClick={() => setSelectedFiles([])}
title={l10n.t(LocalizationKey.dashboardHeaderActionsBarItemsSelected, selectedFiles.length)}
title={localize(LocalizationKey.dashboardHeaderActionsBarItemsSelected, selectedFiles.length)}
>
<XMarkIcon className="w-4 h-4 mr-1" aria-hidden="true" />
<span>{l10n.t(LocalizationKey.dashboardHeaderActionsBarItemsSelected, selectedFiles.length)}</span>
<span>{localize(LocalizationKey.dashboardHeaderActionsBarItemsSelected, selectedFiles.length)}</span>
</ActionsBarItem>
)
}
<ActionsBarItem
disabled={selectedFiles.length === pagedItems.length}
disabled={hasAllItemsSelectedOnPage}
onClick={selectAllItems}
title={l10n.t(LocalizationKey.dashboardHeaderActionsBarSelectAll)}
title={localize(LocalizationKey.dashboardHeaderActionsBarSelectAll)}
>
<div className='w-4 h-4 inline-flex items-center justify-center border border-[var(--vscode-sideBar-foreground)] group-hover:border-[var(--vscode-statusBarItem-warningBackground)] rounded mr-1'>
<CheckIcon className="w-3 h-3" aria-hidden="true" />
</div>
<span>{l10n.t(LocalizationKey.dashboardHeaderActionsBarSelectAll)}</span>
<span>{localize(LocalizationKey.dashboardHeaderActionsBarSelectAll)}</span>
</ActionsBarItem>
</div>
</div >
{showAlert && (
<Alert
title={`${l10n.t(LocalizationKey.dashboardHeaderActionsBarAlertDeleteTitle)}`}
description={l10n.t(LocalizationKey.dashboardHeaderActionsBarAlertDeleteDescription)}
okBtnText={l10n.t(LocalizationKey.commonDelete)}
cancelBtnText={l10n.t(LocalizationKey.commonCancel)}
title={`${localize(LocalizationKey.dashboardHeaderActionsBarAlertDeleteTitle)}`}
description={localize(LocalizationKey.dashboardHeaderActionsBarAlertDeleteDescription)}
okBtnText={localize(LocalizationKey.commonDelete)}
cancelBtnText={localize(LocalizationKey.commonCancel)}
dismiss={() => setShowAlert(false)}
trigger={onDeleteConfirm}
/>

View File

@@ -10,7 +10,7 @@ import { LanguageFilter } from '../Filters/LanguageFilter';
export interface IFiltersProps { }
export const Filters: React.FunctionComponent<IFiltersProps> = (_: React.PropsWithChildren<IFiltersProps>) => {
export const Filters: React.FunctionComponent<IFiltersProps> = () => {
const [crntFilters, setCrntFilters] = useRecoilState(FiltersAtom);
const [crntTag, setCrntTag] = useRecoilState(TagAtom);
const [crntCategory, setCrntCategory] = useRecoilState(CategoryAtom);

View File

@@ -183,7 +183,7 @@ export const Item: React.FunctionComponent<IItemProps> = ({
<div className='inline-block mr-1 mt-1 text-xs text-[var(--vscode-button-secondaryForeground)] bg-[var(--vscode-button-secondaryBackground)] border border-[var(--frontmatter-border)] rounded px-1 py-0.5'>
{
snippet.isMediaSnippet ? l10n.t(LocalizationKey.dashboardSnippetsViewItemTypeContent) : l10n.t(LocalizationKey.dashboardSnippetsViewItemTypeMedia)
snippet.isMediaSnippet ? l10n.t(LocalizationKey.dashboardSnippetsViewItemTypeMedia) : l10n.t(LocalizationKey.dashboardSnippetsViewItemTypeContent)
}
</div>

View File

@@ -14,7 +14,7 @@ import ContentProvider from './providers/ContentProvider';
import { PagesListener } from './listeners/dashboard';
import { ModeSwitch } from './services/ModeSwitch';
import { PagesParser } from './services/PagesParser';
import { ContentType, Telemetry, Extension } from './helpers';
import { ContentType, Extension } from './helpers';
import * as l10n from '@vscode/l10n';
import {
Backers,
@@ -121,8 +121,9 @@ export async function activate(context: vscode.ExtensionContext) {
// Register the taxonomy commands
Taxonomy.registerCommands(subscriptions);
// Register all the article commands
// Register all the article commands and listeners
Article.registerCommands(subscriptions);
Article.registerListeners(subscriptions);
// Template creation
Template.registerCommands();
@@ -181,9 +182,6 @@ export async function activate(context: vscode.ExtensionContext) {
// Automatically run the command
triggerPageUpdate(`main`);
// Listener for file edit changes
subscriptions.push(vscode.workspace.onWillSaveTextDocument(handleAutoDateUpdate));
// Listener for file saves
subscriptions.push(PagesListener.saveFileWatcher());
@@ -241,16 +239,13 @@ export async function activate(context: vscode.ExtensionContext) {
// Subscribe all commands
subscriptions.push(PanelView, collapseAll, fmStatusBarItem);
// eslint-disable-next-line no-console
console.log(`𝖥𝗋𝗈𝗇𝗍 𝖬𝖺𝗍𝗍𝖾𝗋 𝖢𝖬𝖲 𝖺𝖼𝗍𝗂𝗏𝖺𝗍𝖾𝖽! 𝖱𝖾𝖺𝖽𝗒 𝗍𝗈 𝗌𝗍𝖺𝗋𝗍 𝗐𝗋𝗂𝗍𝗂𝗇𝗀... 👩‍💻🧑‍💻👨‍💻`);
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
export function deactivate() {}
const handleAutoDateUpdate = (e: vscode.TextDocumentWillSaveEvent) => {
Article.autoUpdate(e);
};
const triggerPageUpdate = (location: string) => {
Logger.verbose(`Trigger page update: ${location}`);
pageUpdateDebouncer(() => {

View File

@@ -1,5 +1,5 @@
import { Settings } from './SettingsHelper';
import { CommandType, EnvironmentType } from './../models/PanelSettings';
import { CommandType } from './../models/PanelSettings';
import { CustomScript as ICustomScript, ScriptType } from '../models/PanelSettings';
import { window, env as vscodeEnv, ProgressLocation, Uri, commands } from 'vscode';
import { ArticleHelper, Logger, MediaHelpers } from '.';
@@ -13,9 +13,8 @@ import { Dashboard } from '../commands/Dashboard';
import { DashboardCommand } from '../dashboardWebView/DashboardCommand';
import { ParsedFrontMatter } from '../parsers';
import { SETTING_CUSTOM_SCRIPTS } from '../constants';
import { existsAsync } from '../utils';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
import { evaluateCommand, existsAsync, getPlatform } from '../utils';
import { LocalizationKey, localize } from '../localization';
export class CustomScript {
/**
@@ -101,7 +100,7 @@ export class CustomScript {
);
} else {
Notifications.warning(
l10n.t(LocalizationKey.helpersCustomScriptSingleRunArticleWarning, script.title)
localize(LocalizationKey.helpersCustomScriptSingleRunArticleWarning, script.title)
);
}
}
@@ -117,7 +116,7 @@ export class CustomScript {
if (!folders || folders.length === 0) {
Notifications.warning(
l10n.t(LocalizationKey.helpersCustomScriptBulkRunNoFilesWarning, script.title)
localize(LocalizationKey.helpersCustomScriptBulkRunNoFilesWarning, script.title)
);
return;
}
@@ -127,7 +126,7 @@ export class CustomScript {
window.withProgress(
{
location: ProgressLocation.Notification,
title: l10n.t(LocalizationKey.helpersCustomScriptExecuting, script.title),
title: localize(LocalizationKey.helpersCustomScriptExecuting, script.title),
cancellable: false
},
async (_, __) => {
@@ -173,7 +172,7 @@ export class CustomScript {
): Promise<void> {
if (!path) {
Notifications.error(
l10n.t(LocalizationKey.helpersCustomScriptRunMediaScriptNoFolderWarning, script.title)
localize(LocalizationKey.helpersCustomScriptRunMediaScriptNoFolderWarning, script.title)
);
return;
}
@@ -182,7 +181,7 @@ export class CustomScript {
window.withProgress(
{
location: ProgressLocation.Notification,
title: l10n.t(LocalizationKey.helpersCustomScriptExecuting, script.title),
title: localize(LocalizationKey.helpersCustomScriptExecuting, script.title),
cancellable: false
},
async () => {
@@ -309,7 +308,10 @@ export class CustomScript {
throw new Error(`Couldn't update article.`);
}
Notifications.info(
l10n.t(LocalizationKey.helpersCustomScriptShowOutputFrontMatterSuccess, script.title)
localize(
LocalizationKey.helpersCustomScriptShowOutputFrontMatterSuccess,
script.title
)
);
}
} else if (data.fmAction) {
@@ -345,10 +347,12 @@ export class CustomScript {
window
.showInformationMessage(
`${script.title}: ${output}`,
l10n.t(LocalizationKey.helpersCustomScriptShowOutputCopyOutputAction)
localize(LocalizationKey.helpersCustomScriptShowOutputCopyOutputAction)
)
.then((value) => {
if (value === l10n.t(LocalizationKey.helpersCustomScriptShowOutputCopyOutputAction)) {
if (
value === localize(LocalizationKey.helpersCustomScriptShowOutputCopyOutputAction)
) {
vscodeEnv.clipboard.writeText(output);
}
});
@@ -356,7 +360,7 @@ export class CustomScript {
}
} else {
Notifications.info(
l10n.t(LocalizationKey.helpersCustomScriptShowOutputSuccess, script.title)
localize(LocalizationKey.helpersCustomScriptShowOutputSuccess, script.title)
);
}
}
@@ -373,7 +377,7 @@ export class CustomScript {
wsPath: string,
args: string
): Promise<string> {
const osType = os.type();
const platform = getPlatform();
// Check the command to use
let command = script.nodeBin || 'node';
@@ -381,6 +385,10 @@ export class CustomScript {
command = script.command;
}
if (script.command === CommandType.Node && platform !== 'windows') {
command = await evaluateCommand(CommandType.Node);
}
let scriptPath = join(wsPath, script.script);
if (script.script.includes(WORKSPACE_PLACEHOLDER)) {
scriptPath = Folders.getAbsFilePath(script.script);
@@ -388,19 +396,15 @@ export class CustomScript {
// Check if there is an environments overwrite required
if (script.environments) {
let crntType: EnvironmentType | null = null;
if (osType === 'Windows_NT') {
crntType = 'windows';
} else if (osType === 'Darwin') {
crntType = 'macos';
} else {
crntType = 'linux';
}
const environment = script.environments.find((e) => e.type === crntType);
const environment = script.environments.find((e) => e.type === platform);
if (environment && environment.script && environment.command) {
if (await CustomScript.validateCommand(environment.command)) {
command = environment.command;
if (command === CommandType.Node && platform !== 'windows') {
command = await evaluateCommand(CommandType.Node);
}
scriptPath = join(wsPath, environment.script);
if (environment.script.includes(WORKSPACE_PLACEHOLDER)) {
scriptPath = Folders.getAbsFilePath(environment.script);
@@ -414,12 +418,12 @@ export class CustomScript {
throw new Error(`Script not found: ${scriptPath}`);
}
if (osType === 'Windows_NT' && command.toLowerCase() === 'powershell') {
if (platform === 'windows' && command.toLowerCase() === 'powershell') {
command = `${command} -File`;
}
const fullScript = `${command} "${scriptPath}" ${args}`;
Logger.info(l10n.t(LocalizationKey.helpersCustomScriptExecuting, fullScript));
Logger.info(localize(LocalizationKey.helpersCustomScriptExecuting, fullScript));
const output: string = await CustomScript.executeScriptAsync(fullScript, wsPath);
@@ -502,7 +506,7 @@ export class CustomScript {
return true;
} catch (e) {
Logger.error(l10n.t(LocalizationKey.helpersCustomScriptValidateCommandError, command));
Logger.error(localize(LocalizationKey.helpersCustomScriptValidateCommandError, command));
return false;
}
}

View File

@@ -1,5 +1,5 @@
import { GitListener } from './../listeners/general/GitListener';
import { basename, join } from 'path';
import { join } from 'path';
import { workspace } from 'vscode';
import { Folders } from '../commands/Folders';
import { Project } from '../commands/Project';
@@ -23,7 +23,6 @@ import {
SETTING_MEDIA_SUPPORTED_MIMETYPES,
SETTING_TAXONOMY_CUSTOM,
SETTING_TEMPLATES_ENABLED,
SETTING_GIT_ENABLED,
SETTING_DASHBOARD_CONTENT_PAGINATION,
SETTING_SNIPPETS_WRAPPER,
SETTING_DASHBOARD_CONTENT_CARD_DATE,

View File

@@ -12,7 +12,7 @@ import {
} from '../../constants';
import { SettingsListener } from './SettingsListener';
import { Terminal } from '../../services';
import { existsAsync, readFileAsync } from '../../utils';
import { evaluateCommand, existsAsync, getPlatform, readFileAsync } from '../../utils';
import { join } from 'path';
export class SsgListener extends BaseListener {
@@ -170,7 +170,12 @@ export class SsgListener extends BaseListener {
workspace.fs.copy(scriptPath, tempScriptPath, { overwrite: true });
}
const fullScript = `node "${tempScriptPath.fsPath}" "${contentConfigFile.fsPath}"`;
let nodeExecPath = 'node';
const platform = getPlatform();
if (platform !== 'windows') {
nodeExecPath = await evaluateCommand('node');
}
const fullScript = `${nodeExecPath} "${tempScriptPath.fsPath}" "${contentConfigFile.fsPath}"`;
try {
const result: string = await SsgListener.executeScript(fullScript, wsFolder?.fsPath || '');

View File

@@ -39,17 +39,21 @@ export class FieldsListener extends BaseListener {
return;
}
const isLocaleEnabled = await i18n.isLocaleEnabled(data.activePath);
const activeLocale = await i18n.getLocale(data.activePath);
if (!activeLocale?.locale) {
if (isLocaleEnabled && !activeLocale?.locale) {
return;
}
PagesListener.getPagesData(false, async (pages) => {
const fuseKeys: Fuse.FuseOptionKey[] = [{ name: 'fmContentType', weight: 1 }];
if (isLocaleEnabled && data.sameLocale) {
fuseKeys.push({ name: 'fmLocale.locale', weight: 1 });
}
const fuseOptions: Fuse.IFuseOptions<Page> = {
keys: [
{ name: 'fmContentType', weight: 1 },
...(data.sameLocale ? [{ name: 'fmLocale.locale', weight: 1 }] : [])
],
keys: fuseKeys,
findAllMatches: true,
threshold: 0
};
@@ -60,11 +64,14 @@ export class FieldsListener extends BaseListener {
);
const fuseIndex = Fuse.parseIndex(pagesIndex);
const fuse = new Fuse(pages || [], fuseOptions, fuseIndex);
const andExpression: Fuse.Expression[] = [{ fmContentType: data.type ?? '' }];
if (isLocaleEnabled && activeLocale?.locale && data.sameLocale) {
andExpression.push({ 'fmLocale.locale': activeLocale.locale });
}
const results = fuse.search({
$and: [
{ fmContentType: data.type! },
...(data.sameLocale ? [{ 'fmLocale.locale': activeLocale.locale }] : [])
]
$and: andExpression
});
const pageResults = results.map((page) => page.item);

View File

@@ -0,0 +1,3 @@
export interface ShellSetting {
path: string;
}

View File

@@ -22,6 +22,7 @@ export * from './Mode';
export * from './PanelSettings';
export * from './PostMessageData';
export * from './Project';
export * from './ShellSetting';
export * from './Snippets';
export * from './SortOrder';
export * from './SortType';

View File

@@ -1,12 +1,7 @@
import { workspace, window, ThemeIcon, TerminalOptions } from 'vscode';
import * as os from 'os';
import { Folders } from '../commands';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../localization';
interface ShellSetting {
path: string;
}
import { LocalizationKey, localize } from '../localization';
import { getShellPath } from '../utils';
export class Terminal {
public static readonly terminalName: string = 'Local server';
@@ -15,7 +10,7 @@ export class Terminal {
* Return the shell path for the current platform
*/
public static get shell() {
const shell: string | { path: string } | undefined = Terminal.getShellPath();
const shell: string | { path: string } | undefined = getShellPath();
let shellPath: string | undefined = undefined;
if (typeof shell !== 'string' && !!shell) {
@@ -47,7 +42,7 @@ export class Terminal {
const terminalOptions: TerminalOptions = {
name: Terminal.terminalName,
iconPath: new ThemeIcon('server-environment'),
message: l10n.t(
message: localize(
LocalizationKey.servicesTerminalOpenLocalServerTerminalTerminalOptionMessage
)
};
@@ -90,46 +85,4 @@ export class Terminal {
return localServerTerminal;
}
}
/**
* Retrieve the automation profile for the current platform
* @returns
*/
private static getShellPath(): string | ShellSetting | undefined {
const platform = Terminal.getPlatform();
const terminalSettings = workspace.getConfiguration('terminal');
const automationProfile = terminalSettings.get<string | ShellSetting>(
`integrated.automationProfile.${platform}`
);
if (!!automationProfile) {
return automationProfile;
}
const defaultProfile = terminalSettings.get<string>(`integrated.defaultProfile.${platform}`);
const profiles = terminalSettings.get<{ [prop: string]: ShellSetting }>(
`integrated.profiles.${platform}`
);
if (defaultProfile && profiles && profiles[defaultProfile]) {
return profiles[defaultProfile];
}
return terminalSettings.get(`integrated.shell.${platform}`);
}
/**
* Get the current platform
* @returns
*/
private static getPlatform = (): 'windows' | 'linux' | 'osx' => {
const platform = os.platform();
if (platform === 'win32') {
return 'windows';
} else if (platform === 'darwin') {
return 'osx';
}
return 'linux';
};
}

View File

@@ -0,0 +1,30 @@
import { exec } from 'child_process';
import { getShellPath } from '../utils';
import { Logger } from '../helpers';
/**
* Evaluate the command dynamically using `which` command
* @param command
* @returns
*/
export const evaluateCommand = (command: string): Promise<string> => {
const shell = getShellPath();
let shellPath: string | undefined = undefined;
if (typeof shell !== 'string' && !!shell) {
shellPath = shell.path;
} else {
shellPath = shell || undefined;
}
return new Promise((resolve, reject) => {
exec(`which ${command}`, { shell: shellPath }, (error, stdout) => {
if (error) {
Logger.error(`Error evaluating command: ${command}`);
reject(error);
return;
}
resolve(stdout.trim());
});
});
};

20
src/utils/getPlatform.ts Normal file
View File

@@ -0,0 +1,20 @@
import * as os from 'os';
/**
* Determines the current operating system platform.
*
* @returns {'windows' | 'linux' | 'osx'} - A string representing the platform:
* - 'windows' for Windows OS
* - 'osx' for macOS
* - 'linux' for Linux OS
*/
export const getPlatform = (): 'windows' | 'linux' | 'osx' => {
const platform = os.platform();
if (platform === 'win32') {
return 'windows';
} else if (platform === 'darwin') {
return 'osx';
}
return 'linux';
};

36
src/utils/getShellPath.ts Normal file
View File

@@ -0,0 +1,36 @@
import { workspace } from 'vscode';
import { ShellSetting } from '../models';
import { getPlatform } from './getPlatform';
/**
* Retrieves the shell path configuration based on the current platform and terminal settings.
*
* This method checks for the following configurations in order:
* 1. `integrated.automationProfile.<platform>`: Returns the automation profile if it exists.
* 2. `integrated.defaultProfile.<platform>` and `integrated.profiles.<platform>`: Returns the shell setting from the default profile if it exists.
* 3. `integrated.shell.<platform>`: Returns the shell setting if the above configurations are not found.
*
* @returns {string | ShellSetting | undefined} The shell path configuration or undefined if not found.
*/
export const getShellPath = (): string | ShellSetting | undefined => {
const platform = getPlatform();
const terminalSettings = workspace.getConfiguration('terminal');
const automationProfile = terminalSettings.get<string | ShellSetting>(
`integrated.automationProfile.${platform}`
);
if (!!automationProfile) {
return automationProfile;
}
const defaultProfile = terminalSettings.get<string>(`integrated.defaultProfile.${platform}`);
const profiles = terminalSettings.get<{ [prop: string]: ShellSetting }>(
`integrated.profiles.${platform}`
);
if (defaultProfile && profiles && profiles[defaultProfile]) {
return profiles[defaultProfile];
}
return terminalSettings.get(`integrated.shell.${platform}`);
};

View File

@@ -1,6 +1,7 @@
export * from './cn';
export * from './copyFileAsync';
export * from './encodeEmoji';
export * from './evaluateCommand';
export * from './existsAsync';
export * from './fetchWithTimeout';
export * from './fieldWhenClause';
@@ -8,6 +9,8 @@ export * from './flattenObjectKeys';
export * from './getDescriptionField';
export * from './getExtensibilityScripts';
export * from './getLocalizationFile';
export * from './getPlatform';
export * from './getShellPath';
export * from './getTitleField';
export * from './getWebviewJsFiles';
export * from './ignoreMsgCommand';