diff --git a/Cargo.toml b/Cargo.toml index 9b36a1fef..29288a9cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "packages/core", "packages/cli", "packages/core-macro", + "packages/extension", "packages/router", "packages/html", "packages/hooks", @@ -74,6 +75,7 @@ futures-channel = "0.3.21" futures-util = { version = "0.3", default-features = false } rustc-hash = "1.1.0" wasm-bindgen = "0.2.79" +html_parser = "0.7.0" # This is a "virtual package" # It is not meant to be published, but is used so "cargo run --example XYZ" works properly diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index 7d4a88fd2..8e323b74b 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -25,7 +25,7 @@ fs_extra = "1.2.0" cargo_toml = "0.11.4" futures = "0.3.21" notify = { version = "5.0.0-pre.16", features = ["serde"] } -html_parser = "0.6.2" +html_parser.workspace = true binary-install = "0.0.2" convert_case = "0.5.0" cargo_metadata = "0.15.0" diff --git a/packages/cli/extension/dist/.gitignore b/packages/cli/extension/dist/.gitignore deleted file mode 100644 index 1287e9bd7..000000000 --- a/packages/cli/extension/dist/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -** -!.gitignore diff --git a/packages/cli/extension/server/.gitignore b/packages/cli/extension/server/.gitignore deleted file mode 100644 index f42761bea..000000000 --- a/packages/cli/extension/server/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -** -!Readme.md -!.gitignore diff --git a/packages/cli/extension/src/main.ts b/packages/cli/extension/src/main.ts deleted file mode 100644 index adaed0a7d..000000000 --- a/packages/cli/extension/src/main.ts +++ /dev/null @@ -1,282 +0,0 @@ -import * as vscode from 'vscode'; -import { spawn } from "child_process"; -import { TextEncoder } from 'util'; - -let serverPath: string = "dioxus"; - -export async function activate(context: vscode.ExtensionContext) { - let somePath = await bootstrap(context); - - if (somePath == undefined) { - await vscode.window.showErrorMessage('Could not find bundled Dioxus-CLI. Please install it manually.'); - return; - } else { - serverPath = somePath; - } - - context.subscriptions.push( - // vscode.commands.registerTextEditorCommand('editor.action.clipboardPasteAction', onPasteHandler), - vscode.commands.registerCommand('extension.htmlToDioxusRsx', translateBlock), - vscode.commands.registerCommand('extension.htmlToDioxusComponent', translateComponent), - vscode.commands.registerCommand('extension.formatRsx', fmtSelection), - vscode.commands.registerCommand('extension.formatRsxDocument', formatRsxDocument), - vscode.workspace.onWillSaveTextDocument(fmtDocumentOnSave) - ); -} - - -function translateComponent() { - translate(true) -} - -function translateBlock() { - translate(false) -} - -function translate(component: boolean) { - const editor = vscode.window.activeTextEditor; - - if (!editor) return; - - const html = editor.document.getText(editor.selection); - if (html.length == 0) { - vscode.window.showWarningMessage("Please select HTML fragment before invoking this command!"); - return; - } - - let params = ["translate"]; - if (component) params.push("--component"); - params.push("--raw", html); - - const child_proc = spawn(serverPath, params); - - let result = ''; - child_proc.stdout?.on('data', data => result += data); - - child_proc.on('close', () => { - if (result.length > 0) editor.edit(editBuilder => editBuilder.replace(editor.selection, result)); - }); - - child_proc.on('error', (err) => { - vscode.window.showWarningMessage(`Errors occurred while translating. Make sure you have the most recent Dioxus-CLI installed! \n${err}`); - }); -} - -function onPasteHandler() { - // check settings to see if we should convert HTML to Rsx - if (vscode.workspace.getConfiguration('dioxus').get('convertOnPaste')) { - convertHtmlToRsxOnPaste(); - } -} - -function convertHtmlToRsxOnPaste() { - const editor = vscode.window.activeTextEditor; - if (!editor) return; - - // get the cursor location - const cursor = editor.selection.active; - - // try to parse the HTML at the cursor location - const html = editor.document.getText(new vscode.Range(cursor, cursor)); -} - -function formatRsxDocument() { - const editor = vscode.window.activeTextEditor; - if (!editor) return; - fmtDocument(editor.document); -} - -function fmtSelection() { - const editor = vscode.window.activeTextEditor; - if (!editor) return; - - const unformatted = editor.document.getText(editor.selection); - - if (unformatted.length == 0) { - vscode.window.showWarningMessage("Please select rsx invoking this command!"); - return; - } - - const fileDir = editor.document.fileName.slice(0, editor.document.fileName.lastIndexOf('\\')); - - const child_proc = spawn(serverPath, ["fmt", "--raw", unformatted.toString()], { - cwd: fileDir ? fileDir : undefined, - }); - let result = ''; - - child_proc.stdout?.on('data', data => result += data); - - child_proc.on('close', () => { - if (result.length > 0) editor.edit(editBuilder => editBuilder.replace(editor.selection, result)); - }); - - child_proc.on('error', (err) => { - vscode.window.showWarningMessage(`Errors occurred while translating. Make sure you have the most recent Dioxus-CLI installed! \n${err}`); - }); -} - -function fmtDocumentOnSave(e: vscode.TextDocumentWillSaveEvent) { - // check the settings to make sure format on save is configured - const dioxusConfig = vscode.workspace.getConfiguration('dioxus', e.document).get('formatOnSave'); - const globalConfig = vscode.workspace.getConfiguration('editor', e.document).get('formatOnSave'); - if ( - (dioxusConfig === 'enabled') || - (dioxusConfig !== 'disabled' && globalConfig) - ) { - fmtDocument(e.document); - } -} - -function fmtDocument(document: vscode.TextDocument) { - try { - if (document.languageId !== "rust" || document.uri.scheme !== "file") { - return; - } - - const [editor,] = vscode.window.visibleTextEditors.filter(editor => editor.document.fileName === document.fileName); - if (!editor) return; // Need an editor to apply text edits. - - const fileDir = document.fileName.slice(0, document.fileName.lastIndexOf('\\')); - const child_proc = spawn(serverPath, ["fmt", "--file", document.fileName], { - cwd: fileDir ? fileDir : undefined, - }); - - let result = ''; - child_proc.stdout?.on('data', data => result += data); - - /*type RsxEdit = { - formatted: string, - start: number, - end: number - }*/ - - child_proc.on('close', () => { - if (child_proc.exitCode !== 0) { - vscode.window.showWarningMessage(`Errors occurred while formatting. Make sure you have the most recent Dioxus-CLI installed!\nDioxus-CLI exited with exit code ${child_proc.exitCode}\n\nData from Dioxus-CLI:\n${result}`); - return; - } - /*if (result.length === 0) return; - - // Used for error message: - const originalResult = result; - try { - // Only parse the last non empty line, to skip log warning messages: - const lines = result.replaceAll('\r\n', '\n').split('\n'); - const nonEmptyLines = lines.filter(line => line.trim().length !== 0); - result = nonEmptyLines[nonEmptyLines.length - 1] ?? ''; - - if (result.length === 0) return; - - const decoded: RsxEdit[] = JSON.parse(result); - if (decoded.length === 0) return; - - // Preform edits at the end of the file - // first (to not change previous text file - // offsets): - decoded.sort((a, b) => b.start - a.start); - - - // Convert from utf8 offsets to utf16 offsets used by VS Code: - - const utf8Text = new TextEncoder().encode(text); - const utf8ToUtf16Pos = (posUtf8: number) => { - // Find the line of the position as well as the utf8 and - // utf16 indexes for the start of that line: - let startOfLineUtf8 = 0; - let lineIndex = 0; - const newLineUtf8 = '\n'.charCodeAt(0); - // eslint-disable-next-line no-constant-condition - while (true) { - const nextLineAt = utf8Text.indexOf(newLineUtf8, startOfLineUtf8); - if (nextLineAt < 0 || posUtf8 <= nextLineAt) break; - startOfLineUtf8 = nextLineAt + 1; - lineIndex++; - } - const lineUtf16 = document.lineAt(lineIndex); - - // Move forward from a synced position in the text until the - // target pos is found: - let currentUtf8 = startOfLineUtf8; - let currentUtf16 = document.offsetAt(lineUtf16.range.start); - - const decodeBuffer = new Uint8Array(10); - const utf8Encoder = new TextEncoder(); - while (currentUtf8 < posUtf8) { - const { written } = utf8Encoder.encodeInto(text.charAt(currentUtf16), decodeBuffer); - currentUtf8 += written; - currentUtf16++; - } - return currentUtf16; - }; - - - type FixedEdit = { - range: vscode.Range, - formatted: string, - }; - - const edits: FixedEdit[] = []; - for (const edit of decoded) { - // Convert from utf8 to utf16: - const range = new vscode.Range( - document.positionAt(utf8ToUtf16Pos(edit.start)), - document.positionAt(utf8ToUtf16Pos(edit.end)) - ); - - if (editor.document.getText(range) !== document.getText(range)) { - // The text that was formatted has changed while we were working. - vscode.window.showWarningMessage(`Dioxus formatting was ignored since the source file changed before the change could be applied.`); - continue; - } - - edits.push({ - range, - formatted: edit.formatted, - }); - } - - - // Apply edits: - editor.edit(editBuilder => { - edits.forEach((edit) => editBuilder.replace(edit.range, edit.formatted)); - }, { - undoStopAfter: false, - undoStopBefore: false - }); - - } catch (err) { - vscode.window.showWarningMessage(`Errors occurred while formatting. Make sure you have the most recent Dioxus-CLI installed!\n${err}\n\nData from Dioxus-CLI:\n${originalResult}`); - }*/ - }); - - child_proc.on('error', (err) => { - vscode.window.showWarningMessage(`Errors occurred while formatting. Make sure you have the most recent Dioxus-CLI installed! \n${err}`); - }); - } catch (error) { - vscode.window.showWarningMessage(`Errors occurred while formatting. Make sure you have the most recent Dioxus-CLI installed! \n${error}`); - } -} - - - -// I'm using the approach defined in rust-analyzer here -// -// We ship the server as part of the extension, but we need to handle external paths and such -// -// https://github.com/rust-lang/rust-analyzer/blob/fee5555cfabed4b8abbd40983fc4442df4007e49/editors/code/src/main.ts#L270 -async function bootstrap(context: vscode.ExtensionContext): Promise { - - const ext = process.platform === "win32" ? ".exe" : ""; - const bundled = vscode.Uri.joinPath(context.extensionUri, "server", `dioxus${ext}`); - const bundledExists = await vscode.workspace.fs.stat(bundled).then( - () => true, - () => false - ); - - // if bunddled doesn't exist, try using a locally-installed version - if (!bundledExists) { - return "dioxus"; - } - - return bundled.fsPath; -} diff --git a/packages/cli/extension/.eslintrc.js b/packages/extension/.eslintrc.js similarity index 100% rename from packages/cli/extension/.eslintrc.js rename to packages/extension/.eslintrc.js diff --git a/packages/cli/extension/.gitignore b/packages/extension/.gitignore similarity index 100% rename from packages/cli/extension/.gitignore rename to packages/extension/.gitignore diff --git a/packages/extension/.vscode/launch.json b/packages/extension/.vscode/launch.json new file mode 100644 index 000000000..5c7247b40 --- /dev/null +++ b/packages/extension/.vscode/launch.json @@ -0,0 +1,7 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [] +} \ No newline at end of file diff --git a/packages/extension/Cargo.toml b/packages/extension/Cargo.toml new file mode 100644 index 000000000..09dd98ac9 --- /dev/null +++ b/packages/extension/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "dioxus-ext" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +wasm-bindgen.workspace = true +dioxus-autofmt.workspace = true +rsx-rosetta.workspace = true +html_parser.workspace = true + + +[lib] +crate-type = ["cdylib", "rlib"] diff --git a/packages/cli/extension/DEV.md b/packages/extension/DEV.md similarity index 100% rename from packages/cli/extension/DEV.md rename to packages/extension/DEV.md diff --git a/packages/cli/extension/LICENSE.txt b/packages/extension/LICENSE.txt similarity index 100% rename from packages/cli/extension/LICENSE.txt rename to packages/extension/LICENSE.txt diff --git a/packages/cli/extension/README.md b/packages/extension/README.md similarity index 100% rename from packages/cli/extension/README.md rename to packages/extension/README.md diff --git a/packages/cli/extension/package-lock.json b/packages/extension/package-lock.json similarity index 99% rename from packages/cli/extension/package-lock.json rename to packages/extension/package-lock.json index c671ca72c..60ce37622 100644 --- a/packages/cli/extension/package-lock.json +++ b/packages/extension/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.1", "license": "MIT", "dependencies": { + "dioxus-ext": "./pkg", "vsce": "^2.9.2" }, "devDependencies": { @@ -18,6 +19,7 @@ "@typescript-eslint/parser": "^5.30.5", "cross-env": "^7.0.3", "esbuild": "^0.14.27", + "esbuild-plugin-wasm": "^1.1.0", "eslint": "^8.19.0", "eslint-config-prettier": "^8.5.0", "ovsx": "^0.5.1", @@ -728,6 +730,10 @@ "node": ">=8" } }, + "node_modules/dioxus-ext": { + "resolved": "pkg", + "link": true + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1119,6 +1125,19 @@ "node": ">=12" } }, + "node_modules/esbuild-plugin-wasm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esbuild-plugin-wasm/-/esbuild-plugin-wasm-1.1.0.tgz", + "integrity": "sha512-0bQ6+1tUbySSnxzn5jnXHMDvYnT0cN/Wd4Syk8g/sqAIJUg7buTIi22svS3Qz6ssx895NT+TgLPb33xi1OkZig==", + "dev": true, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "individual", + "url": "https://ko-fi.com/tschrock" + } + }, "node_modules/esbuild-sunos-64": { "version": "0.14.48", "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz", @@ -3014,6 +3033,13 @@ "dependencies": { "buffer-crc32": "~0.2.3" } + }, + "pkg": { + "name": "dioxus-ext", + "version": "0.1.0" + }, + "src/pkg/dioxus-ext": { + "extraneous": true } }, "dependencies": { @@ -3485,6 +3511,9 @@ "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", "dev": true }, + "dioxus-ext": { + "version": "file:pkg" + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -3695,6 +3724,12 @@ "dev": true, "optional": true }, + "esbuild-plugin-wasm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esbuild-plugin-wasm/-/esbuild-plugin-wasm-1.1.0.tgz", + "integrity": "sha512-0bQ6+1tUbySSnxzn5jnXHMDvYnT0cN/Wd4Syk8g/sqAIJUg7buTIi22svS3Qz6ssx895NT+TgLPb33xi1OkZig==", + "dev": true + }, "esbuild-sunos-64": { "version": "0.14.48", "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.48.tgz", diff --git a/packages/cli/extension/package.json b/packages/extension/package.json similarity index 94% rename from packages/cli/extension/package.json rename to packages/extension/package.json index 11b32ec88..4f4293465 100644 --- a/packages/cli/extension/package.json +++ b/packages/extension/package.json @@ -24,6 +24,10 @@ "onCommand:extension.formatRsxDocument" ], "main": "./out/main", + "extensionKind": [ + "ui", + "workspace" + ], "contributes": { "commands": [ { @@ -73,7 +77,7 @@ "scripts": { "vscode:prepublish": "npm run build-base -- --minify", "package": "vsce package -o rust-analyzer.vsix", - "build-base": "esbuild ./src/main.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node --target=node16", + "build-base": "node src/build.js", "build": "npm run build-base -- --sourcemap", "watch": "npm run build-base -- --sourcemap --watch", "lint": "prettier --check . && eslint -c .eslintrc.js --ext ts ./src ./tests", @@ -88,15 +92,17 @@ "@typescript-eslint/parser": "^5.30.5", "cross-env": "^7.0.3", "esbuild": "^0.14.27", + "esbuild-plugin-wasm": "^1.1.0", "eslint": "^8.19.0", - "typescript": "^4.7.4", "eslint-config-prettier": "^8.5.0", "ovsx": "^0.5.1", "prettier": "^2.6.2", "tslib": "^2.3.0", + "typescript": "^4.7.4", "vsce": "^2.7.0" }, "dependencies": { + "dioxus-ext": "./pkg", "vsce": "^2.9.2" } -} \ No newline at end of file +} diff --git a/packages/extension/src/build.js b/packages/extension/src/build.js new file mode 100644 index 000000000..de0dffdb9 --- /dev/null +++ b/packages/extension/src/build.js @@ -0,0 +1,23 @@ +// build.ts +import('esbuild').then((esbuild) => { + import('esbuild-plugin-wasm').then((wasmLoader) => { + // "build-base": "esbuild ./src/main.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node --target=node16", + esbuild.build({ + entryPoints: ['src/main.ts'], + outfile: 'out/main.js', + bundle: true, + platform: 'node', + target: 'node16', + format: 'esm', + external: ['vscode'], + plugins: [ + wasmLoader.wasmLoader({ + mode: 'embedded' + }) + ] + }); + }); +}); + + + diff --git a/packages/extension/src/lib.rs b/packages/extension/src/lib.rs new file mode 100644 index 000000000..2dc069aa3 --- /dev/null +++ b/packages/extension/src/lib.rs @@ -0,0 +1,34 @@ +//! This file exports functions into the vscode extension + +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn greeet() { + // +} + +#[wasm_bindgen] +pub fn format_rsx(raw: String) -> String { + let block = dioxus_autofmt::fmt_block(&raw, 0); + block.unwrap() +} + +#[wasm_bindgen] +pub fn translate_rsx(contents: String, component: bool) -> String { + // Ensure we're loading valid HTML + let dom = html_parser::Dom::parse(&contents).unwrap(); + + let callbody = rsx_rosetta::rsx_from_html(&dom); + + // Convert the HTML to RSX + let out = dioxus_autofmt::write_block_out(callbody).unwrap(); + + out +} + +// rsx! { +// div {} +// div {} +// div {} +// div {} div {} +// } diff --git a/packages/extension/src/main.ts b/packages/extension/src/main.ts new file mode 100644 index 000000000..ac2255268 --- /dev/null +++ b/packages/extension/src/main.ts @@ -0,0 +1,277 @@ +import * as vscode from 'vscode'; +import { translate_rsx } from 'dioxus-ext'; + + +export async function activate(context: vscode.ExtensionContext) { + + + context.subscriptions.push( + vscode.commands.registerCommand('extension.htmlToDioxusRsx', () => translate(false)), + vscode.commands.registerCommand('extension.htmlToDioxusComponent', () => translate(true)), + // vscode.commands.registerCommand('extension.formatRsx', fmtSelection), + // vscode.commands.registerCommand('extension.formatRsxDocument', formatRsxDocument), + // vscode.workspace.onWillSaveTextDocument(fmtDocumentOnSave) + ); +} + +function translate(component: boolean) { + const editor = vscode.window.activeTextEditor; + + if (!editor) return; + + const html = editor.document.getText(editor.selection); + if (html.length == 0) { + vscode.window.showWarningMessage("Please select HTML fragment before invoking this command!"); + return; + } + + const out = translate_rsx(html, component); + + if (out.length > 0) { + editor.edit(editBuilder => editBuilder.replace(editor.selection, out)); + } else { + vscode.window.showWarningMessage(`Errors occurred while translating, make sure this block of HTML is valid`); + } + + // const params = ["translate"]; + // if (component) params.push("--component"); + // params.push("--raw", html); + + // const child_proc = spawn(serverPath, params); + + // let result = ''; + // child_proc.stdout?.on('data', data => result += data); + + // child_proc.on('close', () => { + // if (result.length > 0) editor.edit(editBuilder => editBuilder.replace(editor.selection, result)); + // }); + + // child_proc.on('error', (err) => { + // vscode.window.showWarningMessage(`Errors occurred while translating. Make sure you have the most recent Dioxus-CLI installed! \n${err}`); + // }); +} + + + +// function formatRsxDocument() { +// const editor = vscode.window.activeTextEditor; +// if (!editor) return; +// fmtDocument(editor.document); +// } + +// function fmtSelection() { +// const editor = vscode.window.activeTextEditor; +// if (!editor) return; + +// const unformatted = editor.document.getText(editor.selection); + +// if (unformatted.length == 0) { +// vscode.window.showWarningMessage("Please select rsx invoking this command!"); +// return; +// } + +// const fileDir = editor.document.fileName.slice(0, editor.document.fileName.lastIndexOf('\\')); + +// const child_proc = spawn(serverPath, ["fmt", "--raw", unformatted.toString()], { +// cwd: fileDir ? fileDir : undefined, +// }); +// let result = ''; + +// child_proc.stdout?.on('data', data => result += data); + +// child_proc.on('close', () => { +// if (result.length > 0) editor.edit(editBuilder => editBuilder.replace(editor.selection, result)); +// }); + +// child_proc.on('error', (err) => { +// vscode.window.showWarningMessage(`Errors occurred while translating. Make sure you have the most recent Dioxus-CLI installed! \n${err}`); +// }); +// } + +// function fmtDocumentOnSave(e: vscode.TextDocumentWillSaveEvent) { +// // check the settings to make sure format on save is configured +// const dioxusConfig = vscode.workspace.getConfiguration('dioxus', e.document).get('formatOnSave'); +// const globalConfig = vscode.workspace.getConfiguration('editor', e.document).get('formatOnSave'); +// if ( +// (dioxusConfig === 'enabled') || +// (dioxusConfig !== 'disabled' && globalConfig) +// ) { +// fmtDocument(e.document); +// } +// } + +// function fmtDocument(document: vscode.TextDocument) { +// try { +// if (document.languageId !== "rust" || document.uri.scheme !== "file") { +// return; +// } + +// const [editor,] = vscode.window.visibleTextEditors.filter(editor => editor.document.fileName === document.fileName); +// if (!editor) return; // Need an editor to apply text edits. + +// const fileDir = document.fileName.slice(0, document.fileName.lastIndexOf('\\')); +// const child_proc = spawn(serverPath, ["fmt", "--file", document.fileName], { +// cwd: fileDir ? fileDir : undefined, +// }); + +// let result = ''; +// child_proc.stdout?.on('data', data => result += data); + +// /*type RsxEdit = { +// formatted: string, +// start: number, +// end: number +// }*/ + +// child_proc.on('close', () => { +// if (child_proc.exitCode !== 0) { +// vscode.window.showWarningMessage(`Errors occurred while formatting. Make sure you have the most recent Dioxus-CLI installed!\nDioxus-CLI exited with exit code ${child_proc.exitCode}\n\nData from Dioxus-CLI:\n${result}`); +// return; +// } + +// }); + +// child_proc.on('error', (err) => { +// vscode.window.showWarningMessage(`Errors occurred while formatting. Make sure you have the most recent Dioxus-CLI installed! \n${err}`); +// }); +// } catch (error) { +// vscode.window.showWarningMessage(`Errors occurred while formatting. Make sure you have the most recent Dioxus-CLI installed! \n${error}`); +// } +// } + + + +// // I'm using the approach defined in rust-analyzer here +// // +// // We ship the server as part of the extension, but we need to handle external paths and such +// // +// // https://github.com/rust-lang/rust-analyzer/blob/fee5555cfabed4b8abbd40983fc4442df4007e49/editors/code/src/main.ts#L270 +// async function bootstrap(context: vscode.ExtensionContext): Promise { + +// const ext = process.platform === "win32" ? ".exe" : ""; +// const bundled = vscode.Uri.joinPath(context.extensionUri, "server", `dioxus${ext}`); +// const bundledExists = await vscode.workspace.fs.stat(bundled).then( +// () => true, +// () => false +// ); + +// // if bunddled doesn't exist, try using a locally-installed version +// if (!bundledExists) { +// return "dioxus"; +// } + +// return bundled.fsPath; +// } + + +// function onPasteHandler() { +// // check settings to see if we should convert HTML to Rsx +// if (vscode.workspace.getConfiguration('dioxus').get('convertOnPaste')) { +// convertHtmlToRsxOnPaste(); +// } +// } + +// function convertHtmlToRsxOnPaste() { +// const editor = vscode.window.activeTextEditor; +// if (!editor) return; + +// // get the cursor location +// const cursor = editor.selection.active; + +// // try to parse the HTML at the cursor location +// const html = editor.document.getText(new vscode.Range(cursor, cursor)); +// } + +/*if (result.length === 0) return; + +// Used for error message: +const originalResult = result; +try { + // Only parse the last non empty line, to skip log warning messages: + const lines = result.replaceAll('\r\n', '\n').split('\n'); + const nonEmptyLines = lines.filter(line => line.trim().length !== 0); + result = nonEmptyLines[nonEmptyLines.length - 1] ?? ''; + + if (result.length === 0) return; + + const decoded: RsxEdit[] = JSON.parse(result); + if (decoded.length === 0) return; + + // Preform edits at the end of the file + // first (to not change previous text file + // offsets): + decoded.sort((a, b) => b.start - a.start); + + + // Convert from utf8 offsets to utf16 offsets used by VS Code: + + const utf8Text = new TextEncoder().encode(text); + const utf8ToUtf16Pos = (posUtf8: number) => { + // Find the line of the position as well as the utf8 and + // utf16 indexes for the start of that line: + let startOfLineUtf8 = 0; + let lineIndex = 0; + const newLineUtf8 = '\n'.charCodeAt(0); + // eslint-disable-next-line no-constant-condition + while (true) { + const nextLineAt = utf8Text.indexOf(newLineUtf8, startOfLineUtf8); + if (nextLineAt < 0 || posUtf8 <= nextLineAt) break; + startOfLineUtf8 = nextLineAt + 1; + lineIndex++; + } + const lineUtf16 = document.lineAt(lineIndex); + + // Move forward from a synced position in the text until the + // target pos is found: + let currentUtf8 = startOfLineUtf8; + let currentUtf16 = document.offsetAt(lineUtf16.range.start); + + const decodeBuffer = new Uint8Array(10); + const utf8Encoder = new TextEncoder(); + while (currentUtf8 < posUtf8) { + const { written } = utf8Encoder.encodeInto(text.charAt(currentUtf16), decodeBuffer); + currentUtf8 += written; + currentUtf16++; + } + return currentUtf16; + }; + + + type FixedEdit = { + range: vscode.Range, + formatted: string, + }; + + const edits: FixedEdit[] = []; + for (const edit of decoded) { + // Convert from utf8 to utf16: + const range = new vscode.Range( + document.positionAt(utf8ToUtf16Pos(edit.start)), + document.positionAt(utf8ToUtf16Pos(edit.end)) + ); + + if (editor.document.getText(range) !== document.getText(range)) { + // The text that was formatted has changed while we were working. + vscode.window.showWarningMessage(`Dioxus formatting was ignored since the source file changed before the change could be applied.`); + continue; + } + + edits.push({ + range, + formatted: edit.formatted, + }); + } + + + // Apply edits: + editor.edit(editBuilder => { + edits.forEach((edit) => editBuilder.replace(edit.range, edit.formatted)); + }, { + undoStopAfter: false, + undoStopBefore: false + }); + +} catch (err) { + vscode.window.showWarningMessage(`Errors occurred while formatting. Make sure you have the most recent Dioxus-CLI installed!\n${err}\n\nData from Dioxus-CLI:\n${originalResult}`); +}*/ +// import { TextEncoder } from 'util'; diff --git a/packages/cli/extension/static/icon.png b/packages/extension/static/icon.png similarity index 100% rename from packages/cli/extension/static/icon.png rename to packages/extension/static/icon.png diff --git a/packages/cli/extension/tsconfig.json b/packages/extension/tsconfig.json similarity index 61% rename from packages/cli/extension/tsconfig.json rename to packages/extension/tsconfig.json index 32dda5bc9..e6e715d85 100644 --- a/packages/cli/extension/tsconfig.json +++ b/packages/extension/tsconfig.json @@ -2,11 +2,17 @@ "compilerOptions": { "module": "commonjs", "target": "es2021", - "lib": ["ES2021"], + "lib": [ + "ES2021" + ], "outDir": "out", "sourceMap": true, "strict": true, "rootDir": "src" }, - "exclude": ["node_modules", ".vscode-test"] + "exclude": [ + "node_modules", + ".vscode-test" + // "src/pkg" + ] } diff --git a/packages/rsx-rosetta/Cargo.toml b/packages/rsx-rosetta/Cargo.toml index 5a096d56a..eef6b2499 100644 --- a/packages/rsx-rosetta/Cargo.toml +++ b/packages/rsx-rosetta/Cargo.toml @@ -15,7 +15,7 @@ keywords = ["dom", "ui", "gui", "react"] [dependencies] dioxus-autofmt = { workspace = true } dioxus-rsx = { workspace = true } -html_parser = "0.6.3" +html_parser.workspace = true proc-macro2 = "1.0.49" quote = "1.0.23" syn = { version = "1.0.107", features = ["full"] } @@ -27,4 +27,4 @@ convert_case = "0.5.0" # eventually more output options [dev-dependencies] -pretty_assertions = "1.2.1" \ No newline at end of file +pretty_assertions = "1.2.1"