diff --git a/packages/generator-joplin/generators/app/templates/src/manifest.json b/packages/generator-joplin/generators/app/templates/src/manifest.json index 6038168d3c..0253e97dff 100644 --- a/packages/generator-joplin/generators/app/templates/src/manifest.json +++ b/packages/generator-joplin/generators/app/templates/src/manifest.json @@ -8,5 +8,6 @@ "author": "<%= pluginAuthor %>", "homepage_url": "<%= pluginHomepageUrl %>", "repository_url": "<%= pluginRepositoryUrl %>", - "keywords": [] + "keywords": [], + "categories": [] } \ No newline at end of file diff --git a/packages/generator-joplin/generators/app/templates/webpack.config.js b/packages/generator-joplin/generators/app/templates/webpack.config.js index 78d2f7002f..1c2d7e7bf1 100644 --- a/packages/generator-joplin/generators/app/templates/webpack.config.js +++ b/packages/generator-joplin/generators/app/templates/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } diff --git a/packages/lib/services/plugins/utils/manifestFromObject.ts b/packages/lib/services/plugins/utils/manifestFromObject.ts index 7b4f142f0e..9cddea3e81 100644 --- a/packages/lib/services/plugins/utils/manifestFromObject.ts +++ b/packages/lib/services/plugins/utils/manifestFromObject.ts @@ -45,6 +45,7 @@ export default function manifestFromObject(o: any): PluginManifest { homepage_url: getString('homepage_url', false), repository_url: getString('repository_url', false), keywords: getStrings('keywords', false), + categories: getStrings('categories', false), permissions: permissions, _recommended: getBoolean('_recommended', false, false), diff --git a/packages/lib/services/plugins/utils/types.ts b/packages/lib/services/plugins/utils/types.ts index 42b6cd9b9a..edcb3d036b 100644 --- a/packages/lib/services/plugins/utils/types.ts +++ b/packages/lib/services/plugins/utils/types.ts @@ -13,6 +13,7 @@ export interface PluginManifest { homepage_url?: string; repository_url?: string; keywords?: string[]; + categories?: string[]; permissions?: PluginPermission[]; // Private keys diff --git a/readme/api/references/plugin_manifest.md b/readme/api/references/plugin_manifest.md index 4e8d2881f1..bff114af06 100644 --- a/readme/api/references/plugin_manifest.md +++ b/readme/api/references/plugin_manifest.md @@ -13,6 +13,23 @@ Name | Type | Required? | Description `keywords` | string[] | No | Keywords associated with the plugins. They are used in search in particular. `homepage_url` | string | No | Homepage URL of the plugin. It can also be, for example, a link to a GitHub repository. `repository_url` | string | No | Repository URL where the plugin source code is hosted. +`categories` | string[] | No | [Categories](#categories) that describes the functionality of the plugin. | + +## Categories + +| Category | Description | +| --- | --- | +| appearance | dealing with appearance of some element/s of the app. For example line numbers, layout, etc. | +| developer tools | built for the developers. | +| editor | enhancing note editor. | +| files | dealing with files. For example import, export, backup, etc. | +| integrations | integrating third party services or apps. | +| personal knowledge management | managing and organizing notes. | +| productivity | making Joplin more productive to use. | +| search | enhancing search inside the app. | +| tags |  dealing with note tags. | +| themes | changing theme of the app. | +| viewer | enhancing the rendering of a note. | ## Manifest example