Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Second prototype of markdown extensions API #22836

Merged
merged 1 commit into from
Mar 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 41 additions & 15 deletions extensions/markdown/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ interface PreviewSecurityPickItem extends vscode.QuickPickItem {
id: PreviewSecuritySelection;
}

class ExtensionContentSecurityProlicyArbiter implements ContentSecurityPolicyArbiter {
class ExtensionContentSecurityPolicyArbiter implements ContentSecurityPolicyArbiter {
private readonly key = 'trusted_preview_workspace:';

constructor(
Expand All @@ -58,9 +58,16 @@ class ExtensionContentSecurityProlicyArbiter implements ContentSecurityPolicyArb
public removeTrustedWorkspace(rootPath: string): Thenable<void> {
return this.globalState.update(this.key + rootPath, false);
}

}

const resolveExtensionResources = (extension: vscode.Extension<any>, stylePath: string): vscode.Uri => {
const resource = vscode.Uri.parse(stylePath);
if (resource.scheme) {
return resource;
}
return vscode.Uri.file(path.join(extension.extensionPath, stylePath));
};

var telemetryReporter: TelemetryReporter | null;

export function activate(context: vscode.ExtensionContext) {
Expand All @@ -70,12 +77,43 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(telemetryReporter);
}

const cspArbiter = new ExtensionContentSecurityProlicyArbiter(context.globalState);
const cspArbiter = new ExtensionContentSecurityPolicyArbiter(context.globalState);
const engine = new MarkdownEngine();

const contentProvider = new MDDocumentContentProvider(engine, context, cspArbiter);
const contentProviderRegistration = vscode.workspace.registerTextDocumentContentProvider('markdown', contentProvider);

if (vscode.workspace.getConfiguration('markdown').get('enableExperimentalExtensionApi', false)) {
for (const extension of vscode.extensions.all) {
const contributes = extension.packageJSON && extension.packageJSON.contributes;
if (!contributes) {
continue;
}

let styles = contributes['markdown.preview'] && contributes['markdown.preview'].styles;
if (styles) {
if (!Array.isArray(styles)) {
styles = [styles];
}
for (const style of styles) {
try {
contentProvider.addStyle(resolveExtensionResources(extension, style));
} catch (e) {
// noop
}
}
}

if (contributes['markdownit.plugins']) {
extension.activate().then(() => {
if (extension.exports && extension.exports.extendMarkdownIt) {
engine.addPlugin((md: any) => extension.exports.extendMarkdownIt(md));
}
});
}
}
}

const symbolsProvider = new MDDocumentSymbolProvider(engine);
const symbolsProviderRegistration = vscode.languages.registerDocumentSymbolProvider({ language: 'markdown' }, symbolsProvider);
context.subscriptions.push(contentProviderRegistration, symbolsProviderRegistration);
Expand Down Expand Up @@ -231,18 +269,6 @@ export function activate(context: vscode.ExtensionContext) {
});
}
}));

if (vscode.workspace.getConfiguration('markdown').get('enableExperimentalExtensionApi', false)) {
vscode.commands.executeCommand('_markdown.onActivateExtensions')
.then(() => void 0, () => void 0);

return {
addPlugin(factory: (md: any) => any) {
engine.addPlugin(factory);
}
};
}
return undefined;
}


Expand Down
2 changes: 0 additions & 2 deletions extensions/markdown/src/markdownEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ export class MarkdownEngine {

private plugins: Array<(md: any) => any> = [];

constructor() { }

public addPlugin(factory: (md: any) => any): void {
if (this.md) {
this.usePlugin(factory);
Expand Down
10 changes: 7 additions & 3 deletions extensions/markdown/src/previewContentProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,18 @@ export function getMarkdownUri(uri: vscode.Uri) {
export class MDDocumentContentProvider implements vscode.TextDocumentContentProvider {
private _onDidChange = new vscode.EventEmitter<vscode.Uri>();
private _waiting: boolean = false;
private extraStyles: Array<vscode.Uri> = [];

constructor(
private engine: MarkdownEngine,
private context: vscode.ExtensionContext,
private cspArbiter: ContentSecurityPolicyArbiter
) { }

public addStyle(resource: vscode.Uri): void {
this.extraStyles.push(resource);
}

private getMediaPath(mediaFile: string): string {
return vscode.Uri.file(this.context.asAbsolutePath(path.join('media', mediaFile))).toString();
}
Expand Down Expand Up @@ -97,16 +102,15 @@ export class MDDocumentContentProvider implements vscode.TextDocumentContentProv
const baseStyles = [
this.getMediaPath('markdown.css'),
this.getMediaPath('tomorrow.css')
];
].concat(this.extraStyles.map(resource => resource.toString()));

return `${baseStyles.map(href => `<link rel="stylesheet" type="text/css" href="${href}">`).join('\n')}
${this.getSettingsOverrideStyles(nonce)}
${this.computeCustomStyleSheetIncludes(uri)}`;
}

private getScripts(nonce: string): string {
const scripts = [this.getMediaPath('main.js')];
return scripts
return [this.getMediaPath('main.js')]
.map(source => `<script src="${source}" nonce="${nonce}"></script>`)
.join('\n');
}
Expand Down