split all operators

This commit is contained in:
Felix Kaspar 2024-07-13 23:02:46 +02:00
parent 335a879e81
commit 4056d87335
27 changed files with 285 additions and 404 deletions

View File

@ -18,11 +18,11 @@ import {
if (isJsFile) {
const baseName = path.basename(filePath, '.ts');
if(baseName != "index") {
if(baseName != "index" && !baseName.endsWith(".schema")) {
//TODO: Extract more info from operators. Currently not possible see: https://github.com/egoist/vite-plugin-compile-time/issues/25
jsFiles.push({
baseName: baseName
basename: baseName
});
}
}

View File

@ -0,0 +1,26 @@
import { OperatorSchema } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
export default new OperatorSchema(
i18next.t("friendlyName", { ns: "arrangePages" }),
i18next.t("description", { ns: "arrangePages" }),
JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description")),
Joi.object({
arrangementConfig: Joi.string().valid(...[
"REVERSE_ORDER",
"DUPLEX_SORT",
"BOOKLET_SORT",
"SIDE_STITCH_BOOKLET_SORT",
"ODD_EVEN_SPLIT",
"REMOVE_FIRST",
"REMOVE_LAST",
"REMOVE_FIRST_AND_LAST"
]).required()
.label(i18next.t("values.arrangementConfig.friendlyName", { ns: "arrangePages" })).description(i18next.t("values.arrangementConfig.description", { ns: "arrangePages" }))
.example("REVERSE_ORDER").example("DUPLEX_SORT").example("BOOKLET_SORT").required()
}),
JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"))
);

View File

@ -1,49 +1,10 @@
import { Operator, Progress, oneToOne } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import { PdfFile } from "../wrappers/PdfFile";
import { Sorts } from "./common/pageIndexesSorting";
import { getPages } from "./common/getPagesByIndex";
export class ArrangePages extends Operator {
static type = "arrangePages";
/**
* Validation & Localisation
*/
protected static inputSchema = JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description"));
protected static valueSchema = Joi.object({
arrangementConfig: Joi.string().valid(...[
"REVERSE_ORDER",
"DUPLEX_SORT",
"BOOKLET_SORT",
"SIDE_STITCH_BOOKLET_SORT",
"ODD_EVEN_SPLIT",
"REMOVE_FIRST",
"REMOVE_LAST",
"REMOVE_FIRST_AND_LAST"
]).required()
.label(i18next.t("values.arrangementConfig.friendlyName", { ns: "arrangePages" })).description(i18next.t("values.arrangementConfig.description", { ns: "arrangePages" }))
.example("REVERSE_ORDER").example("DUPLEX_SORT").example("BOOKLET_SORT").required()
});
protected static outputSchema = JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"));
static schema = Joi.object({
input: ArrangePages.inputSchema,
values: ArrangePages.valueSchema.required(),
output: ArrangePages.outputSchema
}).label(i18next.t("friendlyName", { ns: "arrangePages" })).description(i18next.t("description", { ns: "arrangePages" }));
/**
* Logic
*/
/** Detect and remove white pages */
async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> {
return oneToOne<PdfFile, PdfFile>(input, async (input, index, max) => {

View File

@ -0,0 +1,19 @@
import { OperatorSchema } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import CommaArrayJoiExt from "../wrappers/CommaArrayJoiExt";
export default new OperatorSchema(
i18next.t("friendlyName", { ns: "extractPages" }),
i18next.t("description", { ns: "extractPages" }),
JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description")),
Joi.object({
pageIndexes: CommaArrayJoiExt.comma_array().items(Joi.number().integer()).required()
.label(i18next.t("values.pageIndexes.friendlyName", { ns: "extractPages" })).description(i18next.t("values.pageIndexes.description", { ns: "extractPages" }))
.example("1").example("1, 2, 3, 4").example("4, 2, 4, 3").required()
}),
JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"))
);

View File

@ -1,40 +1,8 @@
import { PdfFile, RepresentationType } from "../wrappers/PdfFile";
import { PdfFile } from "../wrappers/PdfFile";
import { Operator, Progress, oneToOne } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import { getPages } from "./common/getPagesByIndex";
import CommaArrayJoiExt from "../wrappers/CommaArrayJoiExt";
export class ExtractPages extends Operator {
static type = "extractPages";
/**
* Validation & Localisation
*/
protected static inputSchema = JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description"));
protected static valueSchema = Joi.object({
pageIndexes: CommaArrayJoiExt.comma_array().items(Joi.number().integer()).required()
.label(i18next.t("values.pageIndexes.friendlyName", { ns: "extractPages" })).description(i18next.t("values.pageIndexes.description", { ns: "extractPages" }))
.example("1").example("1, 2, 3, 4").example("4, 2, 4, 3").required()
});
protected static outputSchema = JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"));
static schema = Joi.object({
input: ExtractPages.inputSchema,
values: ExtractPages.valueSchema.required(),
output: ExtractPages.outputSchema
}).label(i18next.t("friendlyName", { ns: "extractPages" })).description(i18next.t("description", { ns: "extractPages" }));
/**
* Logic
*/
/** PDF extraction, specify pages from one pdf and output them to a new pdf */
async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> {
return oneToOne<PdfFile, PdfFile>(input, async (input, index, max) => {

View File

@ -5,10 +5,6 @@ import { Operator, Progress, oneToOne } from ".";
import * as pdfcpuWrapper from "#pdfcpu"; // This is updated by tsconfig.json/paths for the context (browser, node, etc.) this module is used in.
export class Impose extends Operator {
/**
* Logic
*/
/** PDF-Imposition, PDF-N-Up: Put multiple pages of the input document into a single page of the output document. - see: {@link https://en.wikipedia.org/wiki/N-up} */
async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> {
return oneToOne<PdfFile, PdfFile>(input, async (input, index, max) => {

View File

@ -0,0 +1,13 @@
import { OperatorSchema } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
export default new OperatorSchema(
i18next.t("friendlyName", { ns: "merge" }),
i18next.t("description", { ns: "merge" }),
JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description")),
Joi.object({}),
JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"))
);

View File

@ -2,35 +2,9 @@
import { PdfFile, RepresentationType } from "../wrappers/PdfFile";
import { Operator, Progress, nToOne } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import { PDFDocument } from "pdf-lib";
export class Merge extends Operator {
static type = "merge";
/**
* Validation & Localisation
*/
protected static inputSchema = JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description"));
protected static valueSchema = Joi.object({});
protected static outputSchema = JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"));
static schema = Joi.object({
input: Merge.inputSchema,
values: Merge.valueSchema.required(),
output: Merge.outputSchema
}).label(i18next.t("friendlyName", { ns: "merge" })).description(i18next.t("description", { ns: "merge" }));
/**
* Logic
*/
/** Merging pages from multiple pdfs into a singe output document. */
async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> {
return nToOne<PdfFile, PdfFile>(input, async (input) => {

View File

@ -0,0 +1,17 @@
import { OperatorSchema } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
export default new OperatorSchema(
i18next.t("friendlyName", { ns: "removeBlankPages" }),
i18next.t("description", { ns: "removeBlankPages" }),
JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description")),
Joi.object({
whiteThreashold: Joi.number().min(0).max(255).required()
.label(i18next.t("values.whiteThreashold.friendlyName", { ns: "removeBlankPages" })).description(i18next.t("values.whiteThreashold.description", { ns: "removeBlankPages" }))
.example("10").example("0").example("255").required()
}),
JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"))
);

View File

@ -1,41 +1,11 @@
import { Operator, Progress, oneToOne } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import { PdfFile } from "../wrappers/PdfFile";
import { detectEmptyPages } from "./common/detectEmptyPages";
import { getPages } from "./common/getPagesByIndex";
import { invertSelection } from "./common/pageIndexesUtils";
export class RemoveBlankPages extends Operator {
static type = "removeBlankPages";
/**
* Validation & Localisation
*/
protected static inputSchema = JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description"));
protected static valueSchema = Joi.object({
whiteThreashold: Joi.number().min(0).max(255).required()
.label(i18next.t("values.whiteThreashold.friendlyName", { ns: "removeBlankPages" })).description(i18next.t("values.whiteThreashold.description", { ns: "removeBlankPages" }))
.example("10").example("0").example("255").required()
});
protected static outputSchema = JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"));
static schema = Joi.object({
input: RemoveBlankPages.inputSchema,
values: RemoveBlankPages.valueSchema.required(),
output: RemoveBlankPages.outputSchema
}).label(i18next.t("friendlyName", { ns: "removeBlankPages" })).description(i18next.t("description", { ns: "removeBlankPages" }));
/**
* Logic
*/
/** Detect and remove white pages */
async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> {
return oneToOne<PdfFile, PdfFile>(input, async (input, index, max) => {

View File

@ -0,0 +1,19 @@
import { OperatorSchema } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import CommaArrayJoiExt from "../wrappers/CommaArrayJoiExt";
export default new OperatorSchema(
i18next.t("friendlyName", { ns: "removePages" }),
i18next.t("description", { ns: "removePages" }),
JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description")),
Joi.object({
pageIndexes: CommaArrayJoiExt.comma_array().items(Joi.number().integer()).required()
.label(i18next.t("values.pageIndexes.friendlyName", { ns: "removePages" })).description(i18next.t("values.pageIndexes.description", { ns: "removePages" }))
.example("1").example("1, 2, 3, 4").example("4, 2, 4, 3").required()
}),
JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"))
);

View File

@ -1,42 +1,10 @@
import { PdfFile } from "../wrappers/PdfFile";
import { Operator, Progress, oneToOne } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import { getPages } from "./common/getPagesByIndex";
import CommaArrayJoiExt from "../wrappers/CommaArrayJoiExt";
import { invertSelection } from "./common/pageIndexesUtils";
export class RemovePages extends Operator {
static type = "removePages";
/**
* Validation & Localisation
*/
protected static inputSchema = JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description"));
protected static valueSchema = Joi.object({
pageIndexes: CommaArrayJoiExt.comma_array().items(Joi.number().integer()).required()
.label(i18next.t("values.pageIndexes.friendlyName", { ns: "removePages" })).description(i18next.t("values.pageIndexes.description", { ns: "removePages" }))
.example("1").example("1, 2, 3, 4").example("4, 2, 4, 3").required()
});
protected static outputSchema = JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"));
static schema = Joi.object({
input: RemovePages.inputSchema,
values: RemovePages.valueSchema.required(),
output: RemovePages.outputSchema
}).label(i18next.t("friendlyName", { ns: "removePages" })).description(i18next.t("description", { ns: "removePages" }));
/**
* Logic
*/
/** PDF extraction, specify pages from one pdf and output them to a new pdf */
async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> {
return oneToOne<PdfFile, PdfFile>(input, async (input, index, max) => {

View File

@ -0,0 +1,22 @@
import { OperatorSchema } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import CommaArrayJoiExt from "../wrappers/CommaArrayJoiExt";
export default new OperatorSchema(
i18next.t("friendlyName", { ns: "rotatePages" }),
i18next.t("description", { ns: "rotatePages" }),
JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description")),
Joi.object({
rotation: Joi.alternatives().try(
Joi.number().integer().min(-360).max(360).required(),
CommaArrayJoiExt.comma_array().items(Joi.number().integer().min(-360).max(360)).required()
)
.label(i18next.t("values.rotation.friendlyName", { ns: "rotatePages" })).description(i18next.t("values.rotation.description", { ns: "rotatePages" }))
.example("90").example("-180").example("[90, 0, 270]"),
}),
JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"))
);

View File

@ -1,44 +1,9 @@
import { Operator, Progress, oneToOne } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import CommaArrayJoiExt from "../wrappers/CommaArrayJoiExt";
import { degrees } from "pdf-lib";
import { PdfFile, RepresentationType } from "../wrappers/PdfFile";
export class RotatePages extends Operator {
static type = "rotatePages";
/**
* Validation & Localisation
*/
protected static inputSchema = JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description"));
protected static valueSchema = Joi.object({
rotation: Joi.alternatives().try(
Joi.number().integer().min(-360).max(360).required(),
CommaArrayJoiExt.comma_array().items(Joi.number().integer().min(-360).max(360)).required()
)
.label(i18next.t("values.rotation.friendlyName", { ns: "rotatePages" })).description(i18next.t("values.rotation.description", { ns: "rotatePages" }))
.example("90").example("-180").example("[90, 0, 270]"),
});
protected static outputSchema = JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"));
static schema = Joi.object({
input: RotatePages.inputSchema,
values: RotatePages.valueSchema.required(),
output: RotatePages.outputSchema
}).label(i18next.t("friendlyName", { ns: "rotatePages" })).description(i18next.t("description", { ns: "rotatePages" }));
/**
* Logic
*/
/** Detect and remove white pages */
async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> {
return oneToOne<PdfFile, PdfFile>(input, async (input, index, max) => {

View File

@ -0,0 +1,22 @@
import { OperatorSchema } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import CommaArrayJoiExt from "../wrappers/CommaArrayJoiExt";
export default new OperatorSchema(
i18next.t("friendlyName", { ns: "scaleContent" }),
i18next.t("description", { ns: "scaleContent" }),
JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description")),
Joi.object({
scaleFactor: Joi.alternatives().try(
Joi.number().required(),
CommaArrayJoiExt.comma_array().items(Joi.number()).required()
)
.label(i18next.t("values.scaleFactor.friendlyName", { ns: "scaleContent" })).description(i18next.t("values.scaleFactor.description", { ns: "scaleContent" }))
.example("2").example("1.5").example("[1, 1.5, 0.9]"),
}),
JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"))
);

View File

@ -1,44 +1,9 @@
import { Operator, Progress, oneToOne } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import CommaArrayJoiExt from "../wrappers/CommaArrayJoiExt";
import { PDFPage } from "pdf-lib";
import { PdfFile, RepresentationType } from "../wrappers/PdfFile";
export class ScaleContent extends Operator {
static type = "scaleContent";
/**
* Validation & Localisation
*/
protected static inputSchema = JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description"));
protected static valueSchema = Joi.object({
scaleFactor: Joi.alternatives().try(
Joi.number().required(),
CommaArrayJoiExt.comma_array().items(Joi.number()).required()
)
.label(i18next.t("values.scaleFactor.friendlyName", { ns: "scaleContent" })).description(i18next.t("values.scaleFactor.description", { ns: "scaleContent" }))
.example("2").example("1.5").example("[1, 1.5, 0.9]"),
});
protected static outputSchema = JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"));
static schema = Joi.object({
input: ScaleContent.inputSchema,
values: ScaleContent.valueSchema.required(),
output: ScaleContent.outputSchema
}).label(i18next.t("friendlyName", { ns: "scaleContent" })).description(i18next.t("description", { ns: "scaleContent" }));
/**
* Logic
*/
/** Detect and remove white pages */
async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> {
return oneToOne<PdfFile, PdfFile>(input, async (input, index, max) => {

View File

@ -0,0 +1,20 @@
import { OperatorSchema } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
export default new OperatorSchema(
i18next.t("friendlyName", { ns: "scalePage" }),
i18next.t("description", { ns: "scalePage" }),
JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description")),
Joi.object({
height: Joi.number().min(0)
.label(i18next.t("values.height.friendlyName", { ns: "scalePage" })).description(i18next.t("values.height.description", { ns: "scalePage" }))
.example("842").example("595").example("1190"),
width: Joi.number().min(0)
.label(i18next.t("values.width.friendlyName", { ns: "scalePage" })).description(i18next.t("values.width.description", { ns: "scalePage" }))
.example("595").example("420").example("842"),
}).or("height", "width"),
JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"))
);

View File

@ -1,42 +1,9 @@
import { Operator, Progress, oneToOne } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import { PDFPage } from "pdf-lib";
import { PdfFile, RepresentationType } from "../wrappers/PdfFile";
export class ScalePage extends Operator {
static type = "scalePage";
/**
* Validation & Localisation
*/
protected static inputSchema = JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description"));
protected static valueSchema = Joi.object({
height: Joi.number().min(0)
.label(i18next.t("values.height.friendlyName", { ns: "scalePage" })).description(i18next.t("values.height.description", { ns: "scalePage" }))
.example("842").example("595").example("1190"),
width: Joi.number().min(0)
.label(i18next.t("values.width.friendlyName", { ns: "scalePage" })).description(i18next.t("values.width.description", { ns: "scalePage" }))
.example("595").example("420").example("842"),
}).or("height", "width");
protected static outputSchema = JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"));
static schema = Joi.object({
input: ScalePage.inputSchema,
values: ScalePage.valueSchema.required(),
output: ScalePage.outputSchema
}).label(i18next.t("friendlyName", { ns: "scalePage" })).description(i18next.t("description", { ns: "scalePage" }));
/**
* Logic
*/
/** Detect and remove white pages */
async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> {
return oneToOne<PdfFile, PdfFile>(input, async (input, index, max) => {

View File

@ -0,0 +1,26 @@
import { OperatorSchema } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
export default new OperatorSchema(
i18next.t("friendlyName", { ns: "splitPagesByPreset" }),
i18next.t("description", { ns: "splitPagesByPreset" }),
JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description")),
Joi.alternatives().try(
Joi.object({
type: Joi.string().valid("BAR_CODE").required()
}),
Joi.object({
type: Joi.string().valid("QR_CODE").required()
}),
Joi.object({
type: Joi.string().valid("BLANK_PAGE").required(),
whiteThreashold: Joi.number().min(0).max(255).required()
}),
)
.label(i18next.t("values.splitSettings.friendlyName", { ns: "splitPagesByPreset" })).description(i18next.t("values.splitSettings.description", { ns: "splitPagesByPreset" })
),
JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"))
);

View File

@ -13,40 +13,6 @@ import { detectQRCodePages } from "./common/detectQRCodePages";
export class SplitPagesByPreset extends Operator {
static type = "splitPagesByPreset";
/**
* Validation & Localisation
*/
protected static inputSchema = JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description"));
protected static valueSchema = Joi.alternatives().try(
Joi.object({
type: Joi.string().valid("BAR_CODE").required()
}),
Joi.object({
type: Joi.string().valid("QR_CODE").required()
}),
Joi.object({
type: Joi.string().valid("BLANK_PAGE").required(),
whiteThreashold: Joi.number().min(0).max(255).required()
}),
)
.label(i18next.t("values.splitSettings.friendlyName", { ns: "splitPagesByPreset" })).description(i18next.t("values.splitSettings.description", { ns: "splitPagesByPreset" })
);
protected static outputSchema = JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"));
static schema = Joi.object({
input: SplitPagesByPreset.inputSchema,
values: SplitPagesByPreset.valueSchema.required(),
output: SplitPagesByPreset.outputSchema
}).label(i18next.t("friendlyName", { ns: "splitPagesByPreset" })).description(i18next.t("description", { ns: "splitPagesByPreset" }));
/**
* Logic
*/
/** Detect and remove white pages */
async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> {
return oneToN<PdfFile, PdfFile>(input, async (input, index, max) => {

View File

@ -0,0 +1,19 @@
import { OperatorSchema } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import CommaArrayJoiExt from "../wrappers/CommaArrayJoiExt";
export default new OperatorSchema(
i18next.t("friendlyName", { ns: "splitPdfByIndex" }),
i18next.t("description", { ns: "splitPdfByIndex" }),
JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description")),
Joi.object({
pageIndexes: CommaArrayJoiExt.comma_array().items(Joi.number().integer()).required()
.label(i18next.t("values.pageIndexes.friendlyName", { ns: "splitPdfByIndex" })).description(i18next.t("values.pageIndexes.description", { ns: "splitPdfByIndex" }))
.example("1").example("1, 2, 3, 4").example("4, 2, 4, 3")
}),
JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"))
);

View File

@ -2,40 +2,10 @@ import { PdfFile } from "../wrappers/PdfFile";
import { Operator, Progress, oneToN } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
import CommaArrayJoiExt from "../wrappers/CommaArrayJoiExt";
import { splitPagesByIndex } from "./common/splitPagesByIndex";
export class SplitPdfByIndex extends Operator {
static type = "splitPdfByIndex";
/**
* Validation & Localisation
*/
protected static inputSchema = JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description"));
protected static valueSchema = Joi.object({
pageIndexes: CommaArrayJoiExt.comma_array().items(Joi.number().integer()).required()
.label(i18next.t("values.pageIndexes.friendlyName", { ns: "splitPdfByIndex" })).description(i18next.t("values.pageIndexes.description", { ns: "splitPdfByIndex" }))
.example("1").example("1, 2, 3, 4").example("4, 2, 4, 3")
});
protected static outputSchema = JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"));
static schema = Joi.object({
input: SplitPdfByIndex.inputSchema,
values: SplitPdfByIndex.valueSchema.required(),
output: SplitPdfByIndex.outputSchema
}).label(i18next.t("friendlyName", { ns: "splitPdfByIndex" })).description(i18next.t("description", { ns: "splitPdfByIndex" }));
/**
* Logic
*/
/** PDF extraction, specify pages from one pdf and output them to a new pdf */
async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> {
return oneToN<PdfFile, PdfFile>(input, async (input, index, max) => {

View File

@ -0,0 +1,45 @@
import { OperatorSchema } from ".";
import Joi from "@stirling-tools/joi";
import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
export default new OperatorSchema(
i18next.t("friendlyName", { ns: "updateMetadata" }),
i18next.t("description", { ns: "updateMetadata" }),
JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description")),
Joi.object({
deleteAll: Joi.boolean().invalid(false)
.label(i18next.t("values.deleteAll.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.deleteAll.description", { ns: "updateMetadata" }))
.example("true").example("false"),
author: Joi.string().optional().allow('')
.label(i18next.t("values.author.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.author.description", { ns: "updateMetadata" }))
.example("John Doe").example("Anthony Stirling"), // The author of the document
creationDate: Joi.date().allow("").allow(null)
.label(i18next.t("values.creationDate.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.creationDate.description", { ns: "updateMetadata" }))
.example("YYYY-MM-DD").example("2023-01-27"), // The creation date of the document (format: yyyy/MM/dd HH:mm:ss)
creator: Joi.string().optional().allow('')
.label(i18next.t("values.creator.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.creator.description", { ns: "updateMetadata" }))
.example("John Doe").example("Anthony Stirling"), // The creator of the document
keywords: Joi.string().optional().allow('')
.label(i18next.t("values.keywords.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.keywords.description", { ns: "updateMetadata" }))
.example("General").example("finances, leisure").example("finances leisure"), // The keywords for the document
modificationDate: Joi.date().allow("").allow(null)
.label(i18next.t("values.modificationDate.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.modificationDate.description", { ns: "updateMetadata" }))
.example("YYYY-MM-DD").example("2023-01-27"), // The modification date of the document (format: yyyy/MM/dd HH:mm:ss)
producer: Joi.string().optional().allow('')
.label(i18next.t("values.producer.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.producer.description", { ns: "updateMetadata" }))
.example("John Doe").example("Anthony Stirling"), // The producer of the document
subject: Joi.string().optional().allow('')
.label(i18next.t("values.subject.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.subject.description", { ns: "updateMetadata" }))
.example("Subject").example("This is an example Subject."), // The subject of the document
title: Joi.string().optional().allow('')
.label(i18next.t("values.title.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.title.description", { ns: "updateMetadata" }))
.example("Title").example("This is an example title."), // The title of the document
// TODO: trapped?: string, // The trapped status of the document
// TODO: allRequestParams?: {[key: string]: [key: string]}, // Map list of key and value of custom parameters. Note these must start with customKey and customValue if they are non-standard
}),
JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"))
);

View File

@ -8,59 +8,6 @@ import { JoiPDFFileSchema } from "../wrappers/PdfFileJoi";
import i18next from "i18next";
export class UpdateMetadata extends Operator {
static type = "updateMetadata";
/**
* Validation & Localisation
*/
protected static inputSchema = JoiPDFFileSchema.label(i18next.t("inputs.pdffile.name")).description(i18next.t("inputs.pdffile.description"));
protected static valueSchema = Joi.object({
deleteAll: Joi.boolean().invalid(false)
.label(i18next.t("values.deleteAll.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.deleteAll.description", { ns: "updateMetadata" }))
.example("true").example("false"),
author: Joi.string().optional().allow('')
.label(i18next.t("values.author.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.author.description", { ns: "updateMetadata" }))
.example("John Doe").example("Anthony Stirling"), // The author of the document
creationDate: Joi.date().allow("").allow(null)
.label(i18next.t("values.creationDate.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.creationDate.description", { ns: "updateMetadata" }))
.example("YYYY-MM-DD").example("2023-01-27"), // The creation date of the document (format: yyyy/MM/dd HH:mm:ss)
creator: Joi.string().optional().allow('')
.label(i18next.t("values.creator.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.creator.description", { ns: "updateMetadata" }))
.example("John Doe").example("Anthony Stirling"), // The creator of the document
keywords: Joi.string().optional().allow('')
.label(i18next.t("values.keywords.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.keywords.description", { ns: "updateMetadata" }))
.example("General").example("finances, leisure").example("finances leisure"), // The keywords for the document
modificationDate: Joi.date().allow("").allow(null)
.label(i18next.t("values.modificationDate.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.modificationDate.description", { ns: "updateMetadata" }))
.example("YYYY-MM-DD").example("2023-01-27"), // The modification date of the document (format: yyyy/MM/dd HH:mm:ss)
producer: Joi.string().optional().allow('')
.label(i18next.t("values.producer.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.producer.description", { ns: "updateMetadata" }))
.example("John Doe").example("Anthony Stirling"), // The producer of the document
subject: Joi.string().optional().allow('')
.label(i18next.t("values.subject.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.subject.description", { ns: "updateMetadata" }))
.example("Subject").example("This is an example Subject."), // The subject of the document
title: Joi.string().optional().allow('')
.label(i18next.t("values.title.friendlyName", { ns: "updateMetadata" })).description(i18next.t("values.title.description", { ns: "updateMetadata" }))
.example("Title").example("This is an example title."), // The title of the document
// TODO: trapped?: string, // The trapped status of the document
// TODO: allRequestParams?: {[key: string]: [key: string]}, // Map list of key and value of custom parameters. Note these must start with customKey and customValue if they are non-standard
});
protected static outputSchema = JoiPDFFileSchema.label(i18next.t("outputs.pdffile.name")).description(i18next.t("outputs.pdffile.description"));
static schema = Joi.object({
input: UpdateMetadata.inputSchema,
values: UpdateMetadata.valueSchema.required(),
output: UpdateMetadata.outputSchema
}).label(i18next.t("friendlyName", { ns: "updateMetadata" })).description(i18next.t("description", { ns: "updateMetadata" }));
/**
* Logic
*/
/** PDF extraction, specify pages from one pdf and output them to a new pdf */
async run(input: PdfFile[], progressCallback: (state: Progress) => void): Promise<PdfFile[]> {
return oneToOne<PdfFile, PdfFile>(input, async (input, index, max) => {

View File

@ -1,4 +1,4 @@
import { Operator } from "../functions";
import { Operator, OperatorSchema } from "../functions";
import i18next from "i18next";
const compileTimeOperatorList: {basename: string}[] = import.meta.compileTime("../compiletime/operatorDescription.ts"); // The will compile to ["impose", "extractPages", etc...]
@ -7,7 +7,6 @@ export async function getOperatorByName(name: string): Promise<typeof Operator |
// Check if exists
if(!compileTimeOperatorList.find(e => e.basename == name)) return;
i18next.loadNamespaces(name, (err, t) => { if (err) throw err; console.log(t) });
const loadedModule = await import("../functions/" + name + ".ts");
const operator = loadedModule[capitalizeFirstLetter(name)];
if(!operator) {
@ -16,6 +15,19 @@ export async function getOperatorByName(name: string): Promise<typeof Operator |
return operator;
}
export async function getSchemaByName(name: string): Promise<OperatorSchema | undefined> {
// Check if exists
if(!compileTimeOperatorList.find(e => e.basename == name)) return;
i18next.loadNamespaces(name, (err, t) => { if (err) throw err; console.log(t) });
const loadedModule = await import("../functions/" + name + ".schema.ts");
const schema = loadedModule.default;
if(!schema) {
throw Error("This operator does not export its class in the correct format.")
}
return schema;
}
export function listOperatorNames(): string[] {
const availableOperators = compileTimeOperatorList.map(e => e.basename);
return availableOperators;

View File

@ -44,7 +44,7 @@ export function organizeWaitOperations(actions: Action[]) {
}
export type ResultType = Record<string, {
waitCount: number,
doneOperation: Action,
input: PdfFile[]
}>;
waitCount: number,
doneOperation: Action,
input: PdfFile[]
}>;

View File

@ -1,6 +1,6 @@
import { Operator } from "../functions";
import { OperatorSchema } from "../functions";
import { Action } from "../../declarations/Action";
import { getOperatorByName } from "./operatorAccessor";
import { getOperatorByName, getSchemaByName } from "./operatorAccessor";
/** This function validates the "workflow-json" from the API */
export async function validateOperations(actions: Action[]): Promise<{ valid: boolean, reason?: string}> {
@ -18,7 +18,11 @@ export async function validateOperations(actions: Action[]): Promise<{ valid: bo
if(!operator) {
return { valid: false, reason: `action.type ${action.type} does not exist` };
}
const validationResult = operator.schema.validate({values: action.values});
const schema = await getSchemaByName(action.type);
if(!operator) {
return { valid: false, reason: `action.type ${action.type} does not exist` };
}
const validationResult = schema.schema.validate({values: action.values});
// TODO: convert everything to joiresult format instead of returning a new format
if(validationResult.error) {
@ -35,10 +39,10 @@ export async function validateOperations(actions: Action[]): Promise<{ valid: bo
}
for (const afterDoneChild of done[childAction.values.id]?.actions || []) {
const receivingOperator = await getOperatorByName(afterDoneChild.type);
if (receivingOperator === undefined) {
const receivingSchema = await getSchemaByName(afterDoneChild.type);
if (receivingSchema === undefined) {
return { valid: false, reason: `action.type ${afterDoneChild.type} does not exist.` };
} else if (!ioCompatible(operator, receivingOperator)) {
} else if (!ioCompatible(schema, receivingSchema)) {
return { valid: false, reason: `Ouput of action ${action.type} is not compatible with input of action ${afterDoneChild.type}` };
}
}
@ -47,10 +51,10 @@ export async function validateOperations(actions: Action[]): Promise<{ valid: bo
return { valid: false, reason: "There shouldn't be a done action here." };
}
else {
const receivingOperator = await getOperatorByName(childAction.type);
if (receivingOperator === undefined) {
const receivingSchema = await getSchemaByName(childAction.type);
if (receivingSchema === undefined) {
return { valid: false, reason: `action.type ${childAction.type} does not exist.` };
} else if (!ioCompatible(operator, receivingOperator)) {
} else if (!ioCompatible(schema, receivingSchema)) {
return { valid: false, reason: `Ouput of action ${action.type} is not compatible with input of action ${childAction.type}` };
}
}
@ -66,8 +70,8 @@ export async function validateOperations(actions: Action[]): Promise<{ valid: bo
return { valid: true };
}
function ioCompatible(outputingOperator: typeof Operator, receivingOperator: typeof Operator): boolean {
const outputType = outputingOperator.schema.describe().keys.output.label;
const inputType = receivingOperator.schema.describe().keys.input.label;
function ioCompatible(outputingSchema: OperatorSchema, receivingSchema: OperatorSchema): boolean {
const outputType = outputingSchema.schema.describe().keys.output.label;
const inputType = receivingSchema.schema.describe().keys.input.label;
return outputType == inputType;
}