mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-08-07 01:13:08 +02:00
Implementation of custom scripts
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [estruyf]
|
||||
custom: ["https://www.buymeacoffee.com/zMeFRy9"]
|
||||
@@ -0,0 +1,28 @@
|
||||
name: Release
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Build and release"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 14
|
||||
registry-url: https://registry.npmjs.org/
|
||||
|
||||
- name: Install the dependencies
|
||||
run: npm i
|
||||
|
||||
- name: Install vsce
|
||||
run: npm i -g vsce
|
||||
|
||||
- name: Publish
|
||||
run: vsce publish -p ${{ secrets.VSCE_PAT }}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Change Log
|
||||
|
||||
## [1.15.0] - 2020-05-04
|
||||
|
||||
- Added the ability to add your own custom scripts as panel actions.
|
||||
|
||||
## [1.14.0] - 2020-03-19
|
||||
|
||||
- New links added to the Front Matter panel to reveal the file and folder.
|
||||
|
||||
@@ -22,6 +22,24 @@ To leverage most of the capabilities of the extension. SEO information and every
|
||||
|
||||
> **Info**: By default, the tags/categories picker allows you to insert existing and none tags/categories. When you enter a none existing tag/category, the panel shows an add `+` icon in front of that button. This functionality allows you to store this tag/category in your settings. If you want to disable this feature, you can do that by setting the `frontMatter.panel.freeform` setting to `false`.
|
||||
|
||||
Since version `1.15.0`, the extension allows you to create your own custom actions, by running Node.js scripts from your project. In order to use this functionality, you will need to configure the [`frontMatter.custom.scripts`](#frontMatter.custom.scripts) setting for your project.
|
||||
|
||||
Once a custom action has been configured, it will appear on the Front Matter panel.
|
||||
|
||||

|
||||
|
||||
The current workspace- and file-path will be passed as an argument. In your script fetch these arguments as follows:
|
||||
|
||||
```javascript
|
||||
const arguments = process.argv;
|
||||
const workspaceArg = arguments[2];
|
||||
const fileArg = arguments[3];
|
||||
```
|
||||
|
||||
The output of the script will be passed as a notification, and it allows you to copy the output.
|
||||
|
||||

|
||||
|
||||
## Creating articles from templates
|
||||
|
||||
By default, the extension looks for files stored in a `.templates` folder that should be located in your website project's root.
|
||||
@@ -170,6 +188,19 @@ Specifies the modified date field name to use in your Front Matter. Default valu
|
||||
}
|
||||
```
|
||||
|
||||
### `frontMatter.custom.scripts`
|
||||
|
||||
Allows you to specify a title and script path (starting relative from the root of your project). These values will be used to create custom actions on the Front Matter panel. Default value: `[]`.
|
||||
|
||||
```json
|
||||
{
|
||||
"frontMatter.custom.scripts": [{
|
||||
"title": "Generate social image",
|
||||
"script": "./scripts/social-img.js"
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
- Start by opening the command prompt:
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
@@ -151,6 +151,11 @@
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"markdownDescription": "Specifies if you want to allow yourself from entering unknown tags/categories in the tag picker (when enabled, you will have the option to store them afterwards). Default: true."
|
||||
},
|
||||
"frontMatter.custom.scripts": {
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"markdownDescription": "Specify the path to a Node.js script to execute. The current file path will be provided as an argument."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -22,4 +22,6 @@ export const SETTING_SEO_DESCRIPTION_LENGTH = "taxonomy.seoDescriptionLength";
|
||||
export const SETTING_TEMPLATES_FOLDER = "templates.folder";
|
||||
export const SETTING_TEMPLATES_PREFIX = "templates.prefix";
|
||||
|
||||
export const SETTING_PANEL_FREEFORM = "panel.freeform";
|
||||
export const SETTING_PANEL_FREEFORM = "panel.freeform";
|
||||
|
||||
export const SETTING_CUSTOM_SCRIPTS = "custom.scripts";
|
||||
@@ -5,6 +5,7 @@ export interface PanelSettings {
|
||||
tags: string[];
|
||||
categories: string[];
|
||||
freeform: boolean;
|
||||
scripts: CustomScript[];
|
||||
}
|
||||
|
||||
export interface SEO {
|
||||
@@ -15,4 +16,9 @@ export interface SEO {
|
||||
export interface Slug {
|
||||
prefix: number;
|
||||
suffix: number;
|
||||
}
|
||||
|
||||
export interface CustomScript {
|
||||
title: string;
|
||||
script: string;
|
||||
}
|
||||
@@ -10,5 +10,6 @@ export enum CommandToCode {
|
||||
addCategoryToSettings = "add-category",
|
||||
openSettings = "open-settings",
|
||||
openFile = "open-file",
|
||||
openProject = "open-project"
|
||||
openProject = "open-project",
|
||||
runCustomScript = "custom-script"
|
||||
}
|
||||
@@ -48,6 +48,7 @@ export const ViewPanel: React.FunctionComponent<IViewPanelProps> = (props: React
|
||||
{
|
||||
settings && metadata && <Actions metadata={metadata} settings={settings} />
|
||||
}
|
||||
|
||||
{
|
||||
(settings && settings.tags && settings.tags.length > 0) && (
|
||||
<TagPicker type={TagType.tags}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { PanelSettings } from '../../models/PanelSettings';
|
||||
import { CustomScript } from './CustomScript';
|
||||
import { DateAction } from './DateAction';
|
||||
import { PublishAction } from './PublishAction';
|
||||
import { SlugAction } from './SlugAction';
|
||||
@@ -25,6 +26,14 @@ export const Actions: React.FunctionComponent<IActionsProps> = (props: React.Pro
|
||||
<DateAction />
|
||||
|
||||
{ metadata && typeof metadata.draft !== undefined && <PublishAction draft={metadata.draft} />}
|
||||
|
||||
{
|
||||
(settings && settings.scripts && settings.scripts.length > 0) && (
|
||||
settings.scripts.map((value) => (
|
||||
<CustomScript {...value} />
|
||||
))
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
import * as React from 'react';
|
||||
import { CommandToCode } from '../CommandToCode';
|
||||
import { MessageHelper } from '../helper/MessageHelper';
|
||||
|
||||
export interface ICustomScriptProps {
|
||||
title: string;
|
||||
script: string;
|
||||
}
|
||||
|
||||
export const CustomScript: React.FunctionComponent<ICustomScriptProps> = ({title, script}: React.PropsWithChildren<ICustomScriptProps>) => {
|
||||
|
||||
const runCustomScript = () => {
|
||||
MessageHelper.sendMessage(CommandToCode.runCustomScript, { title, script });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`article__action`}>
|
||||
<button onClick={runCustomScript}>{title}</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
import { SETTING_CUSTOM_SCRIPTS } from './../constants/settings';
|
||||
import * as os from 'os';
|
||||
import { PanelSettings } from './../models/PanelSettings';
|
||||
import { CancellationToken, Disposable, Uri, Webview, WebviewView, WebviewViewProvider, WebviewViewResolveContext, window, workspace, commands } from "vscode";
|
||||
import { PanelSettings, CustomScript } from './../models/PanelSettings';
|
||||
import { CancellationToken, Disposable, Uri, Webview, WebviewView, WebviewViewProvider, WebviewViewResolveContext, window, workspace, commands, env as vscodeEnv } from "vscode";
|
||||
import { CONFIG_KEY, SETTING_PANEL_FREEFORM, SETTING_SEO_DESCRIPTION_LENGTH, SETTING_SEO_TITLE_LENGTH, SETTING_SLUG_PREFIX, SETTING_SLUG_SUFFIX, SETTING_TAXONOMY_CATEGORIES, SETTING_TAXONOMY_TAGS } from "../constants";
|
||||
import { ArticleHelper, SettingsHelper } from "../helpers";
|
||||
import { Command } from "../viewpanel/Command";
|
||||
@@ -9,6 +10,7 @@ import { Article } from '../commands';
|
||||
import { TagType } from '../viewpanel/TagType';
|
||||
import { TaxonomyType } from '../models';
|
||||
import { exec } from 'child_process';
|
||||
import * as path from 'path';
|
||||
|
||||
|
||||
export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
@@ -108,6 +110,9 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
case CommandToCode.openFile:
|
||||
commands.executeCommand('revealFileInOS');
|
||||
break;
|
||||
case CommandToCode.runCustomScript:
|
||||
this.runCustomScript(msg);
|
||||
break;
|
||||
case CommandToCode.openProject:
|
||||
const wsFolders = workspace.workspaceFolders;
|
||||
if (wsFolders && wsFolders.length > 0) {
|
||||
@@ -162,6 +167,36 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a custom script
|
||||
* @param msg
|
||||
*/
|
||||
private runCustomScript(msg: { command: string, data: any}) {
|
||||
const config = workspace.getConfiguration(CONFIG_KEY);
|
||||
const scripts: CustomScript[] | undefined = config.get(SETTING_CUSTOM_SCRIPTS);
|
||||
|
||||
|
||||
if (msg?.data?.title && msg?.data?.script && scripts && scripts.find((s: CustomScript) => s.title === msg?.data?.title)?.title) {
|
||||
const editor = window.activeTextEditor;
|
||||
const wsFolders = workspace.workspaceFolders;
|
||||
if (wsFolders && wsFolders.length > 0) {
|
||||
const wsPath = wsFolders[0].uri.fsPath;
|
||||
exec(`node ${path.join(wsPath, msg.data.script)} "${wsPath}" "${editor?.document.uri.fsPath}"`, (error, stdout) => {
|
||||
if (error) {
|
||||
window.showErrorMessage(`${msg?.data?.title}: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
window.showInformationMessage(`${msg?.data?.title}: ${stdout || "Executed your custom script."}`, 'Copy output').then(value => {
|
||||
if (value === 'Copy output') {
|
||||
vscodeEnv.clipboard.writeText(stdout);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the extension settings
|
||||
*/
|
||||
@@ -181,7 +216,8 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
|
||||
},
|
||||
tags: config.get(SETTING_TAXONOMY_TAGS) || [],
|
||||
categories: config.get(SETTING_TAXONOMY_CATEGORIES) || [],
|
||||
freeform: config.get(SETTING_PANEL_FREEFORM)
|
||||
freeform: config.get(SETTING_PANEL_FREEFORM),
|
||||
scripts: config.get(SETTING_CUSTOM_SCRIPTS)
|
||||
} as PanelSettings
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user