mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-03 09:35:40 -05:00
@@ -236,11 +236,14 @@ export class MarkdownToolbarComponent extends AngularDisposable {
|
||||
needsTransform = false;
|
||||
} else {
|
||||
let linkUrl = linkCalloutResult.insertUnescapedLinkUrl;
|
||||
const isFile = URI.parse(linkUrl).scheme === 'file';
|
||||
if (isFile && !path.isAbsolute(linkUrl)) {
|
||||
const notebookDirName = path.dirname(this.cellModel?.notebookModel?.notebookUri.fsPath);
|
||||
const relativePath = (linkUrl).replace(/\\/g, path.posix.sep);
|
||||
linkUrl = path.resolve(notebookDirName, relativePath);
|
||||
const isAnchorLink = linkUrl.startsWith('#');
|
||||
if (!isAnchorLink) {
|
||||
const isFile = URI.parse(linkUrl).scheme === 'file';
|
||||
if (isFile && !path.isAbsolute(linkUrl)) {
|
||||
const notebookDirName = path.dirname(this.cellModel?.notebookModel?.notebookUri.fsPath);
|
||||
const relativePath = (linkUrl).replace(/\\/g, path.posix.sep);
|
||||
linkUrl = path.resolve(notebookDirName, relativePath);
|
||||
}
|
||||
}
|
||||
// Otherwise, re-focus on the output element, and insert the link directly.
|
||||
this.output?.nativeElement?.focus();
|
||||
|
||||
@@ -132,15 +132,28 @@ export class HTMLMarkdownConverter {
|
||||
this.turndownService.addRule('a', {
|
||||
filter: 'a',
|
||||
replacement: (content, node) => {
|
||||
//On Windows, if notebook is not trusted then the href attr is removed for all non-web URL links
|
||||
// href contains either a hyperlink or a URI-encoded absolute path. (See resolveUrls method in notebookMarkdown.ts)
|
||||
const notebookLink = node.href ? URI.parse(node.href) : URI.file(node.title);
|
||||
const notebookFolder = this.notebookUri ? path.join(path.dirname(this.notebookUri.fsPath), path.sep) : '';
|
||||
let relativePath = findPathRelativeToContent(notebookFolder, notebookLink);
|
||||
if (relativePath) {
|
||||
return `[${node.innerText}](${relativePath})`;
|
||||
let href = node.href;
|
||||
let notebookLink: URI | undefined;
|
||||
const isAnchorLinkInFile = (node.attributes.href?.nodeValue.startsWith('#') || href.includes('#')) && href.startsWith('file://');
|
||||
if (isAnchorLinkInFile) {
|
||||
notebookLink = getUriAnchorLink(node, this.notebookUri);
|
||||
} else {
|
||||
//On Windows, if notebook is not trusted then the href attr is removed for all non-web URL links
|
||||
// href contains either a hyperlink or a URI-encoded absolute path. (See resolveUrls method in notebookMarkdown.ts)
|
||||
notebookLink = href ? URI.parse(href) : URI.file(node.title);
|
||||
}
|
||||
return `[${content}](${node.href})`;
|
||||
const notebookFolder = this.notebookUri ? path.join(path.dirname(this.notebookUri.fsPath), path.sep) : '';
|
||||
if (notebookLink.fsPath !== this.notebookUri.fsPath) {
|
||||
let relativePath = findPathRelativeToContent(notebookFolder, notebookLink);
|
||||
if (relativePath) {
|
||||
return `[${node.innerText}](${relativePath})`;
|
||||
}
|
||||
} else if (notebookLink?.fragment) {
|
||||
// if the anchor link is to a section in the same notebook then just add the fragment
|
||||
return `[${content}](${notebookLink.fragment})`;
|
||||
}
|
||||
|
||||
return `[${content}](${href})`;
|
||||
}
|
||||
});
|
||||
// Only nested list case differs from original turndown rule
|
||||
@@ -275,7 +288,7 @@ function blankReplacement(content, node) {
|
||||
export function findPathRelativeToContent(notebookFolder: string, contentPath: URI | undefined): string {
|
||||
if (notebookFolder) {
|
||||
if (contentPath?.scheme === 'file') {
|
||||
let relativePath = path.relative(notebookFolder, contentPath.fsPath);
|
||||
let relativePath = contentPath.fragment ? path.relative(notebookFolder, contentPath.fsPath).concat('#', contentPath.fragment) : path.relative(notebookFolder, contentPath.fsPath);
|
||||
//if path contains whitespaces then it's not identified as a link
|
||||
relativePath = relativePath.replace(/\s/g, '%20');
|
||||
if (relativePath.startsWith(path.join('..', path.sep) || path.join('.', path.sep))) {
|
||||
@@ -295,3 +308,15 @@ export function addHighlightIfYellowBgExists(node, content: string): string {
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
export function getUriAnchorLink(node, notebookUri: URI): URI {
|
||||
const sectionLinkToAnotherFile = node.href.includes('#') && !node.attributes.href?.nodeValue.startsWith('#');
|
||||
if (sectionLinkToAnotherFile) {
|
||||
let absolutePath = !path.isAbsolute(node.attributes.href?.nodeValue) ? path.resolve(path.dirname(notebookUri.fsPath), node.attributes.href?.nodeValue) : node.attributes.href?.nodeValue;
|
||||
// if section link is different from the current notebook
|
||||
return URI.file(absolutePath);
|
||||
} else {
|
||||
// else build an uri using the current notebookUri
|
||||
return URI.from({ scheme: 'file', path: notebookUri.path, fragment: node.attributes.href?.nodeValue });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +143,12 @@ suite('HTML Markdown Converter', function (): void {
|
||||
assert.equal(htmlMarkdownConverter.convert(htmlString), '[msft](http://www.microsoft.com/images/msft.png)', 'Basic http link test failed');
|
||||
htmlString = 'Test <a href="http://www.microsoft.com/images/msft.png">msft</a>';
|
||||
assert.equal(htmlMarkdownConverter.convert(htmlString), 'Test [msft](http://www.microsoft.com/images/msft.png)', 'Basic http link + text test failed');
|
||||
htmlString = '<a href="#hello">hello</a>';
|
||||
assert.equal(htmlMarkdownConverter.convert(htmlString), '[hello](#hello)', 'Basic link to a section failed');
|
||||
htmlString = '<a href="file.md#hello">hello</a>';
|
||||
assert.equal(htmlMarkdownConverter.convert(htmlString), `[hello](.${path.sep}file.md#hello)`, 'Basic anchor link to a section failed');
|
||||
htmlString = '<a href="http://www.microsoft.com/images/msft.png#Hello">hello</a>';
|
||||
assert.equal(htmlMarkdownConverter.convert(htmlString), '[hello](http://www.microsoft.com/images/msft.png#Hello)', 'Http link containing # sign failed');
|
||||
});
|
||||
|
||||
test('Should transform <li> tags', () => {
|
||||
|
||||
Reference in New Issue
Block a user