htmlContent.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. import { illegalArgument } from './errors.js';
  6. import { escapeIcons } from './iconLabels.js';
  7. import { isEqual } from './resources.js';
  8. import { escapeRegExpCharacters } from './strings.js';
  9. import { URI } from './uri.js';
  10. export class MarkdownString {
  11. constructor(value = '', isTrustedOrOptions = false) {
  12. var _a, _b, _c;
  13. this.value = value;
  14. if (typeof this.value !== 'string') {
  15. throw illegalArgument('value');
  16. }
  17. if (typeof isTrustedOrOptions === 'boolean') {
  18. this.isTrusted = isTrustedOrOptions;
  19. this.supportThemeIcons = false;
  20. this.supportHtml = false;
  21. }
  22. else {
  23. this.isTrusted = (_a = isTrustedOrOptions.isTrusted) !== null && _a !== void 0 ? _a : undefined;
  24. this.supportThemeIcons = (_b = isTrustedOrOptions.supportThemeIcons) !== null && _b !== void 0 ? _b : false;
  25. this.supportHtml = (_c = isTrustedOrOptions.supportHtml) !== null && _c !== void 0 ? _c : false;
  26. }
  27. }
  28. appendText(value, newlineStyle = 0 /* MarkdownStringTextNewlineStyle.Paragraph */) {
  29. this.value += escapeMarkdownSyntaxTokens(this.supportThemeIcons ? escapeIcons(value) : value)
  30. .replace(/([ \t]+)/g, (_match, g1) => ' '.repeat(g1.length))
  31. .replace(/\>/gm, '\\>')
  32. .replace(/\n/g, newlineStyle === 1 /* MarkdownStringTextNewlineStyle.Break */ ? '\\\n' : '\n\n');
  33. return this;
  34. }
  35. appendMarkdown(value) {
  36. this.value += value;
  37. return this;
  38. }
  39. appendCodeblock(langId, code) {
  40. this.value += '\n```';
  41. this.value += langId;
  42. this.value += '\n';
  43. this.value += code;
  44. this.value += '\n```\n';
  45. return this;
  46. }
  47. appendLink(target, label, title) {
  48. this.value += '[';
  49. this.value += this._escape(label, ']');
  50. this.value += '](';
  51. this.value += this._escape(String(target), ')');
  52. if (title) {
  53. this.value += ` "${this._escape(this._escape(title, '"'), ')')}"`;
  54. }
  55. this.value += ')';
  56. return this;
  57. }
  58. _escape(value, ch) {
  59. const r = new RegExp(escapeRegExpCharacters(ch), 'g');
  60. return value.replace(r, (match, offset) => {
  61. if (value.charAt(offset - 1) !== '\\') {
  62. return `\\${match}`;
  63. }
  64. else {
  65. return match;
  66. }
  67. });
  68. }
  69. }
  70. export function isEmptyMarkdownString(oneOrMany) {
  71. if (isMarkdownString(oneOrMany)) {
  72. return !oneOrMany.value;
  73. }
  74. else if (Array.isArray(oneOrMany)) {
  75. return oneOrMany.every(isEmptyMarkdownString);
  76. }
  77. else {
  78. return true;
  79. }
  80. }
  81. export function isMarkdownString(thing) {
  82. if (thing instanceof MarkdownString) {
  83. return true;
  84. }
  85. else if (thing && typeof thing === 'object') {
  86. return typeof thing.value === 'string'
  87. && (typeof thing.isTrusted === 'boolean' || typeof thing.isTrusted === 'object' || thing.isTrusted === undefined)
  88. && (typeof thing.supportThemeIcons === 'boolean' || thing.supportThemeIcons === undefined);
  89. }
  90. return false;
  91. }
  92. export function markdownStringEqual(a, b) {
  93. if (a === b) {
  94. return true;
  95. }
  96. else if (!a || !b) {
  97. return false;
  98. }
  99. else {
  100. return a.value === b.value
  101. && a.isTrusted === b.isTrusted
  102. && a.supportThemeIcons === b.supportThemeIcons
  103. && a.supportHtml === b.supportHtml
  104. && (a.baseUri === b.baseUri || !!a.baseUri && !!b.baseUri && isEqual(URI.from(a.baseUri), URI.from(b.baseUri)));
  105. }
  106. }
  107. export function escapeMarkdownSyntaxTokens(text) {
  108. // escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash
  109. return text.replace(/[\\`*_{}[\]()#+\-!~]/g, '\\$&');
  110. }
  111. export function escapeDoubleQuotes(input) {
  112. return input.replace(/"/g, '"');
  113. }
  114. export function removeMarkdownEscapes(text) {
  115. if (!text) {
  116. return text;
  117. }
  118. return text.replace(/\\([\\`*_{}[\]()#+\-.!~])/g, '$1');
  119. }
  120. export function parseHrefAndDimensions(href) {
  121. const dimensions = [];
  122. const splitted = href.split('|').map(s => s.trim());
  123. href = splitted[0];
  124. const parameters = splitted[1];
  125. if (parameters) {
  126. const heightFromParams = /height=(\d+)/.exec(parameters);
  127. const widthFromParams = /width=(\d+)/.exec(parameters);
  128. const height = heightFromParams ? heightFromParams[1] : '';
  129. const width = widthFromParams ? widthFromParams[1] : '';
  130. const widthIsFinite = isFinite(parseInt(width));
  131. const heightIsFinite = isFinite(parseInt(height));
  132. if (widthIsFinite) {
  133. dimensions.push(`width="${width}"`);
  134. }
  135. if (heightIsFinite) {
  136. dimensions.push(`height="${height}"`);
  137. }
  138. }
  139. return { href, dimensions };
  140. }