Skip to content

Extension package format

nicolo-ribaudo edited this page Nov 3, 2014 · 27 revisions

Status: Implemented

The Brackets extension format is inspired by CommonJS and npm. The format may change again in the future - see the ongoing extension API research.

Package Files

A Brackets extension package is a zip file containing two components:

These two files may be nested inside a folder, but they must be inside the same folder.

If your extension is on GitHub, the zip files auto-generated by the "ZIP" download button at the top-left meet these requirements (unless you use git submodules). This is why Brackets can install an extension directly from a GitHub repo URL.

npm uses gzipped tar files, but the standard for Brackets extensions is zip files because (1) they are more convenient for users to create on Windows and Mac; and (2) they can be created with a single click from GitHub. If greater compatibility with npm proves to be desirable, we can always repack the extensions into .tar.gz files.

package.json Format

Brackets uses a format similar to npm's package.json format. Here's a quick example:

{
    "name": "yourname.your-extension-id",
    "title": "Pretty Title for the UI",
    "description": "More useful details to let someone know what your extension is all about.",
    "homepage": "https://github.com/yourname/yourproject",
    "version": "1.0.0",
    "author": "Your Name <your@email> (http://your.url)",
    "license": "MIT",
    "engines": {
        "brackets": ">=0.24.0"
    },
    "i18n": [ "en", "fr"],
    "package-i18n": {
        "fr": {
            "description": "Plus de détails utiles pour laisser quelqu'un savoir ce que votre poste est tout au sujet."
        }
    }
}

Required fields: name, version

Highly recommended: title, description, homepage

Here's how these fields are exposed in the Extension Manager UI:

Details

  • name (required) - unique, lowercase alpha-numeric name without spaces; may include ".", "-", or "_". If you are adding a package.json to an existing extension, making the name field the same as the name of your GitHub repository will make the migration easier for people who already have the extension installed.
  • version (required) - must follow the Semantic Versioning format; typically a three-part version number of the form "x.y.z"
  • title (highly recommended) - short user-visible display name of extension (a few words)
  • description (highly recommended) - longer user-visible description of extension (a couple sentences)
  • engines.brackets (encouraged) - which Brackets versions the extension is compatible with, specified as a string in semver range format. Typically >= 0.xx, where "xx" is a Brackets sprint number (this says the extension won't run on older builds before sprint "xx", but it's assumed to be compatible with all future builds of Brackets)
  • homepage (encouraged) - URL linking to more information (Extension Manager shows this as a "More Info" link)
  • author (encouraged) - name of the developer, in the format "Name <email> (URL)" (email and URL are both optional)
  • license (optional) - license of the extension's source code (not shown in the UI yet)
  • keywords (optional) - array of additional keyword strings; searched when the user filters the list view in Extension Manager
  • i18n (optional) - array of language codes the extension has been translated into
  • package-i18n (optional) - set of language translations to display in the Extension Manager dialog. Each language can optionally provide a translation for the title, description, homepage, and/or keywords.
Future fields (not yet implemented)
  • contributors (optional) - array of strings or single string, in the same format as author
  • files (optional) - will work the same as it does for npm, including the optional use of an .npmignore file
  • Brackets does not yet support any of npm's dependencies-related features on installation. When we implement extension dependencies, those will likely be expressed as peerDependencies
  • We should honor the private flag to not publish private extensions

note by reusing engines and peerDependencies, we may run into friction with npm, assuming that we allow users to install and use npm modules. If need be, we can change to using two other Brackets-specific fields in package.json for these needs.

Categories

Status: Not yet implemented - may change

Our package.json files include a categories field which is not present in npm's format. Categories, unlike keywords, are primarily a "browsing" feature rather than a searching one.

The categories field can be either a string (the common case, since most extensions have only one), or an array of strings.

Each of the strings should be one of the following boldface values:

  • editing – Editing and Navigation
  • snippets – Snippets and Shorthand
  • formatting – Formatting
  • codegen – Code Generation
  • language – Language Support
  • general – General Functionality
  • livedev – Live Development
  • visual – Visual Editing
  • external – External Tools and Online Content
  • docs – Documentation
  • linting – Linting and Warnings
  • testing – Testing and Code Metrics

Keywords

Status: Implemented

Keywords can be anything that will help users find the right extension. Extension Manager searches title, description, and keywords when filtering the list view.

Recommended: if your extension adds support for a specific language, include all its file extensions (with leading ".") in your keywords. (For example, an extension adding TypeScript support should include ".ts" in its keywords).

Keywords must be an array of keywords, not a simple list. For example:

"keywords":["lint","linting","linter"]

Extension Modules and main.js

Status: Implemented

Brackets will automatically load the main.js module (RequireJS format) from the root of the package. Normally extensions are loaded during startup (see application init order). But when an extension is initially installed, the module is loaded immediately even though Brackets may have already been running for quite some time.

Modules that an extension imports via require() are located relative to the root of the extension. For example, require("foo/bar") will look for foo/bar.js in the extension. To import Brackets core modules, use brackets.getModule() instead (with a path relative to the Brackets src root).

Node Modules

Status: Not yet implemented - may change

Brackets extensions will be able to provide modules that run in a Node process. The exact location of these modules will depend on the answers to the open questions at the end of this section.

Brackets extensions will also be able to use modules downloaded via npm. The node_modules directory will be incorporated directly into the extension package. Including dependencies directly in a package for deployment is considered a best practice.

Node modules (or any modules for that matter) are not shared between extensions.

There are open questions surrounding the lifecycle of the Node code and the module format differences between Brackets and Node and these will be resolved as we head toward the Extension API research story.

Open question: npm uses CommonJS modules, Brackets uses AMD, how do we reconcile? This will be investigated during the extension API research. We have discussed a move to pure CommonJS modules.

Changelog

Status: Not yet implemented - may change

Changelogs will be formatted based on the proposed standard at Keep a Changelog. If there is a CHANGELOG.md file at the package root then the following sections will be identified by package manager and pulled apart to display to users:

  • h2 sections (denoted by ##) are in the format: ## x.y.z - yyyy-mm-dd and represent a released update using the semantic version number and the release date.
  • h3 sections (denoted by ###) within an h2 release section will be labelled with 1-5 sub-section headers each with an un-ordered list of items for that sub-section. The sub-section headings will be one of the following:
    • Added for new features.
    • Deprecated for once-stable features removed in upcoming releases.
    • Removed for deprecated features removed in this release.
    • Fixed for any bug fixes.
    • Security to invite users to upgrade in case of vulnerabilities.
  • Note It is not necessary to include sub-section headers that are empty.

Examples of CHANGELOG.md files that follow this standard can be found at:

Unit Tests

Status: Implemented

A Jasmine unit test module can be located at unittests.js at the root of the package. In a developer build of Brackets, where the Debug > Run Tests menu item is enabled, the extension's unittests.js is automatically loaded and included in the list of runnable tests.

Localization

Status: Implemented

The pattern for localizing extensions is to put an nls directory at the root, containing a strings.js module. Next to that module, there is a root directory with the baseline set of strings and a directory for each locale's specific strings. See the Localization Example extension.

Clone this wiki locally