= {
+ 'table': true,
+ 'thead': true,
+ 'tbody': true,
+ 'tfoot': true,
+ 'tr': true,
+ 'colgroup': true
+};
+
/**
* Checks if a node is nested inside a element.
* In elements, whitespace must be preserved per HTML spec.
@@ -107,6 +119,19 @@ function isInsidePreElement(node: HtmlNode | undefined): boolean {
return false;
}
+/**
+ * Checks if a node is a table elemen
+ *
+ * @param node The node to check (typically parent of a text node)
+ * @returns true if node is a table element
+ */
+function isTableElement(node: HtmlNode | undefined): boolean {
+ if (!node || !node.name) {
+ return false;
+ }
+ return tableElements[node.name] === true;
+}
+
/**
* Parses a single HTML tag.
*
@@ -321,14 +346,22 @@ export function parseHtml(html: string): Array {
nextChar &&
nextChar !== '<'
) {
- // This is a text node; add it as a child node
- if (current.children === undefined) {
- current.children = [];
+ const textContent = html.slice(start, html.indexOf('<', start));
+ const isWhitespace = whitespaceRE.test(textContent);
+ // Check if we are in a table element context with whitespace-only text node
+ const whitespaceInTable = isWhitespace && isTableElement(current);
+
+ // Don't add whitespace-only text nodes if they are inside table elements
+ if (!whitespaceInTable) {
+ // This is a text node; add it as a child node
+ if (current.children === undefined) {
+ current.children = [];
+ }
+ current.children.push({
+ type: 'text',
+ content: decode(textContent),
+ });
}
- current.children.push({
- type: 'text',
- content: decode(html.slice(start, html.indexOf('<', start))),
- });
}
// if we're at root, push new base node
@@ -383,11 +416,14 @@ export function parseHtml(html: string): Array {
content = ' ';
}
- // Don't add whitespace-only text nodes if they would be trailing text nodes
- // or if they would be leading whitespace-only text nodes:
+ // Check if we are in a table element context with whitespace-only text node
+ const whitespaceInTable = whitespaceRE.test(content) && isTableElement(current);
+
+ // Don't add whitespace-only text nodes if they would be: trailing text nodes
+ // leading whitespace-only text nodes, or inside table elements:
// * end > -1 indicates this is not a trailing text node
// * leading node is when level is -1 and parent has length 0
- if ((end > -1 && level + parent.length >= 0) || content !== ' ') {
+ if (!whitespaceInTable && ((end > -1 && level + parent.length >= 0) || content !== ' ')) {
parent.push({
type: 'text',
parent: current,
diff --git a/src/vs/workbench/contrib/positronNotebook/browser/markdownRenderer.ts b/src/vs/workbench/contrib/positronNotebook/browser/markdownRenderer.ts
index 05a86394987..d0634ba2a87 100644
--- a/src/vs/workbench/contrib/positronNotebook/browser/markdownRenderer.ts
+++ b/src/vs/workbench/contrib/positronNotebook/browser/markdownRenderer.ts
@@ -108,7 +108,10 @@ function markedHighlight(options: marked.MarkedOptions & {
code({ text, lang, escaped }: marked.Tokens.Code) {
const classAttr = lang ? ` class="language-${escape(lang)}"` : '';
text = text.replace(/\n$/, '');
- return `${escaped ? text : escape(text)}\n
`;
+ // Note: We intentionally omit the trailing \n that marked-highlight includes.
+ // The \n is preserved by 's default white-space:pre behavior
+ // this causes visible whitespace at the bottom of code blocks in Positron notebooks.
+ return `${escaped ? text : escape(text)}
`;
},
},
};
diff --git a/src/vs/workbench/contrib/positronNotebook/browser/notebookCells/Markdown.css b/src/vs/workbench/contrib/positronNotebook/browser/notebookCells/Markdown.css
index c7206821720..e8e09ae8b35 100644
--- a/src/vs/workbench/contrib/positronNotebook/browser/notebookCells/Markdown.css
+++ b/src/vs/workbench/contrib/positronNotebook/browser/notebookCells/Markdown.css
@@ -101,6 +101,7 @@
table {
border-collapse: collapse;
border-spacing: 0;
+ margin-bottom: 0.7em;
}
table th,
@@ -125,21 +126,35 @@
}
blockquote {
- margin: 0 7px 0 5px;
+ margin: 0 7px 0 0;
padding: 0 16px 0 10px;
border-left-width: 5px;
border-left-style: solid;
+ border-left-color: var(--vscode-textBlockQuote-border);
+ background-color: var(--vscode-textBlockQuote-background);
}
+ /* inline code styling */
code {
font-size: 1em;
font-family: var(--vscode-repl-font-family);
+ background-color: var(--vscode-textPreformat-background);
+ padding: 1px 3px;
+ border-radius: 4px;
+ }
+
+ /** code block styling */
+ pre {
+ background-color: var(--vscode-textCodeBlock-background);
+ padding: 16px;
+ border-radius: 4px;
}
pre code {
line-height: 1.357em;
white-space: pre-wrap;
padding: 0;
+ background-color: transparent; /* override inline code style */
}
li p {