mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-08-06 08:52:47 +02:00
#226 - Allow to start the local server for the framework or SSG
This commit is contained in:
@@ -522,6 +522,11 @@
|
||||
"default": "",
|
||||
"markdownDescription": "Specify the ID of your static site generator or framework you are using for your website. [Check in the docs](https://frontmatter.codes/docs/settings#frontmatter.framework.id)"
|
||||
},
|
||||
"frontMatter.framework.startCommand": {
|
||||
"type": ["string", "null"],
|
||||
"default": null,
|
||||
"markdownDescription": "Specify the command you want to use to start your static site generator or framework. [Check in the docs](https://frontmatter.codes/docs/settings#frontmatter.framework.startcommand)"
|
||||
},
|
||||
"frontMatter.media.defaultSorting": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
|
||||
@@ -2,20 +2,32 @@ export const FrameworkDetectors = [
|
||||
{
|
||||
"framework": {"name": "gatsby", "dist": "public", "static": "static", "build": "gatsby build"},
|
||||
"requiredFiles": ["gatsby-config.js"],
|
||||
"requiredDependencies": ["gatsby"]
|
||||
"requiredDependencies": ["gatsby"],
|
||||
"commands": {
|
||||
"start": "npx gatsby develop"
|
||||
}
|
||||
},
|
||||
{
|
||||
"framework": {"name": "hugo", "dist": "public", "static": "static", "build": "hugo"},
|
||||
"requiredFiles": ["config.toml", "config.yaml", "config.yml"]
|
||||
"requiredFiles": ["config.toml", "config.yaml", "config.yml"],
|
||||
"commands": {
|
||||
"start": "hugo server -D"
|
||||
}
|
||||
},
|
||||
{
|
||||
"framework": {"name": "next", "dist": ".next", "static": "public", "build": "next build"},
|
||||
"requiredFiles": ["next.config.js"],
|
||||
"requiredDependencies": ["next"]
|
||||
"requiredDependencies": ["next"],
|
||||
"commands": {
|
||||
"start": "npx next dev"
|
||||
}
|
||||
},
|
||||
{
|
||||
"framework": {"name": "nuxt", "dist": "dist", "static": "static", "build": "nuxt"},
|
||||
"requiredFiles": ["nuxt.config.js"],
|
||||
"requiredDependencies": ["nuxt"]
|
||||
"requiredDependencies": ["nuxt"],
|
||||
"commands": {
|
||||
"start": "npx nuxt"
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -62,6 +62,7 @@ export const SETTINGS_DATA_FOLDERS = "data.folders";
|
||||
export const SETTINGS_DATA_TYPES = "data.types";
|
||||
|
||||
export const SETTINGS_FRAMEWORK_ID = "framework.id";
|
||||
export const SETTINGS_FRAMEWORK_START = "framework.startCommand";
|
||||
|
||||
export const SETTING_SITE_BASEURL = "site.baseURL";
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { DashboardData } from '../models/DashboardData';
|
||||
import { Template } from '../commands/Template';
|
||||
import { DefaultFields, SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT, SETTING_AUTO_UPDATE_DATE, SETTING_CUSTOM_SCRIPTS, SETTING_SEO_CONTENT_MIN_LENGTH, SETTING_SEO_DESCRIPTION_FIELD, SETTING_SLUG_UPDATE_FILE_NAME, SETTING_PREVIEW_HOST, SETTING_DATE_FORMAT, SETTING_COMMA_SEPARATED_FIELDS, SETTING_TAXONOMY_CONTENT_TYPES, SETTING_PANEL_FREEFORM, SETTING_SEO_DESCRIPTION_LENGTH, SETTING_SEO_TITLE_LENGTH, SETTING_SLUG_PREFIX, SETTING_SLUG_SUFFIX, SETTING_TAXONOMY_CATEGORIES, SETTING_TAXONOMY_TAGS, SETTINGS_CONTENT_DRAFT_FIELD, SETTING_SEO_SLUG_LENGTH, SETTING_SITE_BASEURL, SETTING_TAXONOMY_CUSTOM, CONTEXT } from '../constants';
|
||||
import { DefaultFields, SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT, SETTING_AUTO_UPDATE_DATE, SETTING_CUSTOM_SCRIPTS, SETTING_SEO_CONTENT_MIN_LENGTH, SETTING_SEO_DESCRIPTION_FIELD, SETTING_SLUG_UPDATE_FILE_NAME, SETTING_PREVIEW_HOST, SETTING_DATE_FORMAT, SETTING_COMMA_SEPARATED_FIELDS, SETTING_TAXONOMY_CONTENT_TYPES, SETTING_PANEL_FREEFORM, SETTING_SEO_DESCRIPTION_LENGTH, SETTING_SEO_TITLE_LENGTH, SETTING_SLUG_PREFIX, SETTING_SLUG_SUFFIX, SETTING_TAXONOMY_CATEGORIES, SETTING_TAXONOMY_TAGS, SETTINGS_CONTENT_DRAFT_FIELD, SETTING_SEO_SLUG_LENGTH, SETTING_SITE_BASEURL, SETTING_TAXONOMY_CUSTOM, CONTEXT, SETTINGS_FRAMEWORK_ID, SETTINGS_FRAMEWORK_START } from '../constants';
|
||||
import * as os from 'os';
|
||||
import { PanelSettings, CustomScript as ICustomScript } from '../models/PanelSettings';
|
||||
import { CancellationToken, Disposable, Uri, Webview, WebviewView, WebviewViewProvider, WebviewViewResolveContext, window, workspace, commands, env as vscodeEnv } from "vscode";
|
||||
import { CancellationToken, Disposable, Uri, Webview, WebviewView, WebviewViewProvider, WebviewViewResolveContext, window, workspace, commands, env as vscodeEnv, ThemeIcon } from "vscode";
|
||||
import { ArticleHelper, Settings } from "../helpers";
|
||||
import { Command } from "../panelWebView/Command";
|
||||
import { CommandToCode } from '../panelWebView/CommandToCode';
|
||||
@@ -161,13 +161,13 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
await commands.executeCommand(COMMAND_NAME.createTemplate);
|
||||
break;
|
||||
case CommandToCode.updateModifiedUpdating:
|
||||
this.updateModifiedUpdating(msg.data || false);
|
||||
this.updateSetting(SETTING_AUTO_UPDATE_DATE, msg.data || false);
|
||||
break;
|
||||
case CommandToCode.toggleWritingSettings:
|
||||
this.toggleWritingSettings();
|
||||
break;
|
||||
case CommandToCode.updateFmHighlight:
|
||||
this.updateFmHighlight((msg.data !== null && msg.data !== undefined) ? msg.data : false);
|
||||
this.updateSetting(SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT, (msg.data !== null && msg.data !== undefined) ? msg.data : false);
|
||||
break;
|
||||
case CommandToCode.toggleCenterMode:
|
||||
await commands.executeCommand(`workbench.action.toggleCenteredLayout`);
|
||||
@@ -179,7 +179,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
await commands.executeCommand(COMMAND_NAME.dashboard);
|
||||
break;
|
||||
case CommandToCode.updatePreviewUrl:
|
||||
this.updatePreviewUrl(msg.data || "");
|
||||
this.updateSetting(SETTING_PREVIEW_HOST, msg.data || "");
|
||||
break;
|
||||
case CommandToCode.openInEditor:
|
||||
openFileInEditor(msg.data);
|
||||
@@ -194,6 +194,12 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
} as DashboardData);
|
||||
this.getMediaSelection();
|
||||
break;
|
||||
case CommandToCode.frameworkCommand:
|
||||
this.openTerminalWithCommand(msg.data.command);
|
||||
break;
|
||||
case CommandToCode.updateStartCommand:
|
||||
await this.updateSetting(SETTINGS_FRAMEWORK_START, msg.data || "");
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -344,6 +350,29 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
this.pushMetadata(article.data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a terminal and run the passed command
|
||||
* @param command
|
||||
*/
|
||||
private openTerminalWithCommand(command: string) {
|
||||
if (command) {
|
||||
let terminal = window.activeTerminal;
|
||||
|
||||
if (!terminal || (terminal && terminal.state.isInteractedWith === true)) {
|
||||
terminal = window.createTerminal({
|
||||
name: `Starting local server: ${command}`,
|
||||
iconPath: new ThemeIcon('server-environment'),
|
||||
message: `Starting local server: ${command}`,
|
||||
});
|
||||
}
|
||||
|
||||
if (terminal) {
|
||||
terminal.sendText(command);
|
||||
terminal.show(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a custom script
|
||||
* @param msg
|
||||
@@ -405,7 +434,11 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
contentTypes: Settings.get(SETTING_TAXONOMY_CONTENT_TYPES) || [],
|
||||
dashboardViewData: Dashboard.viewData,
|
||||
draftField: Settings.get<DraftField>(SETTINGS_CONTENT_DRAFT_FIELD),
|
||||
isBacker: await Extension.getInstance().getState<boolean | undefined>(CONTEXT.backer, 'global')
|
||||
isBacker: await Extension.getInstance().getState<boolean | undefined>(CONTEXT.backer, 'global'),
|
||||
framework: Settings.get<string>(SETTINGS_FRAMEWORK_ID),
|
||||
commands: {
|
||||
start: Settings.get<string>(SETTINGS_FRAMEWORK_START)
|
||||
}
|
||||
} as PanelSettings
|
||||
});
|
||||
}
|
||||
@@ -702,26 +735,12 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the preview URL
|
||||
* Updates a setting and refreshes the retrieved settings
|
||||
* @param setting
|
||||
* @param value
|
||||
*/
|
||||
private async updatePreviewUrl(previewUrl: string) {
|
||||
await Settings.update(SETTING_PREVIEW_HOST, previewUrl);
|
||||
this.getSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the Front Matter highlighting
|
||||
*/
|
||||
private async updateFmHighlight(autoUpdate: boolean) {
|
||||
await Settings.update(SETTINGS_CONTENT_FRONTMATTER_HIGHLIGHT, autoUpdate);
|
||||
this.getSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the modified auto-update setting
|
||||
*/
|
||||
private async updateModifiedUpdating(autoUpdate: boolean) {
|
||||
await Settings.update(SETTING_AUTO_UPDATE_DATE, autoUpdate);
|
||||
private async updateSetting(setting: string, value: any) {
|
||||
await Settings.update(setting, value);
|
||||
this.getSettings();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,12 @@ export interface PanelSettings {
|
||||
dashboardViewData: DashboardData | undefined;
|
||||
draftField: DraftField;
|
||||
isBacker: boolean | undefined;
|
||||
framework: string | undefined;
|
||||
commands: FrameworkCommands;
|
||||
}
|
||||
|
||||
export interface FrameworkCommands {
|
||||
start: string | undefined;
|
||||
}
|
||||
|
||||
export interface ContentType {
|
||||
|
||||
@@ -28,4 +28,6 @@ export enum CommandToCode {
|
||||
selectImage = "select-image",
|
||||
updateCustomTaxonomy = "updateCustomTaxonomy",
|
||||
addToCustomTaxonomy = "addToCustomTaxonomy",
|
||||
frameworkCommand = "framework-command",
|
||||
updateStartCommand = "update-start-command",
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import { Collapsible } from './Collapsible';
|
||||
import { CustomScript } from './CustomScript';
|
||||
import { Preview } from './Preview';
|
||||
import { SlugAction } from './SlugAction';
|
||||
import { StartServerButton } from './StartServerButton';
|
||||
|
||||
export interface IActionsProps {
|
||||
metadata: any;
|
||||
@@ -24,6 +25,8 @@ const Actions: React.FunctionComponent<IActionsProps> = ({ metadata, settings }:
|
||||
|
||||
{ settings?.preview?.host && <Preview slug={metadata.slug} /> }
|
||||
|
||||
<StartServerButton settings={settings} />
|
||||
|
||||
{
|
||||
(settings && settings.scripts && settings.scripts.length > 0) && (
|
||||
settings.scripts.map((value, idx) => (
|
||||
|
||||
@@ -7,6 +7,7 @@ import { GlobalSettings } from './GlobalSettings';
|
||||
import { OtherActions } from './OtherActions';
|
||||
import { FolderAndFiles } from './FolderAndFiles';
|
||||
import { SponsorMsg } from './SponsorMsg';
|
||||
import { StartServerButton } from './StartServerButton';
|
||||
|
||||
export interface IBaseViewProps {
|
||||
settings: PanelSettings | undefined;
|
||||
@@ -45,6 +46,7 @@ const BaseView: React.FunctionComponent<IBaseViewProps> = ({settings, folderAndF
|
||||
<Collapsible id={`base_actions`} title="Actions">
|
||||
<div className={`base__actions`}>
|
||||
<button onClick={openDashboard}>Open dashboard</button>
|
||||
<StartServerButton settings={settings} />
|
||||
<button onClick={initProject} disabled={settings?.isInitialized}>Initialize project</button>
|
||||
<button onClick={createContent} disabled={!settings?.isInitialized}>Create new content</button>
|
||||
<button onClick={openPreview} disabled={!settings?.preview?.host}>Open site preview</button>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { MessageHelper } from '../../helpers/MessageHelper';
|
||||
import { useDebounce } from '../../hooks/useDebounce';
|
||||
import { Collapsible } from './Collapsible';
|
||||
import { VsCheckbox, VsLabel } from './VscodeComponents';
|
||||
import useStartCommand from '../hooks/useStartCommand';
|
||||
|
||||
export interface IGlobalSettingsProps {
|
||||
settings: PanelSettings | undefined;
|
||||
@@ -14,7 +15,11 @@ export interface IGlobalSettingsProps {
|
||||
const GlobalSettings: React.FunctionComponent<IGlobalSettingsProps> = ({settings, isBase}: React.PropsWithChildren<IGlobalSettingsProps>) => {
|
||||
const { modifiedDateUpdate, fmHighlighting } = settings || {};
|
||||
const [ previewUrl, setPreviewUrl ] = React.useState<string>("");
|
||||
const [ startCommandValue, setStartCommandValue ] = React.useState<string | null>(null);
|
||||
const [ isDirty, setIsDirty ] = React.useState<boolean>(false);
|
||||
const { startCommand } = useStartCommand(settings);
|
||||
|
||||
const debounceStartCommand = useDebounce(startCommandValue, 1000);
|
||||
const debouncePreviewUrl = useDebounce(previewUrl, 1000);
|
||||
|
||||
const onDateCheck = () => {
|
||||
@@ -30,12 +35,21 @@ const GlobalSettings: React.FunctionComponent<IGlobalSettingsProps> = ({settings
|
||||
setPreviewUrl(e.currentTarget.value);
|
||||
};
|
||||
|
||||
const updateStartCommand = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setIsDirty(true);
|
||||
setStartCommandValue(e.currentTarget.value);
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (settings?.preview.host) {
|
||||
setPreviewUrl(settings.preview.host);
|
||||
}
|
||||
}, [settings?.preview.host]);
|
||||
|
||||
React.useEffect(() => {
|
||||
setStartCommandValue(startCommand);
|
||||
}, [startCommand]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isDirty) {
|
||||
setIsDirty(false);
|
||||
@@ -43,6 +57,13 @@ const GlobalSettings: React.FunctionComponent<IGlobalSettingsProps> = ({settings
|
||||
}
|
||||
}, [debouncePreviewUrl]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isDirty) {
|
||||
setIsDirty(false);
|
||||
MessageHelper.sendMessage(CommandToCode.updateStartCommand, debounceStartCommand);
|
||||
}
|
||||
}, [debounceStartCommand]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Collapsible id={`${isBase ? "base_" : ""}settings`} className={`base__actions`} title="Global settings">
|
||||
@@ -62,6 +83,14 @@ const GlobalSettings: React.FunctionComponent<IGlobalSettingsProps> = ({settings
|
||||
value={previewUrl}
|
||||
onChange={previewChange} />
|
||||
</div>
|
||||
<div className={`base__action`}>
|
||||
<VsLabel>Local server command</VsLabel>
|
||||
<input
|
||||
type={`text`}
|
||||
placeholder="Example: hugo server -D"
|
||||
value={startCommandValue || ""}
|
||||
onChange={updateStartCommand} />
|
||||
</div>
|
||||
</Collapsible>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import * as React from 'react';
|
||||
import { FrameworkDetectors } from '../../constants/FrameworkDetectors';
|
||||
import { MessageHelper } from '../../helpers/MessageHelper';
|
||||
import { PanelSettings } from '../../models';
|
||||
import { CommandToCode } from '../CommandToCode';
|
||||
import useStartCommand from '../hooks/useStartCommand';
|
||||
|
||||
export interface IStartServerButtonProps {
|
||||
settings: PanelSettings | undefined;
|
||||
}
|
||||
|
||||
export const StartServerButton: React.FunctionComponent<IStartServerButtonProps> = ({settings}: React.PropsWithChildren<IStartServerButtonProps>) => {
|
||||
const { startCommand } = useStartCommand(settings);
|
||||
|
||||
const startLocalServer = (command: string) => {
|
||||
MessageHelper.sendMessage(CommandToCode.frameworkCommand, { command });
|
||||
};
|
||||
|
||||
return (
|
||||
startCommand ? <button onClick={() => startLocalServer(startCommand)}>Start server</button> : null
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { FrameworkDetectors } from '../../constants/FrameworkDetectors';
|
||||
import { PanelSettings } from '../../models';
|
||||
|
||||
export default function useStartCommand(settings?: PanelSettings) {
|
||||
const [startCommand, setStartCommand] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (settings?.commands?.start) {
|
||||
setStartCommand(settings?.commands?.start);
|
||||
return;
|
||||
}
|
||||
|
||||
let command: string = '';
|
||||
if (settings?.framework) {
|
||||
const framework = FrameworkDetectors.find(f => f.framework.name === settings.framework);
|
||||
if (framework?.commands?.start) {
|
||||
command = framework.commands.start;
|
||||
}
|
||||
}
|
||||
|
||||
setStartCommand(command);
|
||||
}, [settings?.framework, settings?.commands?.start]);
|
||||
|
||||
return {
|
||||
startCommand
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user