Skip to content

Commit

Permalink
Implementation of custom scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
estruyf committed May 4, 2021
1 parent 6949288 commit e0ca17e
Show file tree
Hide file tree
Showing 14 changed files with 153 additions and 5 deletions.
4 changes: 4 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# These are supported funding model platforms

github: [estruyf]
custom: ["https://www.buymeacoffee.com/zMeFRy9"]
28 changes: 28 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -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 }}

4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

![](./assets/custom-actions.png)

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.

![](./assets/custom-action-notification.png)

## 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.
Expand Down Expand Up @@ -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:
Expand Down
Binary file added assets/custom-action-notification.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/custom-actions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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."
}
}
},
Expand Down
4 changes: 3 additions & 1 deletion src/constants/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
6 changes: 6 additions & 0 deletions src/models/PanelSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface PanelSettings {
tags: string[];
categories: string[];
freeform: boolean;
scripts: CustomScript[];
}

export interface SEO {
Expand All @@ -15,4 +16,9 @@ export interface SEO {
export interface Slug {
prefix: number;
suffix: number;
}

export interface CustomScript {
title: string;
script: string;
}
3 changes: 2 additions & 1 deletion src/viewpanel/CommandToCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
1 change: 1 addition & 0 deletions src/viewpanel/ViewPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
9 changes: 9 additions & 0 deletions src/viewpanel/components/Actions.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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>
);
};
21 changes: 21 additions & 0 deletions src/viewpanel/components/CustomScript.tsx
Original file line number Diff line number Diff line change
@@ -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>
);
};
42 changes: 39 additions & 3 deletions src/webview/ExplorerView.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
*/
Expand All @@ -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
});
}
Expand Down

0 comments on commit e0ca17e

Please sign in to comment.