Index color and icon themes

This commit is contained in:
Sandeep Somavarapu 2019-02-06 16:47:40 +01:00
parent 3cee673d7c
commit 994d0b2855
4 changed files with 188 additions and 5 deletions

View file

@ -13,6 +13,8 @@
<Property Id="Microsoft.VisualStudio.Code.ExtensionDependencies" Value="<%- extensionDependencies %>" />
<Property Id="Microsoft.VisualStudio.Code.ExtensionPack" Value="<%- extensionPack %>" />
<Property Id="Microsoft.VisualStudio.Code.LocalizedLanguages" Value="<%- localizedLanguages %>" />
<Property Id="Microsoft.VisualStudio.Code.ColorThemes" Value="<%- colorThemes %>" />
<Property Id="Microsoft.VisualStudio.Code.IconThemes" Value="<%- iconThemes %>" />
<% if (links.repository) { %>
<Property Id="Microsoft.VisualStudio.Services.Links.Source" Value="<%- links.repository %>" />
<Property Id="Microsoft.VisualStudio.Services.Links.Getstarted" Value="<%- links.repository %>" />

View file

@ -16,8 +16,20 @@ export interface Localization {
translations: Translation[];
}
export interface Theme {
id: string;
path: string;
label?: string;
}
export interface ColorTheme extends Theme {
uiTheme: string;
}
export interface Contributions {
'localizations'?: Localization[];
'themes'?: ColorTheme[];
'iconThemes'?: Theme[];
[contributionType: string]: any;
}

View file

@ -3,7 +3,7 @@ import * as path from 'path';
import * as cp from 'child_process';
import * as _ from 'lodash';
import * as yazl from 'yazl';
import { Manifest } from './manifest';
import { Manifest, Theme } from './manifest';
import { ITranslations, patchNLS } from './nls';
import * as util from './util';
import * as _glob from 'glob';
@ -220,7 +220,11 @@ class ManifestProcessor extends BaseProcessor {
extensionDependencies: _(manifest.extensionDependencies || []).uniq().join(','),
extensionPack: _(manifest.extensionPack || []).uniq().join(','),
localizedLanguages: (manifest.contributes && manifest.contributes.localizations) ?
manifest.contributes.localizations.map(loc => loc.localizedLanguageName || loc.languageName || loc.languageId).join(',') : ''
manifest.contributes.localizations.map(loc => loc.localizedLanguageName || loc.languageName || loc.languageId).join(',') : '',
colorThemes: (manifest.contributes && manifest.contributes.themes && manifest.contributes.themes.length > 0) ?
manifest.contributes.themes.map(theme => theme.id).join(',') : '',
iconThemes: (manifest.contributes && manifest.contributes.iconThemes && manifest.contributes.iconThemes.length > 0) ?
manifest.contributes.iconThemes.map(theme => theme.id).join(',') : ''
};
if (isGitHub) {
@ -579,6 +583,56 @@ export class NLSProcessor extends BaseProcessor {
}
}
export class ThemeProcessor extends BaseProcessor {
private colorThemes: { [path: string]: string } = Object.create(null);
private iconThemes: { [path: string]: string } = Object.create(null);
constructor(manifest: Manifest) {
super(manifest);
// Color Themes
if (manifest.contributes && manifest.contributes.themes && manifest.contributes.themes.length > 0) {
this.populateThemes(manifest.contributes.themes, this.colorThemes);
}
// Icon Themes
if (manifest.contributes && manifest.contributes.iconThemes && manifest.contributes.iconThemes.length > 0) {
this.populateThemes(manifest.contributes.iconThemes, this.iconThemes);
}
}
private populateThemes(themes: Theme[], themesPathsMap: { [path: string]: string }) {
const themesMap: { [languageId: string]: string; } = Object.create(null);
// take last reference in the manifest for any given theme
for (const theme of themes) {
themesMap[theme.id] = `extension/${theme.path}`;
}
// invert the map for later easier retrieval
for (const themeId of Object.keys(themesMap)) {
themesPathsMap[themesMap[themeId]] = themeId;
}
}
onFile(file: IFile): Promise<IFile> {
const normalizedPath = util.normalize(file.path);
const colorTheme = this.colorThemes[normalizedPath];
if (colorTheme) {
this.assets.push({ type: `Microsoft.VisualStudio.Code.ColorTheme.${colorTheme}`, path: normalizedPath });
}
const iconTheme = this.iconThemes[normalizedPath];
if (iconTheme) {
this.assets.push({ type: `Microsoft.VisualStudio.Code.IconTheme.${iconTheme}`, path: normalizedPath });
}
return Promise.resolve(file);
}
}
export function validateManifest(manifest: Manifest): Manifest {
validatePublisher(manifest.publisher);
validateExtensionName(manifest.name);
@ -779,7 +833,8 @@ export function createDefaultProcessors(manifest: Manifest, options: IPackageOpt
new ChangelogProcessor(manifest, options),
new LicenseProcessor(manifest),
new IconProcessor(manifest),
new NLSProcessor(manifest)
new NLSProcessor(manifest),
new ThemeProcessor(manifest)
];
}

View file

@ -683,7 +683,7 @@ describe('toVsixManifest', () => {
version: '0.0.1',
engines: Object.create(null),
contributes: {
themes: [{ label: 'monokai', uiTheme: 'vs', path: 'monokai.tmTheme' }]
themes: [{ label: 'monokai', uiTheme: 'vs', path: 'monokai.tmTheme', id: 'monokai' }]
}
};
@ -718,7 +718,7 @@ describe('toVsixManifest', () => {
version: '0.0.1',
engines: Object.create(null),
contributes: {
themes: [{ label: 'monokai', uiTheme: 'vs', path: 'monokai.tmTheme' }]
themes: [{ label: 'monokai', uiTheme: 'vs', path: 'monokai.tmTheme', id: 'monokai' }]
}
};
@ -730,6 +730,66 @@ describe('toVsixManifest', () => {
});
});
it('should expose color theme contributions as properties', () => {
const manifest = {
name: 'test',
publisher: 'mocha',
version: '0.0.1',
engines: Object.create(null),
contributes: {
themes: [
{ label: 'monokai', uiTheme: 'vs', path: 'monokai.tmTheme', id: 'monokai' },
{ label: 'monokai-dark', uiTheme: 'vs-dark', path: 'monokai-dark.tmTheme', id: 'monokai-dark' }
]
}
};
const files = [
{ path: 'extension/monokai.tmTheme', contents: new Buffer('') },
{ path: 'extension/monokai-dark.tmTheme', contents: new Buffer('') },
];
return _toVsixManifest(manifest, files)
.then(parseXmlManifest)
.then(result => {
const properties = result.PackageManifest.Metadata[0].Properties[0].Property;
const colorThemesProp = properties.filter(p => p.$.Id === 'Microsoft.VisualStudio.Code.ColorThemes');
assert.equal(colorThemesProp.length, 1);
const colorThemes = colorThemesProp[0].$.Value.split(',');
assert.deepEqual(colorThemes, ['monokai', 'monokai-dark']);
});
});
it('should expose color theme contributions as assets', () => {
const manifest = {
name: 'test',
publisher: 'mocha',
version: '0.0.1',
engines: Object.create(null),
contributes: {
themes: [
{ label: 'monokai', uiTheme: 'vs', path: 'monokai.tmTheme', id: 'monokai' },
{ label: 'monokai-dark', uiTheme: 'vs-dark', path: 'monokai-dark.tmTheme', id: 'monokai-dark' }
]
}
};
const files = [
{ path: 'extension/monokai.tmTheme', contents: new Buffer('') },
{ path: 'extension/monokai-dark.tmTheme', contents: new Buffer('') },
];
return _toVsixManifest(manifest, files)
.then(parseXmlManifest)
.then(result => {
const assets = result.PackageManifest.Assets[0].Asset;
assert(assets.some(asset => asset.$.Type === 'Microsoft.VisualStudio.Code.ColorTheme.monokai' && asset.$.Path === 'extension/monokai.tmTheme'));
assert(assets.some(asset => asset.$.Type === 'Microsoft.VisualStudio.Code.ColorTheme.monokai-dark' && asset.$.Path === 'extension/monokai-dark.tmTheme'));
});
});
it('should automatically add theme tag for icon themes', () => {
const manifest = {
name: 'test',
@ -768,6 +828,60 @@ describe('toVsixManifest', () => {
});
});
it('should expose icon theme contributions as properties', () => {
const manifest = {
name: 'test',
publisher: 'mocha',
version: '0.0.1',
engines: Object.create(null),
contributes: {
iconThemes: [
{ label: 'fakeicons', path: 'fake.icons', id: 'fakeicons' }
]
}
};
const files = [
{ path: 'extension/fake.icons', contents: new Buffer('') },
];
return _toVsixManifest(manifest, files)
.then(parseXmlManifest)
.then(result => {
const properties = result.PackageManifest.Metadata[0].Properties[0].Property;
const iconThemesProp = properties.filter(p => p.$.Id === 'Microsoft.VisualStudio.Code.IconThemes');
assert.equal(iconThemesProp.length, 1);
const iconThemes = iconThemesProp[0].$.Value.split(',');
assert.deepEqual(iconThemes, ['fakeicons']);
});
});
it('should expose icon theme contributions as assets', () => {
const manifest = {
name: 'test',
publisher: 'mocha',
version: '0.0.1',
engines: Object.create(null),
contributes: {
iconThemes: [
{ label: 'fakeicons', path: 'fake.icons', id: 'fakeicons' }
]
}
};
const files = [
{ path: 'extension/fake.icons', contents: new Buffer('') },
];
return _toVsixManifest(manifest, files)
.then(parseXmlManifest)
.then(result => {
const assets = result.PackageManifest.Assets[0].Asset;
assert(assets.some(asset => asset.$.Type === 'Microsoft.VisualStudio.Code.IconTheme.fakeicons' && asset.$.Path === 'extension/fake.icons'));
});
});
it('should automatically add language tag with activationEvent', () => {
const manifest = {
name: 'test',