From 6a0ecda322895227b6a5acb99e95403d5a611def Mon Sep 17 00:00:00 2001 From: Lance Pollard Date: Thu, 18 Jan 2024 08:30:37 -0800 Subject: [PATCH] cleaned up --- code/node/archive.ts | 67 +++------- code/node/base.ts | 197 +--------------------------- code/node/call/convert.ts | 20 +-- code/node/command.ts | 9 +- code/node/document.ts | 112 ++++------------ code/node/font.ts | 23 +--- code/node/html.ts | 3 +- code/node/image.ts | 34 +---- code/node/video.ts | 23 +--- code/shared/archive.ts | 1 + code/shared/document.ts | 32 +++-- code/shared/font.ts | 13 +- code/shared/image.ts | 63 ++++----- code/shared/type/cast.ts | 73 ++++++----- code/shared/type/source/archive.ts | 30 ++++- code/shared/type/source/document.ts | 59 +++++---- code/shared/type/source/font.ts | 4 +- code/shared/type/source/image.ts | 5 + code/shared/type/take.ts | 57 ++++---- code/shared/video.ts | 11 +- readme.md | 1 + 21 files changed, 271 insertions(+), 566 deletions(-) diff --git a/code/node/archive.ts b/code/node/archive.ts index 2fdc8fe..30fb945 100644 --- a/code/node/archive.ts +++ b/code/node/archive.ts @@ -1,16 +1,3 @@ -import { - BuildBaseInputFileOutputDirectoryModel, - UNARCHIVER_FORMAT_KEY, - buildCommandToConvertArchive, - buildCommandToDecompressWith7z, - buildCommandToDecompressWithUnarchiver, -} from '../shared/index.js' -import { - buildUseConvert, - buildUseDecompress, - transform_input_file_output_directory_array, - transform_input_output_file_array, -} from './base.js' import { handleCommand } from './command.js' // defineCompress('rar', buildCommandToCreateRar, runRarCommand) @@ -27,50 +14,26 @@ import { handleCommand } from './command.js' // await run7zCommand(cmd) // } -const IO7z = BuildBaseInputFileOutputDirectoryModel.superRefine( - transform_input_file_output_directory_array(['7z']), -) - -export const useDecompressWith7z = buildUseDecompress(['7z'], '7z') - export async function decompressWith7z(source) { - const input = IO7z.parse(source) - const list = buildCommandToDecompressWith7z(input) - for (const cmd of list) { - await handleCommand(cmd) - } + // const input = IO7z.parse(source) + // const list = buildCommandToDecompressWith7z(input) + // for (const cmd of list) { + // await handleCommand(cmd) + // } } -const IOUnarchiver = BuildBaseInputFileOutputDirectoryModel.superRefine( - transform_input_file_output_directory_array(UNARCHIVER_FORMAT_KEY), -) - -export const useDecompressWithUnarchiver = buildUseDecompress( - UNARCHIVER_FORMAT_KEY, - 'unarchiver', -) - export async function decompressWithUnarchiver(source) { - const input = IOUnarchiver.parse(source) - const list = buildCommandToDecompressWithUnarchiver(input) - for (const cmd of list) { - await handleCommand(cmd) - } + // const input = IOUnarchiver.parse(source) + // const list = buildCommandToDecompressWithUnarchiver(input) + // for (const cmd of list) { + // await handleCommand(cmd) + // } } -const IOConvertArchive = BuildBaseFileInputOutputModel.superRefine( - transform_input_output_file_array(UNARCHIVER_FORMAT_KEY, ['zip']), -) - -export const useConvertArchive = buildUseConvert( - UNARCHIVER_FORMAT_KEY, - ['zip'], -) - export async function convertArchive(source) { - const input = IOConvertArchive.parse(source) - const list = buildCommandToConvertArchive(input) - for (const cmd of list) { - await handleCommand(cmd) - } + // const input = IOConvertArchive.parse(source) + // const list = buildCommandToConvertArchive(input) + // for (const cmd of list) { + // await handleCommand(cmd) + // } } diff --git a/code/node/base.ts b/code/node/base.ts index 3b3cf3b..66bfbba 100644 --- a/code/node/base.ts +++ b/code/node/base.ts @@ -1,12 +1,7 @@ import { RefinementCtx, z } from 'zod' import { replaceFileExtension } from '../shared/tool.js' import path from 'path' -import { - BuildBaseFileInputModel, - BuildBaseFileInputOutputModel, - Task, -} from '../shared/index.js' -import kink from '../shared/kink.js' +import { BuildBaseFileInputModel, Task } from '../shared/index.js' export const transform_input_output_file = (a: string, b: string) => (v: any, ctx: RefinementCtx) => { @@ -47,193 +42,3 @@ export const transform_input_output_file = return v } - -export const transform_input_output_file_array = - (a: ReadonlyArray, b: ReadonlyArray) => - (v: any, ctx: RefinementCtx) => { - const inputPathFormat = path - .extname(v.input.file.path as string) - .slice(1) - - if (!a.includes(inputPathFormat)) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: `Input path has incorrect extension.`, - path: ['input', 'file', 'path'], - params: { - format: a, - }, - }) - } - - v.input.format = inputPathFormat - - const outputFormat = b.filter(x => x !== inputPathFormat) - - if (!v.output.file?.path) { - if (!v.output.format) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: `Must specify a an output file path or format.`, - path: ['output'], - }) - } else if (!outputFormat.includes(v.output.format as string)) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: `Output format is incorrect.`, - path: ['output', 'format'], - params: { - format: b, - }, - }) - } else { - v.output.file ??= {} - v.output.file.path = replaceFileExtension( - v.input.file.path as string, - `.${v.output.format}`, - ) - } - } else { - const outputPathFormat = path - .extname(v.output.file.path as string) - .slice(1) - - if (!outputFormat.includes(outputPathFormat)) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: `Output path has incorrect extension.`, - path: ['output', 'file', 'path'], - }) - } - } - - return v - } - -export const transform_input_file_output_directory_array = - (a: ReadonlyArray) => (v: any, ctx: RefinementCtx) => { - const inputPathFormat = path - .extname(v.input.file.path as string) - .slice(1) - - if (!a.includes(inputPathFormat)) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: `Input path has incorrect extension.`, - path: ['input', 'file', 'path'], - params: { - format: a, - }, - }) - } - - return v - } - -export function buildUseConvert( - i: ReadonlyArray, - o: ReadonlyArray, - tool?: string, -) { - return async (task: Task, source): Promise => { - if (task !== 'convert') { - return false - } - - const input = BuildBaseFileInputOutputModel.parse(source) - const inputFormat = path - .extname(input.input.file.path) - .slice(1) - .toLowerCase() - - if (!i.includes(inputFormat as (typeof i)[number])) { - return false - } - - const outputFormat = input.output.file?.path - ? path.extname(input.output.file.path).slice(1).toLowerCase() - : input.output.format - ? input.output.format.toLowerCase() - : undefined - - if ( - !outputFormat || - !o.includes(outputFormat as (typeof o)[number]) - ) { - return false - } - - if (inputFormat === outputFormat) { - return false - } - - if (tool && input.tool && input.tool !== tool) { - return false - } - - return true - } -} - -export function buildUseSplit(i: ReadonlyArray, tool: string) { - return async (task: Task, source): Promise => { - if (task !== 'split') { - return false - } - - const input = BuildBaseFileInputModel.parse(source) - const inputFormat = path - .extname(input.input.file.path as string) - .slice(1) - .toLowerCase() - - if (!i.includes(inputFormat as (typeof i)[number])) { - return false - } - - const outputFormat = path - .extname(input.output.file.path as string) - .slice(1) - .toLowerCase() - - if ( - !outputFormat || - !i.includes(outputFormat as (typeof i)[number]) - ) { - return false - } - - if (input.tool && input.tool !== tool) { - return false - } - - return true - } -} - -export function buildUseDecompress( - i: ReadonlyArray, - tool: string, -) { - return async (task: Task, source): Promise => { - if (task !== 'decompress') { - return false - } - - const input = BuildBaseFileInputOutputModel.parse(source) - const inputFormat = path - .extname(input.input.file.path) - .slice(1) - .toLowerCase() - - if (!i.includes(inputFormat as (typeof i)[number])) { - return false - } - - if (input.tool && input.tool !== tool) { - return false - } - - return true - } -} diff --git a/code/node/call/convert.ts b/code/node/call/convert.ts index 782c0be..118f1dc 100644 --- a/code/node/call/convert.ts +++ b/code/node/call/convert.ts @@ -1,9 +1,9 @@ /* eslint-disable react-hooks/rules-of-hooks */ import { - CALIBRE_INPUT_FORMAT_CONTENT_KEY, - CALIBRE_OUTPUT_FORMAT_CONTENT_KEY, - CalibreInputFormatContentKey, - CalibreOutputFormatContentKey, + CALIBRE_INPUT_FORMAT, + CALIBRE_OUTPUT_FORMAT, + CalibreInputFormat, + CalibreOutputFormat, FFMPEG_FORMAT, FONT_FORMAT, FfmpegFormat, @@ -138,18 +138,10 @@ export function useConvertDocumentWithCalibre(a: string, b: string) { if (a === b) { return false } - if ( - !CALIBRE_INPUT_FORMAT_CONTENT_KEY.includes( - a as CalibreInputFormatContentKey, - ) - ) { + if (!CALIBRE_INPUT_FORMAT.includes(a as CalibreInputFormat)) { return false } - if ( - !CALIBRE_OUTPUT_FORMAT_CONTENT_KEY.includes( - b as CalibreOutputFormatContentKey, - ) - ) { + if (!CALIBRE_OUTPUT_FORMAT.includes(b as CalibreOutputFormat)) { return false } return true diff --git a/code/node/command.ts b/code/node/command.ts index 586c60d..17cdb01 100644 --- a/code/node/command.ts +++ b/code/node/command.ts @@ -2,7 +2,7 @@ import bytes from 'bytes' import child_process from 'child_process' import { Command, CommandCall, CommandName } from '../shared/index.js' import kink from '../shared/kink.js' -import { ChildProcessError, Message, exec, spawn } from './process.js' +import { ChildProcessError, Message, exec } from './process.js' import Kink from '@termsurf/kink' export type CommandHandle = (cmd: CommandCall) => Promise @@ -36,6 +36,7 @@ export const COMMAND_HANDLE: Record = { zip: handleZipCommand, tar: handleTarCommand, exiftool: handleExiftoolCommand, + gifsicle: handleGifsicleCommand, 'ebook-convert': handleEbookConvertCommand, soffice: handleSofficeCommand, jupyter: handleJupyterCommand, @@ -46,7 +47,7 @@ export const COMMAND_HANDLE: Record = { export async function handleFfmpegCommand( cmd: CommandCall, onUpdate?: (msg: Message) => void, -) { +): Promise { return new Promise((res, rej) => { const command = cmd.shift() as string const child = child_process.spawn(command, cmd) @@ -81,6 +82,10 @@ export async function handleFfmpegCommand( }) } +export async function handleGifsicleCommand(cmd: CommandCall) { + return await exec(cmd.join(' ')) +} + export async function handleBlackCommand(cmd: CommandCall) { return await exec(cmd.join(' ')) } diff --git a/code/node/document.ts b/code/node/document.ts index f6db4d3..8bf02b1 100644 --- a/code/node/document.ts +++ b/code/node/document.ts @@ -2,28 +2,20 @@ import tmp from 'tmp-promise' import libre from 'libreoffice-convert' import fs from 'node:fs/promises' import { - BuildBaseFileInputOutputModel, - CALIBRE_INPUT_FORMAT, - CALIBRE_OUTPUT_FORMAT, - LIBRE_OFFICE_INPUT_FORMAT, - LIBRE_OFFICE_OUTPUT_FORMAT, - PANDOC_INPUT_FORMAT, - PANDOC_OUTPUT_FORMAT, + BuildCommandToConvertDocumentWithCalibreModel, + BuildCommandToConvertDocumentWithLibreOfficeModel, + BuildCommandToConvertDocumentWithPandocModel, + BuildCommandToConvertLatexToPdfWithPdfLatexModel, SlicePdfModel, buildCommandToConvertDocumentWithCalibre, buildCommandToConvertDocumentWithLibreOffice, buildCommandToConvertDocumentWithPandoc, - buildCommandToGenerateLatexPdf, + buildCommandToConvertLatexToPdfWithPdfLatex, slicePdfUsingBytes, } from '../shared/index.js' -import { RefinementCtx, z } from 'zod' -import { - buildUseConvert, - buildUseSplit, - transform_input_output_file_array, -} from './base.js' import _ from 'lodash' import { handleCommand } from './command.js' +import path from 'node:path' // https://help.libreoffice.org/latest/en-US/text/shared/guide/convertfilters.html export async function convertDocumentWithLibreOfficeNative({ @@ -138,64 +130,29 @@ export async function convertDocumentWithLibreOfficeNative({ // fs.writeFileSync(inputPath, bytes) // } -const IOPandoc = BuildBaseFileInputOutputModel.superRefine( - transform_input_output_file_array( - PANDOC_INPUT_FORMAT, - PANDOC_OUTPUT_FORMAT, - ), -) - -export const useConvertDocumentWithPandoc = buildUseConvert( - PANDOC_INPUT_FORMAT, - PANDOC_OUTPUT_FORMAT, - 'pandoc', -) - export async function convertDocumentWithPandoc(source) { - const input = IOPandoc.parse(source) + const input = + BuildCommandToConvertDocumentWithPandocModel.parse(source) const list = buildCommandToConvertDocumentWithPandoc(input) for (const cmd of list) { await handleCommand(cmd) } + return input.output.file.path } -const IOLibreOffice = BuildBaseFileInputOutputModel.superRefine( - transform_input_output_file_array( - LIBRE_OFFICE_INPUT_FORMAT, - LIBRE_OFFICE_OUTPUT_FORMAT, - ), -) - -export const useConvertDocumentWithLibreOffice = buildUseConvert( - LIBRE_OFFICE_INPUT_FORMAT, - LIBRE_OFFICE_OUTPUT_FORMAT, - 'libre_office', -) - export async function convertDocumentWithLibreOffice(source) { - const input = IOLibreOffice.parse(source) + const input = + BuildCommandToConvertDocumentWithLibreOfficeModel.parse(source) const list = buildCommandToConvertDocumentWithLibreOffice(input) for (const cmd of list) { await handleCommand(cmd) } - // return input.output.file.path as string + return input.output.directory.path } -const IOCalibre = BuildBaseFileInputOutputModel.superRefine( - transform_input_output_file_array( - CALIBRE_INPUT_FORMAT, - CALIBRE_OUTPUT_FORMAT, - ), -) - -export const useConvertDocumentWithCalibre = buildUseConvert( - CALIBRE_INPUT_FORMAT, - CALIBRE_OUTPUT_FORMAT, - 'calibre', -) - export async function convertDocumentWithCalibre(source) { - const input = IOCalibre.parse(source) + const input = + BuildCommandToConvertDocumentWithCalibreModel.parse(source) const list = buildCommandToConvertDocumentWithCalibre(input) for (const cmd of list) { await handleCommand(cmd) @@ -203,41 +160,18 @@ export async function convertDocumentWithCalibre(source) { return input.output.file?.path as string } -const IOPdf = BuildBaseFileInputOutputModel.superRefine( - transform_input_output_file_array(['pdf'], ['pdf']), -) - -export const useSplitPdf = buildUseSplit(['pdf'], 'pdf_lib') - -const IO = BuildBaseFileInputOutputModel.superRefine( - (v: any, ctx: RefinementCtx) => { - if (!v.input.file.path.endsWith(`.tex`)) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: `Input path must have extension .tex`, - path: ['input', 'file', 'path'], - }) - } - - return v - }, -) - -export async function convertDocumentWithPdfLatex(source) { - const input = IO.parse(source) - const tmpDirectory = await tmp.dir() - const list = buildCommandToGenerateLatexPdf({ - ...input, - output: { - directory: tmpDirectory, - file: { - name: 'document', - }, - }, - }) +export async function convertLatexToPdfWithPdfLatex(source) { + const input = + BuildCommandToConvertLatexToPdfWithPdfLatexModel.parse(source) + const list = buildCommandToConvertLatexToPdfWithPdfLatex(input) for (const cmd of list) { await handleCommand(cmd) } + const outputPath = path.join( + input.output.directory.path, + `${input.output.file.name}.pdf`, + ) + return outputPath } export async function convertLatexToHtml() { diff --git a/code/node/font.ts b/code/node/font.ts index 57543a7..7a0db76 100644 --- a/code/node/font.ts +++ b/code/node/font.ts @@ -1,29 +1,16 @@ import { - BuildBaseFileInputOutputModel, - FONT_FORMAT, + BuildCommandToConvertFontWithFontForgeModel, buildCommandToConvertFontWithFontForge, } from '../shared/index.js' -import { - buildUseConvert, - transform_input_output_file_array, -} from './base.js' import { handleCommand } from './command.js' -const IOFontForge = BuildBaseFileInputOutputModel.superRefine( - transform_input_output_file_array(FONT_FORMAT, FONT_FORMAT), -) - -export const useConvertFontWithFontForge = buildUseConvert( - FONT_FORMAT, - FONT_FORMAT, - 'fontforge', -) - export async function convertFontWithFontForge(source) { - const input = IOFontForge.parse(source) + const input = + BuildCommandToConvertFontWithFontForgeModel.parse(source) + const list = await buildCommandToConvertFontWithFontForge(input) for (const cmd of list) { await handleCommand(cmd) } - return input.output.file?.path as string + return input.output.file.path } diff --git a/code/node/html.ts b/code/node/html.ts index a74dd48..ba0dd31 100644 --- a/code/node/html.ts +++ b/code/node/html.ts @@ -3,7 +3,6 @@ import puppeteer from 'puppeteer-extra' import fs from 'fs' // add stealth plugin and use defaults (all evasion techniques) import StealthPlugin from 'puppeteer-extra-plugin-stealth' -import { ConvertHtmlToPdf, ConvertHtmlToPdfModel } from '../shared' puppeteer.use(StealthPlugin()) @@ -97,7 +96,7 @@ export async function inspectWebpage(source) { await wait(1000) - let data = await p.evaluate(() => task.getWebpageData()) + let data = await p.evaluate('task.getWebpageData()') await b.close() return data } diff --git a/code/node/image.ts b/code/node/image.ts index 181382a..f3e475a 100644 --- a/code/node/image.ts +++ b/code/node/image.ts @@ -1,6 +1,7 @@ import _ from 'lodash' import { - BuildBaseFileInputOutputModel, + BuildCommandToConvertAiToSvgWithInkscapeModel, + BuildCommandToProcessImageModel, IMAGE_MAGICK_INPUT_FORMAT, IMAGE_MAGICK_OUTPUT_FORMAT, INKSCAPE_EXPORT_FORMAT, @@ -51,42 +52,21 @@ import { handleCommand } from './command.js' // https://exiv2.org/tags.html -const IOImageMagick = BuildBaseFileInputOutputModel.superRefine( - transform_input_output_file_array( - IMAGE_MAGICK_INPUT_FORMAT, - IMAGE_MAGICK_OUTPUT_FORMAT, - ), -) - -export const useConvertImageWithImageMagick = buildUseConvert( - IMAGE_MAGICK_INPUT_FORMAT, - IMAGE_MAGICK_OUTPUT_FORMAT, - 'image_magick', -) - export async function convertImageWithImageMagick(source) { - const input = IOImageMagick.parse(source) + const input = BuildCommandToProcessImageModel.parse(source) const list = buildCommandToProcessImage(input) for (const cmd of list) { await handleCommand(cmd) } - return input.output.file?.path as string + return input.output.file.path } -const IOInkscape = BuildBaseFileInputOutputModel.superRefine( - transform_input_output_file_array(['ai'], INKSCAPE_EXPORT_FORMAT), -) - -export const useConvertImageWithInkscape = buildUseConvert( - ['ai'], - INKSCAPE_EXPORT_FORMAT, - 'inkscape', -) - export async function convertImageWithInkscape(source) { - const input = IOInkscape.parse(source) + const input = + BuildCommandToConvertAiToSvgWithInkscapeModel.parse(source) const list = await buildCommandToConvertAIToSVGWithInkscape(input) for (const cmd of list) { await handleCommand(cmd) } + return input.output.file.path } diff --git a/code/node/video.ts b/code/node/video.ts index 07d9438..85a64a6 100644 --- a/code/node/video.ts +++ b/code/node/video.ts @@ -1,12 +1,5 @@ import { buildCommandToConvertVideoWithFfmpeg } from '../shared/index.js' -import { - BuildBaseFileInputOutputModel, - FFMPEG_FORMAT, -} from '../shared/type/index.js' -import { - buildUseConvert, - transform_input_output_file_array, -} from './base.js' +import { BuildCommandToConvertVideoWithFfmpegModel } from '../shared/type/index.js' import { handleFfmpegCommand } from './command.js' import { Message } from './process.js' @@ -20,25 +13,15 @@ import { Message } from './process.js' // ) // } -const IOFfmpeg = BuildBaseFileInputOutputModel.superRefine( - transform_input_output_file_array(FFMPEG_FORMAT, FFMPEG_FORMAT), -) - -export const useConvertVideoWithFfmpeg = buildUseConvert( - FFMPEG_FORMAT, - FFMPEG_FORMAT, - 'ffmpeg', -) - export async function convertVideoWithFfmpeg( source, onUpdate?: (msg: Message) => void, ) { - const input = IOFfmpeg.parse(source) + const input = BuildCommandToConvertVideoWithFfmpegModel.parse(source) const list = await buildCommandToConvertVideoWithFfmpeg(input) const cmd = list[0] if (cmd) { await handleFfmpegCommand(cmd.list, onUpdate) } - return input.output.file?.path as string + return input.output.file.path } diff --git a/code/shared/archive.ts b/code/shared/archive.ts index 7b277dc..6e89d26 100644 --- a/code/shared/archive.ts +++ b/code/shared/archive.ts @@ -98,3 +98,4 @@ export function buildCommandToCreateRar(source) { // https://superuser.com/questions/190053/universal-command-line-unarchiving-tool-on-a-mac // atool // .tar.gz, .tgz, .tar.bz, .tbz, .tar.bz2, .tbz2, .tar.Z, .tZ, .tar.lzo, .tzo, .tar.lz, .tlz, .tar.xz, .txz, .tar.7z, .t7z, .tar, .zip, .jar, .war, .rar, .lha, .lzh, .7z, .alz, .ace, .a, .arj, .arc, .rpm, .deb, .cab, .gz, .bz, .bz2, .gz, .bz, .bz2, .Z, .lzma, .lzo, .lz, .xz, .rz, .lrz, .7z, .cpio +// https://linux.die.net/man/1/apack diff --git a/code/shared/document.ts b/code/shared/document.ts index 465e139..785a42d 100644 --- a/code/shared/document.ts +++ b/code/shared/document.ts @@ -2,14 +2,20 @@ import { PDFDocument } from 'pdf-lib' import _sanitizeHtml from 'sanitize-html' import path from 'path' import { + BuildCommandToConvertDocumentWithCalibre, BuildCommandToConvertDocumentWithCalibreModel, BuildCommandToConvertDocumentWithJupyterModel, + BuildCommandToConvertDocumentWithLibreOffice, BuildCommandToConvertDocumentWithLibreOfficeModel, + BuildCommandToConvertDocumentWithPandoc, BuildCommandToConvertDocumentWithPandocModel, - BuildCommandToGenerateLatexPdfModel, + convertLatexToPdfWithPdfLatexModel, CheckIfPdfIsValidWithDataModel, SanitizeHtmlFromContentModel, SlicePdfWithDataModel, + BuildCommandToConvertLatexToPdfWithPdfLatexModelModel, + BuildCommandToConvertLatexToPdfWithPdfLatexModel, + BuildCommandToConvertLatexToPdfWithPdfLatex, } from './type/index.js' import { getCommand } from './command.js' @@ -23,9 +29,9 @@ export async function checkIfPdfIsValid(source) { } } -export function buildCommandToConvertDocumentWithLibreOffice(source) { - const input = - BuildCommandToConvertDocumentWithLibreOfficeModel.parse(source) +export function buildCommandToConvertDocumentWithLibreOffice( + input: BuildCommandToConvertDocumentWithLibreOffice, +) { const cmd = getCommand('soffice') cmd.list.push('--headless') cmd.list.push('--convert-to') @@ -36,9 +42,10 @@ export function buildCommandToConvertDocumentWithLibreOffice(source) { return [cmd] } -export function buildCommandToConvertDocumentWithPandoc(source: any) { - const { input, output } = - BuildCommandToConvertDocumentWithPandocModel.parse(source) +export function buildCommandToConvertDocumentWithPandoc( + source: BuildCommandToConvertDocumentWithPandoc, +) { + const { input, output } = source const cmd = getCommand(`pandoc`) cmd.list.push( @@ -57,8 +64,9 @@ export function buildCommandToConvertDocumentWithPandoc(source: any) { // https://www.reddit.com/r/hacking/comments/108sp8f/how_to_know_if_a_pdf_contains_malware/ -export function buildCommandToGenerateLatexPdf(source: any) { - const input = BuildCommandToGenerateLatexPdfModel.parse(source) +export function buildCommandToConvertLatexToPdfWithPdfLatex( + input: BuildCommandToConvertLatexToPdfWithPdfLatex, +) { const cmd = getCommand(`pdflatex`) cmd.list.push( `-interaction=nonstopmode`, @@ -72,9 +80,9 @@ export function buildCommandToGenerateLatexPdf(source: any) { return [cmd] } -export function buildCommandToConvertDocumentWithCalibre(source: any) { - const input = - BuildCommandToConvertDocumentWithCalibreModel.parse(source) +export function buildCommandToConvertDocumentWithCalibre( + input: BuildCommandToConvertDocumentWithCalibre, +) { const cmd = getCommand(`ebook-convert`) cmd.list.push(input.input.file.path, input.output.file.path) return [cmd] diff --git a/code/shared/font.ts b/code/shared/font.ts index 83c16b5..6bc8a74 100644 --- a/code/shared/font.ts +++ b/code/shared/font.ts @@ -1,17 +1,16 @@ import { getCommand } from './command.js' -import { BuildCommandToConvertFontWithFontForgeModel } from './type/index.js' - -export async function buildCommandToConvertFontWithFontForge(source) { - const { input, output } = - BuildCommandToConvertFontWithFontForgeModel.parse(source) +import { BuildCommandToConvertFontWithFontForge } from './type/index.js' +export async function buildCommandToConvertFontWithFontForge( + input: BuildCommandToConvertFontWithFontForge, +) { const cmd = getCommand(`fontforge`) cmd.list.push( `-lang=ff`, `-c`, `'Open($1); Generate($2)'`, - `"${input.file.path}"`, - `"${output.file.path}"`, + `"${input.input.file.path}"`, + `"${input.output.file.path}"`, ) return [cmd] diff --git a/code/shared/image.ts b/code/shared/image.ts index 9fafca0..25db9fa 100644 --- a/code/shared/image.ts +++ b/code/shared/image.ts @@ -1,7 +1,9 @@ import { YYYY_MM_DD_HH_MM_SS, toDayJs } from './date.js' import { + BuildCommandToConvertAiToSvgWithInkscape, BuildCommandToConvertAiToSvgWithInkscapeModel, BuildCommandToExtractMetadataFromImageModel, + BuildCommandToProcessImage, BuildCommandToProcessImageModel, BuildCommandToReplaceImageColorWithImageMagickModel, BuildCommandToResizeImageWithImageMagickModel, @@ -25,63 +27,49 @@ import _ from 'lodash' // return [cmd] // } -export function buildCommandToProcessImage(source) { - const { - input, - output, - colorCount, - colorMatrix, - colorSpace, - compare, - compression, - } = BuildCommandToProcessImageModel.parse(source) - +export function buildCommandToProcessImage( + input: BuildCommandToProcessImage, +) { const cmd = getCommand(`convert`) - let inputPath = input.file.path.match(/\.cr2$/i) - ? `cr2:${input.file.path}` - : input.file.path + let inputPath = input.input.file.path.match(/\.cr2$/i) + ? `cr2:${input.input.file.path}` + : input.input.file.path cmd.list.push(`"${inputPath}"`) - let outputPath = output.file.path - ? output.file.path - : replaceFileExtension( - input.file.path as string, - `.${output.format}`, - ) - - if (compare) { + if (input.compare) { cmd.list.push(`-compare`) } - if (colorMatrix) { + if (input.colorMatrix) { cmd.list.push( `-color-matrix`, - `"${colorMatrix.row}x${ - colorMatrix.column - }: ${colorMatrix.value.join(' ')}"`, + `"${input.colorMatrix.row}x${ + input.colorMatrix.column + }: ${input.colorMatrix.value.join(' ')}"`, ) } - if (colorSpace) { + if (input.colorSpace) { cmd.list.push( `-colorspace`, - IMAGE_MAGICK_COLOR_SPACE_CONTENT[colorSpace].head, + IMAGE_MAGICK_COLOR_SPACE_CONTENT[input.colorSpace].head, ) } - if (compression) { + if (input.compression) { cmd.list.push( `-compress`, - IMAGE_MAGICK_COMPRESSION_CONTENT[compression].head as string, + IMAGE_MAGICK_COMPRESSION_CONTENT[input.compression] + .head as string, ) } - if (colorCount) { - cmd.list.push(`-colors`, String(colorCount)) + if (input.colorCount) { + cmd.list.push(`-colors`, String(input.colorCount)) } - cmd.list.push(`"${outputPath}"`) + cmd.list.push(`"${input.output.file.path}"`) // const cmd = [ // `magick`, @@ -276,17 +264,14 @@ export function buildCommandToGenerateGifWithGifsicle(source) { } export async function buildCommandToConvertAIToSVGWithInkscape( - source: any, + input: BuildCommandToConvertAiToSvgWithInkscape, ) { - const { input, output } = - BuildCommandToConvertAiToSvgWithInkscapeModel.parse(source) - const cmd = getCommand(`inkscape`) cmd.list.push( - `"${input.file.path}"`, + `"${input.input.file.path}"`, `-${process.platform === 'darwin' ? 'o' : 'l'}`, - `"${output.file.path}"`, + `"${input.output.file.path}"`, ) return [cmd] diff --git a/code/shared/type/cast.ts b/code/shared/type/cast.ts index 1265628..c98c792 100644 --- a/code/shared/type/cast.ts +++ b/code/shared/type/cast.ts @@ -1,5 +1,9 @@ import _ from 'lodash' +export const ARCHIVE_FORMAT = ['zip'] as const + +export type ArchiveFormat = (typeof ARCHIVE_FORMAT)[number] + export const ASSEMBLY_SYNTAX = ['intel', 'att'] as const export type AssemblySyntax = (typeof ASSEMBLY_SYNTAX)[number] @@ -194,7 +198,7 @@ export type BuildCommandToConvertArchive = { } } input: { - format: string + format: UnarchiverFormat file: { path: string } @@ -209,13 +213,13 @@ export type BuildCommandToConvertArchive = { export type BuildCommandToConvertDocumentWithCalibre = { input: { - format: string + format: CalibreInputFormat file: { path: string } } output: { - format: string + format: CalibreOutputFormat file: { path: string } @@ -239,13 +243,13 @@ export type BuildCommandToConvertDocumentWithJupyter = { export type BuildCommandToConvertDocumentWithLibreOffice = { input: { - format: string + format: LibreOfficeInputFormat file: { path: string } } output: { - format: string + format: LibreOfficeOutputFormat directory: { path: string } @@ -269,17 +273,34 @@ export type BuildCommandToConvertDocumentWithPandoc = { export type BuildCommandToConvertFontWithFontForge = { input: { - format: string + format: FontFormat file: { path: string } } output: { + format: FontFormat + file: { + path: string + } + } +} + +export type BuildCommandToConvertLatexToPdfWithPdfLatex = { + input: { format: string file: { path: string } } + output: { + directory: { + path: string + } + file: { + name: string + } + } } export type BuildCommandToConvertMp4ToGifWithFfmpeg = { @@ -562,21 +583,6 @@ export type BuildCommandToGenerateGifWithGifsicle = { unoptimize?: boolean } -export type BuildCommandToGenerateLatexPdf = { - input: { - format: string - file: { - path: string - } - } - output: { - directory: string - file: { - name: string - } - } -} - export type BuildCommandToProcessImage = { input: { format: string @@ -95313,6 +95319,11 @@ export const INKSCAPE_EXPORT_FORMAT = [ export type InkscapeExportFormat = (typeof INKSCAPE_EXPORT_FORMAT)[number] +export const INKSCAPE_IMPORT_FORMAT = ['ai'] as const + +export type InkscapeImportFormat = + (typeof INKSCAPE_IMPORT_FORMAT)[number] + export const LIBRE_OFFICE_INPUT_FORMAT = [ 'html', 'mediawiki', @@ -108033,11 +108044,7 @@ export const TASK = [ export type Task = (typeof TASK)[number] -export type UnarchiverFormatValue = { - head: string -} - -export const UNARCHIVER_FORMAT_KEY = [ +export const UNARCHIVER_FORMAT = [ 'zip', 'rar', '7z', @@ -108052,14 +108059,18 @@ export const UNARCHIVER_FORMAT_KEY = [ 'iso', ] as const -export type UnarchiverFormatKey = (typeof UNARCHIVER_FORMAT_KEY)[number] +export type UnarchiverFormat = (typeof UNARCHIVER_FORMAT)[number] + +export type UnarchiverFormatContentValue = { + head: string +} -export type UnarchiverFormat = Record< - UnarchiverFormatKey, - UnarchiverFormatValue +export type UnarchiverFormatContent = Record< + UnarchiverFormat, + UnarchiverFormatContentValue > -export const UNARCHIVER_FORMAT: UnarchiverFormat = { +export const UNARCHIVER_FORMAT_CONTENT: UnarchiverFormatContent = { zip: { head: 'Zip', }, diff --git a/code/shared/type/source/archive.ts b/code/shared/type/source/archive.ts index a56ae7b..318a0bf 100644 --- a/code/shared/type/source/archive.ts +++ b/code/shared/type/source/archive.ts @@ -1,4 +1,4 @@ -import { Form, Hash } from '@termsurf/form' +import { Form, Hash, List } from '@termsurf/form' export const build_command_to_decompress7z: Form = { form: 'form', @@ -65,9 +65,28 @@ export const build_command_to_create_rar: Form = { }, } +export const unarchiver_format: List = { + form: 'list', + list: [ + 'zip', + 'rar', + '7z', + 'tar', + 'gzip', + 'bzip2', + 'lzma', + 'cab', + 'msi', + 'nsis', + 'exe', + 'iso', + ], +} + // https://github.com/ashang/unar/blob/master/README.md -export const unarchiver_format: Hash = { +export const unarchiver_format_content: Hash = { form: 'hash', + link: 'unarchiver_format', bond: { head: { like: 'string' }, }, @@ -87,6 +106,11 @@ export const unarchiver_format: Hash = { }, } +export const archive_format: List = { + form: 'list', + list: ['zip'], +} + export const build_command_to_convert_archive: Form = { form: 'form', link: { @@ -101,7 +125,7 @@ export const build_command_to_convert_archive: Form = { }, input: { link: { - format: { like: 'string', name: { mark: 'I' } }, + format: { like: 'unarchiver_format', name: { mark: 'I' } }, file: { link: { path: { like: 'string' } }, }, diff --git a/code/shared/type/source/document.ts b/code/shared/type/source/document.ts index 6b5bd79..4a42ce5 100644 --- a/code/shared/type/source/document.ts +++ b/code/shared/type/source/document.ts @@ -545,38 +545,43 @@ export const calibre_output_profile: List = { // https://manpages.ubuntu.com/manpages/bionic/man1/ebook-convert.1.html -export const build_command_to_generate_latex_pdf: Form = { - form: 'form', - link: { - input: { - link: { - format: { like: 'string', name: { mark: 'I' } }, - file: { - link: { - path: { like: 'string' }, +export const build_command_to_convert_latex_to_pdf_with_pdf_latex: Form = + { + form: 'form', + link: { + input: { + link: { + format: { like: 'string', name: { mark: 'I' } }, + file: { + link: { + path: { like: 'string' }, + }, }, }, }, - }, - output: { - link: { - directory: { like: 'string' }, - file: { - link: { - name: { like: 'string' }, + output: { + link: { + directory: { + link: { + path: { like: 'string' }, + }, + }, + file: { + link: { + name: { like: 'string' }, + }, }, }, }, }, - }, -} + } export const build_command_to_convert_document_with_calibre: Form = { form: 'form', link: { input: { link: { - format: { like: 'string', name: { mark: 'I' } }, + format: { like: 'calibre_input_format', name: { mark: 'I' } }, file: { link: { path: { like: 'string' }, @@ -586,7 +591,7 @@ export const build_command_to_convert_document_with_calibre: Form = { }, output: { link: { - format: { like: 'string', name: { mark: 'O' } }, + format: { like: 'calibre_output_format', name: { mark: 'O' } }, file: { link: { path: { like: 'string' }, @@ -603,20 +608,26 @@ export const build_command_to_convert_document_with_libre_office: Form = link: { input: { link: { - format: { like: 'string', name: { mark: 'I' } }, + format: { + like: 'libre_office_input_format', + name: { mark: 'I' }, + }, file: { link: { - path: { like: 'string' }, + path: { like: 'string', name: { mark: 'i' } }, }, }, }, }, output: { link: { - format: { like: 'string', name: { mark: 'O' } }, + format: { + like: 'libre_office_output_format', + name: { mark: 'O' }, + }, directory: { link: { - path: { like: 'string' }, + path: { like: 'string', name: { mark: 'b' } }, }, }, }, diff --git a/code/shared/type/source/font.ts b/code/shared/type/source/font.ts index 9fecf6f..9ae2b47 100644 --- a/code/shared/type/source/font.ts +++ b/code/shared/type/source/font.ts @@ -10,7 +10,7 @@ export const build_command_to_convert_font_with_font_forge: Form = { link: { input: { link: { - format: { like: 'string', name: { mark: 'I' } }, + format: { like: 'font_format', name: { mark: 'I' } }, file: { link: { path: { like: 'string', name: { mark: 'i' } }, @@ -20,7 +20,7 @@ export const build_command_to_convert_font_with_font_forge: Form = { }, output: { link: { - format: { like: 'string', name: { mark: 'O' } }, + format: { like: 'font_format', name: { mark: 'O' } }, file: { link: { path: { like: 'string', name: { mark: 'o' } }, diff --git a/code/shared/type/source/image.ts b/code/shared/type/source/image.ts index 1f43df4..02bc478 100644 --- a/code/shared/type/source/image.ts +++ b/code/shared/type/source/image.ts @@ -1434,6 +1434,11 @@ export const build_command_to_convert_ai_to_svg_with_inkscape: Form = { }, } +export const inkscape_import_format: List = { + form: 'list', + list: ['ai'], +} + export const inkscape_export_format: List = { form: 'list', list: ['svg', 'png', 'ps', 'eps', 'pdf', 'emf', 'wmf', 'xaml'], diff --git a/code/shared/type/take.ts b/code/shared/type/take.ts index 967ca7a..2ec8f71 100644 --- a/code/shared/type/take.ts +++ b/code/shared/type/take.ts @@ -3,6 +3,10 @@ import * as Cast from './cast.js' import { MAKE, TEST } from '@termsurf/form' import * as code from './source/index.js' +export const ArchiveFormatModel: z.ZodType = z.enum( + Cast.ARCHIVE_FORMAT, +) + export const AssemblySyntaxModel: z.ZodType = z.enum(Cast.ASSEMBLY_SYNTAX) @@ -226,7 +230,7 @@ export const BuildCommandToConvertArchiveModel: z.ZodType UnarchiverFormatModel), file: z.object({ path: z.string(), }), @@ -242,13 +246,13 @@ export const BuildCommandToConvertArchiveModel: z.ZodType = z.object({ input: z.object({ - format: z.string(), + format: z.lazy(() => CalibreInputFormatModel), file: z.object({ path: z.string(), }), }), output: z.object({ - format: z.string(), + format: z.lazy(() => CalibreOutputFormatModel), file: z.object({ path: z.string(), }), @@ -274,13 +278,13 @@ export const BuildCommandToConvertDocumentWithJupyterModel: z.ZodType = z.object({ input: z.object({ - format: z.string(), + format: z.lazy(() => LibreOfficeInputFormatModel), file: z.object({ path: z.string(), }), }), output: z.object({ - format: z.string(), + format: z.lazy(() => LibreOfficeOutputFormatModel), directory: z.object({ path: z.string(), }), @@ -306,17 +310,35 @@ export const BuildCommandToConvertDocumentWithPandocModel: z.ZodType = z.object({ input: z.object({ - format: z.string(), + format: z.lazy(() => FontFormatModel), file: z.object({ path: z.string(), }), }), output: z.object({ + format: z.lazy(() => FontFormatModel), + file: z.object({ + path: z.string(), + }), + }), + }) + +export const BuildCommandToConvertLatexToPdfWithPdfLatexModel: z.ZodType = + z.object({ + input: z.object({ format: z.string(), file: z.object({ path: z.string(), }), }), + output: z.object({ + directory: z.object({ + path: z.string(), + }), + file: z.object({ + name: z.string(), + }), + }), }) export const BuildCommandToConvertMp4ToGifWithFfmpegModel: z.ZodType = @@ -692,22 +714,6 @@ export const BuildCommandToGenerateGifWithGifsicleModel: z.ZodType = - z.object({ - input: z.object({ - format: z.string(), - file: z.object({ - path: z.string(), - }), - }), - output: z.object({ - directory: z.string(), - file: z.object({ - name: z.string(), - }), - }), - }) - export const BuildCommandToProcessImageModel: z.ZodType = z.object({ input: z.object({ @@ -1367,6 +1373,9 @@ export const ImageMagickOutputFormatModel: z.ZodType = z.enum(Cast.INKSCAPE_EXPORT_FORMAT) +export const InkscapeImportFormatModel: z.ZodType = + z.enum(Cast.INKSCAPE_IMPORT_FORMAT) + export const LibreOfficeInputFormatModel: z.ZodType = z.enum(Cast.LIBRE_OFFICE_INPUT_FORMAT) @@ -1442,5 +1451,5 @@ export const SlicePdfWithDataModel: z.ZodType = export const TaskModel: z.ZodType = z.enum(Cast.TASK) -export const UnarchiverFormatKeyModel: z.ZodType = - z.enum(Cast.UNARCHIVER_FORMAT_KEY) +export const UnarchiverFormatModel: z.ZodType = + z.enum(Cast.UNARCHIVER_FORMAT) diff --git a/code/shared/video.ts b/code/shared/video.ts index 0662048..9f7f45d 100644 --- a/code/shared/video.ts +++ b/code/shared/video.ts @@ -2,6 +2,7 @@ import { getCommand } from './command.js' import { BuildCommandToCompressMp4WithFfmpegModel, BuildCommandToConvertMp4ToGifWithFfmpegModel, + BuildCommandToConvertVideoWithFfmpeg, BuildCommandToConvertVideoWithFfmpegModel, FfmpegCodecAudio, IOPath, @@ -98,9 +99,11 @@ export async function buildCommandToCompressMP4WithFfmpeg(source) { // extract sound from video // ffmpeg -i source_video.avi -vn -ar 44100 -ac 2 -ab 192k -f mp3 sound.mp3 // https://catswhocode.com/ffmpeg-commands/ -export async function buildCommandToConvertVideoWithFfmpeg(source) { +export async function buildCommandToConvertVideoWithFfmpeg( + input: BuildCommandToConvertVideoWithFfmpeg, +) { let { - input, + input: i, output, audioCodec, videoCodec, @@ -119,7 +122,7 @@ export async function buildCommandToConvertVideoWithFfmpeg(source) { rotation, overwrite, progress, - } = BuildCommandToConvertVideoWithFfmpegModel.parse(source) + } = input const cmd = getCommand(`ffmpeg`) @@ -135,7 +138,7 @@ export async function buildCommandToConvertVideoWithFfmpeg(source) { cmd.list.push(`-stats`, `-progress`, `-`) } - cmd.list.push(`-i`, `${input.file.path}`) + cmd.list.push(`-i`, `${i.file.path}`) if (startTime) { cmd.list.push(`-ss`, `${startTime}`) diff --git a/readme.md b/readme.md index fde80b5..5ed7b57 100644 --- a/readme.md +++ b/readme.md @@ -55,6 +55,7 @@ brew install pyenv brew install jupyter pip install nbconvert pip install docx2pdf +brew install atool ``` To use `docx2pdf` you need to have the Microsoft Word app installed on your machine as well.