<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import DOM = require('vs/base/browser/dom');
import {IHTMLContentElement} from 'vs/base/common/htmlContent';
import {TPromise} from 'vs/base/common/winjs.base';
// import {WorkerClient} from 'vs/base/common/worker/workerClient';
// import {DefaultWorkerFactory} from 'vs/base/worker/defaultWorkerFactory';
import {marked, MarkedOptions} from 'vs/base/common/marked/marked';

export type RenderableContent = string | IHTMLContentElement | IHTMLContentElement[];

export interface RenderOptions {
	actionCallback?: (content: string, event?: DOM.IMouseEvent) => void;
	codeBlockRenderer?: (modeId: string, value: string) => string;
}

/**
 * Create html nodes for the given content element.
 *
 * @param content a html element description
 * @param actionCallback a callback function for any action links in the string. Argument is the zero-based index of the clicked action.
 */
export function renderHtml(content: RenderableContent, options: RenderOptions = {}): Node {
	if (typeof content === 'string') {
		return _renderHtml({ isText: true, text: content }, options);
	} else if (Array.isArray(content)) {
		return _renderHtml({ children: content }, options);
	} else if (content) {
		return _renderHtml(content, options);
	}
}

function _renderHtml(content: IHTMLContentElement, options: RenderOptions = {}): Node {

	let {codeBlockRenderer, actionCallback} = options;

	if (content.isText) {
		return document.createTextNode(content.text);
	}

	var tagName = getSafeTagName(content.tagName) || 'div';
	var element = document.createElement(tagName);

	if (content.className) {
		element.className = content.className;
	}
	if (content.text) {
		element.textContent = content.text;
	}
	if (content.style) {
		element.setAttribute('style', content.style);
	}
	if (content.customStyle) {
		Object.keys(content.customStyle).forEach((key) => {
			element.style[key] = content.customStyle[key];
		});
	}
	if (content.code && codeBlockRenderer) {
		let html = codeBlockRenderer(content.code.language, content.code.value);
		element.innerHTML = html;
	}
	if (content.children) {
		content.children.forEach((child) => {
			element.appendChild(renderHtml(child, options));
		});
	}
	if (content.formattedText) {
		renderFormattedText(element, parseFormattedText(content.formattedText), actionCallback);
	}
	if (content.markdown) {
		const renderer = new marked.Renderer();
		renderer.link = (href, title, text): string => {
			return `<a href="#" data-href="${href}" title="${title || text}">${text}</a>`
		}

		let highlight: (code: string, lang: string) => string;
		if (options.codeBlockRenderer) {
			highlight = (code, lang) => {
				return options.codeBlockRenderer(lang, code);
			}
		}

		if (options.actionCallback) {
			DOM.addStandardDisposableListener(element, 'click', event => {
				if (event.target.tagName === 'A') {
					const href = event.target.dataset['href'];
					if (href) {
						options.actionCallback(href, event);
					}
				}
			});
		}

		element.innerHTML = marked(content.markdown, {
			sanitize: true,
			renderer,
			highlight
		});
	}

	return element;
}

var SAFE_TAG_NAMES = {
	a: true,
	b: true,
	blockquote: true,
	code: true,
	del: true,
	dd: true,
	div: true,
	dl: true,
	dt: true,
	em: true,
	h1h2h3i: true,
	img: true,
	kbd: true,
	li: true,
	ol: true,
	p: true,
	pre: true,
	s: true,
	span: true,
	sup: true,
	sub: true,
	strong: true,<commit_msg>use Renderer#code<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import DOM = require('vs/base/browser/dom');
import {IHTMLContentElement} from 'vs/base/common/htmlContent';
import {TPromise} from 'vs/base/common/winjs.base';
// import {WorkerClient} from 'vs/base/common/worker/workerClient';
// import {DefaultWorkerFactory} from 'vs/base/worker/defaultWorkerFactory';
import {marked, MarkedOptions} from 'vs/base/common/marked/marked';

export type RenderableContent = string | IHTMLContentElement | IHTMLContentElement[];

export interface RenderOptions {
	actionCallback?: (content: string, event?: DOM.IMouseEvent) => void;
	codeBlockRenderer?: (modeId: string, value: string) => string;
}

/**
 * Create html nodes for the given content element.
 *
 * @param content a html element description
 * @param actionCallback a callback function for any action links in the string. Argument is the zero-based index of the clicked action.
 */
export function renderHtml(content: RenderableContent, options: RenderOptions = {}): Node {
	if (typeof content === 'string') {
		return _renderHtml({ isText: true, text: content }, options);
	} else if (Array.isArray(content)) {
		return _renderHtml({ children: content }, options);
	} else if (content) {
		return _renderHtml(content, options);
	}
}

function _renderHtml(content: IHTMLContentElement, options: RenderOptions = {}): Node {

	let {codeBlockRenderer, actionCallback} = options;

	if (content.isText) {
		return document.createTextNode(content.text);
	}

	var tagName = getSafeTagName(content.tagName) || 'div';
	var element = document.createElement(tagName);

	if (content.className) {
		element.className = content.className;
	}
	if (content.text) {
		element.textContent = content.text;
	}
	if (content.style) {
		element.setAttribute('style', content.style);
	}
	if (content.customStyle) {
		Object.keys(content.customStyle).forEach((key) => {
			element.style[key] = content.customStyle[key];
		});
	}
	if (content.code && codeBlockRenderer) {
		let html = codeBlockRenderer(content.code.language, content.code.value);
		element.innerHTML = html;
	}
	if (content.children) {
		content.children.forEach((child) => {
			element.appendChild(renderHtml(child, options));
		});
	}
	if (content.formattedText) {
		renderFormattedText(element, parseFormattedText(content.formattedText), actionCallback);
	}
	if (content.markdown) {
		const renderer = new marked.Renderer();
		renderer.link = (href, title, text): string => {
			return `<a href="#" data-href="${href}" title="${title || text}">${text}</a>`
		}

		if (options.codeBlockRenderer) {
			renderer.code = (code, lang) => {
				return options.codeBlockRenderer(lang, code);
			}
		}

		if (options.actionCallback) {
			DOM.addStandardDisposableListener(element, 'click', event => {
				if (event.target.tagName === 'A') {
					const href = event.target.dataset['href'];
					if (href) {
						options.actionCallback(href, event);
					}
				}
			});
		}

		element.innerHTML = marked(content.markdown, {
			sanitize: true,
			renderer
		});
	}

	return element;
}

var SAFE_TAG_NAMES = {
	a: true,
	b: true,
	blockquote: true,
	code: true,
	del: true,
	dd: true,
	div: true,
	dl: true,
	dt: true,
	em: true,
	h1h2h3i: true,
	img: true,
	kbd: true,
	li: true,
	ol: true,
	p: true,
	pre: true,
	s: true,
	span: true,
	sup: true,
	sub: true,
	strong: true,
{'fraction_non_alphanumeric': 0.18432685867381113, 'fraction_numerical': 0.0008037508372404555, 'mean_word_length': 3.415138971023063, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2968032', 'n_tokens_mistral': 2419, 'n_tokens_neox': 2278, 'n_words': 580}