feat(pdfengines): add PDF/UA (#714)

This commit is contained in:
Julien Neuhart
2023-11-05 20:14:36 +01:00
committed by GitHub
parent 9c3dfc78df
commit 143b7ce678
39 changed files with 1300 additions and 1013 deletions

View File

@@ -24,27 +24,27 @@ func (mod *ValidatorMock) Validate() error {
return mod.ValidateMock()
}
// PDFEngineMock is a mock for the [PDFEngine] interface.
type PDFEngineMock struct {
// PdfEngineMock is a mock for the [PdfEngine] interface.
type PdfEngineMock struct {
MergeMock func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error
ConvertMock func(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error
ConvertMock func(ctx context.Context, logger *zap.Logger, formats PdfFormats, inputPath, outputPath string) error
}
func (engine *PDFEngineMock) Merge(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
func (engine *PdfEngineMock) Merge(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
return engine.MergeMock(ctx, logger, inputPaths, outputPath)
}
func (engine *PDFEngineMock) Convert(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error {
return engine.ConvertMock(ctx, logger, format, inputPath, outputPath)
func (engine *PdfEngineMock) Convert(ctx context.Context, logger *zap.Logger, formats PdfFormats, inputPath, outputPath string) error {
return engine.ConvertMock(ctx, logger, formats, inputPath, outputPath)
}
// PDFEngineProviderMock is a mock for the [PDFEngineProvider] interface.
type PDFEngineProviderMock struct {
PDFEngineMock func() (PDFEngine, error)
// PdfEngineProviderMock is a mock for the [PdfEngineProvider] interface.
type PdfEngineProviderMock struct {
PdfEngineMock func() (PdfEngine, error)
}
func (provider *PDFEngineProviderMock) PDFEngine() (PDFEngine, error) {
return provider.PDFEngineMock()
func (provider *PdfEngineProviderMock) PdfEngine() (PdfEngine, error) {
return provider.PdfEngineMock()
}
// ProcessMock is a mock for the [Process] interface.
@@ -113,8 +113,8 @@ func (provider *LoggerProviderMock) Logger(mod Module) (*zap.Logger, error) {
var (
_ Module = (*ModuleMock)(nil)
_ Validator = (*ValidatorMock)(nil)
_ PDFEngine = (*PDFEngineMock)(nil)
_ PDFEngineProvider = (*PDFEngineProviderMock)(nil)
_ PdfEngine = (*PdfEngineMock)(nil)
_ PdfEngineProvider = (*PdfEngineProviderMock)(nil)
_ Process = (*ProcessMock)(nil)
_ ProcessSupervisor = (*ProcessSupervisorMock)(nil)
_ LoggerProvider = (*LoggerProviderMock)(nil)

View File

@@ -35,36 +35,36 @@ func TestValidatorMock(t *testing.T) {
}
func TestPDFEngineMock(t *testing.T) {
mock := &PDFEngineMock{
mock := &PdfEngineMock{
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
return nil
},
ConvertMock: func(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error {
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats PdfFormats, inputPath, outputPath string) error {
return nil
},
}
err := mock.Merge(context.Background(), zap.NewNop(), nil, "")
if err != nil {
t.Errorf("expected no error from PDFEngineMock.Merge, but got: %v", err)
t.Errorf("expected no error from PdfEngineMock.Merge, but got: %v", err)
}
err = mock.Convert(context.Background(), zap.NewNop(), "", "", "")
err = mock.Convert(context.Background(), zap.NewNop(), PdfFormats{}, "", "")
if err != nil {
t.Errorf("expected no error from PDFEngineMock.Convert, but got: %v", err)
t.Errorf("expected no error from PdfEngineMock.Convert, but got: %v", err)
}
}
func TestPDFEngineProviderMock(t *testing.T) {
mock := &PDFEngineProviderMock{
PDFEngineMock: func() (PDFEngine, error) {
return new(PDFEngineMock), nil
mock := &PdfEngineProviderMock{
PdfEngineMock: func() (PdfEngine, error) {
return new(PdfEngineMock), nil
},
}
_, err := mock.PDFEngine()
_, err := mock.PdfEngine()
if err != nil {
t.Errorf("expected no error from PDFEngineProviderMock.PDFEngine, but got: %v", err)
t.Errorf("expected no error from PdfEngineProviderMock.PdfEngine, but got: %v", err)
}
}

View File

@@ -8,45 +8,74 @@ import (
)
var (
// ErrPDFEngineMethodNotAvailable happens if a PDFEngine method is not
// available in the implementation.
ErrPDFEngineMethodNotAvailable = errors.New("method not available")
// ErrPdfEngineMethodNotSupported is returned when a specific method of the
// PdfEngine interface is not supported by its current implementation.
ErrPdfEngineMethodNotSupported = errors.New("method not supported")
// ErrPDFFormatNotAvailable happens if a PDFEngine Convert's method does
// not handle a specific format.
ErrPDFFormatNotAvailable = errors.New("PDF format not available")
// ErrPdfFormatNotSupported is returned when the Convert method of the
// PdfEngine interface does not support a requested PDF format conversion.
ErrPdfFormatNotSupported = errors.New("PDF format not supported")
)
const (
FormatPDFA1a string = "PDF/A-1a"
FormatPDFA1b string = "PDF/A-1b"
FormatPDFA2a string = "PDF/A-2a"
FormatPDFA2b string = "PDF/A-2b"
FormatPDFA2u string = "PDF/A-2u"
FormatPDFA3a string = "PDF/A-3a"
FormatPDFA3b string = "PDF/A-3b"
FormatPDFA3u string = "PDF/A-3u"
// PdfA1a represents the PDF/A-1a format.
PdfA1a string = "PDF/A-1a"
// PdfA1b represents the PDF/A-1b format.
PdfA1b string = "PDF/A-1b"
// PdfA2a represents the PDF/A-2a format.
PdfA2a string = "PDF/A-2a"
// PdfA2b represents the PDF/A-2b format.
PdfA2b string = "PDF/A-2b"
// PdfA2u represents the PDF/A-2u format.
PdfA2u string = "PDF/A-2u"
// PdfA3a represents the PDF/A-3a format.
PdfA3a string = "PDF/A-3a"
// PdfA3b represents the PDF/A-3b format.
PdfA3b string = "PDF/A-3b"
// PdfA3u represents the PDF/A-3u format.
PdfA3u string = "PDF/A-3u"
)
// PDFEngine is a module interface which exposes methods for manipulating one
// or more PDFs. Implementations may abstract powerful tools like PDFtk, or
// fulfill those methods contracts in Golang directly.
type PDFEngine interface {
// Merge merges the given PDFs into a unique PDF. The pages' order reflects
// order of the given files.
// PdfFormats specifies the target formats for a PDF conversion.
type PdfFormats struct {
// PdfA denotes the PDF/A standard format (e.g., PDF/A-1a).
PdfA string
// PdfUa indicates whether the PDF should comply
// with the PDF/UA (Universal Accessibility) standard.
PdfUa bool
}
// PdfEngine provides an interface for operations on PDFs. Implementations
// can utilize various tools like PDFtk, or implement functionality directly in
// Go.
type PdfEngine interface {
// Merge combines multiple PDFs into a single PDF. The resulting page order
// is determined by the order of files provided in inputPaths.
Merge(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error
// Convert converts the given PDF to a specific PDF format.
Convert(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error
// Convert transforms a given PDF to the specified formats defined in
// PdfFormats. If no format, it does nothing.
Convert(ctx context.Context, logger *zap.Logger, formats PdfFormats, inputPath, outputPath string) error
}
// PDFEngineProvider is a module interface which exposes a method for creating a
// PDFEngine for other modules.
// PdfEngineProvider offers an interface to instantiate a [PdfEngine].
// This is used to decouple the creation of a [PdfEngine] from its consumers.
//
// Example:
//
// func (m *YourModule) Provision(ctx *gotenberg.Context) error {
// provider, _ := ctx.Module(new(gotenberg.PDFEngineProvider))
// pdfengines, _ := provider.(gotenberg.PDFEngineProvider).PDFEngine()
// provider, _ := ctx.Module(new(gotenberg.PdfEngineProvider))
// engine, _ := provider.(gotenberg.PdfEngineProvider).PdfEngine()
// }
type PDFEngineProvider interface {
PDFEngine() (PDFEngine, error)
type PdfEngineProvider interface {
// PdfEngine returns an instance of the PdfEngine interface for PDF operations.
PdfEngine() (PdfEngine, error)
}