Skip to content

Extension package format

Peter Flynn edited this page Aug 6, 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"
    }
}

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 (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
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

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

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

If there is a CHANGELOG.md file at the package root, the h2 headers (delimited by ##) are assumed to contain version numbers and the sections of the file will be pulled apart to display update information to users.

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