jiebi/CodeConvo huggingface dataset:
await this._webview?.removeMarkdownPreview(cell.id); } <ins> async updateMarkdownPreviewSelectionState(cell: ICellViewModel, isSelected: boolean): Promise<void> { if (!this._webview) { return; } await this._resolveWebview(); await this._webview?.updateMarkdownPreviewSelectionState(cell.id, isSelected); } </ins> async createInset(cell: CodeCellViewModel, output: IInsetRenderOutput, offset: number): Promise<void> { this._insetModifyQueueByOutputId.queue(output.source.model.outputId, async () => { if (!this._webview) {
}); } <ins> async updateMarkdownPreviewSelectionState(cellId: any, isSelected: boolean) { if (this._disposed) { return; } this._sendMessageToWebview({ type: 'updateMarkdownPreviewSelectionState', id: cellId, isSelected }); } async updateMarkdownPreviewDecpratopms(cellId: any, isSelected: boolean) { if (this._disposed) { return; } this._sendMessageToWebview({ type: 'updateMarkdownPreviewSelectionState', id: cellId, isSelected }); } </ins> async initializeMarkdown(cells: Array<{ cellId: string, content: string }>) { await this._loaded;
} private updateForLayout(element: MarkdownCellViewModel, templateData: MarkdownCellRenderTemplate): void { <del> // templateData.focusIndicatorLeft.style.height = `${element.layoutInfo.indicatorHeight}px`; </del> templateData.focusIndicatorBottom.style.top = `${element.layoutInfo.totalHeight - BOTTOM_CELL_TOOLBAR_GAP - CELL_BOTTOM_MARGIN}px`; const focusSideHeight = element.layoutInfo.totalHeight - BOTTOM_CELL_TOOLBAR_GAP;
} })); <ins> // Update for selection if (this.useRenderer) { this._register(this.notebookEditor.onDidChangeSelection(() => { const selectedCells = this.notebookEditor.getSelectionViewModels(); const isSelected = selectedCells.length > 1 && selectedCells.some(selectedCell => selectedCell === viewCell); this.notebookEditor.updateMarkdownPreviewSelectionState(viewCell, isSelected); })); } // apply decorations </ins> this._register(viewCell.onCellDecorationsChanged((e) => { e.added.forEach(options => { if (options.className) { <del> templateData.rootContainer.classList.add(options.className); </del> <ins> if (this.useRenderer) { this.notebookEditor.deltaCellOutputContainerClassNames(this.viewCell.id, [options.className], []); } else { templateData.rootContainer.classList.add(options.className); } </ins> } }); e.removed.forEach(options => { if (options.className) { <del> templateData.rootContainer.classList.remove(options.className); </del> <ins> if (this.useRenderer) { this.notebookEditor.deltaCellOutputContainerClassNames(this.viewCell.id, [], [options.className]); } else { templateData.rootContainer.classList.remove(options.className); } </ins> } }); })); <del> // apply decorations </del> viewCell.getCellDecorations().forEach(options => { if (options.className) { <del> templateData.rootContainer.classList.add(options.className); </del> <ins> if (this.useRenderer) { this.notebookEditor.deltaCellOutputContainerClassNames(this.viewCell.id, [options.className], []); } else { templateData.rootContainer.classList.add(options.className); } </ins> } });
const data = event.data; let cellContainer = document.getElementById(data.id); if (cellContainer) { <del> cellContainer?.parentElement?.removeChild(cellContainer); </del> <ins> cellContainer.parentElement?.removeChild(cellContainer); } } break; case 'updateMarkdownPreviewSelectionState': { const data = event.data; const previewNode = document.getElementById(`${data.id}_preview`); if (previewNode) { previewNode.classList.toggle('selected', data.isSelected); </ins> } } break;
markdownCellDragEnd(cellId: string, position: { clientY: number }): void { throw new Error('Method not implemented.'); } <ins> updateMarkdownPreviewSelectionState(cell: ICellViewModel, isSelected: boolean): Promise<void> { throw new Error('Method not implemented.'); } </ins> async beginComputeContributedKernels(): Promise<INotebookKernel[]> { return []; }
protected _modifyText(text: string, wordSeparators: string): string { return (text .replace(/(p{Ll})(p{Lu})/gmu, '$1_$2') <del> .replace(/([^b_])(p{Lu})(p{Ll})/gmu, '$1_$2$3') </del> <ins> .replace(/(p{Lu}|p{N})(p{Lu})(p{Ll})/gmu, '$1_$2$3') </ins> .toLocaleLowerCase() ); }
`function helloWorld() { return someGlobalObject.printHelloWorld("en", "utf-8"); } <del> helloWorld();`.replace(/^s+/gm, '') </del> <ins> helloWorld();`.replace(/^s+/gm, ''), `'JavaScript'`, 'parseHTML4String', '_accessor: ServicesAccessor' </ins> ], {}, (editor) => { let model = editor.getModel()!; let uppercaseAction = new UpperCaseAction();
} hello_world();`.replace(/^s+/gm, '')); assertSelection(editor, new Selection(14, 1, 17, 15)); <ins> editor.setSelection(new Selection(18, 1, 18, 13)); executeAction(snakecaseAction, editor); assert.strictEqual(model.getLineContent(18), `'java_script'`); assertSelection(editor, new Selection(18, 1, 18, 14)); editor.setSelection(new Selection(19, 1, 19, 17)); executeAction(snakecaseAction, editor); assert.strictEqual(model.getLineContent(19), 'parse_html4_string'); assertSelection(editor, new Selection(19, 1, 19, 19)); editor.setSelection(new Selection(20, 1, 20, 28)); executeAction(snakecaseAction, editor); assert.strictEqual(model.getLineContent(20), '_accessor: services_accessor'); assertSelection(editor, new Selection(20, 1, 20, 29)); </ins> } );
return this._remoteTerminalChannel.setTerminalLayoutInfo(layout); } <del> public getTerminalLayoutInfo(): Promise<ITerminalsLayoutInfo | undefined> { </del> <ins> public async getTerminalLayoutInfo(): Promise<ITerminalsLayoutInfo | undefined> { await this._remoteTerminalChannel?.listProcesses(true); </ins> if (!this._remoteTerminalChannel) { throw new Error(`Cannot call getActiveInstanceId when there is no remote`); }
private async onDidClickPreviewLink(href: string) { let [hrefPath, fragment] = decodeURIComponent(href).split('#'); <del> // We perviously already resolve absolute paths. // Now make sure we handle relative file paths </del> if (hrefPath[0] !== '/') { <del> // Fix #93691, use this.resource.fsPath instead of this.resource.path hrefPath = path.join(path.dirname(this.resource.fsPath), hrefPath); </del> <ins> // We perviously already resolve absolute paths. // Now make sure we handle relative file paths const dirnameUri = vscode.Uri.parse(path.dirname(this.resource.path)); hrefPath = vscode.Uri.joinPath(dirnameUri, hrefPath).path; </ins> } else { // Handle any normalized file paths <del> hrefPath = vscode.Uri.parse(hrefPath.replace('/file', '')).fsPath; </del> <ins> hrefPath = vscode.Uri.parse(hrefPath.replace('/file', '')).path; </ins> } const config = vscode.workspace.getConfiguration('markdown', this.resource);
assert.strictEqual(count, 0); }); <ins> test('correct cell selection on undo/redo of cell creation', async function () { const resource = await createRandomFile('', undefined, '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); await vscode.commands.executeCommand('undo'); const selectionUndo = [...vscode.window.activeNotebookEditor!.selections]; await vscode.commands.executeCommand('redo'); const selectionRedo = vscode.window.activeNotebookEditor!.selections; // On undo, the selected cell must be the upper cell, ie the first one assert.strictEqual(selectionUndo.length, 1); assert.strictEqual(selectionUndo[0].start, 0); assert.strictEqual(selectionUndo[0].end, 1); // On redo, the selected cell must be the new cell, ie the second one assert.strictEqual(selectionRedo.length, 1); assert.strictEqual(selectionRedo[0].start, 1); assert.strictEqual(selectionRedo[0].end, 2); }); </ins> test('editor editing event 2', async function () { const resource = await createRandomFile('', undefined, '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
} async runWithContext(accessor: ServicesAccessor, context: INotebookActionContext): Promise<void> { <del> const newCell = context.notebookEditor.insertNotebookCell(context.cell, this.kind, this.direction, undefined, true); if (newCell) { context.notebookEditor.focusNotebookCell(newCell, 'editor'); } </del> <ins> context.notebookEditor.insertNotebookCell(context.cell, this.kind, this.direction, undefined, true); </ins> } }
createCell(index: number, source: string, language: string, type: CellKind, metadata: NotebookCellMetadata | undefined, outputs: IOutputDto[], synchronous: boolean, pushUndoStop: boolean = true, previouslyPrimary: number | null = null, previouslyFocused: ICellViewModel[] = []): CellViewModel { const beforeSelections = previouslyFocused.map(e => e.handle); <ins> const endSelections: ISelectionState = { kind: SelectionStateType.Index, focus: { start: index, end: index + 1 }, selections: [{ start: index, end: index + 1 }] }; </ins> this._notebook.applyEdits([ { editType: CellEditType.Replace,
if (useWslProfiles) { const distroOutput = await new Promise<string>((resolve, reject) => { // wsl.exe output is encoded in utf16le (ie. A -> 0x4100) <del> cp.exec('wsl.exe -l', { encoding: 'utf16le' }, (err, stdout) => { </del> <ins> cp.exec('wsl.exe -l -q', { encoding: 'utf16le' }, (err, stdout) => { </ins> if (err) { return reject('Problem occurred when getting wsl distros'); }
if (distroOutput) { const regex = new RegExp(/[r?n]/); const distroNames = distroOutput.split(regex).filter(t => t.trim().length > 0 && t !== ''); <del> // don't need the Windows Subsystem for Linux Distributions header distroNames.shift(); </del> for (let distroName of distroNames) { <del> // Remove default from distro name distroName = distroName.replace(/ (Default)$/, ''); </del> // Skip empty lines if (distroName === '') { continue;
this.textArea.setAttribute('aria-haspopup', 'false'); this.textArea.setAttribute('aria-autocomplete', 'both'); <del> if (options.get(EditorOption.domReadOnly)) { </del> <ins> if (options.get(EditorOption.domReadOnly) && options.get(EditorOption.readOnly)) { </ins> this.textArea.setAttribute('readonly', 'true'); }
this.textArea.setAttribute('aria-label', this._getAriaLabel(options)); this.textArea.setAttribute('tabindex', String(options.get(EditorOption.tabIndex))); <del> if (e.hasChanged(EditorOption.domReadOnly)) { if (options.get(EditorOption.domReadOnly)) { </del> <ins> if (e.hasChanged(EditorOption.domReadOnly) || e.hasChanged(EditorOption.readOnly)) { if (options.get(EditorOption.domReadOnly) && options.get(EditorOption.readOnly)) { </ins> this.textArea.setAttribute('readonly', 'true'); } else { this.textArea.removeAttribute('readonly');
import { ModesGlyphHoverWidget } from 'vs/editor/contrib/hover/modesGlyphHover'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IOpenerService } from 'vs/platform/opener/common/opener'; <del> import { editorHoverBackground, editorHoverBorder, editorHoverHighlight, textCodeBlockBackground, textLinkForeground, editorHoverStatusBarBackground, editorHoverForeground } from 'vs/platform/theme/common/colorRegistry'; </del> <ins> import { editorHoverBackground, editorHoverBorder, editorHoverHighlight, textCodeBlockBackground, textLinkForeground, editorHoverStatusBarBackground, editorHoverForeground, textLinkActiveForeground } from 'vs/platform/theme/common/colorRegistry'; </ins> import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; import { GotoDefinitionAtPositionEditorContribution } from 'vs/editor/contrib/gotoSymbol/link/goToDefinitionAtPosition';
if (link) { collector.addRule(`.monaco-editor .monaco-hover a { color: ${link}; }`); } <ins> const linkHover = theme.getColor(textLinkActiveForeground); if (linkHover) { collector.addRule(`.monaco-editor .monaco-hover a:hover { color: ${linkHover}; }`); } </ins> const hoverForeground = theme.getColor(editorHoverForeground); if (hoverForeground) { collector.addRule(`.monaco-editor .monaco-hover { color: ${hoverForeground}; }`);
assert.deepStrictEqual(Array.from(container.querySelectorAll('.monaco-list-row')).map(e => e.textContent), ['a', 'b2']); }); <ins> test('issue #121567', async () => { const container = document.createElement('div'); const calls: Element[] = []; const dataSource = new class implements IAsyncDataSource<Element, Element> { hasChildren(element: Element): boolean { return !!element.children && element.children.length > 0; } async getChildren(element: Element) { calls.push(element); return element.children ?? Iterable.empty(); } }; const model = new Model({ id: 'root', children: [{ id: 'a', children: [{ id: 'aa' }] }] }); const a = model.get('a'); const tree = new AsyncDataTree<Element, Element>('test', container, new VirtualDelegate(), [new Renderer()], dataSource, { identityProvider: new IdentityProvider() }); tree.layout(200); await tree.setInput(model.root); assert.strictEqual(calls.length, 1, 'There should be a single getChildren call for the root'); assert(tree.isCollapsible(a), 'a is collapsible'); assert(tree.isCollapsed(a), 'a is collapsed'); await tree.updateChildren(a, false); assert.strictEqual(calls.length, 1, 'There should be no changes to the calls list, since a was collapsed'); assert(tree.isCollapsible(a), 'a is collapsible'); assert(tree.isCollapsed(a), 'a is collapsed'); const children = a.children; a.children = []; await tree.updateChildren(a, false); assert.strictEqual(calls.length, 1, 'There should still be no changes to the calls list, since a was collapsed'); assert(!tree.isCollapsible(a), 'a is no longer collapsible'); assert(tree.isCollapsed(a), 'a is collapsed'); a.children = children; await tree.updateChildren(a, false); assert.strictEqual(calls.length, 1, 'There should still be no changes to the calls list, since a was collapsed'); assert(tree.isCollapsible(a), 'a is collapsible again'); assert(tree.isCollapsed(a), 'a is collapsed'); await tree.expand(a); assert.strictEqual(calls.length, 2, 'Finally, there should be a getChildren call for a'); assert(tree.isCollapsible(a), 'a is still collapsible'); assert(!tree.isCollapsed(a), 'a is expanded'); }); </ins> });
import { Event } from 'vs/base/common/event'; const WAIT_TIME_TO_SHOW_SURVEY = 1000 * 60 * 60; // 1 hour <del> const MIN_WAIT_TIME_TO_SHOW_SURVEY = 1000 * 60 * 5; // 5 minutes </del> <ins> const MIN_WAIT_TIME_TO_SHOW_SURVEY = 1000 * 60 * 2; // 2 minutes </ins> const MAX_INSTALL_AGE = 1000 * 60 * 60 * 24; // 24 hours const REMIND_LATER_DELAY = 1000 * 60 * 60 * 4; // 4 hours const SKIP_SURVEY_KEY = 'ces/skipSurvey';
run: () => { sendTelemetry('accept'); this.telemetryService.getTelemetryInfo().then(info => { <del> this.openerService.open(URI.parse(`${this.productService.cesSurveyUrl}?o=${encodeURIComponent(platform)}&v=${encodeURIComponent(this.productService.version)}&m=${encodeURIComponent(info.machineId)}`)); </del> <ins> let surveyUrl = `${this.productService.cesSurveyUrl}?o=${encodeURIComponent(platform)}&v=${encodeURIComponent(this.productService.version)}&m=${encodeURIComponent(info.machineId)}`; const usedParams = this.productService.surveys ?.filter(surveyData => surveyData.surveyId && surveyData.languageId) // Counts provided by contrib/surveys/browser/languageSurveys .filter(surveyData => this.storageService.getNumber(`${surveyData.surveyId}.editedCount`, StorageScope.GLOBAL, 0) > 0) .map(surveyData => `${encodeURIComponent(surveyData.languageId)}Lang=1`) .join('&'); if (usedParams) { surveyUrl += `&${usedParams}`; } this.openerService.open(URI.parse(surveyUrl)); </ins> this.skipSurvey(); }); }
import { ContributedEditorInfo, ContributedEditorPriority, ContributionPointOptions, DEFAULT_EDITOR_ASSOCIATION, DiffEditorInputFactoryFunction, EditorAssociation, EditorAssociations, EditorInputFactoryFunction, editorsAssociationsSettingId, globMatchesResource, IEditorOverrideService, priorityToRank } from 'vs/workbench/services/editor/common/editorOverrideService'; import { IKeyMods, IQuickInputService, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; import { localize } from 'vs/nls'; <del> import { Codicon } from 'vs/base/common/codicons'; </del> import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
export class EditorOverrideService extends Disposable implements IEditorOverrideService { readonly _serviceBrand: undefined; <ins> private static readonly configureDefaultID = 'promptOpenWith.configureDefault'; </ins> private _contributionPoints: Map<string | glob.IRelativePattern, ContributionPoints> = new Map<string | glob.IRelativePattern, ContributionPoints>(); private static readonly overrideCacheStorageID = 'editorOverrideService.cache'; private cache: Set<string> | undefined;
}); } <del> private mapContributionsToQuickPickEntry(resource: URI, group: IEditorGroup, alwaysUpdateSetting?: boolean) { </del> <ins> private mapContributionsToQuickPickEntry(resource: URI, group: IEditorGroup, showDefaultPicker?: boolean) { </ins> const currentEditor = firstOrDefault(group.findEditors(resource)); // If untitled, we want all contribution points let contributionPoints = resource.scheme === Schemas.untitled ? distinct(flatten(Array.from(this._contributionPoints.values())), (contrib) => contrib.editorInfo.id) : this.findMatchingContributions(resource);
return priorityToRank(b.editorInfo.priority) - priorityToRank(a.editorInfo.priority); } }); <del> const contribGroups: { defaults: Array<IQuickPickSeparator | IQuickPickItem>, optional: Array<IQuickPickSeparator | IQuickPickItem> } = { defaults: [ { type: 'separator', label: localize('editorOverride.picker.default', 'Defaults') } ], optional: [ { type: 'separator', label: localize('editorOverride.picker.optional', 'Optional') } ], }; </del> <ins> const quickPickEntries: Array<IQuickPickItem | IQuickPickSeparator> = []; </ins> // Get the matching contribtuions and call resolve whether they're active for the picker contributionPoints.forEach(contribPoint => { const isActive = currentEditor ? contribPoint.editorInfo.describes(currentEditor) : false; <del> const quickPickEntry = { </del> <ins> const quickPickEntry: IQuickPickItem = { </ins> id: contribPoint.editorInfo.id, label: contribPoint.editorInfo.label, description: isActive ? localize('promptOpenWith.currentlyActive', "Currently Active") : undefined, detail: contribPoint.editorInfo.detail ?? contribPoint.editorInfo.priority, <del> buttons: alwaysUpdateSetting ? [] : [{ iconClass: Codicon.gear.classNames, tooltip: localize('promptOpenWith.setDefaultTooltip', "Set as default editor for '{0}' files", extname(resource)) }], </del> }; <del> if (contribPoint.editorInfo.priority === ContributedEditorPriority.option) { contribGroups.optional.push(quickPickEntry); } else { contribGroups.defaults.push(quickPickEntry); } </del> <ins> quickPickEntries.push(quickPickEntry); </ins> }); <del> return [...contribGroups.defaults, ...contribGroups.optional]; </del> <ins> if (!showDefaultPicker) { const separator: IQuickPickSeparator = { type: 'separator' }; quickPickEntries.push(separator); const configureDefaultEntry = { id: EditorOverrideService.configureDefaultID, label: localize('promptOpenWith.configureDefault', "Configure default editor....") }; quickPickEntries.push(configureDefaultEntry); } return quickPickEntries; </ins> } <del> private async doPickEditorOverride(editor: IEditorInput, options: IEditorOptions | undefined, group: IEditorGroup, alwaysUpdateSetting?: boolean): Promise<[IEditorOptions, IEditorGroup | undefined] | undefined> { </del> <ins> private async doPickEditorOverride(editor: IEditorInput, options: IEditorOptions | undefined, group: IEditorGroup, showDefaultPicker?: boolean): Promise<[IEditorOptions, IEditorGroup | undefined] | undefined> { </ins> type EditorOverridePick = { readonly item: IQuickPickItem;
} // Text editor has the lowest priority because we <del> const editorOverridePicks = this.mapContributionsToQuickPickEntry(resource, group, alwaysUpdateSetting); </del> <ins> const editorOverridePicks = this.mapContributionsToQuickPickEntry(resource, group, showDefaultPicker); </ins> // Create editor override picker const editorOverridePicker = this.quickInputService.createQuickPick<IQuickPickItem>(); <del> const placeHolderMessage = alwaysUpdateSetting ? </del> <ins> const placeHolderMessage = showDefaultPicker ? </ins> localize('prompOpenWith.updateDefaultPlaceHolder', "Select new default editor for '{0}'", basename(resource)) : localize('promptOpenWith.placeHolder', "Select editor for '{0}'", basename(resource)); editorOverridePicker.placeholder = placeHolderMessage;
// options and group to use accordingly if (picked) { <ins> // If the user selected to configure default we trigger this picker again and tell it to show the default picker if (picked.item.id === EditorOverrideService.configureDefaultID) { return this.doPickEditorOverride(editor, options, group, true); } </ins> // Figure out target group let targetGroup: IEditorGroup | undefined; if (picked.keyMods?.alt || picked.keyMods?.ctrlCmd) {
collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > .cell-inner-container { padding-top: ${CELL_TOP_MARGIN}px; }`); collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container { padding-bottom: ${MARKDOWN_CELL_BOTTOM_MARGIN}px; padding-top: ${MARKDOWN_CELL_TOP_MARGIN}px; }`); collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container.webview-backed-markdown-cell { padding: 0; }`); <del> collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .webview-backed-markdown-cell.markdown-cell-edit-mode .cell.code { padding-top: ${MARKDOWN_CELL_TOP_MARGIN}px; }`); </del> <ins> collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .webview-backed-markdown-cell.markdown-cell-edit-mode .cell.code { padding-bottom: ${MARKDOWN_CELL_BOTTOM_MARGIN}px; padding-top: ${MARKDOWN_CELL_TOP_MARGIN}px; }`); </ins> collector.addRule(`.notebookOverlay .output { margin: 0px ${CELL_RIGHT_MARGIN}px 0px ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px; }`); collector.addRule(`.notebookOverlay .output { width: calc(100% - ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER + CELL_RIGHT_MARGIN}px); }`);
jsonFoldingLimit = normalizeLimit(workspace.getConfiguration(SettingIds.editorSection, { languageId: 'json' }).get(SettingIds.foldingMaximumRegions)); jsoncFoldingLimit = normalizeLimit(workspace.getConfiguration(SettingIds.editorSection, { languageId: 'jsonc' }).get(SettingIds.foldingMaximumRegions)); <ins> const schemas: JSONSchemaSettings[] = []; </ins> const settings: Settings = { http: { proxy: httpSettings.get('proxy'),
url = schema.schema.id || `vscode://schemas/custom/${encodeURIComponent(hash(schema.schema).toString(16))}`; } } else if (folderUri && (url[0] === '.' || url[0] === '/')) { <del> url = Uri.joinPath(folderUri, url).toString(); </del> <ins> url = Uri.joinPath(folderUri, url).toString(false); </ins> } return url; }