Просмотр исходного кода

convert md to html on pdf export

Futa Arai 1 год назад
Родитель
Сommit
394cad5f9d

+ 9 - 3
apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/index.ts

@@ -1,4 +1,5 @@
 import fs from 'fs';
 import fs from 'fs';
+import path from 'path';
 import type { Readable } from 'stream';
 import type { Readable } from 'stream';
 
 
 import type { IUser } from '@growi/core';
 import type { IUser } from '@growi/core';
@@ -40,7 +41,7 @@ export interface IPageBulkExportJobCronService {
   setStreamInExecution(jobId: ObjectIdLike, stream: Readable): void;
   setStreamInExecution(jobId: ObjectIdLike, stream: Readable): void;
   handlePipelineError(err: Error | null, pageBulkExportJob: PageBulkExportJobDocument): void;
   handlePipelineError(err: Error | null, pageBulkExportJob: PageBulkExportJobDocument): void;
   notifyExportResultAndCleanUp(action: SupportedActionType, pageBulkExportJob: PageBulkExportJobDocument): Promise<void>;
   notifyExportResultAndCleanUp(action: SupportedActionType, pageBulkExportJob: PageBulkExportJobDocument): Promise<void>;
-  getTmpOutputDir(pageBulkExportJob: PageBulkExportJobDocument): string;
+  getTmpOutputDir(pageBulkExportJob: PageBulkExportJobDocument, isHtmlPath: boolean): string;
 }
 }
 
 
 /**
 /**
@@ -99,9 +100,14 @@ class PageBulkExportJobCronService extends CronService implements IPageBulkExpor
 
 
   /**
   /**
    * Get the output directory on the fs to temporarily store page files before compressing and uploading
    * Get the output directory on the fs to temporarily store page files before compressing and uploading
+   * @param pageBulkExportJob page bulk export job in execution
+   * @param isHtmlPath whether the tmp output path is for html files
    */
    */
-  getTmpOutputDir(pageBulkExportJob: PageBulkExportJobDocument): string {
-    return `${this.tmpOutputRootDir}/${pageBulkExportJob._id}`;
+  getTmpOutputDir(pageBulkExportJob: PageBulkExportJobDocument, isHtmlPath = false): string {
+    if (isHtmlPath) {
+      return path.join(this.tmpOutputRootDir, 'html', pageBulkExportJob._id.toString());
+    }
+    return path.join(this.tmpOutputRootDir, pageBulkExportJob._id.toString());
   }
   }
 
 
   /**
   /**

+ 22 - 2
apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/steps/export-pages-to-fs-async.ts

@@ -4,6 +4,9 @@ import { Writable, pipeline } from 'stream';
 
 
 import { isPopulated } from '@growi/core';
 import { isPopulated } from '@growi/core';
 import { getParentPath, normalizePath } from '@growi/core/dist/utils/path-utils';
 import { getParentPath, normalizePath } from '@growi/core/dist/utils/path-utils';
+import remark from 'remark';
+import html from 'remark-html';
+
 
 
 import { PageBulkExportFormat, PageBulkExportJobStatus } from '~/features/page-bulk-export/interfaces/page-bulk-export';
 import { PageBulkExportFormat, PageBulkExportJobStatus } from '~/features/page-bulk-export/interfaces/page-bulk-export';
 
 
@@ -12,11 +15,22 @@ import type { PageBulkExportJobDocument } from '../../../models/page-bulk-export
 import type { PageBulkExportPageSnapshotDocument } from '../../../models/page-bulk-export-page-snapshot';
 import type { PageBulkExportPageSnapshotDocument } from '../../../models/page-bulk-export-page-snapshot';
 import PageBulkExportPageSnapshot from '../../../models/page-bulk-export-page-snapshot';
 import PageBulkExportPageSnapshot from '../../../models/page-bulk-export-page-snapshot';
 
 
+async function convertMdToHtml(md: string, remarkHtml): Promise<string> {
+  const htmlString = (await remarkHtml
+    .process(md))
+    .toString();
+
+  return htmlString;
+}
+
 /**
 /**
  * Get a Writable that writes the page body temporarily to fs
  * Get a Writable that writes the page body temporarily to fs
  */
  */
 function getPageWritable(this: IPageBulkExportJobCronService, pageBulkExportJob: PageBulkExportJobDocument): Writable {
 function getPageWritable(this: IPageBulkExportJobCronService, pageBulkExportJob: PageBulkExportJobDocument): Writable {
-  const outputDir = this.getTmpOutputDir(pageBulkExportJob);
+  const isHtmlPath = pageBulkExportJob.format === PageBulkExportFormat.pdf;
+  const outputDir = this.getTmpOutputDir(pageBulkExportJob, isHtmlPath);
+  // define before the stream starts to avoid creating multiple instances
+  const remarkHtml = remark().use(html);
   return new Writable({
   return new Writable({
     objectMode: true,
     objectMode: true,
     write: async(page: PageBulkExportPageSnapshotDocument, encoding, callback) => {
     write: async(page: PageBulkExportPageSnapshotDocument, encoding, callback) => {
@@ -30,7 +44,13 @@ function getPageWritable(this: IPageBulkExportJobCronService, pageBulkExportJob:
           const fileOutputParentPath = getParentPath(fileOutputPath);
           const fileOutputParentPath = getParentPath(fileOutputPath);
 
 
           await fs.promises.mkdir(fileOutputParentPath, { recursive: true });
           await fs.promises.mkdir(fileOutputParentPath, { recursive: true });
-          await fs.promises.writeFile(fileOutputPath, markdownBody);
+          if (pageBulkExportJob.format === PageBulkExportFormat.md) {
+            await fs.promises.writeFile(fileOutputPath, markdownBody);
+          }
+          else {
+            const htmlString = await convertMdToHtml(markdownBody, remarkHtml);
+            await fs.promises.writeFile(fileOutputPath, htmlString);
+          }
           pageBulkExportJob.lastExportedPagePath = page.path;
           pageBulkExportJob.lastExportedPagePath = page.path;
           await pageBulkExportJob.save();
           await pageBulkExportJob.save();
         }
         }