Skip to content

Commit

Permalink
fix: docx export
Browse files Browse the repository at this point in the history
by swapping dependencies
  • Loading branch information
davidenke committed Oct 24, 2024
1 parent 31f7a1f commit 641527c
Show file tree
Hide file tree
Showing 15 changed files with 573 additions and 1,271 deletions.
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
"name": "David Enke"
},
"dependencies": {
"@adobe/helix-md2docx": "2.1.79",
"@fontsource-variable/inter-tight": "5.1.0",
"@fontsource-variable/material-symbols-outlined": "5.1.3",
"@tauri-apps/api": "2.0.3",
"@tauri-apps/plugin-dialog": "2.0.1",
"@tauri-apps/plugin-fs": "2.0.1",
"@tauri-apps/plugin-shell": "2.0.1",
"@turbodocx/html-to-docx": "1.10.0",
"jszip": "3.10.1",
"lit": "3.2.1",
"marked": "14.1.3",
Expand All @@ -48,11 +48,9 @@
"eslint-plugin-prettier": "5.2.1",
"eslint-plugin-simple-import-sort": "12.1.1",
"eslint-plugin-unused-imports": "4.1.4",
"node-stdlib-browser": "1.2.1",
"postcss": "8.4.47",
"postject": "1.0.0-alpha.6",
"prettier": "3.3.3",
"rollup-plugin-node-externals": "7.1.3",
"typescript": "5.6.3",
"typescript-eslint": "8.11.0",
"vite": "5.4.9",
Expand Down
1,669 changes: 473 additions & 1,196 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions scripts/prepare-sidecar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { execPath, platform, version } from 'node:process';
import { parseArgs, promisify } from 'node:util';

import { inject } from 'postject';
import { nodeExternals } from 'rollup-plugin-node-externals';
import { build } from 'vite';
import { nodePolyfills } from 'vite-plugin-node-polyfills';

const exec = promisify(_exec);
const isMac = platform === 'darwin';
Expand All @@ -26,18 +26,20 @@ const { out = resolve(import.meta.dirname, '../bin') } = values;
if (existsSync(out)) await rm(out, { recursive: true });
await mkdir(out, { recursive: true });

// compile the TypeScript code
// compile the TypeScript code with tsc
// const fromData = await readFile(values.from, 'utf-8');
// const { outputText } = transpileModule(fromData, {});
// await writeFile(resolve(out, `${name}.js`), outputText, 'utf-8');

// compile the TypeScript code with vite
const [{ output }] = (await build({
build: {
lib: { entry: values.from, formats: ['cjs'], fileName: name },
minify: false, // we still need to clean up afterwards
target: ['es2020', `node${version.replace(/^v(\d+)\..*$/, '$1')}`],
write: false,
},
plugins: [nodeExternals({ exclude: ['@adobe/helix-md2docx'] })],
plugins: [nodePolyfills({ include: ['stream'] })],
})) as unknown as [{ output: [{ code: string; preliminaryFileName: string }] }];

// remove the nasty stuff
Expand Down
18 changes: 9 additions & 9 deletions src-node/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { argv } from 'node:process';
// import { argv } from 'node:process';

import { md2docx } from '@adobe/helix-md2docx';
// import { md2docx } from '@adobe/helix-md2docx';

(async () => {
console.info('Hello World!');
// (async () => {
// const [, , markdown] = argv;
// const buffer = await md2docx(markdown);
// const doc = new TextDecoder().decode(buffer);
// console.log(doc);
// })();

const [, , markdown] = argv;
const buffer = await md2docx(markdown);
const doc = new TextDecoder().decode(buffer);
console.log(doc);
})();
console.log('Hello World!');
3 changes: 1 addition & 2 deletions src/components/root/root.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,7 @@ export class Root extends LitElement {
const defaultPath = `${fileBaseName}.docx`;
const filters = [{ name: 'Document', extensions: ['docx', 'doc'] }];
const path = await save({ defaultPath, filters });
// const content = await convertToDocx(this.contents.md);
const content = await convertToDocx(`file://${this.contents.path}`);
const content = await convertToDocx(this.contents.html);
if (path !== null) await exportFile(path, content);
break;
}
Expand Down
3 changes: 0 additions & 3 deletions src/mocks/node/buffer.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/mocks/node/fs.promises.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/mocks/node/fs.ts

This file was deleted.

2 changes: 0 additions & 2 deletions src/mocks/node/http2.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/mocks/node/module.ts

This file was deleted.

5 changes: 0 additions & 5 deletions src/mocks/node/url.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/mocks/node/zlib.ts

This file was deleted.

16 changes: 11 additions & 5 deletions src/utils/conversion.utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { md2docx } from '@adobe/helix-md2docx';
// import { md2docx } from '@adobe/helix-md2docx';
import HTMLtoDOCX from '@turbodocx/html-to-docx';
import { parse } from 'marked';
import type { Sheet, Topic, Workbook } from 'xmind-model';

Expand Down Expand Up @@ -66,11 +67,16 @@ export async function convertToHtml(markdown: string): Promise<string> {
}

/**
* Convert markdown to docx
* Convert html to docx
*/
export async function convertToDocx(markdown: string): Promise<string> {
const buffer = await md2docx(markdown);
return new TextDecoder().decode(buffer);
export async function convertToDocx(html: string): Promise<Uint8Array> {
// return md2docx(markdown);
return HTMLtoDOCX(html, undefined, {
table: { row: { cantSplit: true } },
footer: true,
pageNumber: true,
preprocessing: { skipHTMLMinify: false },
});
}

/**
Expand Down
61 changes: 61 additions & 0 deletions typings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,64 @@ declare module 'postject' {
}

declare module 'mock:buffer' {}

// https://github.com/TurboDocx/html-to-docx
declare module '@turbodocx/html-to-docx' {
export type DocumentOptions = {
orientation: 'portrait' | 'landscape';
pageSize: Partial<{ height: number; width: number }>;
margins: Partial<{
top: number;
right: number;
bottom: number;
left: number;
header: number;
footer: number;
gutter: number;
}>;
title: string;
subject: string;
creator: string;
keywords: string[];
description: string;
lastModifiedBy: string;
revision: number;
createdAt: Date;
modifiedAt: Date;
headerType: 'default' | 'first' | 'even';
header: boolean;
footerType: 'default' | 'first' | 'even';
footer: boolean;
font: string;
fontSize: number;
complexScriptFontSize: number;
table: Partial<{
row: { cantSplit: boolean };
borderOptions: Partial<{
size: number;
stroke: string;
color: string;
}>;
}>;
pageNumber: boolean;
skipFirstHeaderFooter: boolean;
lineNumber: boolean;
lineNumberOptions: Partial<{
start: number;
countBy: number;
restart: 'continuous' | 'newPage' | 'newSection';
}>;
numbering: { defaultOrderedListStyleType: 'decimal' | string };
decodeUnicode: boolean;
lang: `${Lowercase<string>}-${Uppercase<string>}`;
preprocessing: { skipHTMLMinify: boolean };
};

declare function HTMLtoDOCX(
htmlString: string,
headerHTMLString?: string,
documentOptions?: Partial<DocumentOptions>,
footerHTMLString?: string,
): Promise<Uint8Array>;
export default HTMLtoDOCX;
}
48 changes: 12 additions & 36 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,47 +56,23 @@ export default defineConfig(async config => ({
plugins: [
// add type check directly to vite
checker({ typescript: true, overlay: false }),
// (1) that nasty docx converter uses node stuff, so we need to polyfill it;
// but some need manual mocking so they're excluded and aliased below
nodePolyfills({ exclude: ['buffer', 'fs', 'http2', 'module', 'url', 'zlib'] }),
// html-to-docx imports node modules, which are not available in the browser
nodePolyfills(),
],
define: {
global: 'window',
process: { env: { version }, version, mode: config.mode === 'detached' },
import: { meta: { url: 'http://localhost' } },
},
resolve: {
alias: [
// node
{ find: 'mock:buffer', replacement: resolve(import.meta.dirname, 'node_modules/buffer') },
{ find: 'buffer', replacement: resolve(import.meta.dirname, 'src/mocks/node/buffer.ts') },
{ find: /^fs$/, replacement: resolve(import.meta.dirname, 'src/mocks/node/fs.ts') },
{ find: 'fs/promises', replacement: resolve(import.meta.dirname, 'src/mocks/node/fs.promises.ts') },
{ find: 'http2', replacement: resolve(import.meta.dirname, 'src/mocks/node/http2.ts') },
{ find: 'module', replacement: resolve(import.meta.dirname, 'src/mocks/node/module.ts') },
{ find: 'url', replacement: resolve(import.meta.dirname, 'src/mocks/node/url.ts') },
{ find: 'zlib', replacement: resolve(import.meta.dirname, 'src/mocks/node/zlib.ts') },

// tauri (1)
...(config.mode === 'detached'
? [
{
find: '@tauri-apps/api/window',
replacement: resolve(import.meta.dirname, 'src/mocks/tauri/api.window.ts'),
},
{
find: '@tauri-apps/api/event',
replacement: resolve(import.meta.dirname, 'src/mocks/tauri/api.event.ts'),
},
{
find: '@tauri-apps/plugin-dialog',
replacement: resolve(import.meta.dirname, 'src/mocks/tauri/plugin-dialog.ts'),
},
{
find: '@tauri-apps/plugin-fs',
replacement: resolve(import.meta.dirname, 'src/mocks/tauri/plugin-fs.ts'),
},
]
: []),
],
alias:
config.mode === 'detached'
? {
'@tauri-apps/api/window': resolve(import.meta.dirname, 'src/mocks/tauri/api.window.ts'),
'@tauri-apps/api/event': resolve(import.meta.dirname, 'src/mocks/tauri/api.event.ts'),
'@tauri-apps/plugin-dialog': resolve(import.meta.dirname, 'src/mocks/tauri/plugin-dialog.ts'),
'@tauri-apps/plugin-fs': resolve(import.meta.dirname, 'src/mocks/tauri/plugin-fs.ts'),
}
: [],
},
}));

0 comments on commit 641527c

Please sign in to comment.