Index color and icon themes
This commit is contained in:
parent
3cee673d7c
commit
994d0b2855
4 changed files with 188 additions and 5 deletions
|
@ -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 %>" />
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Add table
Reference in a new issue