Dave Jarvis' Repositories

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

Decoupled HTML preview pane from Markdown rendering. Added text processors to manipulate the text editor content before the HTML preview renders the final document.

Authordjarvis <email>
Date2016-11-24 23:38:54 GMT-0800
Commite11743b4e4e296087057e20311e8ce96e7aa0c39
Parent205c4c6
Delta330 lines added, 2 lines removed, 328-line increase
src/main/resources/META-INF/services/com.scrivenvar.service.DocumentProcessorFactory
-com.scrivenvar.service.impl.DefaultDocumentProcessorFactory
+
src/main/java/com/scrivenvar/service/DocumentProcessorFactory.java
package com.scrivenvar.service;
+import com.scrivenvar.processors.Processor;
+
/**
* Responsible for creating a chain of document processors for a given file
* extension).
*/
- public DocumentProcessor createDocumentProcessor(String filetype);
+ public Processor createDocumentProcessor(String filetype);
}
src/main/java/com/scrivenvar/processors/MarkdownProcessor.java
+/*
+ * Copyright 2016 White Magic Software, Ltd.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.scrivenvar.processors;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.commonmark.Extension;
+import org.commonmark.ext.gfm.tables.TablesExtension;
+import org.commonmark.parser.Parser;
+import org.commonmark.renderer.html.HtmlRenderer;
+
+/**
+ * Responsible for parsing a Markdown document and rendering it as HTML.
+ *
+ * @author White Magic Software, Ltd.
+ */
+public class MarkdownProcessor extends AbstractProcessor<String> {
+
+ private List<Extension> extensions;
+
+ /**
+ * Constructs a new Markdown processor that can create HTML documents.
+ *
+ * @param successor Usually the HTML Preview Processor.
+ */
+ public MarkdownProcessor( final Processor<String> successor ) {
+ super( successor );
+ }
+
+ /**
+ * Converts the given Markdown string into HTML, without the doctype, html,
+ * head, and body tags.
+ *
+ * @param markdown The string to convert from Markdown to HTML.
+ *
+ * @return The HTML representation of the Markdown document.
+ */
+ @Override
+ public String processLink( final String markdown ) {
+ return toHtml( markdown );
+ }
+
+ /**
+ * Converts a string of markdown into HTML.
+ *
+ * @param markdown The markdown text to convert to HTML, must not be null.
+ *
+ * @return The markdown rendered as an HTML document.
+ */
+ private String toHtml( final String markdown ) {
+ return createRenderer().render( createParser().parse( markdown ) );
+ }
+
+ /**
+ * Returns the list of extensions to use when parsing and rendering Markdown
+ * into HTML.
+ *
+ * @return A non-null list of Markdown extensions.
+ */
+ private synchronized List<Extension> getExtensions() {
+ if( this.extensions == null ) {
+ this.extensions = createExtensions();
+ }
+
+ return this.extensions;
+ }
+
+ /**
+ * Creates a list that includes a TablesExtension. Subclasses may override
+ * this method to insert more extensions, or remove the table extension.
+ *
+ * @return A list with an extension for parsing and rendering tables.
+ */
+ protected List<Extension> createExtensions() {
+ final List<Extension> result = new ArrayList<>();
+ result.add( TablesExtension.create() );
+ return result;
+ }
+
+ /**
+ * Creates the Markdown document processor.
+ *
+ * @return A Parser that can build an abstract syntax tree.
+ */
+ private Parser createParser() {
+ return Parser.builder().extensions( getExtensions() ).build();
+ }
+
+ /**
+ * Creates the HTML document renderer.
+ *
+ * @return A renderer that can convert a Markdown AST to HTML.
+ */
+ private HtmlRenderer createRenderer() {
+ return HtmlRenderer.builder().extensions( getExtensions() ).build();
+ }
+}
src/main/java/com/scrivenvar/processors/Processor.java
+/*
+ * Copyright 2016 White Magic Software, Ltd.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.scrivenvar.processors;
+
+/**
+ * Responsible for processing documents from one known format to another.
+ *
+ * @author White Magic Software, Ltd.
+ * @param <T> The type of processor to create.
+ */
+public interface Processor<T> {
+
+ /**
+ * Processes the given content providing a transformation from one document
+ * format into another. For example, this could convert from XML to text using
+ * an XSLT processor, or from markdown to HTML.
+ *
+ * @param t The type of object to process.
+ *
+ * @return The post-processed document, or null if processing should stop.
+ */
+ public T processLink( T t );
+
+ /**
+ * Adds a document processor to call after this processor finishes processing
+ * the document given to the process method.
+ *
+ * @return The processor that should transform the document after this
+ * instance has finished processing.
+ */
+ public Processor<T> next();
+}
src/main/java/com/scrivenvar/processors/TextChangeProcessor.java
+/*
+ * Copyright 2016 White Magic Software, Ltd.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.scrivenvar.processors;
+
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+
+/**
+ * Responsible for forwarding change events to the document process chain. This
+ * class isolates knowledge of the change events from the other processors.
+ *
+ * @author White Magic Software, Ltd.
+ */
+public class TextChangeProcessor extends AbstractProcessor<String>
+ implements ChangeListener<String> {
+
+ /**
+ * Constructs a new text processor that listens for changes to text and then
+ * injects them into the processing chain.
+ *
+ * @param successor Usually the HTML Preview Processor.
+ */
+ public TextChangeProcessor( final Processor<String> successor ) {
+ super( successor );
+ }
+
+ /**
+ * Called when the text editor changes.
+ *
+ * @param observable Unused.
+ * @param oldValue The value before being changed (unused).
+ * @param newValue The value after being changed (passed to processChain).
+ */
+ @Override
+ public void changed(
+ final ObservableValue<? extends String> observable,
+ final String oldValue,
+ final String newValue ) {
+ processChain( newValue );
+ }
+
+ /**
+ * Performs no processing.
+ *
+ * @param t Returned value.
+ *
+ * @return t, without any processing.
+ */
+ @Override
+ public String processLink( String t ) {
+ return t;
+ }
+}
src/main/java/com/scrivenvar/processors/VariableNameProcessor.java
+/*
+ * The MIT License
+ *
+ * Copyright 2016 .
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.scrivenvar.processors;
+
+import javafx.scene.control.TreeView;
+
+/**
+ * Processes variables in the document and inserts their values into the
+ * post-processed text.
+ *
+ * @author White Magic Software, Ltd.
+ */
+public class VariableNameProcessor extends AbstractProcessor<String> {
+
+ private TreeView<String> treeView;
+
+ /**
+ * Constructs a new Markdown processor that can create HTML documents.
+ *
+ * @param successor Usually the HTML Preview Processor.
+ */
+ private VariableNameProcessor( final Processor<String> successor ) {
+ super( successor );
+ }
+
+ public VariableNameProcessor( final Processor<String> successor, final TreeView<String> root ) {
+ this( successor );
+ setTreeView( root );
+ }
+
+ @Override
+ public String processLink( final String text ) {
+ final TreeView<String> root = getTreeView();
+ final StringBuilder sb = new StringBuilder( text.length() * 2 );
+
+ sb.append( text.replaceAll( "\\$c\\.protagonist\\.name\\.First\\$", "Chloe" ) );
+
+ return sb.toString();
+ }
+
+ private TreeView<String> getTreeView() {
+ return this.treeView;
+ }
+
+ private void setTreeView( final TreeView<String> treeView ) {
+ this.treeView = treeView;
+ }
+}