diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000..5d875945
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,4 @@
+# These are supported funding model platforms
+
+github: [estruyf]
+custom: ["https://www.buymeacoffee.com/zMeFRy9"]
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 00000000..6471eb9e
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -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 }}
+
diff --git a/.vscode/launch.json b/.vscode/launch.json
index a47e93c5..ae2fc84b 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -18,6 +18,18 @@
],
"preLaunchTask": "npm: build:ext"
},
+ {
+ "name": "Attach Extension",
+ "type": "extensionHost",
+ "request": "launch",
+ "runtimeExecutable": "${execPath}",
+ "args": [
+ "--extensionDevelopmentPath=${workspaceFolder}"
+ ],
+ "outFiles": [
+ "${workspaceFolder}/dist/**/*.js"
+ ]
+ },
{
"name": "Extension Tests",
"type": "extensionHost",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bd170853..9213bbc8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,55 @@
# Change Log
+## [1.19.0] - 2020-07-20
+
+- Sidebar background styling match the VSCode defined sidebar color
+
+## [1.18.0] - 2020-07-20
+
+- Updated README
+
+## [1.17.1] - 2020-06-28
+
+- [#34](https://github.com/estruyf/vscode-front-matter/issues/34): Fix that last modification date does not update the publication date
+- [#38](https://github.com/estruyf/vscode-front-matter/issues/38): Update the last modification date on new page creation from the template
+
+## [1.17.0] - 2020-06-14
+
+- [#36](https://github.com/estruyf/vscode-front-matter/issues/36): Add the option to change the Front Matter its description field
+
+## [1.16.1] - 2020-05-27
+
+- Fix for Node.js v14.16.0
+
+## [1.16.0] - 2020-05-04
+
+- Add all front matter properties as an argument for custom scripts
+
+## [1.15.1] - 2020-05-04
+
+- Add the ability to specify a custom Node path
+
+## [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.
+
+## [1.13.0] - 2020-02-26
+
+- Implemented links to quickly open the extension settings + issue from the FrontMatter view panel
+- Added button to update the modified time in the FrontMatter view panel
+
+## [1.12.1] - 2020-02-13
+
+- Fix Front Matter SVG
+
+## [1.12.0] - 2020-01-26
+
+- [#29](https://github.com/estruyf/vscode-front-matter/issues/29): Open file after creating it from the template
+
## [1.11.1] - 2020-12-10
- [#26](https://github.com/estruyf/vscode-front-matter/issues/26): Fix for arrow selection in the dropdown.
diff --git a/README.md b/README.md
index 8ea99ecb..dc3a9a57 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,24 @@
-[](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter)
-
-[](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter)
-
-[](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter&ssr=false#review-details)
+
+
+Front Matter is an essential Visual Studio Code extension when you want to manage the markdown pages of your static sites.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This VSCode extension simplifies working with your markdown articles' front matter when using a static site generator like Hugo, Jekyll, Hexo, NextJs, Gatsby, and many more... For example, you can keep a list of used tags, categories and add/remove them from your article with the extension.
@@ -22,6 +38,32 @@ 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`](#frontmattercustomscripts) setting for your project.
+
+Once a custom action has been configured, it will appear on the Front Matter panel.
+
+
+
+The current workspace-, file-path, and front matter data will be passed as an argument. In your script fetch these arguments as follows:
+
+```javascript
+const arguments = process.argv;
+
+if (arguments && arguments.length > 0) {
+ const workspaceArg = arguments[2]; // The workspace path
+ const fileArg = arguments[3]; // The file path
+ const frontMatterArg = arguments[4]; // Front matter data
+
+ console.log(`The content returned for your notification.`);
+}
+```
+
+> A sample file can be found here: [script-sample.js](./sample/script-sample.js)
+
+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.
@@ -119,6 +161,15 @@ Specifies the optimal description length for SEO (set to `-1` to turn it off). D
"frontMatter.taxonomy.seoDescriptionLength": 160
}
```
+### `frontMatter.taxonomy.seoDescriptionLength`
+
+Specifies the name of the SEO description field for your page. Default is `description`.
+
+```json
+{
+ "frontMatter.taxonomy.seoDescriptionField": "description"
+}
+```
### `frontMatter.taxonomy.frontMatterType`
@@ -170,6 +221,22 @@ 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",
+ "nodeBin": "~/.nvm/versions/node/v14.15.5/bin/node"
+ }]
+}
+```
+
+> **Important**: When the command execution would fail when it cannot find the `node` command. You are able to specify your path to the node app. This is for instance required when using `nvm`.
+
## Usage
- Start by opening the command prompt:
@@ -180,3 +247,9 @@ Specifies the modified date field name to use in your Front Matter. Default valu
## Feedback / issues / ideas
Please submit them via creating an issue in the project repository: [issue list](https://github.com/estruyf/vscode-front-matter/issues).
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/custom-action-notification.png b/assets/custom-action-notification.png
new file mode 100644
index 00000000..65b6a193
Binary files /dev/null and b/assets/custom-action-notification.png differ
diff --git a/assets/custom-actions.png b/assets/custom-actions.png
new file mode 100644
index 00000000..d2594b88
Binary files /dev/null and b/assets/custom-actions.png differ
diff --git a/assets/frontmatter-panel-old.png b/assets/frontmatter-panel-old.png
new file mode 100644
index 00000000..2d4a4ffb
Binary files /dev/null and b/assets/frontmatter-panel-old.png differ
diff --git a/assets/frontmatter-panel.png b/assets/frontmatter-panel.png
index 2d4a4ffb..b0f2f068 100644
Binary files a/assets/frontmatter-panel.png and b/assets/frontmatter-panel.png differ
diff --git a/assets/frontmatter.svg b/assets/frontmatter.svg
index 6b8187cc..3c56d871 100644
--- a/assets/frontmatter.svg
+++ b/assets/frontmatter.svg
@@ -1,17 +1,39 @@
-
+
-FRONT
-
-MATTER
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/media/styles.css b/assets/media/styles.css
index df2a9242..736dd20e 100644
--- a/assets/media/styles.css
+++ b/assets/media/styles.css
@@ -21,6 +21,10 @@
}
}
+#app, .frontmatter {
+ height: 100%;
+}
+
.spinner,
.spinner:before,
.spinner:after {
@@ -58,6 +62,12 @@
left: 3.5em;
}
+.frontmatter {
+ padding: var(--input-margin-vertical) 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+}
.frontmatter h3 {
margin-bottom: 1rem;
@@ -69,6 +79,16 @@
margin-bottom: .5rem;
}
+.article__tags h3,
+.seo__status h3 {
+ display: flex;
+ align-items: center;
+}
+
+.section h3 i {
+ margin-right: 0.5rem;
+}
+
.seo__status__details {
margin-bottom: 2rem;
}
@@ -154,22 +174,28 @@
}
.article__tags__items__item {
- display: inline-block;
+ display: inline-flex;
margin-bottom: .5rem;
margin-right: .5rem;
}
-.article__tags__items__item_add,
-.article__tags__items__item_delete {
- display: inline-block;
+.article__tags__items__item_add {
+ display: inline-flex;
+ align-items: center;
width: auto;
}
-.article__tags__items__item svg {
- display: inline;
- vertical-align: bottom;
+.article__tags__items__item_delete {
+ display: inline-flex;
+ align-items: center;
+ width: auto;
}
+.article__tags__items__item_delete i {
+ margin-left: 0.5rem;
+}
+
+
.article__tags__items__item_delete span {
margin-left: .5rem;
}
@@ -199,4 +225,30 @@
border-right: 1px solid var(--vscode-inputValidation-infoBorder);
filter: contrast(60%);
+}
+
+.ext_settings > * + * {
+ --tw-space-y-reverse: 0;
+ margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
+ margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
+}
+
+.ext_link_block {
+ display: flex;
+ align-items: center;
+}
+
+.ext_link_block i {
+ margin-right: .5rem;
+}
+
+.ext_link_block a {
+ color: var(--vscode-textLink-foreground);
+}
+
+.ext_link_block a:hover,
+.ext_link_block a:active,
+.ext_link_block a:focus,
+.ext_link_block a:visited {
+ color: var(--vscode-textLink-activeForeground);
}
\ No newline at end of file
diff --git a/assets/media/vscode.css b/assets/media/vscode.css
index cb0a647b..8c491f11 100644
--- a/assets/media/vscode.css
+++ b/assets/media/vscode.css
@@ -6,13 +6,17 @@
--input-margin-horizontal: 0;
}
+html, body {
+ height: 100%;
+}
+
body {
padding: 0 var(--container-paddding);
color: var(--vscode-foreground);
font-size: var(--vscode-font-size);
font-weight: var(--vscode-font-weight);
font-family: var(--vscode-font-family);
- background-color: var(--vscode-editor-background);
+ background-color: var(--vscode-sideBar-background);
}
ol,
@@ -20,12 +24,6 @@ ul {
padding-left: var(--container-paddding);
}
-body > *,
-form > * {
- margin-block-start: var(--input-margin-vertical);
- margin-block-end: var(--input-margin-vertical);
-}
-
*:focus {
outline-color: var(--vscode-focusBorder) !important;
}
diff --git a/package-lock.json b/package-lock.json
index 6ffd4b1d..bd0eda2c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "vscode-front-matter",
- "version": "1.11.0",
+ "version": "1.18.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -39,6 +39,15 @@
"regenerator-runtime": "^0.13.4"
}
},
+ "@bendera/vscode-webview-elements": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@bendera/vscode-webview-elements/-/vscode-webview-elements-0.5.0.tgz",
+ "integrity": "sha512-mlZi8RG+tsqr1bDbA7H82spyWzZyj/tsyHb9eta7kE0xRhvx7ON6w6DG4PONew1rVJv1knTKOAW4iQKVBYQhVQ==",
+ "dev": true,
+ "requires": {
+ "lit-element": "^2.5.1"
+ }
+ },
"@emotion/hash": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
@@ -52,23 +61,36 @@
"dev": true
},
"@material-ui/core": {
- "version": "4.11.1",
- "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.11.1.tgz",
- "integrity": "sha512-aesI8lOaaw0DRIfNG+Anepf61NH5Q+cmkxJOZvI1oHkmD5cKubkZ0C7INqFKjfFpSFlFnqHkTasoM7ogFAvzOg==",
+ "version": "4.12.2",
+ "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.2.tgz",
+ "integrity": "sha512-Q1npB8V73IC+eV2X6as+g71MpEGQwqKHUI2iujY62npk35V8nMx/bUXAHjv5kKG1BZ8s8XUWoG6s/VkjYPjjQA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.4.4",
- "@material-ui/styles": "^4.11.1",
- "@material-ui/system": "^4.9.14",
- "@material-ui/types": "^5.1.0",
- "@material-ui/utils": "^4.10.2",
+ "@material-ui/styles": "^4.11.4",
+ "@material-ui/system": "^4.12.1",
+ "@material-ui/types": "5.1.0",
+ "@material-ui/utils": "^4.11.2",
"@types/react-transition-group": "^4.2.0",
"clsx": "^1.0.4",
"hoist-non-react-statics": "^3.3.2",
"popper.js": "1.16.1-lts",
"prop-types": "^15.7.2",
- "react-is": "^16.8.0",
+ "react-is": "^16.8.0 || ^17.0.0",
"react-transition-group": "^4.4.0"
+ },
+ "dependencies": {
+ "@material-ui/utils": {
+ "version": "4.11.2",
+ "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz",
+ "integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.4.4",
+ "prop-types": "^15.7.2",
+ "react-is": "^16.8.0 || ^17.0.0"
+ }
+ }
}
},
"@material-ui/icons": {
@@ -81,66 +103,88 @@
}
},
"@material-ui/lab": {
- "version": "4.0.0-alpha.56",
- "resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.56.tgz",
- "integrity": "sha512-xPlkK+z/6y/24ka4gVJgwPfoCF4RCh8dXb1BNE7MtF9bXEBLN/lBxNTK8VAa0qm3V2oinA6xtUIdcRh0aeRtVw==",
+ "version": "4.0.0-alpha.60",
+ "resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.60.tgz",
+ "integrity": "sha512-fadlYsPJF+0fx2lRuyqAuJj7hAS1tLDdIEEdov5jlrpb5pp4b+mRDUqQTUxi4inRZHS1bEXpU8QWUhO6xX88aA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.4.4",
- "@material-ui/utils": "^4.10.2",
+ "@material-ui/utils": "^4.11.2",
"clsx": "^1.0.4",
"prop-types": "^15.7.2",
- "react-is": "^16.8.0"
+ "react-is": "^16.8.0 || ^17.0.0"
}
},
"@material-ui/styles": {
- "version": "4.11.1",
- "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.1.tgz",
- "integrity": "sha512-GqzsFsVWT8jXa8OWAd1WD6WIaqtXr2mUPbRZ1EjkiM3Dlta4mCRaToDxkFVv6ZHfXlFjMJzdaIEvCpZOCvZTvg==",
+ "version": "4.11.4",
+ "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",
+ "integrity": "sha512-KNTIZcnj/zprG5LW0Sao7zw+yG3O35pviHzejMdcSGCdWbiO8qzRgOYL8JAxAsWBKOKYwVZxXtHWaB5T2Kvxew==",
"dev": true,
"requires": {
"@babel/runtime": "^7.4.4",
"@emotion/hash": "^0.8.0",
- "@material-ui/types": "^5.1.0",
- "@material-ui/utils": "^4.9.6",
+ "@material-ui/types": "5.1.0",
+ "@material-ui/utils": "^4.11.2",
"clsx": "^1.0.4",
"csstype": "^2.5.2",
"hoist-non-react-statics": "^3.3.2",
- "jss": "^10.0.3",
- "jss-plugin-camel-case": "^10.0.3",
- "jss-plugin-default-unit": "^10.0.3",
- "jss-plugin-global": "^10.0.3",
- "jss-plugin-nested": "^10.0.3",
- "jss-plugin-props-sort": "^10.0.3",
- "jss-plugin-rule-value-function": "^10.0.3",
- "jss-plugin-vendor-prefixer": "^10.0.3",
+ "jss": "^10.5.1",
+ "jss-plugin-camel-case": "^10.5.1",
+ "jss-plugin-default-unit": "^10.5.1",
+ "jss-plugin-global": "^10.5.1",
+ "jss-plugin-nested": "^10.5.1",
+ "jss-plugin-props-sort": "^10.5.1",
+ "jss-plugin-rule-value-function": "^10.5.1",
+ "jss-plugin-vendor-prefixer": "^10.5.1",
"prop-types": "^15.7.2"
},
"dependencies": {
+ "@material-ui/utils": {
+ "version": "4.11.2",
+ "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz",
+ "integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.4.4",
+ "prop-types": "^15.7.2",
+ "react-is": "^16.8.0 || ^17.0.0"
+ }
+ },
"csstype": {
- "version": "2.6.14",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.14.tgz",
- "integrity": "sha512-2mSc+VEpGPblzAxyeR+vZhJKgYg0Og0nnRi7pmRXFYYxSfnOnW8A5wwQb4n4cE2nIOzqKOAzLCaEX6aBmNEv8A==",
+ "version": "2.6.17",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.17.tgz",
+ "integrity": "sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A==",
"dev": true
}
}
},
"@material-ui/system": {
- "version": "4.9.14",
- "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.9.14.tgz",
- "integrity": "sha512-oQbaqfSnNlEkXEziDcJDDIy8pbvwUmZXWNqlmIwDqr/ZdCK8FuV3f4nxikUh7hvClKV2gnQ9djh5CZFTHkZj3w==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.1.tgz",
+ "integrity": "sha512-lUdzs4q9kEXZGhbN7BptyiS1rLNHe6kG9o8Y307HCvF4sQxbCgpL2qi+gUk+yI8a2DNk48gISEQxoxpgph0xIw==",
"dev": true,
"requires": {
"@babel/runtime": "^7.4.4",
- "@material-ui/utils": "^4.9.6",
+ "@material-ui/utils": "^4.11.2",
"csstype": "^2.5.2",
"prop-types": "^15.7.2"
},
"dependencies": {
+ "@material-ui/utils": {
+ "version": "4.11.2",
+ "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz",
+ "integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.4.4",
+ "prop-types": "^15.7.2",
+ "react-is": "^16.8.0 || ^17.0.0"
+ }
+ },
"csstype": {
- "version": "2.6.14",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.14.tgz",
- "integrity": "sha512-2mSc+VEpGPblzAxyeR+vZhJKgYg0Og0nnRi7pmRXFYYxSfnOnW8A5wwQb4n4cE2nIOzqKOAzLCaEX6aBmNEv8A==",
+ "version": "2.6.17",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.17.tgz",
+ "integrity": "sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A==",
"dev": true
}
}
@@ -152,14 +196,14 @@
"dev": true
},
"@material-ui/utils": {
- "version": "4.10.2",
- "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.10.2.tgz",
- "integrity": "sha512-eg29v74P7W5r6a4tWWDAAfZldXIzfyO1am2fIsC39hdUUHm/33k6pGOKPbgDjg/U/4ifmgAePy/1OjkKN6rFRw==",
+ "version": "4.11.2",
+ "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.2.tgz",
+ "integrity": "sha512-Uul8w38u+PICe2Fg2pDKCaIG7kOyhowZ9vjiC1FsVwPABTW8vPPKfF6OvxRq3IiBaI1faOJmgdvMG7rMJARBhA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.4.4",
"prop-types": "^15.7.2",
- "react-is": "^16.8.0"
+ "react-is": "^16.8.0 || ^17.0.0"
}
},
"@types/anymatch": {
@@ -240,9 +284,9 @@
}
},
"@types/react-transition-group": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.0.tgz",
- "integrity": "sha512-/QfLHGpu+2fQOqQaXh8MG9q03bFENooTb/it4jr5kKaZlDQfWvjqWZg48AwzPVMBHlRuTRAY7hRHCEOXz5kV6w==",
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.2.tgz",
+ "integrity": "sha512-KibDWL6nshuOJ0fu8ll7QnV/LVTo3PzQ9aCPnRUYPfX7eZohHwLIdNHj7pftanREzHNP4/nJa8oeM73uSiavMQ==",
"dev": true,
"requires": {
"@types/react": "*"
@@ -324,6 +368,12 @@
}
}
},
+ "@vscode/codicons": {
+ "version": "0.0.20",
+ "resolved": "https://registry.npmjs.org/@vscode/codicons/-/codicons-0.0.20.tgz",
+ "integrity": "sha512-LlO6K7nzrIWDCZN1Zi6J6ibxrpMibSAct+zNjAwpkNkwup6cJLx5diYvsOJODMPWOuQlBO21qkxtdkSRzW6+Jw==",
+ "dev": true
+ },
"@webassemblyjs/ast": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
@@ -1427,9 +1477,9 @@
}
},
"dom-helpers": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.0.tgz",
- "integrity": "sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ==",
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.8.7",
@@ -1520,24 +1570,24 @@
}
},
"elliptic": {
- "version": "6.5.3",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz",
- "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==",
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
+ "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
"dev": true,
"requires": {
- "bn.js": "^4.4.0",
- "brorand": "^1.0.1",
+ "bn.js": "^4.11.9",
+ "brorand": "^1.1.0",
"hash.js": "^1.0.0",
- "hmac-drbg": "^1.0.0",
- "inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0",
- "minimalistic-crypto-utils": "^1.0.0"
+ "hmac-drbg": "^1.0.1",
+ "inherits": "^2.0.4",
+ "minimalistic-assert": "^1.0.1",
+ "minimalistic-crypto-utils": "^1.0.1"
},
"dependencies": {
"bn.js": {
- "version": "4.11.9",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
- "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
"dev": true
}
}
@@ -2510,15 +2560,6 @@
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
"dev": true
},
- "indefinite-observable": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/indefinite-observable/-/indefinite-observable-2.0.1.tgz",
- "integrity": "sha512-G8vgmork+6H9S8lUAg1gtXEj2JxIQTo0g2PbFiYOdjkziSI0F7UYBiVwhZRuixhBCNGczAls34+5HJPyZysvxQ==",
- "dev": true,
- "requires": {
- "symbol-observable": "1.2.0"
- }
- },
"infer-owner": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
@@ -2542,9 +2583,9 @@
"dev": true
},
"ini": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
- "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz",
+ "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==",
"dev": true
},
"interpret": {
@@ -2797,90 +2838,89 @@
}
},
"jss": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/jss/-/jss-10.5.0.tgz",
- "integrity": "sha512-B6151NvG+thUg3murLNHRPLxTLwQ13ep4SH5brj4d8qKtogOx/jupnpfkPGSHPqvcwKJaCLctpj2lEk+5yGwMw==",
+ "version": "10.7.1",
+ "resolved": "https://registry.npmjs.org/jss/-/jss-10.7.1.tgz",
+ "integrity": "sha512-5QN8JSVZR6cxpZNeGfzIjqPEP+ZJwJJfZbXmeABNdxiExyO+eJJDy6WDtqTf8SDKnbL5kZllEpAP71E/Lt7PXg==",
"dev": true,
"requires": {
"@babel/runtime": "^7.3.1",
"csstype": "^3.0.2",
- "indefinite-observable": "^2.0.1",
"is-in-browser": "^1.1.3",
"tiny-warning": "^1.0.2"
}
},
"jss-plugin-camel-case": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.5.0.tgz",
- "integrity": "sha512-GSjPL0adGAkuoqeYiXTgO7PlIrmjv5v8lA6TTBdfxbNYpxADOdGKJgIEkffhlyuIZHlPuuiFYTwUreLUmSn7rg==",
+ "version": "10.7.1",
+ "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.7.1.tgz",
+ "integrity": "sha512-+ioIyWvmAfgDCWXsQcW1NMnLBvRinOVFkSYJUgewQ6TynOcSj5F1bSU23B7z0p1iqK0PPHIU62xY1iNJD33WGA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.3.1",
"hyphenate-style-name": "^1.0.3",
- "jss": "10.5.0"
+ "jss": "10.7.1"
}
},
"jss-plugin-default-unit": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.5.0.tgz",
- "integrity": "sha512-rsbTtZGCMrbcb9beiDd+TwL991NGmsAgVYH0hATrYJtue9e+LH/Gn4yFD1ENwE+3JzF3A+rPnM2JuD9L/SIIWw==",
+ "version": "10.7.1",
+ "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.7.1.tgz",
+ "integrity": "sha512-tW+dfYVNARBQb/ONzBwd8uyImigyzMiAEDai+AbH5rcHg5h3TtqhAkxx06iuZiT/dZUiFdSKlbe3q9jZGAPIwA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.3.1",
- "jss": "10.5.0"
+ "jss": "10.7.1"
}
},
"jss-plugin-global": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.5.0.tgz",
- "integrity": "sha512-FZd9+JE/3D7HMefEG54fEC0XiQ9rhGtDHAT/ols24y8sKQ1D5KIw6OyXEmIdKFmACgxZV2ARQ5pAUypxkk2IFQ==",
+ "version": "10.7.1",
+ "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.7.1.tgz",
+ "integrity": "sha512-FbxCnu44IkK/bw8X3CwZKmcAnJqjAb9LujlAc/aP0bMSdVa3/MugKQRyeQSu00uGL44feJJDoeXXiHOakBr/Zw==",
"dev": true,
"requires": {
"@babel/runtime": "^7.3.1",
- "jss": "10.5.0"
+ "jss": "10.7.1"
}
},
"jss-plugin-nested": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.5.0.tgz",
- "integrity": "sha512-ejPlCLNlEGgx8jmMiDk/zarsCZk+DV0YqXfddpgzbO9Toamo0HweCFuwJ3ZO40UFOfqKwfpKMVH/3HUXgxkTMg==",
+ "version": "10.7.1",
+ "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.7.1.tgz",
+ "integrity": "sha512-RNbICk7FlYKaJyv9tkMl7s6FFfeLA3ubNIFKvPqaWtADK0KUaPsPXVYBkAu4x1ItgsWx67xvReMrkcKA0jSXfA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.3.1",
- "jss": "10.5.0",
+ "jss": "10.7.1",
"tiny-warning": "^1.0.2"
}
},
"jss-plugin-props-sort": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.5.0.tgz",
- "integrity": "sha512-kTLRvrOetFKz5vM88FAhLNeJIxfjhCepnvq65G7xsAQ/Wgy7HwO1BS/2wE5mx8iLaAWC6Rj5h16mhMk9sKdZxg==",
+ "version": "10.7.1",
+ "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.7.1.tgz",
+ "integrity": "sha512-eyd5FhA+J0QrpqXxO7YNF/HMSXXl4pB0EmUdY4vSJI4QG22F59vQ6AHtP6fSwhmBdQ98Qd9gjfO+RMxcE39P1A==",
"dev": true,
"requires": {
"@babel/runtime": "^7.3.1",
- "jss": "10.5.0"
+ "jss": "10.7.1"
}
},
"jss-plugin-rule-value-function": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.5.0.tgz",
- "integrity": "sha512-jXINGr8BSsB13JVuK274oEtk0LoooYSJqTBCGeBu2cG/VJ3+4FPs1gwLgsq24xTgKshtZ+WEQMVL34OprLidRA==",
+ "version": "10.7.1",
+ "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.7.1.tgz",
+ "integrity": "sha512-fGAAImlbaHD3fXAHI3ooX6aRESOl5iBt3LjpVjxs9II5u9tzam7pqFUmgTcrip9VpRqYHn8J3gA7kCtm8xKwHg==",
"dev": true,
"requires": {
"@babel/runtime": "^7.3.1",
- "jss": "10.5.0",
+ "jss": "10.7.1",
"tiny-warning": "^1.0.2"
}
},
"jss-plugin-vendor-prefixer": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.5.0.tgz",
- "integrity": "sha512-rux3gmfwDdOKCLDx0IQjTwTm03IfBa+Rm/hs747cOw5Q7O3RaTUIMPKjtVfc31Xr/XI9Abz2XEupk1/oMQ7zRA==",
+ "version": "10.7.1",
+ "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.7.1.tgz",
+ "integrity": "sha512-1UHFmBn7hZNsHXTkLLOL8abRl8vi+D1EVzWD4WmLFj55vawHZfnH1oEz6TUf5Y61XHv0smdHabdXds6BgOXe3A==",
"dev": true,
"requires": {
"@babel/runtime": "^7.3.1",
"css-vendor": "^2.0.8",
- "jss": "10.5.0"
+ "jss": "10.7.1"
}
},
"kind-of": {
@@ -2889,6 +2929,21 @@
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"dev": true
},
+ "lit-element": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-2.5.1.tgz",
+ "integrity": "sha512-ogu7PiJTA33bEK0xGu1dmaX5vhcRjBXCFexPja0e7P7jqLhTpNKYRPmE+GmiCaRVAbiQKGkUgkh/i6+bh++dPQ==",
+ "dev": true,
+ "requires": {
+ "lit-html": "^1.1.1"
+ }
+ },
+ "lit-html": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-1.4.1.tgz",
+ "integrity": "sha512-B9btcSgPYb1q4oSOb/PrOT6Z/H+r6xuNzfH4lFli/AWhYwdtrgQkQWBbIc6mdnf6E2IL3gDXdkkqNktpU0OZQA==",
+ "dev": true
+ },
"loader-runner": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
@@ -2917,9 +2972,9 @@
}
},
"lodash": {
- "version": "4.17.19",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
- "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"loose-envify": {
@@ -3507,14 +3562,6 @@
"requires": {
"lodash": "^4.17.20",
"renderkid": "^2.0.4"
- },
- "dependencies": {
- "lodash": {
- "version": "4.17.20",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
- "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
- "dev": true
- }
}
},
"process": {
@@ -3672,9 +3719,9 @@
"dev": true
},
"react-transition-group": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
- "integrity": "sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==",
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
+ "integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==",
"dev": true,
"requires": {
"@babel/runtime": "^7.5.5",
@@ -3777,12 +3824,6 @@
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true
},
- "lodash": {
- "version": "4.17.20",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
- "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
- "dev": true
- },
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
@@ -4227,9 +4268,9 @@
"dev": true
},
"ssri": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
- "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz",
+ "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==",
"dev": true,
"requires": {
"figgy-pudding": "^3.5.1"
@@ -4310,12 +4351,6 @@
"integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=",
"dev": true
},
- "symbol-observable": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
- "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
- "dev": true
- },
"tapable": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
@@ -4993,6 +5028,12 @@
}
}
},
+ "wc-react": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/wc-react/-/wc-react-0.5.0.tgz",
+ "integrity": "sha512-3c4KzBArlfCqCYqY8hoJAIvxmzpWvoQqsOmy9OiwbnopSTE270i3R+LVD7NjE00UJkjXq7kmhobnx0qhi/eOrA==",
+ "dev": true
+ },
"webpack": {
"version": "4.44.2",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz",
@@ -5317,9 +5358,9 @@
"dev": true
},
"y18n": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
- "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
+ "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
"dev": true
},
"yallist": {
diff --git a/package.json b/package.json
index 3118029b..d3b5f7b4 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"displayName": "Front Matter",
"description": "Simplifies working with front matter of your articles. Useful extension when you are using a static site generator like: Hugo, Jekyll, Hexo, NextJs, Gatsby, and many more...",
"icon": "assets/front-matter.png",
- "version": "1.11.0",
+ "version": "1.18.0",
"preview": false,
"publisher": "eliostruyf",
"galleryBanner": {
@@ -15,6 +15,11 @@
"description": "version",
"url": "https://img.shields.io/github/package-json/v/estruyf/vscode-front-matter?color=green&label=vscode-front-matter&style=flat-square",
"href": "https://github.com/estruyf/vscode-front-matter"
+ },
+ {
+ "description": "Buy me a coffee",
+ "url": "https://img.shields.io/badge/Buy%20me%20a%20coffee-€%203-blue?logo=buy-me-a-coffee&style=flat-square",
+ "href": "https://www.buymeacoffee.com/zMeFRy9"
}
],
"engines": {
@@ -137,6 +142,11 @@
"default": 160,
"description": "Specifies the optimal description length for SEO (set to `-1` to turn it off)."
},
+ "frontMatter.taxonomy.seoDescriptionField": {
+ "type": "string",
+ "default": "description",
+ "description": "Specifies the name of the SEO description field for your page. Default is 'description'."
+ },
"frontMatter.templates.folder": {
"type": "string",
"default": ".templates",
@@ -151,6 +161,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."
}
}
},
@@ -223,10 +238,11 @@
"clean": "rm -rf dist"
},
"devDependencies": {
+ "@bendera/vscode-webview-elements": "0.5.0",
"@iarna/toml": "2.2.3",
- "@material-ui/core": "4.11.1",
+ "@material-ui/core": "4.12.2",
"@material-ui/icons": "4.11.2",
- "@material-ui/lab": "4.0.0-alpha.56",
+ "@material-ui/lab": "4.0.0-alpha.60",
"@types/glob": "7.1.3",
"@types/js-yaml": "3.12.1",
"@types/mocha": "^5.2.6",
@@ -234,7 +250,9 @@
"@types/react": "17.0.0",
"@types/react-dom": "17.0.0",
"@types/vscode": "1.51.0",
+ "@vscode/codicons": "0.0.20",
"date-fns": "2.0.1",
+ "downshift": "6.0.6",
"glob": "7.1.6",
"gray-matter": "4.0.2",
"html-loader": "1.3.2",
@@ -244,9 +262,9 @@
"ts-loader": "8.0.3",
"tslint": "6.1.3",
"typescript": "4.0.2",
+ "wc-react": "0.5.0",
"webpack": "4.44.2",
- "webpack-cli": "3.3.12",
- "downshift": "6.0.6"
+ "webpack-cli": "3.3.12"
},
"dependencies": {}
}
diff --git a/sample/script-sample.js b/sample/script-sample.js
new file mode 100644
index 00000000..e950e688
--- /dev/null
+++ b/sample/script-sample.js
@@ -0,0 +1,10 @@
+
+const arguments = process.argv;
+
+if (arguments && arguments.length > 0) {
+ const workspaceArg = arguments[2]; // The workspace path
+ const fileArg = arguments[3]; // The file path
+ const frontMatterArg = arguments[4]; // Front matter data
+
+ console.log(`The content returned for your notification.`);
+}
\ No newline at end of file
diff --git a/src/commands/Article.ts b/src/commands/Article.ts
index 2885cbf8..0da99c86 100644
--- a/src/commands/Article.ts
+++ b/src/commands/Article.ts
@@ -101,14 +101,11 @@ export class Article {
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
const dateFormat = config.get(SETTING_DATE_FORMAT) as string;
const dateField = config.get(SETTING_DATE_FIELD) as string || "date";
+ const modField = config.get(SETTING_MODIFIED_FIELD) as string || "date";
+
+ article = this.articleDate(article, dateFormat, dateField, forceCreate);
+ article = this.articleDate(article, dateFormat, modField, false);
- if (typeof article.data[dateField] !== "undefined" || forceCreate) {
- if (dateFormat && typeof dateFormat === "string") {
- article.data[dateField] = format(new Date(), dateFormat);
- } else {
- article.data[dateField] = new Date();
- }
- }
return article;
}
@@ -133,7 +130,7 @@ export class Article {
if (dateFormat && typeof dateFormat === "string") {
article.data[dateField] = format(new Date(), dateFormat);
} else {
- article.data[dateField] = new Date();
+ article.data[dateField] = new Date().toISOString();
}
ArticleHelper.update(editor, article);
@@ -185,4 +182,22 @@ export class Article {
article.data["draft"] = newDraftStatus;
ArticleHelper.update(editor, article);
}
+
+ /**
+ * Update the article date and return it
+ * @param article
+ * @param dateFormat
+ * @param field
+ * @param forceCreate
+ */
+ private static articleDate(article: matter.GrayMatterFile, dateFormat: string, field: string, forceCreate: boolean) {
+ if (typeof article.data[field] !== "undefined" || forceCreate) {
+ if (dateFormat && typeof dateFormat === "string") {
+ article.data[field] = format(new Date(), dateFormat);
+ } else {
+ article.data[field] = new Date().toISOString();
+ }
+ }
+ return article;
+ }
}
diff --git a/src/commands/StatusListener.ts b/src/commands/StatusListener.ts
index e940f7fb..77752ff5 100644
--- a/src/commands/StatusListener.ts
+++ b/src/commands/StatusListener.ts
@@ -1,4 +1,4 @@
-import { SETTING_SEO_DESCRIPTION_LENGTH, SETTING_SEO_TITLE_LENGTH } from './../constants/settings';
+import { SETTING_SEO_DESCRIPTION_FIELD, SETTING_SEO_DESCRIPTION_LENGTH, SETTING_SEO_TITLE_LENGTH } from './../constants/settings';
import * as vscode from 'vscode';
import { CONFIG_KEY } from '../constants';
import { ArticleHelper, SeoHelper } from '../helpers';
@@ -41,13 +41,14 @@ export class StatusListener {
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
const titleLength = config.get(SETTING_SEO_TITLE_LENGTH) as number || -1;
const descLength = config.get(SETTING_SEO_DESCRIPTION_LENGTH) as number || -1;
+ const fieldName = config.get(SETTING_SEO_DESCRIPTION_FIELD) as string || "description";
if (article.data.title && titleLength > -1) {
SeoHelper.checkLength(editor, collection, article, "title", titleLength);
}
- if (article.data.description && descLength > -1) {
- SeoHelper.checkLength(editor, collection, article, "description", descLength);
+ if (article.data[fieldName] && descLength > -1) {
+ SeoHelper.checkLength(editor, collection, article, fieldName, descLength);
}
}
diff --git a/src/commands/Template.ts b/src/commands/Template.ts
index 79625df2..9945028b 100644
--- a/src/commands/Template.ts
+++ b/src/commands/Template.ts
@@ -92,6 +92,8 @@ export class Template {
frontMatter = Article.updateDate(frontMatter);
fs.writeFileSync(newFilePath, ArticleHelper.stringifyFrontMatter(frontMatter.content, frontMatter.data), { encoding: "utf8" });
+
+ await vscode.commands.executeCommand('vscode.open', vscode.Uri.file(newFilePath));
}
const txtDoc = await vscode.workspace.openTextDocument(vscode.Uri.parse(newFilePath));
diff --git a/src/constants/settings.ts b/src/constants/settings.ts
index c690f22f..2a184ba3 100644
--- a/src/constants/settings.ts
+++ b/src/constants/settings.ts
@@ -18,8 +18,11 @@ export const SETTING_FRONTMATTER_TYPE = "taxonomy.frontMatterType";
export const SETTING_SEO_TITLE_LENGTH = "taxonomy.seoTitleLength";
export const SETTING_SEO_DESCRIPTION_LENGTH = "taxonomy.seoDescriptionLength";
+export const SETTING_SEO_DESCRIPTION_FIELD = "taxonomy.seoDescriptionField";
export const SETTING_TEMPLATES_FOLDER = "templates.folder";
export const SETTING_TEMPLATES_PREFIX = "templates.prefix";
-export const SETTING_PANEL_FREEFORM = "panel.freeform";
\ No newline at end of file
+export const SETTING_PANEL_FREEFORM = "panel.freeform";
+
+export const SETTING_CUSTOM_SCRIPTS = "custom.scripts";
\ No newline at end of file
diff --git a/src/models/PanelSettings.ts b/src/models/PanelSettings.ts
index 03d6061a..4ad2ce25 100644
--- a/src/models/PanelSettings.ts
+++ b/src/models/PanelSettings.ts
@@ -5,14 +5,22 @@ export interface PanelSettings {
tags: string[];
categories: string[];
freeform: boolean;
+ scripts: CustomScript[];
}
export interface SEO {
title: number;
description: number;
+ descriptionField: string;
}
export interface Slug {
prefix: number;
suffix: number;
+}
+
+export interface CustomScript {
+ title: string;
+ script: string;
+ nodeBin?: string;
}
\ No newline at end of file
diff --git a/src/viewpanel/CommandToCode.ts b/src/viewpanel/CommandToCode.ts
index b3e02fcf..e3b1630f 100644
--- a/src/viewpanel/CommandToCode.ts
+++ b/src/viewpanel/CommandToCode.ts
@@ -2,9 +2,14 @@ export enum CommandToCode {
getData = "get-data",
updateSlug = 'update-slug',
updateDate = 'update-date',
+ updateLastMod = 'update-lastmod',
publish = 'publish',
updateTags = "update-tags",
updateCategories = "update-categories",
addTagToSettings = "add-tag",
- addCategoryToSettings = "add-category"
+ addCategoryToSettings = "add-category",
+ openSettings = "open-settings",
+ openFile = "open-file",
+ openProject = "open-project",
+ runCustomScript = "custom-script"
}
\ No newline at end of file
diff --git a/src/viewpanel/ViewPanel.tsx b/src/viewpanel/ViewPanel.tsx
index 716b780c..8bdc5cfb 100644
--- a/src/viewpanel/ViewPanel.tsx
+++ b/src/viewpanel/ViewPanel.tsx
@@ -1,8 +1,11 @@
import * as React from 'react';
+import { CommandToCode } from './CommandToCode';
import { Actions } from './components/Actions';
+import { Icon } from './components/Icon';
import { SeoStatus } from './components/SeoStatus';
import { Spinner } from './components/Spinner';
import { TagPicker } from './components/TagPicker';
+import { MessageHelper } from './helper/MessageHelper';
import useMessages from './hooks/useMessages';
import { TagType } from './TagType';
@@ -26,34 +29,73 @@ export const ViewPanel: React.FunctionComponent = (props: React
);
}
+ const openSettings = () => {
+ MessageHelper.sendMessage(CommandToCode.openSettings);
+ };
+
+ const openFile = () => {
+ MessageHelper.sendMessage(CommandToCode.openFile);
+ };
+
+ const openProject = () => {
+ MessageHelper.sendMessage(CommandToCode.openProject);
+ };
+
return (
- {
- settings && settings.seo &&
- }
- {
- settings && metadata &&
- }
- {
- (settings && settings.tags && settings.tags.length > 0) && (
-
- )
- }
- {
- (settings && settings.categories && settings.categories.length > 0) && (
-
- )
- }
+
+ {
+ settings && settings.seo &&
+ }
+ {
+ settings && metadata &&
+ }
+
+ {
+ (settings && settings.tags && settings.tags.length > 0) && (
+
}
+ crntSelected={metadata.tags || []}
+ options={settings.tags}
+ freeform={settings.freeform}
+ focussed={focusElm === TagType.tags}
+ unsetFocus={unsetFocus} />
+ )
+ }
+ {
+ (settings && settings.categories && settings.categories.length > 0) && (
+
}
+ crntSelected={metadata.categories || []}
+ options={settings.categories}
+ freeform={settings.freeform}
+ focussed={focusElm === TagType.categories}
+ unsetFocus={unsetFocus} />
+ )
+ }
+
+
+
);
};
\ No newline at end of file
diff --git a/src/viewpanel/components/Actions.tsx b/src/viewpanel/components/Actions.tsx
index 42b67fb9..630d4894 100644
--- a/src/viewpanel/components/Actions.tsx
+++ b/src/viewpanel/components/Actions.tsx
@@ -1,6 +1,8 @@
import * as React from 'react';
import { PanelSettings } from '../../models/PanelSettings';
+import { CustomScript } from './CustomScript';
import { DateAction } from './DateAction';
+import { Icon } from './Icon';
import { PublishAction } from './PublishAction';
import { SlugAction } from './SlugAction';
@@ -17,14 +19,22 @@ export const Actions: React.FunctionComponent = (props: React.Pro
}
return (
-
-
Actions
+
+
Actions
{ metadata && metadata.title &&
}
{ metadata && typeof metadata.draft !== undefined &&
}
+
+ {
+ (settings && settings.scripts && settings.scripts.length > 0) && (
+ settings.scripts.map((value) => (
+
+ ))
+ )
+ }
);
};
\ No newline at end of file
diff --git a/src/viewpanel/components/CustomScript.tsx b/src/viewpanel/components/CustomScript.tsx
new file mode 100644
index 00000000..bffa4f9d
--- /dev/null
+++ b/src/viewpanel/components/CustomScript.tsx
@@ -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
= ({title, script}: React.PropsWithChildren) => {
+
+ const runCustomScript = () => {
+ MessageHelper.sendMessage(CommandToCode.runCustomScript, { title, script });
+ };
+
+ return (
+
+ {title}
+
+ );
+};
\ No newline at end of file
diff --git a/src/viewpanel/components/DateAction.tsx b/src/viewpanel/components/DateAction.tsx
index d18a94d0..27c49aeb 100644
--- a/src/viewpanel/components/DateAction.tsx
+++ b/src/viewpanel/components/DateAction.tsx
@@ -1,5 +1,3 @@
-
-
import * as React from 'react';
import { CommandToCode } from '../CommandToCode';
import { MessageHelper } from '../helper/MessageHelper';
@@ -11,10 +9,19 @@ export const DateAction: React.FunctionComponent = (props: Rea
const setDate = () => {
MessageHelper.sendMessage(CommandToCode.updateDate);
};
+
+ const setLastMod = () => {
+ MessageHelper.sendMessage(CommandToCode.updateLastMod);
+ };
return (
-
- Set current date
-
+ <>
+
+ Set publish date
+
+
+ Set modified date
+
+ >
);
};
\ No newline at end of file
diff --git a/src/viewpanel/components/Icon.tsx b/src/viewpanel/components/Icon.tsx
new file mode 100644
index 00000000..81848dd3
--- /dev/null
+++ b/src/viewpanel/components/Icon.tsx
@@ -0,0 +1,10 @@
+import * as React from 'react';
+
+export interface IIconProps {
+ name: string;
+}
+
+export const Icon: React.FunctionComponent = ({ name }: React.PropsWithChildren) => {
+
+ return ( );
+};
\ No newline at end of file
diff --git a/src/viewpanel/components/SeoStatus.tsx b/src/viewpanel/components/SeoStatus.tsx
index 466683bc..448e2d59 100644
--- a/src/viewpanel/components/SeoStatus.tsx
+++ b/src/viewpanel/components/SeoStatus.tsx
@@ -1,5 +1,6 @@
import * as React from 'react';
import { SEO } from '../../models/PanelSettings';
+import { Icon } from './Icon';
import { SeoDetails } from './SeoDetails';
export interface ISeoStatusProps {
@@ -9,17 +10,21 @@ export interface ISeoStatusProps {
export const SeoStatus: React.FunctionComponent = (props: React.PropsWithChildren) => {
const { data, seo } = props;
- const { title, description } = data;
+ const { title } = data;
- if (!title && !description) {
+ const { descriptionField } = seo;
+
+ if (!title && !data[descriptionField]) {
return null;
}
return (
-
-
SEO Status
+
+
+ SEO Status
+
{ (title && seo.title > 0) && }
- { (description && seo.description > 0) && }
+ { (data[descriptionField] && seo.description > 0) && }
);
};
\ No newline at end of file
diff --git a/src/viewpanel/components/Tag.tsx b/src/viewpanel/components/Tag.tsx
index 180aefe2..2f1b88c3 100644
--- a/src/viewpanel/components/Tag.tsx
+++ b/src/viewpanel/components/Tag.tsx
@@ -1,6 +1,7 @@
import * as React from 'react';
import AddIcon from '@material-ui/icons/Add';
-import DeleteForeverTwoToneIcon from '@material-ui/icons/DeleteForeverTwoTone';
+import DeleteIcon from '@material-ui/icons/Delete';
+import { Icon } from './Icon';
export interface ITagProps {
className: string;
@@ -18,9 +19,10 @@ export const Tag: React.FunctionComponent
= (props: React.PropsWithCh
{
onCreate &&
-
onCreate(value)}>
+
onCreate(value)}>
}
-
onRemove(value)}>{value}
+
+
onRemove(value)}>{value}
);
};
\ No newline at end of file
diff --git a/src/viewpanel/components/TagPicker.tsx b/src/viewpanel/components/TagPicker.tsx
index c6a4f58c..804f8ade 100644
--- a/src/viewpanel/components/TagPicker.tsx
+++ b/src/viewpanel/components/TagPicker.tsx
@@ -9,6 +9,7 @@ import LocalOfferTwoToneIcon from '@material-ui/icons/LocalOfferTwoTone';
export interface ITagPickerProps {
type: string;
+ icon: JSX.Element;
crntSelected: string[];
options: string[];
freeform: boolean;
@@ -17,7 +18,7 @@ export interface ITagPickerProps {
}
export const TagPicker: React.FunctionComponent = (props: React.PropsWithChildren) => {
- const { type, crntSelected, options, freeform, focussed, unsetFocus } = props;
+ const { icon, type, crntSelected, options, freeform, focussed, unsetFocus } = props;
const [ selected, setSelected ] = React.useState([]);
const [ inputValue, setInputValue ] = React.useState("");
const prevSelected = usePrevious(crntSelected);
@@ -115,8 +116,8 @@ export const TagPicker: React.FunctionComponent = (props: React
}, [crntSelected]);
return (
-
-
{type}
+
+
{icon} {type}
onSelect(selected || "")}
diff --git a/src/viewpanel/components/VscodeComponents.ts b/src/viewpanel/components/VscodeComponents.ts
new file mode 100644
index 00000000..81a3b561
--- /dev/null
+++ b/src/viewpanel/components/VscodeComponents.ts
@@ -0,0 +1,3 @@
+import {wrapWc} from 'wc-react';
+
+export const VscodeIcon = wrapWc(`vscode-icon`);
\ No newline at end of file
diff --git a/src/viewpanel/index.tsx b/src/viewpanel/index.tsx
index 527cdbb7..4d5d7504 100644
--- a/src/viewpanel/index.tsx
+++ b/src/viewpanel/index.tsx
@@ -2,6 +2,8 @@ import * as React from "react";
import { render } from "react-dom";
import { ViewPanel } from "./ViewPanel";
+import '@bendera/vscode-webview-elements/dist/vscode-icon';
+
declare const acquireVsCodeApi: () => {
getState: () => T;
setState: (data: T) => void;
@@ -9,4 +11,4 @@ declare const acquireVsCodeApi: () => {
};
const elm = document.querySelector("#app");
-render( , elm);
\ No newline at end of file
+render( , elm);
diff --git a/src/webview/ExplorerView.ts b/src/webview/ExplorerView.ts
index fec3ed65..c3856f3c 100644
--- a/src/webview/ExplorerView.ts
+++ b/src/webview/ExplorerView.ts
@@ -1,5 +1,7 @@
-import { PanelSettings } from './../models/PanelSettings';
-import { CancellationToken, Disposable, Uri, Webview, WebviewView, WebviewViewProvider, WebviewViewResolveContext, window, workspace } from "vscode";
+import { SETTING_CUSTOM_SCRIPTS, SETTING_SEO_DESCRIPTION_FIELD } from './../constants/settings';
+import * as os from 'os';
+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";
@@ -7,6 +9,8 @@ import { CommandToCode } from '../viewpanel/CommandToCode';
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 {
@@ -54,8 +58,6 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
*/
public async resolveWebviewView(webviewView: WebviewView, context: WebviewViewResolveContext, token: CancellationToken): Promise {
- console.log(context);
-
this.panel = webviewView;
webviewView.webview.options = {
@@ -82,6 +84,9 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
case CommandToCode.updateDate:
Article.setDate();
break;
+ case CommandToCode.updateLastMod:
+ Article.setLastModifiedDate();
+ break;
case CommandToCode.publish:
Article.toggleDraft();
break;
@@ -97,6 +102,28 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
case CommandToCode.addCategoryToSettings:
this.addTags(TagType.categories, msg.data);
break;
+ case CommandToCode.openSettings:
+ commands.executeCommand('workbench.action.openSettings', '@ext:eliostruyf.vscode-front-matter');
+ break;
+ 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) {
+ const wsPath = wsFolders[0].uri.fsPath;
+ if (os.type() === "Darwin") {
+ exec(`open ${wsPath}`);
+ } else if (os.type() === "Windows_NT") {
+ exec(`explorer ${wsPath}`);
+ } else {
+ exec(`xdg-open ${wsPath}`);
+ }
+ }
+ break;
}
});
@@ -138,6 +165,48 @@ 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) {
+ const customScript = scripts.find((s: CustomScript) => s.title === msg.data.title);
+ if (customScript?.script && customScript?.title) {
+ const editor = window.activeTextEditor;
+ if (!editor) return;
+
+ const article = ArticleHelper.getFrontMatter(editor);
+
+ const wsFolders = workspace.workspaceFolders;
+ if (wsFolders && wsFolders.length > 0) {
+ const wsPath = wsFolders[0].uri.fsPath;
+
+ let articleData = `'${JSON.stringify(article?.data)}'`;
+ if (os.type() === "Windows_NT") {
+ articleData = `"${JSON.stringify(article?.data).replace(/"/g, `""`)}"`;
+ }
+
+ exec(`${customScript.nodeBin || "node"} ${path.join(wsPath, msg.data.script)} "${wsPath}" "${editor?.document.uri.fsPath}" ${articleData}`, (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
*/
@@ -149,7 +218,8 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
data: {
seo: {
title: config.get(SETTING_SEO_TITLE_LENGTH) as number || -1,
- description: config.get(SETTING_SEO_DESCRIPTION_LENGTH) as number || -1
+ description: config.get(SETTING_SEO_DESCRIPTION_LENGTH) as number || -1,
+ descriptionField: config.get(SETTING_SEO_DESCRIPTION_FIELD) as string || "description"
},
slug: {
prefix: config.get(SETTING_SLUG_PREFIX) || "",
@@ -157,7 +227,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
});
}
@@ -241,6 +312,7 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
const styleResetUri = webView.asWebviewUri(Uri.joinPath(this.extPath, 'assets/media', 'reset.css'));
const stylesUri = webView.asWebviewUri(Uri.joinPath(this.extPath, 'assets/media', 'styles.css'));
const scriptUri = webView.asWebviewUri(Uri.joinPath(this.extPath, 'dist', 'viewpanel.js'));
+ const codiconsUri = webView.asWebviewUri(Uri.joinPath(this.extPath, 'node_modules', '@vscode/codicons', 'dist', 'codicon.css'));
const nonce = this.getNonce();
return `
@@ -252,8 +324,9 @@ export class ExplorerView implements WebviewViewProvider, Disposable {
+
- FrontMatter
+ Front Matter