diff --git a/package-lock.json b/package-lock.json index 9c8f3d6..13c827c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@esi_package/ckeditor5-import", - "version": "0.0.1", + "version": "0.0.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@esi_package/ckeditor5-import", - "version": "0.0.1", + "version": "0.0.3", "license": "MIT", "dependencies": { - "@esi_package/ckeditor5-mathlive": "^0.0.16", + "@esi_package/ckeditor5-mathlive": "^0.0.18", "mathml-to-latex": "^1.4.3", "temml": "^0.10.32" }, @@ -3555,9 +3555,9 @@ } }, "node_modules/@esi_package/ckeditor5-mathlive": { - "version": "0.0.16", - "resolved": "http://158.108.215.151:8081/api/packages/esirepository/npm/%40esi_package%2Fckeditor5-mathlive/-/0.0.16/ckeditor5-mathlive-0.0.16.tgz", - "integrity": "sha512-ySfBtw7q4TbpEgj7nWz3WCDab/76wfcmzCwjplC23+vzvEi4QEIcEuNdnZ8Q6M5SYbqbKX4LCmXHokOwSzvnqg==", + "version": "0.0.18", + "resolved": "http://158.108.215.151:8081/api/packages/esirepository/npm/%40esi_package%2Fckeditor5-mathlive/-/0.0.18/ckeditor5-mathlive-0.0.18.tgz", + "integrity": "sha512-439dOU0BkKhT+TYCTZDfC60spnvgGF5gKE9njG6SsTRL/BC0Prs9lyTgkvhIfdE7ystQ7aZllcE1P+vjUOYbtQ==", "license": "MIT", "dependencies": { "@ckeditor/ckeditor5-dev-webpack-plugin": "^31.1.13", diff --git a/package.json b/package.json index a13810e..ed44fb7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@esi_package/ckeditor5-import", - "version": "0.0.3", + "version": "0.0.4", "description": "A plugin for CKEditor 5.", "keywords": [ "ckeditor", @@ -93,7 +93,7 @@ } }, "dependencies": { - "@esi_package/ckeditor5-mathlive": "^0.0.16", + "@esi_package/ckeditor5-mathlive": "^0.0.18", "mathml-to-latex": "^1.4.3", "temml": "^0.10.32" } diff --git a/sample/ckeditor.ts b/sample/ckeditor.ts index fb1f82e..abd87d0 100644 --- a/sample/ckeditor.ts +++ b/sample/ckeditor.ts @@ -84,7 +84,8 @@ ClassicEditor 'undo', 'redo', '|', - 'importButton', + 'importDocx', + 'insertDocx', 'mathlive', '|', 'heading', @@ -172,7 +173,7 @@ ClassicEditor }; }, mathPanelDestroyOnClose: true, - openPanelWhenEquationSelected: false + openPanelWhenEquationSelected: true }, fontColor: { colorPicker: { diff --git a/src/import.ts b/src/import.ts index 139bcd2..2f754b7 100644 --- a/src/import.ts +++ b/src/import.ts @@ -19,11 +19,11 @@ export default class Import extends Plugin { const model = editor.model; // Add the "importButton" to feature components. - editor.ui.componentFactory.add( 'importButton', locale => { + editor.ui.componentFactory.add( 'importDocx', locale => { const view = new ButtonView( locale ); view.set( { - label: t( 'Import' ), + label: t( 'Import Docx' ), icon: ckeditor5Icon, tooltip: true } ); @@ -125,5 +125,116 @@ export default class Import extends Plugin { return view; } ); + + // Add the "insertButton" to feature components. + editor.ui.componentFactory.add( 'insertDocx', locale => { + const view = new ButtonView( locale ); + + view.set( { + label: t( 'Insert Docx' ), + icon: ckeditor5Icon, + tooltip: true + } ); + + // POST fetch html from docx + this.listenTo( view, 'execute', async () => { + // curl -X 'POST' \ + // 'http://localhost:8080/aspose/word-to-html' \ + // -H 'accept: text/plain' \ + // -H 'Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document' \ + // --data-binary '@stou(207).docx' + + // file accpt docx + const input = document.createElement('input'); + input.type = 'file'; + input.accept = '.docx'; + input.click(); + + input.addEventListener('change', async () => { + const file = input.files![0]; + const formData = new FormData(); + formData.append("file", file); + + try { + const response = await fetch("http://localhost:8080/aspose/word-to-html", { + method: "POST", + headers: { + // Do not set `Content-Type` manually when using FormData; + // the browser will automatically set the correct boundary for multipart/form-data. + }, + body: file, // directly sending file bytes as the backend expects byte[] + }); + + if (!response.ok) { + throw new Error(`Failed to upload file: ${response.statusText}`); + } + + const htmlText = await response.text(); + // console.log("Converted HTML:", htmlText); + const htmlDoc = new DOMParser().parseFromString(htmlText, "text/html"); + const body = htmlDoc.body; + // pre-process mathml to latex + // get all mathml elements + // replace all mathml element in the body with script type math/tex with inside content latex + const mathmlElements = body.querySelectorAll("math"); + mathmlElements.forEach(mathmlElement => { + const latex = MathMLToLaTeX.convert(mathmlElement.outerHTML); + const scriptElement = document.createElement("script"); + scriptElement.type = "math/tex"; + scriptElement.textContent = latex; + const spanElement = document.createElement("span"); + spanElement.appendChild(scriptElement); + mathmlElement.replaceWith(spanElement); + }); + // font-family for concat with , serif + const spans = body.querySelectorAll("span"); + spans.forEach(span => { + // span.style.fontFamily += ", serif"; + // check if it's

tag has font-size attribute, then apply to tag + const p = span.parentElement; + if (p && p.tagName === "P") { + const fontSize = p.style.fontSize; + if (fontSize && span.style.fontSize === "") { + span.setAttribute("style", `${span.getAttribute("style")}; font-size: ${fontSize}`); + } + } + const li = span.parentElement; + if (li && li.tagName === "LI") { + const outerli = li.parentElement?.parentElement; + if (outerli && outerli.tagName === "LI") { + const fontSize = outerli.style.fontSize; + if (fontSize && li.style.fontSize === "") { + li.setAttribute("style", `${span.getAttribute("style")}; font-size: ${fontSize}`); + } + } + const fontSize = li.style.fontSize; + if (fontSize && span.style.fontSize === "") { + span.setAttribute("style", `${span.getAttribute("style")}; font-size: ${fontSize}`); + } + } + const pp = span.parentElement?.parentElement; + if (pp && span.parentElement.tagName === "A") { + const fontSize = pp.style.fontSize; + if (fontSize && span.style.fontSize === "") { + span.setAttribute("style", `${span.getAttribute("style")}; font-size: ${fontSize}`); + } + } + }); + console.log("Converted HTML:", body.innerHTML); + // this.editor.setData(body.innerHTML); + const viewFragment = editor.data.processor.toView(body.innerHTML); + const modelFragment = editor.data.toModel(viewFragment); + model.insertContent(modelFragment); + } catch (error) { + console.error("Error uploading file:", error); + throw error; + } + + editor.editing.view.focus(); + }); + } ); + + return view; + } ); } }