From ee71934050fdd14658162a75922b4eafa1fdd059 Mon Sep 17 00:00:00 2001 From: mesanjeetk Date: Wed, 30 Sep 2026 09:36:00 +0530 Subject: [PATCH 1/8] docs: improve plugin development guides --- .vitepress/config.mts | 4 + bun.lock | 1 + docs/getting-started/create-plugin.md | 257 +++++++++---------- docs/getting-started/intro.md | 65 ++--- docs/getting-started/understanding-plugin.md | 5 + docs/utilities/fullscreen-orientation.md | 94 +++++++ 6 files changed, 244 insertions(+), 182 deletions(-) create mode 100644 docs/utilities/fullscreen-orientation.md diff --git a/.vitepress/config.mts b/.vitepress/config.mts index 8a40a56..4c9bcd5 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -244,6 +244,10 @@ export default defineConfig({ text: "Window Resize", link: "/docs/utilities/window-resize", }, + { + text: "Fullscreen and Orientation", + link: "/docs/utilities/fullscreen-orientation", + }, ], }, { diff --git a/bun.lock b/bun.lock index cc70825..536a06b 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "acode-plugin-docs", diff --git a/docs/getting-started/create-plugin.md b/docs/getting-started/create-plugin.md index f972f93..d9863c4 100644 --- a/docs/getting-started/create-plugin.md +++ b/docs/getting-started/create-plugin.md @@ -1,201 +1,182 @@ --- lang: en-US -title: Create Acode Plugin +title: Create an Acode Plugin +description: Set up a plugin project from a template, run it on your phone, and publish it. --- -# Create Acode Plugin +# Create an Acode Plugin -## Overview +Plugins are written in JavaScript (or TypeScript) and run inside Acode. This page takes you from an empty folder to a plugin installed on your device and, when you are ready, published. -Acode opens up a world of possibilities with its extensibility through plugins. In this guide, you'll learn how to create plugins using JavaScript, with the added option of TypeScript. Whether you're customizing your coding experience or adding entirely new features, creating plugins for Acode is a straightforward and rewarding process. - -## Plugin Structure - -Acode plugins follow a specific structure within a zip file. The necessary components include: - -1. **plugin.json:** - - - Contains crucial information about the plugin, such as its name, version, author, and more. - -2. **main.js:** - - - The heart of the plugin, this file contains the actual plugin code. +::: tip New to plugins? +Read [Understanding Plugins](./understanding-plugin.md) after this page. It explains how Acode loads and runs your code. +::: -3. **readme.md:** - - Contains the description or about plugin +## Plugin structure -3. **changelogs.md:** - - contains changelogs of your plugin updates. +A plugin is a zip file with these files at its root: -## Plugin Templates +| File | Required | Purpose | +| --- | --- | --- | +| `plugin.json` | Yes | The [manifest](../plugin-essentials/manifest.md): id, name, version and more. | +| `main.js` | Yes | The [core file](../plugin-essentials/core-file.md) with your plugin code. Its name and location are set by `main` in the manifest. | +| `readme.md` | Recommended | Description shown in the plugin store. | +| `icon.png` | Recommended | Icon shown in the plugin store (50 KB or smaller). | +| `changelogs.md` | No | Release notes. Also list it in `files` in the manifest. | -To make your journey smoother, we provide comprehensive plugin templates, which are preconfigured and catering to various use cases: +## Templates -1. **[JavaScript Template](https://github.com/Acode-Foundation/acode-plugin)** : Javascript based template for plugin development and comes preconfigured +Start from one of the official templates. Both come preconfigured with a bundler and build script that creates the zip for you. -2. **[TypeScript Template](https://github.com/Acode-Foundation/AcodeTSTemplate)** : Typescript template for plugin development and comes with type checking and all typescript feature +| Template | Use it when | +| --- | --- | +| [JavaScript template](https://github.com/Acode-Foundation/acode-plugin) | You want the simplest setup. | +| [TypeScript template](https://github.com/Acode-Foundation/AcodeTSTemplate) | You want type checking and editor autocomplete for the Acode API. | -## Getting Started +You can also start from scratch or use a different bundler. The only hard requirement is a zip with `plugin.json` and the file named by `main` at its root. -1. **Clone the Plugin Template:** +## Set up the project - - Choose the template that suits your needs and clone it. +### 1. Clone a template -2. **Customize plugin.json:** +```sh +git clone https://github.com/Acode-Foundation/acode-plugin.git my-plugin +cd my-plugin +``` - - Open the `plugin.json` file and update it with your plugin's information. +Replace the URL with the TypeScript template if you prefer it. -3. **Install the dependency:** +### 2. Edit `plugin.json` - - Install the required dependency by your package manager but first navigate to the plugin template folder by `cd acode-template` +Set at least a unique `id`, a `name` and a `version`. Every field is explained in the [manifest reference](../plugin-essentials/manifest.md). - ::: code-group - ```sh [npm] - $ npm install - ``` +### 3. Install dependencies - ```sh [pnpm] - $ pnpm install - ``` +::: code-group +```sh [npm] +$ npm install +``` - ```sh [yarn] - $ yarn install - ``` +```sh [pnpm] +$ pnpm install +``` - ```sh [bun] - $ bun install - ``` - ::: +```sh [yarn] +$ yarn install +``` -4. **Develop Locally:** +```sh [bun] +$ bun install +``` +::: - - Use given commands to initiate a development server that watches for changes. - - The development server automatically creates a plugin zip file, ready for installation. - - ::: code-group - ```sh [npm] - $ npm run dev - ``` +### 4. Start the development server - ```sh [pnpm] - $ pnpm dev - ``` +::: code-group +```sh [npm] +$ npm run dev +``` - ```sh [yarn] - $ yarn dev - ``` +```sh [pnpm] +$ pnpm dev +``` - ```sh [bun] - $ bun run dev - ``` - ::: +```sh [yarn] +$ yarn dev +``` - - Or you can build every time manually on changes using(this will build production build): +```sh [bun] +$ bun run dev +``` +::: - ::: code-group - ```sh [npm] - $ npm run build - ``` +The server watches your files and rebuilds the plugin zip whenever you save a change. - ```sh [pnpm] - $ pnpm build - ``` +::: info +The server only rebuilds on file changes. If you start it and change nothing, no zip is created yet. +::: - ```sh [yarn] - $ yarn build - ``` +If you prefer to build by hand, run the production build instead. It creates a smaller zip: - ```sh [bun] - $ bun run build - ``` - ::: +::: code-group +```sh [npm] +$ npm run build +``` -5. **Install the Plugin:** +```sh [pnpm] +$ pnpm build +``` - - Use the **REMOTE** option in Acode's plugin manager. - - This option is available on both sidebar extension tab or on Plugin page from settings. - - Provide the plugin URL (e.g., `http://\:3000/dist.zip`) when prompted. - - Or if you are building manually then you can use the **Local** option in Acode's plugin manager and select the plugin zip +```sh [yarn] +$ yarn build +``` -:::info -Development server will only build the zip on file changes +```sh [bun] +$ bun run build +``` ::: -:::tip -For local development, start a dev server using `npm run dev`. In Acode, use the **Remote** option, either from the **sidebar** or the **plugin page**. Enter the server URL, hit **Install**, and the plugin will be installed. +### 5. Install the plugin in Acode -It's more convenient to manage this from the sidebar. When you install a local plugin(either using url or selecting the zip), Acode will add a **reload** icon in the **Extensions** tab of the sidebar. This is useful because the server automatically builds the plugin ZIP when changes are made. Simply press the reload button to apply the latest changes instantly. +Open Acode's plugin manager from either the **Extensions** tab in the sidebar or **Settings → Plugins**, then pick an install source: -This makes plugin development a much smoother experience—previously, it was quite frustrating, but this feature was recently added to improve the workflow. -::: +- **Remote**: enter the URL of the zip served by your dev server, for example `http://:3000/dist.zip`. Use this while developing. +- **Local**: choose a zip file on your device. Use this if you built by hand. -## Creating Plugins with the CLI +::: tip Reload without reinstalling +Plugins installed from a URL or a local zip get a **reload** icon in the **Extensions** tab of the sidebar. After the dev server rebuilds the zip, tap reload to load the new version immediately. +::: -You can also quickly scaffold new Acode plugins using the [Acode Plugin CLI](https://github.com/itsvks19/acode-plugin-cli). This tool provides an interactive wizard to generate a plugin project from the official JavaScript or TypeScript templates. +## Create a plugin with the CLI -### Installation +The community-maintained [Acode Plugin CLI](https://github.com/itsvks19/acode-plugin-cli) scaffolds a project from the official templates with an interactive wizard. -If you have Rust installed, you can install the CLI with: +Install it (requires [Rust](https://www.rust-lang.org/tools/install)): -```bash -cargo install acode-plugin-cli +```sh +$ cargo install acode-plugin-cli ``` -### Usage +Run it: -Run the CLI in your terminal: - -```bash -acode-plugin-cli +```sh +$ acode-plugin-cli ``` -The wizard will guide you to: - -- Choose plugin name, ID, version, and description -- Enter author information -- Pick license and keywords -- Select JavaScript or TypeScript template - -After completion, your plugin folder will be ready to use. - -## Building and Publishing +The wizard asks for the plugin name, id, version and description, author details, license and keywords, and whether to use the JavaScript or TypeScript template. When it finishes, the project is ready to use. -To share your plugin with the Acode community, follow these steps: +## Build and publish -1. **Bundle for production:** - - - Use `build` command to create a production build. which will be lower in size +1. **Create a production build.** It is smaller than the development build. ::: code-group + ```sh [npm] + $ npm run build + ``` - ```sh [npm] - $ npm run build - ``` - - ```sh [pnpm] - $ pnpm build - ``` - - ```sh [yarn] - $ yarn build - ``` - - ```sh [bun] - $ bun run build - ``` + ```sh [pnpm] + $ pnpm build + ``` -2. **Publish:** + ```sh [yarn] + $ yarn build + ``` - - Publish your release build on [Acode's](https://acode.app) official website, making your plugin accessible to the broader community. + ```sh [bun] + $ bun run build + ``` + ::: - - Tutorial for publishing a plugin : [Youtube](https://youtube.com/shorts/cxF2pxyN1HM?si=kQ5_BRtIO2RU-zhb) +2. **Upload the zip** to [acode.app](https://acode.app) to publish it in the plugin store. Watch the [publishing walkthrough](https://youtube.com/shorts/cxF2pxyN1HM?si=kQ5_BRtIO2RU-zhb) if you have not done it before. -## Tutorial +To release an update, increase `version` in `plugin.json`, build again and upload the new zip. See [Publishing updates](../plugin-essentials/manifest.md#publishing-updates). -- Checkout a small tutorial of 👉 [How to create Acode Plugins?](https://youtu.be/ls--txHX3RQ?si=ZSvJMsb1KFeQA8zd) +## Video tutorial -## Customization +[How to create Acode plugins](https://youtu.be/ls--txHX3RQ?si=ZSvJMsb1KFeQA8zd) -Certainly! You have the flexibility to either utilize your own template or start your plugin from scratch. Additionally, you're free to employ alternative bundlers and tools. We'll delve deeper into these customization possibilities in subsequent sections. +## Next steps -Happy coding, and may your plugins bring new dimensions to your Acode experience! 🚀✨ +- [Understanding Plugins](./understanding-plugin.md): the lifecycle of a plugin +- [Core File](../plugin-essentials/core-file.md): what `main.js` must contain +- [Acode API](../global-apis/acode.md): the API your plugin talks to diff --git a/docs/getting-started/intro.md b/docs/getting-started/intro.md index c160722..d36d995 100644 --- a/docs/getting-started/intro.md +++ b/docs/getting-started/intro.md @@ -1,59 +1,36 @@ --- lang: en-US title: Acode Plugins +description: What Acode plugins are, how to install them, and where to go to build your own. --- -# Acode Plugins - -> Welcome to the world of Acode plugins! 🚀 - - -### What are Acode Plugins? - -**Acode** plugins serve as powerful tools to enhance and extend the functionality of your **Acode editor**. Whether you're looking to introduce new features or tweak existing ones, plugins provide a flexible and customizable way to tailor Acode to your specific needs. - -### Language Flexibility - -Acode plugins are primarily written in JavaScript, offering a familiar and widely-used language for developers. Additionally, for those who prefer TypeScript, **good news 🥳** — Acode supports `TypeScript` for plugin development, providing the benefits of static typing and improved developer experience. -## Installing Acode Plugins - -Discovering and integrating plugins into your Acode editor is a simple and customizable process. There are multiple methods to install plugins, ensuring flexibility and convenience for developers. Before you proceed, it's essential to exercise caution when installing plugins from unknown sources, as they may potentially contain malicious code. - -### Installation Methods: - -1. **Local Installation:** - - Download the plugin file(`.zip`) to your device. - - Open Acode and navigate to **Settings**. - - Click on **Plugins** and then the `'+'` icon. - - Select **LOCAL** and choose the downloaded plugin file. +# Acode Plugins -2. **Remote Installation:** - - If you have a plugin file URL (e.g., a plugin file hosted on GitHub): - - Open Acode and go to **Settings**. - - Navigate to **Plugins** and click on the `'+'` icon. - - Choose **REMOTE** and enter the plugin file URL. +Plugins extend the Acode editor: add commands, themes, languages, formatters, sidebar panels and more, or change how existing features behave. -3. **Acode Plugins Manager:** - - Access the Acode **Settings** and click on **Plugins**. - - Explore the available plugins and select the one you want. - - Click on **Install** to seamlessly integrate the chosen plugin into your Acode editor. +Plugins are written in **JavaScript**. **TypeScript** is supported too, and the [official TypeScript template](./create-plugin.md#templates) gives you type checking for the Acode API. -4. **Acode SideBar:** - - Click on three horizontal slashes from top left corner - - Select plugin icon and Explore the plugins +## Install a plugin +Open the plugin manager from **Settings → Plugins**, or from the **Extensions** tab of the sidebar (open the sidebar with the menu button at the top left). Then pick one of these ways to install: -:::info +| Method | Steps | +| --- | --- | +| **From the store** | Browse the list, choose a plugin and tap **Install**. | +| **Local file** | Download the plugin `.zip` to your device. Tap **+**, choose **LOCAL** and select the file. | +| **Remote URL** | Tap **+**, choose **REMOTE** and enter the URL of the plugin `.zip`, for example one hosted on GitHub. | -**Source Persistence:** -Once installed, plugins remember their source. If you choose to uninstall and reinstall, the plugin will be sourced from the same location, ensuring consistency in your development environment. +::: info Source persistence +Acode remembers where a plugin was installed from. If you uninstall and reinstall it, it is fetched from the same source again. ::: -:::danger - -**Exercise Caution:** -It's crucial to exercise caution when installing plugins, especially from unfamiliar sources. Plugins have the potential to contain malicious code, so be discerning and opt for reputable and well-known plugins whenever possible. +::: danger Only install plugins you trust +A plugin runs inside Acode with access to your files and the editor. Install plugins from reputable authors, and be careful with `.zip` files and URLs from unknown sources. ::: -
-Your Acode journey has just begun. Dive in, experiment, and let your coding adventure flourish in this realm of endless possibilities! 🚀✨ +## Build your own + +1. [Create a plugin](./create-plugin.md): set up a project from a template and run it on your device. +2. [Understanding Plugins](./understanding-plugin.md): how Acode loads and unloads plugin code. +3. [Manifest](../plugin-essentials/manifest.md) and [Core File](../plugin-essentials/core-file.md): the two files every plugin needs. +4. [Acode API](../global-apis/acode.md): what your plugin can use. diff --git a/docs/getting-started/understanding-plugin.md b/docs/getting-started/understanding-plugin.md index 15e3396..4f3c8e3 100644 --- a/docs/getting-started/understanding-plugin.md +++ b/docs/getting-started/understanding-plugin.md @@ -1,3 +1,8 @@ +--- +title: Understanding Plugins +description: How Acode loads, runs and unloads a plugin. +--- + # Understanding How Plugins Work This page is the practical mental model for writing Acode plugins: what Acode does, what your plugin must do, and what happens during load/unload. diff --git a/docs/utilities/fullscreen-orientation.md b/docs/utilities/fullscreen-orientation.md new file mode 100644 index 0000000..f520170 --- /dev/null +++ b/docs/utilities/fullscreen-orientation.md @@ -0,0 +1,94 @@ +--- +title: Fullscreen and Orientation +description: Handle the Android Back button and lock screen orientation while an element is fullscreen. +--- + +# Fullscreen and Orientation + +Two small modules help plugins that show content in the browser's **fullscreen mode** (for example a video, canvas or game): + +- `fullscreen` decides what the Android **Back** button does while something is fullscreen. +- `orientation` temporarily locks the screen to portrait or landscape during that session. + +```js +const fullscreen = acode.require("fullscreen"); +const orientation = acode.require("orientation"); +``` + +Neither module enters fullscreen for you. Call the standard `element.requestFullscreen()` first. + +## `fullscreen.setBackHandler(callback)` + +By default, Back exits fullscreen. Claim Back to run your own code instead, or release it by passing `null`. + +```ts +fullscreen.setBackHandler(callback: (() => void | Promise) | null): Promise +``` + +- `callback` runs when the user presses Back. It must call `document.exitFullscreen()` itself if you want to leave fullscreen. Acode will not do it for you. +- If `callback` throws or its promise rejects, Acode exits fullscreen so the user is never stuck. +- `null` releases Back, restoring the default behavior. +- The returned promise resolves when the native side has accepted the change. + +**Rules** + +- A callback can only be set **while an element is fullscreen**. Otherwise the promise rejects with `Back handler requires fullscreen.` +- The handler belongs to the current fullscreen session. When the fullscreen element changes or fullscreen ends, it is released automatically. Set it again for the next session. +- Passing anything other than a function or `null` throws a `TypeError`. + +```js +await video.requestFullscreen(); + +await fullscreen.setBackHandler(async () => { + if (isPlayerMenuOpen()) { + closePlayerMenu(); // first Back closes the menu + } else { + await document.exitFullscreen(); // second Back leaves fullscreen + } +}); +``` + +## `orientation.lock(mode)` + +Locks the screen orientation for the current fullscreen session. + +```ts +orientation.lock(mode: "landscape" | "portrait"): Promise +``` + +Any other `mode` throws a `TypeError`. The promise rejects with an `Error` if the native request fails. + +## `orientation.unlock()` + +Restores the orientation policy that was in effect before `lock`. + +```ts +orientation.unlock(): Promise +``` + +Always unlock when you leave fullscreen, or the screen may stay locked. + +## Example: landscape video player + +```js +async function enterPlayer(video) { + await video.requestFullscreen(); + await orientation.lock("landscape"); + await fullscreen.setBackHandler(exitPlayer); +} + +async function exitPlayer() { + await orientation.unlock(); + await fullscreen.setBackHandler(null); + await document.exitFullscreen(); +} + +document.addEventListener("fullscreenchange", () => { + // Also covers the user leaving fullscreen by other means + if (!document.fullscreenElement) orientation.unlock().catch(() => {}); +}); +``` + +::: tip +Wrap the calls in `try`/`catch`. They can fail if the WebView refuses the fullscreen request or the fullscreen session ends while a request is in flight. +::: From 42f85a938b59b8aee119043c318d623b0401a034 Mon Sep 17 00:00:00 2001 From: mesanjeetk Date: Wed, 30 Sep 2026 10:02:47 +0530 Subject: [PATCH 2/8] docs: update plugin documentation with improved structure and descriptions --- docs/plugin-essentials/core-file.md | 175 +++++++++-------- docs/plugin-essentials/manifest.md | 238 +++++++++++++++-------- docs/plugin-essentials/plugin-context.md | 5 + 3 files changed, 255 insertions(+), 163 deletions(-) diff --git a/docs/plugin-essentials/core-file.md b/docs/plugin-essentials/core-file.md index fb7a6d3..783e9f5 100644 --- a/docs/plugin-essentials/core-file.md +++ b/docs/plugin-essentials/core-file.md @@ -1,114 +1,125 @@ -# Plugin Main File +--- +title: Core File (main.js) +description: The entry point of a plugin - how to register init and unmount handlers. +--- -The `main.js`(can be of any name but that must be specified in `plugin.json`) file is the heart of your Acode plugin, serving as the entry point and execution hub when the plugin is loaded. Here we'll explore the essential concept of `main.js`, focusing on initialization, registration, and cleanup. +# Core File: `main.js` -For loader behavior and runtime lifecycle details, see [Understanding Plugin Lifecycle](../getting-started/understanding-plugin.md). +The core file is the script Acode runs when your plugin loads. It can have any name and location, as long as `plugin.json` points to it with the [`main`](./manifest.md#main) field. -## Plugin Initialization +It has two jobs: -### Entry Point for Your Plugin +1. **Register** an `init` function that starts your plugin. +2. **Register** an `unmount` function that undoes everything `init` did. -The `main.js` file acts as the entry point for your Acode plugin. It is executed upon loading, providing the ideal space to initialize and configure your plugin. +For when and how Acode calls them, see [Understanding Plugins](../getting-started/understanding-plugin.md). -### Access to Acode API +::: tip You rarely write this by hand +The [official templates](../getting-started/create-plugin.md#templates) already contain the registration code below. You only fill in the `init` and `destroy` methods of the `AcodePlugin` class. +::: + +## Register the plugin + +Your script has access to the global [`acode`](../global-apis/acode.md) object. Register the init function with `acode.setPluginInit`: + +```js +acode.setPluginInit(pluginId, init, settings?) +``` -Within `main.js`, you gain access to the Acode API through the global variable [acode](../global-apis/acode). This variable serves as your gateway to interact with various Acode methods, enabling seamless integration of your plugin with the editor. +| Parameter | Description | +| --- | --- | +| `pluginId` | The `id` from your `plugin.json`. | +| `init` | Function Acode calls to start the plugin. | +| `settings` | Optional. Adds a settings page for your plugin. See [Plugin settings](../global-apis/acode.md#plugin-settings). | -### Registering Your Plugin +### `init` arguments -To register your plugin, utilize the `acode.setPluginInit(pluginId: string, init: Function)` method. This method requires two parameters: +`init` receives three arguments: -1. **pluginId:** - - The unique identifier for your plugin. +| Argument | Type | Description | +| --- | --- | --- | +| `baseUrl` | `string` | URL of your plugin folder, for loading bundled files. | +| `$page` | [`Page`](../editor-components/page.md) | A blank page for your UI. Call `$page.show()` to open it. | +| `options` | `object` | Extra information, described below. | -2. **init function:** - - The function to be executed when the plugin is loaded. +`options` contains: -Upon execution, the `init` function will receive three arguments: +| Property | Description | +| --- | --- | +| `cacheFileUrl` | URL of your plugin's cache file. | +| `cacheFile` | File object for the cache file, so you can read and write it. | +| `firstInit` | `true` only on the run right after installation. | +| `ctx` | Encrypted secret storage and permission checks. See [Plugin Context](./plugin-context.md). | +| `fileIcons` | Plugin-bound [File Icons](../utilities/file-icons.md) API. Available from versionCode `1012`. | -- **baseUrl (string):** - - The base URL of the plugin, allowing access to files within the plugin directory. +Every property is documented in more detail under [`acode.setPluginInit`](../global-apis/acode.md#init-arguments). -- **$page (WcPage):** - - A page object that facilitates the display of content within Acode. +## Register the unmount handler -- **cache (object):** - - An object providing access to cached files, including: - - **cacheFileUrl (string):** - - URL of the cached file. - - **cacheFile (File):** - - File object of the cached file, enabling file read/write operations. - - **firstInit (boolean):** - - `true` when the plugin is being installed/loaded for the first time. - - **ctx (PluginContext):** - - Your plugin's native context. Provides encrypted secret storage (`getSecret`, `setSecret`, `deleteSecret`, `clearAllSecrets`) and permission checks (`grantedPermission`, `listAllPermissions`). See [Plugin Context (`ctx`)](./plugin-context.md). - - **fileIcons:** - - Plugin-bound [File Icons](../utilities/file-icons.md) API (`register`, `icon`, `onChange`). Same instance as `acode.require("fileIcons")` captured in the main script. Available from **versionCode `1012`**. +```js +acode.setPluginUnmount(pluginId, unmount) +``` + +Acode calls `unmount` when the plugin is disabled, uninstalled or reloaded. Use it to remove everything you added: commands, event listeners, timers, UI elements and formatters. Anything left behind stays active until Acode restarts. -### Example main.js File +::: warning +Do not skip this. A plugin that does not clean up will leave duplicate commands and listeners behind every time it is reloaded during development. +::: -The official templates structure the plugin as an `AcodePlugin` class. Here is an illustrative example of a `main.js` file: +## Full example -```javascript +This is the shape used by the official templates: + +```js import plugin from "../plugin.json"; class AcodePlugin { - baseUrl = ""; - - async init($page, cacheFile, cacheFileUrl, firstInit, ctx, fileIcons) { - const commands = acode.require("commands"); - commands.addCommand({ - name: "example-plugin", - bindKey: { win: "Ctrl-Alt-E", mac: "Command-Alt-E" }, - exec: () => { - $page.innerHTML = ` + baseUrl = ""; + + async init($page, cacheFile, cacheFileUrl, firstInit, ctx, fileIcons) { + const commands = acode.require("commands"); + + commands.addCommand({ + name: "example-plugin", + description: "Open the example plugin", + bindKey: { win: "Ctrl-Alt-E", mac: "Command-Alt-E" }, + exec: () => { + $page.innerHTML = `

Example Plugin

This is an example plugin.

`; - $page.show(); - }, - }); - } - - async destroy() { - const commands = acode.require("commands"); - commands.removeCommand("example-plugin"); - } + $page.show(); + }, + }); + } + + async destroy() { + const commands = acode.require("commands"); + commands.removeCommand("example-plugin"); + } } if (window.acode) { - const acodePlugin = new AcodePlugin(); - - acode.setPluginInit(plugin.id, async (baseUrl, $page, { cacheFileUrl, cacheFile, firstInit, ctx, fileIcons }) => { - acodePlugin.baseUrl = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`; - await acodePlugin.init($page, cacheFile, cacheFileUrl, firstInit, ctx, fileIcons); - }); - - acode.setPluginUnmount(plugin.id, () => { - acodePlugin.destroy(); - }); + const acodePlugin = new AcodePlugin(); + + acode.setPluginInit( + plugin.id, + async (baseUrl, $page, { cacheFileUrl, cacheFile, firstInit, ctx, fileIcons }) => { + // Make sure baseUrl ends with "/" so you can append file names to it + acodePlugin.baseUrl = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`; + await acodePlugin.init($page, cacheFile, cacheFileUrl, firstInit, ctx, fileIcons); + }, + ); + + acode.setPluginUnmount(plugin.id, () => { + acodePlugin.destroy(); + }); } ``` -## Plugin Unmount Function - -The `main.js` file must also define cleanup logic, which is called when the plugin is unloaded or uninstalled. This cleanup allows you to remove listeners, commands, intervals, and UI hooks associated with your plugin. In the class template this lives in the `destroy()` method, registered via `acode.setPluginUnmount`. - -### Example Unmount Function - -```javascript -acode.setPluginUnmount(plugin.id, () => { - const commands = acode.require("commands"); - commands.removeCommand('example-plugin'); -}); -``` - -In this example, the unmount function removes the 'example-plugin' command, ensuring that the plugin's impact on Acode is cleanly reverted upon unloading. +The `if (window.acode)` check lets the same bundle be loaded outside Acode (for example in tests) without throwing. -::: tip -For command registration APIs, see [Commands](../utilities/commands.md). -::: +## Related -:::tip -You will not need to write these `init`/`destroy` registration functions for your plugin because the templates ship with them. You only need to write your plugin code inside the `AcodePlugin` class. -::: +- [Commands](../utilities/commands.md): register editor commands +- [Understanding Plugins](../getting-started/understanding-plugin.md): lifecycle details diff --git a/docs/plugin-essentials/manifest.md b/docs/plugin-essentials/manifest.md index 1061282..57aedd6 100644 --- a/docs/plugin-essentials/manifest.md +++ b/docs/plugin-essentials/manifest.md @@ -1,112 +1,188 @@ -# Manifesto - `plugin.json` +--- +title: Manifest (plugin.json) +description: Every field of plugin.json, which are required, and how Acode reads them. +--- + +# Manifest: `plugin.json` + +Every plugin has a `plugin.json` file at the root of its zip. It tells Acode and the plugin store who your plugin is, which file to run, and which files to ship. + +## Quick reference + +| Field | Type | Required | Summary | +| --- | --- | --- | --- | +| [`id`](#id) | `string` | Yes | Unique plugin identifier. | +| [`name`](#name) | `string` | Yes | Display name. | +| [`version`](#version) | `string` | Yes | Version of this release. | +| [`main`](#main) | `string` | Yes | Path of the script Acode runs. | +| [`minVersionCode`](#minversioncode) | `number` | Recommended | Oldest Acode build that can run it. | +| [`author`](#author) | `object` | Recommended | Who made the plugin. | +| [`readme`](#readme) | `string` | Recommended | Path of the store description. | +| [`icon`](#icon) | `string` | Recommended | Path of the store icon. | +| [`files`](#files) | `string[]` | No | Extra files to include. | +| [`dependencies`](#dependencies) | `string[]` | No | Plugins to install first. | +| [`price`](#price) | `number` | No | Price in INR. `0` is free. | +| [`license`](#license) | `string` | No | License name. | +| [`keywords`](#keywords) | `string[]` | No | Search terms. | +| [`changelogs`](#changelogs) | `string` | No | Path of the changelog. | +| [`contributors`](#contributors) | `object[]` | No | People who contributed. | +| [`repository`](#repository) | `string` | No | Source code URL (free plugins only). | + +## Example -The `plugin.json` file is a crucial component of every Acode plugin, serving as a manifest file that provides essential information about the plugin. This file is required for the proper functioning and identification of your plugin within the Acode ecosystem. Let's delve into the details of the `plugin.json` structure and its key attributes. +```json [plugin.json] +{ + "id": "com.example.plugin", + "name": "Example Plugin", + "version": "1.0.0", + "main": "dist/main.js", + "readme": "readme.md", + "icon": "icon.png", + "files": ["worker.js"], + "minVersionCode": 292, + "price": 0, + "license": "MIT", + "keywords": ["example", "starter"], + "changelogs": "changelogs.md", + "author": { + "name": "Example Author", + "email": "example@email.com", + "url": "https://example.com", + "github": "example" + } +} +``` -# Attributes in plugin.json: +## Required fields -## 1. **id:** - - Unique identifier for the plugin, following the reverse domain name format or what ever you want *(e.g., "com.example.plugin")*. +### `id` -## 2. **name:** - - Descriptive name of the plugin. +Unique identifier of the plugin. The reverse-domain style (`com.example.plugin`) is recommended because it avoids clashes, but any unique string works. -## 3. **main:** - - Path to the bundled `main.js` file or your plugin's main javascript file, which contains the actual code for the plugin. +This is the same id you pass to [`acode.setPluginInit`](../global-apis/acode.md#setplugininit-pluginid-init-settings) and [`acode.setPluginUnmount`](../global-apis/acode.md#setpluginunmount-pluginid-unmount). -## 4. **version:** - - Version number of the plugin. Must be incremented for updates. +::: warning +Changing the `id` creates a **different plugin**. Users of the old one will not receive it as an update. +::: -## 5. **readme:** - - Path to the `readme.md` file, providing documentation and information about the plugin. +### `name` -## 6. **icon:** - - Path to the `icon.png` file, serving as the visual representation of the plugin. +Display name shown in the plugin list and store. - :::info - Icon file size must less than or equal to **50Kb** - ::: +### `version` -## 7. **files:** - - An array listing the files to be included in the plugin zip file. +Version of this release, for example `1.2.0`. Acode compares this with the store's version to decide whether an update is available, so **increase it for every release**. -## 8. **minVersionCode:** - - Minimum Acode version code required to run the plugin. The plugin will be available only for Acode versions greater than or equal to the specified code. - :::info - You can simply use `290`, as this option became available in that version. If you are using the latest Acode plugin API, specify the corresponding version. - ::: +### `main` +Path, inside the zip, of the script Acode loads when the plugin starts. This is usually your bundled output (for example `dist/main.js`). See [Core File](./core-file.md) for what it must contain. -## 9. **price:** - - Price of the plugin in INR (Indian Rupees). If set to 0 or omitted, the plugin is free. This attribute allows for monetization of plugins with a defined price range. +## Recommended fields - :::info - Price should be between INR 0 to 10,000 - ::: +### `author` -## 10. **author:** - - Details about the plugin author, including name, email, URL, and GitHub username. +An object describing the author. -## 11. **license:** - - Name of the license under which the plugin is released. +| Key | Description | +| --- | --- | +| `name` | Author name. | +| `email` | Contact email. | +| `url` | Website. | +| `github` | GitHub username. | -## 12. **keywords:** - - An array of strings providing searchable terms related to the plugin. +### `minVersionCode` -## 13. **changelogs:** - - Path to the changelog file documenting version updates and modifications. +The oldest Acode **version code** that can run the plugin. Older builds do not offer it. - ::: warning - Make sure to include `changelogs.md` or whatever you named it, in the plugin zip. - ::: +Use the version code of the newest API your plugin needs. If it uses nothing recent, `290` is a safe floor because the field itself was introduced then. Pages in these docs mark newer APIs with badges such as `v954+`; use that number. -## 14. **contributors:** - - An array of objects containing details about project contributors. - - Each object requires: - - `name`: Contributor's name - - `role`: Their role in the project - - `github`: Their GitHub username +### `readme` -## 15. **repository:** - - Github/Gitlab url of your plugin source(only for free plugins) +Path of a Markdown file shown as the plugin's description in the store. -# Updating Plugins: +### `icon` -If you wish to publish an update for your plugin, follow these guidelines: +Path of a PNG shown as the plugin's icon. -- **Version Increment:** - - Increase the version number in the `plugin.json` file. +::: info +The icon must be **50 KB or smaller**. +::: -- **Update Information:** - - For changes in name, description, icon, etc., upload a new zip file containing the updated `plugin.json`. +## Optional fields -- **Price Modification:** - - If altering the plugin's price, update the `price` attribute in the `plugin.json` file and upload the new zip file. +### `files` -## Example plugin.json: +Extra files your plugin needs at runtime besides `main`, `readme` and `icon`: for example a web worker, fonts or images. List every one so it ends up in the zip, then load it through `baseUrl`. -::: code-group -```json [plugin.json] -{ - "id": "com.example.plugin", - "name": "Example Plugin", - "main": "dist/main.js", - "version": "1.0.0", - "readme": "readme.md", - "icon": "icon.png", - "files": ["worker.js"], - "minVersionCode": 292, - "price": 0, - "license": "MIT", - "keywords": ["foo","bar"], - "changelogs": "changelogs.md", - "author": { - "name": "Example Author", - "email": "example@email.com", - "url": "https://example.com", - "github": "example" - } -} +```json +"files": ["worker.js", "fonts/Mono.woff2", "images/logo.png"] +``` + +### `dependencies` + +Ids of other plugins that must be installed first. + +```json +"dependencies": ["com.example.core", "com.example.themes"] ``` + +When a user installs your plugin, Acode looks each id up in the store, lists the ones that are missing or outdated, and asks for confirmation. If the user agrees, they are installed before your plugin. Dependencies of dependencies are resolved too. + +::: warning +Installation fails if an id does not exist in the store. Use exact ids of published plugins. ::: -This example illustrates a basic `plugin.json` file. +### `price` + +Price in Indian Rupees (INR). `0` or omitted means free. The allowed range is **0 to 10,000**. + +### `license` + +Name of the license, for example `MIT` or `GPL-3.0`. + +### `keywords` + +Search terms that help people find the plugin. + +### `changelogs` + +Path of a Markdown changelog. + +::: warning +The file must be listed in [`files`](#files), or it will not be in the zip. +::: + +### `contributors` + +People who helped build the plugin. Each entry needs: + +| Key | Description | +| --- | --- | +| `name` | Contributor's name. | +| `role` | What they did. | +| `github` | GitHub username. | + +### `repository` + +URL of the source code on GitHub or GitLab. Only available for **free** plugins. + +## How Acode reads the file + +When installing, Acode checks the manifest against the zip: + +- `plugin.json` must exist at the **root** of the zip, or the plugin is rejected as invalid. +- If `main` is missing or points to a file that is not in the zip, Acode falls back to `main.js`. If that is missing too, installation fails. +- If `icon` or `readme` is missing or does not exist in the zip, Acode falls back to `icon.png` and `readme.md`. + +So a typo in `main` does not always fail loudly. Check that the path matches a real file. + +## Publishing updates + +1. Increase `version`. +2. Make your changes, including any to `name`, `icon`, `readme` or `price`. +3. Build a new zip that contains the updated `plugin.json`, and upload it. + +## Related + +- [Core File](./core-file.md) +- [Create a plugin](../getting-started/create-plugin.md) diff --git a/docs/plugin-essentials/plugin-context.md b/docs/plugin-essentials/plugin-context.md index 61c44d0..a7280c5 100644 --- a/docs/plugin-essentials/plugin-context.md +++ b/docs/plugin-essentials/plugin-context.md @@ -1,3 +1,8 @@ +--- +title: Plugin Context (ctx) +description: Encrypted secret storage and permission checks for your plugin. +--- + # Plugin Context (`ctx`) The plugin context (`ctx`) is the third argument of the options object passed to your plugin's `init` function. It is a native-backed handle for your plugin that provides **encrypted secret storage** and **permission checks**. From 8727d4f7c67b0f3fb4f1fd0db344c3b4d79265d4 Mon Sep 17 00:00:00 2001 From: mesanjeetk Date: Wed, 30 Sep 2026 10:04:33 +0530 Subject: [PATCH 3/8] docs: update example in manifest.md to reflect correct main file path --- docs/plugin-essentials/manifest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/plugin-essentials/manifest.md b/docs/plugin-essentials/manifest.md index 57aedd6..26cb95a 100644 --- a/docs/plugin-essentials/manifest.md +++ b/docs/plugin-essentials/manifest.md @@ -35,7 +35,7 @@ Every plugin has a `plugin.json` file at the root of its zip. It tells Acode and "id": "com.example.plugin", "name": "Example Plugin", "version": "1.0.0", - "main": "dist/main.js", + "main": "main.js", "readme": "readme.md", "icon": "icon.png", "files": ["worker.js"], From 13b48ee44696dca00437527c9f34ef01adeba9ac Mon Sep 17 00:00:00 2001 From: mesanjeetk Date: Wed, 30 Sep 2026 10:27:29 +0530 Subject: [PATCH 4/8] docs: update acode and core-file documentation for clarity and consistency --- docs/global-apis/acode.md | 184 ++++++++++++++++------------ docs/plugin-essentials/core-file.md | 2 +- 2 files changed, 107 insertions(+), 79 deletions(-) diff --git a/docs/global-apis/acode.md b/docs/global-apis/acode.md index 04197c2..0668a7d 100644 --- a/docs/global-apis/acode.md +++ b/docs/global-apis/acode.md @@ -1,3 +1,8 @@ +--- +title: Acode +description: The global acode object: register plugins, load modules, and more. +--- + # Acode ## window.acode or acode @@ -6,92 +11,102 @@ The `acode` object is the global object that provides access to the **Acode API* ## Methods -### `setPluginInit(pluginId: string, init: Function, settings? Object)` +### `setPluginInit(pluginId, init, settings?)` -This method is used to register the plugin. This method takes two parameters, `pluginId` and init function. The `pluginId` is the ID of your plugin. The `init` function is the function that will be called when the plugin is loaded. +Registers the function Acode calls to start your plugin. See [Understanding Plugins](../getting-started/understanding-plugin.md) for when it runs. -**Example:** +| Parameter | Type | Description | +| --- | --- | --- | +| `pluginId` | `string` | The `id` from your `plugin.json`. | +| `init` | `(baseUrl, $page, options) => void \| Promise` | Called when the plugin loads. See [`init` arguments](#init-arguments). | +| `settings` | `PluginSettings` | Optional. Adds a settings page for your plugin. See [Plugin settings](#plugin-settings). | ```js -acode.setPluginInit('com.example.plugin', (baseUrl, $page, cache) => { // [!code focus] +acode.setPluginInit("com.example.plugin", async (baseUrl, $page, options) => { const commands = acode.require("commands"); commands.addCommand({ - name: 'example-plugin', - bindKey: { win: 'Ctrl-Alt-E', mac: 'Command-Alt-E' }, + name: "example-plugin", + bindKey: { win: "Ctrl-Alt-E", mac: "Command-Alt-E" }, exec: () => { - $page.innerHTML = ` -

Example Plugin

-

This is an example plugin.

- `; + $page.innerHTML = `

Example Plugin

`; $page.show(); }, }); }); ``` -### `init(baseUrl: string, $page: WCPage, options: object)` - -When the init function is called, it will receive 3 parameters: - -* `baseUrl: string` The base URL of the plugin. You can use this URL to access the files in the plugin directory. - -* `$page: WcPage` This page object can be used to show content. - -* `options: object` This object can be used to access the cached files. - - * `cacheFileUrl: string` Url of the cached file. - - * `cacheFile File: object` File object of the cached file. Using this object, you can write/read the file. - * `firstInit: boolean` If this is the first time the plugin is loaded, this value will be true. Otherwise, it will be `false`. - * `ctx: PluginContext | null` Your plugin's native context: encrypted secret storage and permission checks. It may be `null` if the trusted native session is unavailable, so guard it before use. See [Plugin Context (`ctx`)](../plugin-essentials/plugin-context.md). - * `fileIcons` Plugin-bound [File Icons](../utilities/file-icons.md) API. Same instance as `acode.require("fileIcons")` captured in the main script. Available from **versionCode `1012`**. - -### `Settings Object` - -This parameter is optional. You can use this parameter to define the settings of the plugin. The settings will be displayed in the plugin page. - -Settings requires the following properties - -* `list: Array` An array of settings. - - * `key: string` The key of the setting. This key will be used to access the value of the setting. - - * `text: string` The text of the setting. This text will be displayed in the settings page. - - * `icon?: string` The icon of the setting. This icon will be displayed in the settings page. - - * `iconColor?: string` The icon color of the setting. This icon color will be displayed in the settings page. - - * `info?: string` The info of the setting. This info will be displayed in the settings page. +#### `init` arguments - * `value?: any` The value of the setting. This value will be displayed in the settings page. +| Argument | Type | Description | +| --- | --- | --- | +| `baseUrl` | `string` | Internal URL of your plugin folder. Use it to load files that ship with the plugin. It may not end with `/`; see [Understanding Plugins](../getting-started/understanding-plugin.md#recommended-main-js-shape). | +| `$page` | `WcPage` | A page object that facilitates the display of content within Acode. | +| `options.cacheFileUrl` | `string` | Internal URL of your plugin's cache file. | +| `options.cacheFile` | `fsOperation` | File handle for the cache file. Use its `readFile()` and `writeFile()` methods. | +| `options.firstInit` | `boolean` | `true` only on the run right after the plugin was installed. | +| `options.ctx` | `PluginContext \| null` | Encrypted secret storage and permission checks. May be `null` if the trusted native session is unavailable, so check it before use. See [Plugin Context](../plugin-essentials/plugin-context.md). | +| `options.fileIcons` | `object` | Plugin-bound [File Icons](../utilities/file-icons.md) API. Same as `acode.require("fileIcons")` called from your main script. Available from versionCode `1012`. | - * `valueText?: (value:any)=>string` The value text of the setting. This value text will be displayed in the settings page. +#### Plugin settings - * `checkbox?: boolean` If this property is set to true, the setting will be displayed as a checkbox. +Pass a third argument to give your plugin a settings page under **Settings → Plugins → your plugin**. - * `select?: Array|string>` If this property is set to an array, the setting will be displayed as a select. The array should contain the options of the select. Each option can be a string or an array of two strings. If the option is a string, the value and the text of the option will be the same. If the option is an array of two strings, the first string will be the value of the option and the second string will be the text of the option. - - * `prompt?: string` If this property is set to true, the setting will be displayed as a prompt. - - * `promptType?: string` The type of the prompt. This property is only used when the prompt property is set to true. The default value is text. - - * `promptOptions?: Array` The options of the prompt. This property is only used when the prompt property is set to true and the promptType property is set to select. - - * `match: RegExp` The regular expression to match the value. - - * `required: boolean` If this property is set to true, the value is required. - - * `placeholder: string` The placeholder of the prompt. +```ts +{ + list: SettingItem[], + cb: (key: string, value: any) => void +} +``` - * `test: (value: any) => boolean` The test function to test the value. +`cb` runs when the user changes an item. You are responsible for saving the value, for example with the [Settings](../editor-components/settings.md) module. + +**`SettingItem` fields** + +| Field | Type | Description | +| --- | --- | --- | +| `key` | `string` | **Required.** Identifier passed to `cb`. | +| `text` | `string` | **Required.** Label. | +| `info` | `string` | Description shown under the label. | +| `value` | `any` | Current value. | +| `valueText` | `(value) => string` | Turns `value` into the text displayed for it. | +| `icon` | `string` | Icon class shown on the row. | +| `iconColor` | `string` | Color of that icon. | +| `category` | `string` | Groups items under a heading. | +| `hidden` | `boolean` | Hide the item. | + +Set exactly one of the following to choose how the user edits the item: + +| Field | Type | Editing UI | +| --- | --- | --- | +| `checkbox` | `boolean` | A checkbox. The value passed to `cb` is `true` or `false`. | +| `select` | `Array` | A [select](../ui-components/dialogs/select.md) dialog. | +| `prompt` | `string` | A [prompt](../ui-components/dialogs/prompt.md) with this text as the message. | +| `promptType` | `string` | Input type of that prompt (default `text`). Only with `prompt`. | +| `promptOptions` | `object` | [Prompt options](../ui-components/dialogs/prompt.md#options) such as `match`, `required`, `placeholder` and `test`. Only with `prompt`. | +| `color` | `boolean` | A [color picker](../ui-components/dialogs/color-picker.md). | +| `file` / `folder` | `boolean` | The file browser, in file or folder mode. The value is the chosen URL. | +| `link` | `string` | Opens this URL in the browser. `cb` is not called. | - * `cb: (key: string, value: any) => void` The callback function that will be called when the settings are changed. +```js +acode.setPluginInit( + plugin.id, + init, + { + list: [ + { key: "enabled", text: "Enable feature", checkbox: true, value: true }, + { key: "port", text: "Port", prompt: "Port number", promptType: "number", value: 8080 }, + { key: "mode", text: "Mode", select: ["fast", "safe"], value: "safe" }, + ], + cb: (key, value) => save(key, value), + }, +); +``` +### `setPluginUnmount(pluginId, unmount)` -### `setPluginUnmount(pluginId: string, unmount: Function)` +Registers the function Acode calls when your plugin is disabled, uninstalled or reloaded. Use it to remove everything `init` added: commands, listeners, timers, UI elements and registered formatters. -This method is used to set the unmount function. This function will be called when the plugin is unloaded. You can use this function to clean up the plugin. +Errors thrown by `unmount` are caught and logged, so they will not stop the plugin from unloading. Acode also deletes your plugin's cache file after `unmount` runs. **Example:** @@ -102,9 +117,9 @@ acode.setPluginUnmount("com.example.plugin", () => { // [!code focus] }); ``` -### `define(moduleName: string, module: any)` +### `define(moduleName, module)` -This method is used to define a module. This method takes two parameters, `moduleName` and module. The `moduleName` is the name of the module. The module is the module object. Module name is case insensitive. +Registers a module that other plugins can load with [`require`](#require-modulename). Module names are case-insensitive. Defining a name that already exists replaces the module, so prefix your names (for example `"my-plugin.utils"`) to avoid clashing with built-ins. **Example:** @@ -120,9 +135,9 @@ acode.define("say-hello", { acode.require("say-hello").hello(); // Hello World! ``` -### `require(moduleName: string)` +### `require(moduleName)` -This method is used to require a module. This method takes one parameter, `moduleName`. The `moduleName` is the name of the module. Module name is case insensitive. +Returns a built-in or plugin-defined module, or `undefined` if the name is unknown. Module names are case-insensitive. See [Available Modules](./modules.md) for the list of built-in names. **Example:** @@ -130,9 +145,9 @@ This method is used to require a module. This method takes one parameter, `modul acode.require("say-hello").hello(); // Hello World! ``` -### `exec(command: string, value?: any)` +### `exec(command, value?)` -This method executes a command defined in file `src/lib/commands.js`. This method takes one or two parameters, `command` and `value`. The command is the name of the command. The value is the value of the command. Command name is case insensitive. +Runs one of Acode's built-in app commands (the ones defined in Acode's `src/lib/commands.js`) and returns its result, or `false` if no command has that name. This is different from the [Commands API](../utilities/commands.md), which registers your own editor commands. **Example:** @@ -140,9 +155,13 @@ This method executes a command defined in file `src/lib/commands.js`. This metho acode.exec("console"); // Opens the console ``` -### `registerFormatter(pluginId: string, extensions: string[], format: Function, displayName?: string)` +### `registerFormatter(pluginId, extensions, format, displayName?)` + +Registers a code formatter. Users choose it per language in **Settings → Formatter**. -This method is used to register a formatter. It takes `pluginId`, `extensions`, formatter function, and optional display name. +- `extensions`: file extensions the formatter supports, for example `["js", "ts"]`. An empty array or missing value means all files (`"*"`). +- `format`: function that formats the active file. It receives no arguments and should modify the editor itself. +- `displayName`: name shown in the formatter picker. Defaults to the plugin id if omitted. **Example:** @@ -158,9 +177,9 @@ acode.registerFormatter("com.example.plugin", ["js"], () => { // [!code focus] }); ``` -### `unregisterFormatter(pluginId: string)` +### `unregisterFormatter(pluginId)` -This method is used to unregister a formatter. This method takes one parameter, `pluginId`. The pluginId is the ID of your plugin. +Removes the formatter registered with `pluginId` and clears it from any language where the user had selected it. Call it from your unmount handler. ### `format(selectIfNull = true): Promise` @@ -190,9 +209,13 @@ Returns formatter options for the given extensions. const options = acode.getFormatterFor(["js", "ts"]); ``` -### `addIcon(iconName: string, iconSrc: string, options?: { monochrome?: boolean })` +### `addIcon(iconName, iconSrc, options?)` -This method is used to add an icon. This method takes two parameters, `iconName` , `iconSrc` and a optional. The `iconName` is the name of the icon. The `iconSrc` is the URL of the icon. If `options.monochrome` true, uses CSS masks to render the icon. This allows it to inherit the theme's currentColor(in case of svg). +Registers a CSS class that shows an image as an icon. + +- `iconName`: the class name to create. +- `iconSrc`: URL or data URI of the image. +- `options.monochrome`: when `true`, the image is used as a mask and takes the current text color, so an SVG follows the theme. Otherwise the image keeps its own colors. ::: info The `options.monochrome` is added in versionCode `967`. @@ -212,9 +235,14 @@ Later you can use the icon by adding to class name my-icon to an element. ``` -### `toInternalUrl(url: string): Promise` +### `toInternalUrl(url)` + +Converts a `file://` URL into an internal URL that `fetch`, `` and `