mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-21 09:38:01 +02:00
Plugin Repo: Allow overridding manifest properties and added recommended plugins
This commit is contained in:
parent
dc008ecf64
commit
9c44133bd0
@ -1644,6 +1644,12 @@ packages/plugin-repo-cli/lib/gitCompareUrl.js.map
|
||||
packages/plugin-repo-cli/lib/gitCompareUrl.test.d.ts
|
||||
packages/plugin-repo-cli/lib/gitCompareUrl.test.js
|
||||
packages/plugin-repo-cli/lib/gitCompareUrl.test.js.map
|
||||
packages/plugin-repo-cli/lib/overrideUtils.d.ts
|
||||
packages/plugin-repo-cli/lib/overrideUtils.js
|
||||
packages/plugin-repo-cli/lib/overrideUtils.js.map
|
||||
packages/plugin-repo-cli/lib/overrideUtils.test.d.ts
|
||||
packages/plugin-repo-cli/lib/overrideUtils.test.js
|
||||
packages/plugin-repo-cli/lib/overrideUtils.test.js.map
|
||||
packages/plugin-repo-cli/lib/types.d.ts
|
||||
packages/plugin-repo-cli/lib/types.js
|
||||
packages/plugin-repo-cli/lib/types.js.map
|
||||
@ -1653,6 +1659,9 @@ packages/plugin-repo-cli/lib/updateReadme.js.map
|
||||
packages/plugin-repo-cli/lib/updateReadme.test.d.ts
|
||||
packages/plugin-repo-cli/lib/updateReadme.test.js
|
||||
packages/plugin-repo-cli/lib/updateReadme.test.js.map
|
||||
packages/plugin-repo-cli/lib/utils.d.ts
|
||||
packages/plugin-repo-cli/lib/utils.js
|
||||
packages/plugin-repo-cli/lib/utils.js.map
|
||||
packages/plugins/ToggleSidebars/api/index.d.ts
|
||||
packages/plugins/ToggleSidebars/api/index.js
|
||||
packages/plugins/ToggleSidebars/api/index.js.map
|
||||
|
9
.gitignore
vendored
9
.gitignore
vendored
@ -1629,6 +1629,12 @@ packages/plugin-repo-cli/lib/gitCompareUrl.js.map
|
||||
packages/plugin-repo-cli/lib/gitCompareUrl.test.d.ts
|
||||
packages/plugin-repo-cli/lib/gitCompareUrl.test.js
|
||||
packages/plugin-repo-cli/lib/gitCompareUrl.test.js.map
|
||||
packages/plugin-repo-cli/lib/overrideUtils.d.ts
|
||||
packages/plugin-repo-cli/lib/overrideUtils.js
|
||||
packages/plugin-repo-cli/lib/overrideUtils.js.map
|
||||
packages/plugin-repo-cli/lib/overrideUtils.test.d.ts
|
||||
packages/plugin-repo-cli/lib/overrideUtils.test.js
|
||||
packages/plugin-repo-cli/lib/overrideUtils.test.js.map
|
||||
packages/plugin-repo-cli/lib/types.d.ts
|
||||
packages/plugin-repo-cli/lib/types.js
|
||||
packages/plugin-repo-cli/lib/types.js.map
|
||||
@ -1638,6 +1644,9 @@ packages/plugin-repo-cli/lib/updateReadme.js.map
|
||||
packages/plugin-repo-cli/lib/updateReadme.test.d.ts
|
||||
packages/plugin-repo-cli/lib/updateReadme.test.js
|
||||
packages/plugin-repo-cli/lib/updateReadme.test.js.map
|
||||
packages/plugin-repo-cli/lib/utils.d.ts
|
||||
packages/plugin-repo-cli/lib/utils.js
|
||||
packages/plugin-repo-cli/lib/utils.js.map
|
||||
packages/plugins/ToggleSidebars/api/index.d.ts
|
||||
packages/plugins/ToggleSidebars/api/index.js
|
||||
packages/plugins/ToggleSidebars/api/index.js.map
|
||||
|
@ -10,18 +10,8 @@ import updateReadme from './lib/updateReadme';
|
||||
import { NpmPackage } from './lib/types';
|
||||
import gitCompareUrl from './lib/gitCompareUrl';
|
||||
import commandUpdateRelease from './commands/updateRelease';
|
||||
|
||||
function stripOffPackageOrg(name: string): string {
|
||||
const n = name.split('/');
|
||||
if (n[0][0] === '@') n.splice(0, 1);
|
||||
return n.join('/');
|
||||
}
|
||||
|
||||
function isJoplinPluginPackage(pack: any): boolean {
|
||||
if (!pack.keywords || !pack.keywords.includes('joplin-plugin')) return false;
|
||||
if (stripOffPackageOrg(pack.name).indexOf('joplin-plugin') !== 0) return false;
|
||||
return true;
|
||||
}
|
||||
import { isJoplinPluginPackage, readJsonFile } from './lib/utils';
|
||||
import { applyManifestOverrides, getObsoleteManifests, readManifestOverrides } from './lib/overrideUtils';
|
||||
|
||||
function pluginInfoFromSearchResults(results: any[]): NpmPackage[] {
|
||||
const output: NpmPackage[] = [];
|
||||
@ -44,21 +34,13 @@ async function checkPluginRepository(dirPath: string, dryRun: boolean) {
|
||||
if (!(await fs.pathExists(`${dirPath}/.git`))) throw new Error(`Directory is not a Git repository: ${dirPath}`);
|
||||
|
||||
const previousDir = chdir(dirPath);
|
||||
if (!dryRun) {
|
||||
await gitRepoCleanTry();
|
||||
if (!dryRun) await gitPullTry();
|
||||
await gitPullTry();
|
||||
}
|
||||
chdir(previousDir);
|
||||
}
|
||||
|
||||
async function readJsonFile(manifestPath: string, defaultValue: any = null): Promise<any> {
|
||||
if (!(await fs.pathExists(manifestPath))) {
|
||||
if (defaultValue === null) throw new Error(`No such file: ${manifestPath}`);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
const content = await fs.readFile(manifestPath, 'utf8');
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
async function extractPluginFilesFromPackage(existingManifests: any, workDir: string, packageName: string, destDir: string): Promise<any> {
|
||||
const previousDir = chdir(workDir);
|
||||
|
||||
@ -147,14 +129,14 @@ function chdir(path: string): string {
|
||||
return previous;
|
||||
}
|
||||
|
||||
async function processNpmPackage(npmPackage: NpmPackage, repoDir: string) {
|
||||
async function processNpmPackage(npmPackage: NpmPackage, repoDir: string, dryRun: boolean) {
|
||||
const tempDir = `${repoDir}/temp`;
|
||||
const obsoleteManifestsPath = path.resolve(repoDir, 'obsoletes.json');
|
||||
|
||||
await fs.mkdirp(tempDir);
|
||||
|
||||
const originalPluginManifests = await readManifests(repoDir);
|
||||
const obsoleteManifests = await readJsonFile(obsoleteManifestsPath, {});
|
||||
const manifestOverrides = await readManifestOverrides(repoDir);
|
||||
const obsoleteManifests = getObsoleteManifests(manifestOverrides);
|
||||
const existingManifests = {
|
||||
...originalPluginManifests,
|
||||
...obsoleteManifests,
|
||||
@ -199,6 +181,8 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string) {
|
||||
...manifests,
|
||||
};
|
||||
|
||||
manifests = applyManifestOverrides(manifests, manifestOverrides);
|
||||
|
||||
await writeManifests(repoDir, manifests);
|
||||
await updateReadme(`${repoDir}/README.md`, manifests);
|
||||
}
|
||||
@ -206,6 +190,7 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string) {
|
||||
chdir(repoDir);
|
||||
await fs.remove(tempDir);
|
||||
|
||||
if (!dryRun) {
|
||||
if (!(await gitRepoClean())) {
|
||||
await execCommand2('git add -A', { showOutput: false });
|
||||
await execCommand2(['git', 'commit', '-m', commitMessage(actionType, manifest, previousManifest, npmPackage, error)], { showOutput: false });
|
||||
@ -213,6 +198,7 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string) {
|
||||
console.info('Nothing to commit');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function commandBuild(args: CommandBuildArgs) {
|
||||
const dryRun = !!args.dryRun;
|
||||
@ -223,36 +209,40 @@ async function commandBuild(args: CommandBuildArgs) {
|
||||
await checkPluginRepository(repoDir, dryRun);
|
||||
|
||||
// When starting, always update and commit README, in case something has
|
||||
// been updated via a pull request (for example obsoletes.json being
|
||||
// modified). We do that separately so that the README update doesn't get
|
||||
// mixed up with plugin updates, as in this example:
|
||||
// been updated via a pull request. We do that separately so that the README
|
||||
// update doesn't get mixed up with plugin updates, as in this example:
|
||||
// https://github.com/joplin/plugins/commit/8a65bbbf64bf267674f854a172466ffd4f07c672
|
||||
const manifests = await readManifests(repoDir);
|
||||
await updateReadme(`${repoDir}/README.md`, manifests);
|
||||
const previousDir = chdir(repoDir);
|
||||
|
||||
if (!dryRun) {
|
||||
if (!(await gitRepoClean())) {
|
||||
console.info('Updating README...');
|
||||
await execCommand2('git add -A', { showOutput: true });
|
||||
await execCommand2('git commit -m "Update README"', { showOutput: true });
|
||||
}
|
||||
}
|
||||
|
||||
chdir(previousDir);
|
||||
|
||||
const searchResults = (await execCommand2('npm search joplin-plugin --searchlimit 5000 --json', { showOutput: false })).trim();
|
||||
const npmPackages = pluginInfoFromSearchResults(JSON.parse(searchResults));
|
||||
|
||||
for (const npmPackage of npmPackages) {
|
||||
await processNpmPackage(npmPackage, repoDir);
|
||||
await processNpmPackage(npmPackage, repoDir, dryRun);
|
||||
}
|
||||
|
||||
if (!dryRun) {
|
||||
await commandUpdateRelease(args);
|
||||
|
||||
if (!(await gitRepoClean())) {
|
||||
await execCommand2('git add -A', { showOutput: true });
|
||||
await execCommand2('git commit -m "Update stats"', { showOutput: true });
|
||||
}
|
||||
}
|
||||
|
||||
if (!dryRun) await execCommand2('git push');
|
||||
await execCommand2('git push');
|
||||
}
|
||||
}
|
||||
|
||||
async function commandVersion() {
|
||||
|
95
packages/plugin-repo-cli/lib/overrideUtils.test.ts
Normal file
95
packages/plugin-repo-cli/lib/overrideUtils.test.ts
Normal file
@ -0,0 +1,95 @@
|
||||
import { applyManifestOverrides, getObsoleteManifests, ManifestOverrides } from './overrideUtils';
|
||||
|
||||
describe('overrideUtils', () => {
|
||||
|
||||
test('should get the obsolete manifests', () => {
|
||||
const manifestOverrides: any = {
|
||||
'ambrt.backlinksToNote': {
|
||||
'manifest_version': 1,
|
||||
'id': 'ambrt.backlinksToNote',
|
||||
'app_min_version': '1.5',
|
||||
'version': '1.0.2',
|
||||
'name': 'Backlinks to note',
|
||||
'description': 'Creates backlinks to opened note',
|
||||
'author': 'a',
|
||||
'homepage_url': 'https://discourse.joplinapp.org/t/insert-referencing-notes-backlinks-plugin/13632',
|
||||
'_publish_hash': 'sha256:5676da6b9ad71fc5a9779d3bde13f17de5352344711e135f0db8c62c6dbb5696',
|
||||
'_publish_commit': 'master:19e515bd67e51cc37bd270a32d2898ca009a0de2',
|
||||
'_npm_package_name': 'joplin-plugin-backlinks',
|
||||
'_obsolete': true,
|
||||
},
|
||||
'MyPlugin': {
|
||||
'manifest_version': 1,
|
||||
'id': 'MyPlugin',
|
||||
'app_min_version': '1.6',
|
||||
'version': '1.0.0',
|
||||
'name': 'Testing New Plugin',
|
||||
'description': 'bla',
|
||||
'author': 'bla',
|
||||
'homepage_url': 'bla',
|
||||
'repository_url': 'bla',
|
||||
'_publish_hash': 'sha256:065285d06ea3c084e7f8f8c23583de8d70c4d586274a242c4c750f6faad8c7cb',
|
||||
'_publish_commit': '',
|
||||
'_npm_package_name': 'joplin-plugin-testing-new-plugin',
|
||||
'_obsolete': true,
|
||||
},
|
||||
'io.github.jackgruber.copytags': {
|
||||
'_recommended': true,
|
||||
},
|
||||
};
|
||||
|
||||
const obsoletes = getObsoleteManifests(manifestOverrides);
|
||||
expect(Object.keys(obsoletes).sort()).toEqual(['MyPlugin', 'ambrt.backlinksToNote']);
|
||||
expect(obsoletes['ambrt.backlinksToNote'].description).toBe('Creates backlinks to opened note');
|
||||
});
|
||||
|
||||
test('should apply the overrides', () => {
|
||||
const manifests: any = {
|
||||
'io.github.jackgruber.copytags': {
|
||||
'manifest_version': 1,
|
||||
'id': 'io.github.jackgruber.copytags',
|
||||
'app_min_version': '1.6.2',
|
||||
'version': '1.0.1',
|
||||
'name': 'Tagging',
|
||||
'description': 'Plugin to extend the Joplin tagging menu with a coppy all tags and a tagging dialog with more control. (Formerly Copy Tags).',
|
||||
'author': 'JackGruber',
|
||||
'homepage_url': 'https://github.com/JackGruber/joplin-plugin-tagging/blob/master/README.md',
|
||||
'repository_url': 'https://github.com/JackGruber/joplin-plugin-tagging',
|
||||
'keywords': [
|
||||
'duplicate',
|
||||
'copy',
|
||||
'tags',
|
||||
'tagging',
|
||||
'tag',
|
||||
],
|
||||
'_publish_hash': 'sha256:88daaf234a9b47e5644a8de6f830a801d12edbe41ea5364d994773e89eeafeef',
|
||||
'_publish_commit': 'master:64c0510e3236df7788a8d10ec28dcfbb4c2bdbb7',
|
||||
'_npm_package_name': 'joplin-plugin-copytags',
|
||||
},
|
||||
'joplin.plugin.ambrt.backlinksToNote': {
|
||||
'manifest_version': 1,
|
||||
'id': 'joplin.plugin.ambrt.backlinksToNote',
|
||||
'app_min_version': '1.7',
|
||||
'version': '2.0.11',
|
||||
'name': 'Automatic Backlinks to note',
|
||||
'description': 'Creates backlinks to opened note, also in automatic way',
|
||||
'author': 'ambrt,cyingfan',
|
||||
'homepage_url': 'https://discourse.joplinapp.org/t/insert-referencing-notes-backlinks-plugin/13632',
|
||||
'_publish_hash': 'sha256:df57930d1ab62d4297dad0bb1764888935fcbf6ca8c04e3a843e86a260735c51',
|
||||
'_publish_commit': 'master:98102718a9c0fa9416d654451b18602798c4d3bb',
|
||||
'_npm_package_name': 'joplin-plugin-backlinks',
|
||||
},
|
||||
};
|
||||
|
||||
const overrides: ManifestOverrides = {
|
||||
'io.github.jackgruber.copytags': {
|
||||
_recommended: true,
|
||||
},
|
||||
};
|
||||
|
||||
const updatedManifests = applyManifestOverrides(manifests, overrides);
|
||||
expect(updatedManifests['io.github.jackgruber.copytags']._recommended).toBe(true);
|
||||
expect(updatedManifests['joplin.plugin.ambrt.backlinksToNote']._recommended).toBe(undefined);
|
||||
});
|
||||
|
||||
});
|
51
packages/plugin-repo-cli/lib/overrideUtils.ts
Normal file
51
packages/plugin-repo-cli/lib/overrideUtils.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import * as path from 'path';
|
||||
import { readJsonFile } from './utils';
|
||||
|
||||
export interface ManifestOverride {
|
||||
_obsolete?: boolean;
|
||||
_recommended?: boolean;
|
||||
}
|
||||
|
||||
export type ManifestOverrides = Record<string, ManifestOverride>;
|
||||
|
||||
export function applyManifestOverrides(manifests: any, overrides: ManifestOverrides) {
|
||||
for (const [pluginId, override] of Object.entries(overrides)) {
|
||||
const manifest: any = manifests[pluginId];
|
||||
|
||||
if (!manifest) {
|
||||
// If the manifest does not exist in the destination, it means the
|
||||
// plugin has been taken out, so the obsolete property should be set
|
||||
// to `true`. If not, it's an error.
|
||||
if (!override._obsolete) {
|
||||
console.error(`Could not find manifest for plugin ${pluginId} when applying override`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const [propName, propValue] of Object.entries(override)) {
|
||||
manifest[propName] = propValue;
|
||||
}
|
||||
}
|
||||
|
||||
return manifests;
|
||||
}
|
||||
|
||||
export function getObsoleteManifests(overrides: ManifestOverrides) {
|
||||
const output: any = {};
|
||||
|
||||
for (const [pluginId, override] of Object.entries(overrides)) {
|
||||
if (override._obsolete) {
|
||||
output[pluginId] = override;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
function pluginManifestOverridesPath(repoDir: string): string {
|
||||
return path.resolve(repoDir, 'manifestOverrides.json');
|
||||
}
|
||||
|
||||
export async function readManifestOverrides(repoDir: string): Promise<ManifestOverrides> {
|
||||
return readJsonFile(pluginManifestOverridesPath(repoDir), {});
|
||||
}
|
23
packages/plugin-repo-cli/lib/utils.ts
Normal file
23
packages/plugin-repo-cli/lib/utils.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import * as fs from 'fs-extra';
|
||||
|
||||
export async function readJsonFile(manifestPath: string, defaultValue: any = null): Promise<any> {
|
||||
if (!(await fs.pathExists(manifestPath))) {
|
||||
if (defaultValue === null) throw new Error(`No such file: ${manifestPath}`);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
const content = await fs.readFile(manifestPath, 'utf8');
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
function stripOffPackageOrg(name: string): string {
|
||||
const n = name.split('/');
|
||||
if (n[0][0] === '@') n.splice(0, 1);
|
||||
return n.join('/');
|
||||
}
|
||||
|
||||
export function isJoplinPluginPackage(pack: any): boolean {
|
||||
if (!pack.keywords || !pack.keywords.includes('joplin-plugin')) return false;
|
||||
if (stripOffPackageOrg(pack.name).indexOf('joplin-plugin') !== 0) return false;
|
||||
return true;
|
||||
}
|
@ -13,7 +13,8 @@
|
||||
"tsc": "tsc --project tsconfig.json",
|
||||
"watch": "tsc --watch --project tsconfig.json",
|
||||
"test": "jest",
|
||||
"test-ci": "npm run test"
|
||||
"test-ci": "npm run test",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
|
Loading…
Reference in New Issue
Block a user