Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
@frontmatter/extensibility
Advanced tools
This module provides a way to extend the CMS its UI with custom functionality, and it provides helpers for creating your custom content or media scripts.
To make it easier to create your custom scripts, you can make use of the @frontmatter/extensibility
module its ContentScript
, MediaScript
, and PlaceholderScript
classes.
If you want to write a script for content management in Front Matter CMS, you can make use of the ContentScript
class. This class provides methods to retrieve the arguments, ask questions, and let the script know its done.
To retrieve all arguments, you can use the getArguments
method.
import { ContentScript } from '@frontmatter/extensibility';
const { command, scriptPath, workspacePath, filePath, frontMatter, answers } = ContentScript.getArguments();
To ask a question to the user in the CMS, you can use the askQuestions
method:
if (!answers) {
MediaScript.askQuestions([{
name: "customId",
message: "Which ID do you want to use?",
default: ""
}]);
return;
}
In case you want to have a multi-select question, you can just add the options to the question:
if (!answers) {
MediaScript.askQuestions([{
name: "category",
message: "Which category do you want to use?",
options: [
"Category 1",
"Category 2",
"Category 3"
]
}]);
return;
}
Important: Front Matter will execute the same script, so you first need to check if the answers were provided.
You can retrieve the answer from the answers
object:
const customId = answers.customId;
To let the CMS know you want to update the article its front matter, you can make use of the updateFrontMatter
method:
ContentScript.updateFrontMatter({
"field": "value"
});
To let the CMS know you want to open a file or page after the script is done, you can make use of the open
method:
// Open a URL
ContentScript.open("https://frontmatter.codes");
// Or open a file
ContentScript.open("./path/to/file.md");
To let the CMS know you are done with your script, you can make use of the done
method:
ContentScript.done("The script is done");
The MediaScript
class provides the same functionality as the ContentScript
class, but it is used for media management scripts. There are a couple differences:
frontMatter
object;updateFrontMatter
method.Additionally, they provide the following methods:
MediaScript.copyMetadata(source, destination)
: This method will copy the metadata from the source file to the destination file.MediaScript.copyMetadataAndDelete(source, destination)
; This method will copy the metadata from the source file to the destination file and delete the source file.MediaScript.delete(source)
: This method will delete the source file.The PlaceholderScript
class provides the same functionality as the ContentScript
class, but it is used for placeholders which can be used on content creation. The main difference between the ContentScript
and PlaceholderScript
is that it will not provide the frontMatter
object. Instead it returns the title
of the page.
Card extensibility points:
Extension version 9.0.0 and higher:
You can make use of ESM modules in order to make use of the extensibility dependency. We recommend to use the CDN from Skypack or jsdelivr.
URLs:
https://cdn.skypack.dev/@frontmatter/extensibility
https://cdn.jsdelivr.net/npm/@frontmatter/extensibility/+esm
https://esm.run/@frontmatter/extensibility
Turn on the development mode in order to quickly reload the webviews (panel + dashboard) when you make changes to the code.
import { enableDevelopmentMode } from "https://cdn.jsdelivr.net/npm/@frontmatter/extensibility/+esm";
enableDevelopmentMode();
import { registerCardImage } from "https://cdn.jsdelivr.net/npm/@frontmatter/extensibility/+esm";
/**
* @param {string} filePath - The path of the file
* @param {object} data - The metadata of the file
* @returns {string} - The HTML to be rendered in the card footer
*/
registerCardImage(async (filePath, metadata) => {
return `<span>Your HTML</span>`;
});
import { registerCardStatus } from "https://cdn.jsdelivr.net/npm/@frontmatter/extensibility/+esm";
/**
* @param {string} filePath - The path of the file
* @param {object} data - The metadata of the file
* @returns {string} - The HTML to be rendered in the card footer
*/
registerCardStatus(async (filePath, metadata) => {
return `<span>Your HTML</span>`;
});
import { registerCardDate } from "https://cdn.jsdelivr.net/npm/@frontmatter/extensibility/+esm";
/**
* @param {string} filePath - The path of the file
* @param {object} data - The metadata of the file
* @returns {string} - The HTML to be rendered in the card footer
*/
registerCardDate(async (filePath, metadata) => {
return `<span>Your HTML</span>`;
});
import { registerCardTitle } from "https://cdn.jsdelivr.net/npm/@frontmatter/extensibility/+esm";
/**
* @param {string} filePath - The path of the file
* @param {object} data - The metadata of the file
* @returns {string} - The HTML to be rendered in the card footer
*/
registerCardTitle(async (filePath, metadata) => {
return `<span>Your HTML</span>`;
});
import { registerCardDescription } from "https://cdn.jsdelivr.net/npm/@frontmatter/extensibility/+esm";
/**
* @param {string} filePath - The path of the file
* @param {object} data - The metadata of the file
* @returns {string} - The HTML to be rendered in the card footer
*/
registerCardDescription(async (filePath, metadata) => {
return `<span>Your HTML</span>`;
});
import { registerCardTags } from "https://cdn.jsdelivr.net/npm/@frontmatter/extensibility/+esm";
/**
* @param {string} filePath - The path of the file
* @param {object} data - The metadata of the file
* @returns {string} - The HTML to be rendered in the card footer
*/
registerCardTags(async (filePath, metadata) => {
return `<span>Your HTML</span>`;
});
import { registerCardFooter } from "https://cdn.jsdelivr.net/npm/@frontmatter/extensibility/+esm";
/**
* @param {string} filePath - The path of the file
* @param {object} data - The metadata of the file
* @returns {string} - The HTML to be rendered in the card footer
*/
registerCardFooter(async (filePath, metadata) => {
return `<span>Your HTML</span>`;
});
import { registerPanelView } from "https://cdn.jsdelivr.net/npm/@frontmatter/extensibility/+esm";
/**
* @param {object} data - The metadata of the file
* @returns {object} - The view to be rendered in the panel
*/
registerPanelView(async (metadata) => {
return {
title: "Custom View",
content: `
<div>
<h1>Custom view...</h1>
<p>Here you can add your own custom view.</p>
</div>
`,
};
});
The following example makes use of lit to render a custom field, by creating a web component, it makes it easier to have more control over the field.
import { registerCustomField } from "https://cdn.jsdelivr.net/npm/@frontmatter/extensibility/+esm";
import { css, html, LitElement } from "https://esm.run/lit";
let CustomFieldValueChange;
class CustomField extends LitElement {
static styles = css`
input {
border: 1px solid transparent;
box-sizing: border-box;
font-family: var(--vscode-font-family);
padding: var(--input-padding-vertical) var(--input-padding-horizontal);
color: var(--vscode-input-foreground);
outline: none;
background-color: var(--vscode-input-background);
width: 100%;
}
input:focus {
border: 1px solid var(--vscode-inputValidation-infoBorder);
}
`;
static properties = {
inputValue: {
type: String,
},
};
constructor() {
super();
this.inputValue = "";
}
_internalChange(e) {
this.inputValue = e.target.value;
CustomFieldValueChange(e.target.value);
}
render() {
return html`
<input
type="text"
value="${this.inputValue}"
@change=${(e) => this._internalChange(e)}
/>
`;
}
}
customElements.define("custom-field", CustomField);
/**
* @param {string} name - The name of the custom field to use in the content-type
* @param {function} callback - The callback that will be used for rendering the custom field
*/
registerCustomField("customField", async (value, onChange) => {
// Bind the event handler for the onChange evet
CustomFieldValueChange = onChange;
// Return the HTML of the custom field
return `
<custom-field inputValue="${value || ""}"></custom-field>
`;
});
Please report any issues you find in the Front Matter CMS issue list.
FAQs
Front Matter CMS extensibility library
The npm package @frontmatter/extensibility receives a total of 0 weekly downloads. As such, @frontmatter/extensibility popularity was classified as not popular.
We found that @frontmatter/extensibility demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.