Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/keenwrite.git

Add preliminary export to PDF code (non-functional)

AuthorDaveJarvis <email>
Date2021-03-21 23:57:50 GMT-0700
Commitcd8d7bc5c796e49edef5b345f7716c60db79203d
Parentc728521
src/main/java/com/keenwrite/ExportFormat.java
/**
+ * Exports as PDF file format.
+ */
+ APPLICATION_PDF( ".pdf" ),
+
+ /**
* Indicates no special export format is to be created. No extension is
* applicable. Image links must use absolute directories.
src/main/java/com/keenwrite/MainPane.java
public ProcessorContext createProcessorContext() {
- return createProcessorContext( NONE );
+ return createProcessorContext( null, NONE );
}
- public ProcessorContext createProcessorContext( final ExportFormat format ) {
+ public ProcessorContext createProcessorContext(
+ final File exportPath, final ExportFormat format ) {
final var editor = getActiveTextEditor();
return createProcessorContext(
- editor.getPath(), editor.getCaret(), format );
+ editor.getPath(), editor.getCaret(), exportPath, format );
+ }
+
+ private ProcessorContext createProcessorContext(
+ final Path path, final Caret caret ) {
+ return createProcessorContext( path, caret, null, ExportFormat.NONE );
}
/**
- * @param path Used by {@link ProcessorFactory} to determine
- * {@link Processor} type to create based on file type.
- * @param caret Used by {@link CaretExtension} to add ID attribute into
- * preview document for scrollbar synchronization.
+ * @param path Used by {@link ProcessorFactory} to determine
+ * {@link Processor} type to create based on file type.
+ * @param caret Used by {@link CaretExtension} to add ID attribute into
+ * preview document for scrollbar synchronization.
+ * @param exportPath Used when exporting to a PDF file (binary).
+ * @param format Used when processors export to a new text format.
* @return A new {@link ProcessorContext} to use when creating an instance of
* {@link Processor}.
*/
private ProcessorContext createProcessorContext(
- final Path path, final Caret caret, final ExportFormat format ) {
+ final Path path, final Caret caret,
+ final File exportPath, final ExportFormat format ) {
return new ProcessorContext(
- mPreview, mResolvedMap, path, caret, format, mWorkspace
+ mPreview, mResolvedMap, path, caret, exportPath, format, mWorkspace
);
}
final var editor = new MarkdownEditor( file, getWorkspace() );
final var caret = editor.getCaret();
- final var context = createProcessorContext( path, caret, NONE );
+ final var context = createProcessorContext( path, caret );
mProcessors.computeIfAbsent( editor, p -> createProcessors( context ) );
src/main/java/com/keenwrite/processors/PdfProcessor.java
+/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
+package com.keenwrite.processors;
+
+import java.io.File;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+
+import static java.io.File.pathSeparator;
+import static java.lang.System.getenv;
+import static java.util.regex.Pattern.quote;
+
+/**
+ * Responsible for using a typesetting engine to convert an XHTML document
+ * into a PDF file.
+ */
+public final class PdfProcessor extends ExecutorProcessor<String> {
+ private static final String TYPESETTER = "context";
+
+ private final File mExportPath;
+
+ public PdfProcessor( final File exportPath ) {
+ assert exportPath != null;
+ mExportPath = exportPath;
+ }
+
+ /**
+ * Converts a document by calling a third-party library to typeset the given
+ * XHTML document.
+ *
+ * @param xhtml The document to convert to a PDF file.
+ * @return {@code null} because there is no valid return value from generating
+ * a PDF file.
+ */
+ public String apply( final String xhtml ) {
+ if( canExecute( TYPESETTER ) ) {
+ System.out.println( "CONTEXT IS CONFIGURED" );
+ System.out.println( "EXPORT AS: " + mExportPath );
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings( "SameParameterValue" )
+ private boolean canExecute( final String exe ) {
+ final var paths = getenv( "PATH" ).split( quote( pathSeparator ) );
+ return Stream.of( paths ).map( Paths::get ).anyMatch(
+ path -> {
+ final var p = path.resolve( exe );
+ final var extensions = new String[]{"", ".com", ".exe", ".bat", ".cmd"};
+ var found = false;
+
+ for( final var extension : extensions ) {
+ final var f = new File( p.toString() + extension );
+
+ if( f.exists() && f.canExecute() ) {
+ found = true;
+ break;
+ }
+ }
+
+ return found;
+ }
+ );
+ }
+}
src/main/java/com/keenwrite/processors/ProcessorContext.java
import com.keenwrite.preview.HtmlPreview;
+import java.io.File;
import java.nio.file.Path;
import java.util.Map;
private final Path mDocumentPath;
private final Caret mCaret;
+ private final File mExportPath;
private final ExportFormat mExportFormat;
private final Workspace mWorkspace;
* @param caret Location of the caret in the edited document, which is
* used to synchronize the scrollbars.
+ * @param exportPath Fully qualified filename to use when exporting.
* @param exportFormat Indicate configuration options for export format.
+ * @param workspace Persistent user preferences settings.
*/
public ProcessorContext(
final HtmlPreview htmlPreview,
final Map<String, String> resolvedMap,
final Path documentPath,
final Caret caret,
+ final File exportPath,
final ExportFormat exportFormat,
final Workspace workspace ) {
mDocumentPath = documentPath;
mCaret = caret;
+ mExportPath = exportPath;
mExportFormat = exportFormat;
mWorkspace = workspace;
Map<String, String> getResolvedMap() {
return mResolvedMap;
+ }
+
+ public File getExportPath() {
+ return mExportPath;
}
src/main/java/com/keenwrite/processors/ProcessorFactory.java
import com.keenwrite.processors.markdown.MarkdownProcessor;
-import static com.keenwrite.ExportFormat.NONE;
-import static com.keenwrite.ExportFormat.XHTML_TEX;
+import static com.keenwrite.ExportFormat.*;
+import static com.keenwrite.processors.IdentityProcessor.IDENTITY;
/**
: context.isExportFormat( XHTML_TEX )
? createXhtmlProcessor( context.getWorkspace() )
+ : context.isExportFormat( APPLICATION_PDF )
+ ? createPdfProcessor( context )
: createIdentityProcessor();
*/
private Processor<String> createIdentityProcessor() {
- return IdentityProcessor.IDENTITY;
- }
-
- /**
- * Instantiates a new {@link Processor} that wraps an HTML document into
- * its final, well-formed state (including head and body tags). This is
- * useful for generating XHTML documents suitable for typesetting (using
- * an engine such as LuaTeX).
- *
- * @return An instance of {@link Processor} that completes an HTML document.
- */
- private Processor<String> createXhtmlProcessor( final Workspace workspace ) {
- return new XhtmlProcessor( workspace );
+ return IDENTITY;
}
final var xmlp = new XmlProcessor( successor, getProcessorContext() );
return createDefinitionProcessor( xmlp );
+ }
+
+ /**
+ * Instantiates a new {@link Processor} that wraps an HTML document into
+ * its final, well-formed state (including head and body tags). This is
+ * useful for generating XHTML documents suitable for typesetting (using
+ * an engine such as LuaTeX).
+ *
+ * @return An instance of {@link Processor} that completes an HTML document.
+ */
+ private Processor<String> createXhtmlProcessor( final Workspace workspace ) {
+ return createXhtmlProcessor( IDENTITY, workspace );
+ }
+
+ private Processor<String> createXhtmlProcessor(
+ final Processor<String> successor, final Workspace workspace ) {
+ return new XhtmlProcessor( successor, workspace );
+ }
+
+ private Processor<String> createPdfProcessor(
+ final ProcessorContext context ) {
+ final var pdfp = new PdfProcessor( context.getExportPath() );
+ return createXhtmlProcessor( pdfp, context.getWorkspace() );
}
src/main/java/com/keenwrite/processors/XhtmlProcessor.java
private final Workspace mWorkspace;
- public XhtmlProcessor( final Workspace workspace ) {
+ public XhtmlProcessor(
+ final Processor<String> successor, final Workspace workspace ) {
+ super( successor );
mWorkspace = workspace;
}
MediaType mediaType;
Path imageFile = null;
- InputStream svgIn ;
+ InputStream svgIn;
final var protocol = ProtocolScheme.getProtocol( src );
src/main/java/com/keenwrite/processors/markdown/extensions/tex/TexNodeRenderer.java
public class TexNodeRenderer {
+ private static final RendererFacade RENDERER = new TexElementNodeRenderer();
+
private static final Map<ExportFormat, RendererFacade> EXPORT_RENDERERS =
Map.of(
+ APPLICATION_PDF, new TexElementNodeRenderer(),
HTML_TEX_SVG, new TexSvgNodeRenderer(),
HTML_TEX_DELIMITED, new TexDelimNodeRenderer(),
XHTML_TEX, new TexElementNodeRenderer(),
MARKDOWN_PLAIN, new TexDelimNodeRenderer(),
- NONE, new TexElementNodeRenderer()
+ NONE, RENDERER
);
public static class Factory implements NodeRendererFactory {
private final RendererFacade mNodeRenderer;
public Factory(
final ExportFormat exportFormat, final Processor<String> processor ) {
- mNodeRenderer = EXPORT_RENDERERS.get( exportFormat );
+ mNodeRenderer = EXPORT_RENDERERS.getOrDefault( exportFormat, RENDERER );
mNodeRenderer.setProcessor( processor );
}
@NotNull
@Override
- public NodeRenderer apply( @NotNull DataHolder options ) {
+ public NodeRenderer apply( @NotNull final DataHolder options ) {
return mNodeRenderer;
}
src/main/java/com/keenwrite/ui/actions/Action.java
}
+ // Do not display mnemonic accelerator character in tooltip text.
+ // The accelerator key will still be available, this is display-only.
+ tooltip = tooltip.replace( "_", "" );
+
if( mAccelerator != null ) {
tooltip += " (" + mAccelerator.getDisplayText() + ')';
src/main/java/com/keenwrite/ui/actions/ApplicationActions.java
}
+ private void file‿export( final ExportFormat format ) {
+ final var main = getMainPane();
+ final var editor = main.getActiveTextEditor();
+ final var filename = format.toExportFilename( editor.getPath() );
+ final var chooser = createFileChooser();
+ final var selection = chooser.exportAs( filename );
+
+ selection.ifPresent( ( file ) -> {
+ final var doc = editor.getText();
+ final var context = main.createProcessorContext( file, format );
+ final var chain = createProcessors( context );
+ final var export = chain.apply( doc );
+
+ try {
+ // Processors can export in binary formats that are incompatible with
+ // Java language String objects. In such cases, the processor will
+ // return the null sentinel to signal no further processing is needed.
+ if( export != null ) {
+ writeString( file.toPath(), export );
+ }
+
+ clue( get( "Main.status.export.success", file.toString() ) );
+ } catch( final Exception ex ) {
+ clue( ex );
+ }
+ } );
+ }
+
+ public void file‿export‿pdf() { file‿export( APPLICATION_PDF ); }
+
public void file‿export‿html_svg() {
file‿export( HTML_TEX_SVG );
public void file‿export‿markdown() {
file‿export( MARKDOWN_PLAIN );
- }
-
- private void file‿export( final ExportFormat format ) {
- final var main = getMainPane();
- final var context = main.createProcessorContext( format );
- final var chain = createProcessors( context );
- final var editor = main.getActiveTextEditor();
- final var doc = editor.getText();
- final var export = chain.apply( doc );
- final var filename = format.toExportFilename( editor.getPath() );
- final var chooser = createFileChooser();
- final var file = chooser.exportAs( filename );
-
- file.ifPresent( ( f ) -> {
- try {
- writeString( f.toPath(), export );
- clue( get( "Main.status.export.success", f.toString() ) );
- } catch( final Exception ex ) {
- clue( ex );
- }
- } );
}
src/main/java/com/keenwrite/ui/actions/ApplicationBars.java
addAction( "file.export", e -> {} )
.addSubActions(
+ addAction( "file.export.pdf", e -> actions.file‿export‿pdf() ),
addAction( "file.export.html_svg", e -> actions.file‿export‿html_svg() ),
addAction( "file.export.html_tex", e -> actions.file‿export‿html_tex() ),
getAction( "file.open" ),
getAction( "file.save" ),
+ SEPARATOR_ACTION,
+ getAction( "file.export.pdf" ),
SEPARATOR_ACTION,
getAction( "edit.undo" ),
src/main/resources/com/keenwrite/messages.properties
Action.file.save_all.text=Save A_ll
+Action.file.export.pdf.description=Typeset the document
+Action.file.export.pdf.text=_PDF
+Action.file.export.pdf.icon=FILE_PDF_ALT
+
Action.file.export.html_svg.description=Export the current document as HTML + SVG
Action.file.export.text=_Export As
src/main/resources/com/keenwrite/preview/webview.css
/* ITEMIZED LISTS ***/
-
ol, ul {
margin: 0 0 0 2em;
tex/setups.tex
\startxmlsetups xml:tex
- \mathematics{\xmlflushcontext{#1}}
+ %\mathematics{\xmlflushcontext{#1}}
+ \xmlflushcontext{#1}
\stopxmlsetups
Delta180 lines added, 53 lines removed, 127-line increase