| 1 | # Build | |
| 1 | # Introduction | |
| 2 | 2 | |
| 3 | This document describes how to build the application. | |
| 3 | This document describes how to build the application and platform binaries. | |
| 4 | 4 | |
| 5 | 5 | # Requirements |
| 6 | 6 | |
| 7 | 7 | Download and install the following software packages: |
| 8 | 8 | |
| 9 | 9 | * [OpenJDK 14](https://openjdk.java.net) |
| 10 | 10 | * [Gradle 6.4](https://gradle.org/releases) |
| 11 | 11 | |
| 12 | # Compile | |
| 12 | # Build | |
| 13 | 13 | |
| 14 | Build the application as follows: | |
| 14 | Build the application überjar as follows: | |
| 15 | 15 | |
| 16 | 16 | gradle clean jar |
| ... | ||
| 27 | 27 | |
| 28 | 28 | java -jar build\libs\scrivenvar.jar |
| 29 | ||
| 30 | # Installers | |
| 31 | ||
| 32 | This section describes how to set up the development environment and | |
| 33 | build native executables for supported operating systems. | |
| 34 | ||
| 35 | ## Setup | |
| 36 | ||
| 37 | Follow these one-time setup instructions to begin: | |
| 38 | ||
| 39 | 1. Ensure `$HOME/bin` is set in the `PATH` environment variable. | |
| 40 | 1. Move `build-template` into `$HOME/bin`. | |
| 41 | ||
| 42 | Setup is complete. | |
| 43 | ||
| 44 | ## Binaries | |
| 45 | ||
| 46 | Run the `installer` script to build platform-specific binaries, such as: | |
| 47 | ||
| 48 | ./installer -V -o linux | |
| 49 | ||
| 50 | The `installer` script: | |
| 51 | ||
| 52 | * downloads a JDK; | |
| 53 | * generates a run script; | |
| 54 | * bundles the JDK, run script, and JAR file; and | |
| 55 | * creates a standalone binary, so no installation required. | |
| 56 | ||
| 57 | Run `./installer -h` to see all command-line options. | |
| 58 | ||
| 59 | # Versioning | |
| 60 | ||
| 61 | Version numbers are read directly from Git using a plugin. The version | |
| 62 | number is written to `app.properties`, a properties file in the `resources` | |
| 63 | directory that can be read from within the application. | |
| 29 | 64 | |
| 30 | 65 | |
| 1 | # Credits | |
| 2 | ||
| 3 | * Dave Jarvis: [Scrivenvar](https://github.com/DaveJarvis/scrivenvar/) | |
| 4 | * Karl Tauber: [Markdown Writer FX](https://github.com/JFormDesigner/markdown-writer-fx) | |
| 5 | * Tomas Mikula: [RichTextFX](https://github.com/TomasMikula/RichTextFX), [ReactFX](https://github.com/TomasMikula/ReactFX), [WellBehavedFX](https://github.com/TomasMikula/WellBehavedFX), [Flowless](https://github.com/TomasMikula/Flowless), and [UndoFX](https://github.com/TomasMikula/UndoFX) | |
| 6 | * Mikael Grev: [MigLayout](http://www.miglayout.com/) | |
| 7 | * Tom Eugelink: [MigPane](https://github.com/mikaelgrev/miglayout/blob/master/javafx/src/main/java/org/tbee/javafx/scene/layout/fxml/MigPane.java) | |
| 8 | * Jens Deters: [FontAwesomeFX](https://bitbucket.org/Jerady/fontawesomefx) | |
| 9 | * Dieter Holz, [PreferencesFX](https://github.com/dlsc-software-consulting-gmbh/PreferencesFX) | |
| 10 | * David Croft, [File Preferences](http://www.davidc.net/programming/java/java-preferences-using-file-backing-store) | |
| 11 | * Alex Bertram, [Renjin](https://www.renjin.org/) | |
| 12 | * Vladimir Schneider: [flexmark](https://github.com/vsch/flexmark-java) | |
| 13 | * Michael Kay, [XSLT Processor](http://www.saxonica.com/) | |
| 14 | * Shy Shalom, Kohei Taketa: [juniversalchardet](https://github.com/takscape/juniversalchardet) | |
| 15 | ||
| 16 | 1 |
| 45 | 45 | ## Usage |
| 46 | 46 | |
| 47 | See the following documents for more information: | |
| 48 | ||
| 49 | * [USAGE.md](USAGE.md) -- Variable definitions and string interpolation | |
| 50 | * [USAGE-R.md](USAGE-R.md) -- Call R functions within R Markdown documents | |
| 51 | * [USAGE-SVG.md](USAGE-SVG.md) -- Fix known issues with displaying SVG files | |
| 47 | See the [detailed documentation](docs/README.md) for information about | |
| 48 | using the application. | |
| 52 | 49 | |
| 53 | 50 | ## Future Features |
| 1 | # Introduction | |
| 2 | ||
| 3 | This document describes how to use the [R](https://www.r-project.org/) | |
| 4 | programming language from within the application. The application uses an | |
| 5 | interpreter known as [Renjin](https://www.renjin.org/) to integrate with R. | |
| 6 | ||
| 7 | # Hello world | |
| 8 | ||
| 9 | Complete the following steps to see R in action: | |
| 10 | ||
| 11 | 1. Start the application. | |
| 12 | 1. Click **File → New** to create a new file. | |
| 13 | 1. Click **File → Save As**. | |
| 14 | 1. Set **Name** to: `addition.Rmd` | |
| 15 | 1. Click **Save**. | |
| 16 | ||
| 17 | Setting the file name extension tells the application what processor to | |
| 18 | use when transforming the contents for display in the preview pane. Continue | |
| 19 | by typing in the following text, including the backticks: | |
| 20 | ||
| 21 | ```r | |
| 22 | `r#1 + 1` | |
| 23 | ``` | |
| 24 | ||
| 25 | The preview pane shows the result of `1` plus `1`: | |
| 26 | ||
| 27 | ``` | |
| 28 | 2.0 | |
| 29 | ``` | |
| 30 | ||
| 31 | # Bootstrap script | |
| 32 | ||
| 33 | Being able to run R code while editing an R Markdown document is convenient. | |
| 34 | Having the ability to call functions is where the power of R can be | |
| 35 | leveraged. | |
| 36 | ||
| 37 | Complete the following steps to call an R function from your own library: | |
| 38 | ||
| 39 | 1. Click **File → New** to create a new file. | |
| 40 | 1. Click **File → Save As**. | |
| 41 | 1. Browse to your home directory. | |
| 42 | 1. Set **Name** to: `library.R`. | |
| 43 | 1. Click **Save**. | |
| 44 | 1. Set the contents to: | |
| 45 | ``` r | |
| 46 | sum <- function( a, b ) { | |
| 47 | a + b | |
| 48 | } | |
| 49 | ``` | |
| 50 | 1. Click the **Save** icon. | |
| 51 | 1. Click **R → Script**. | |
| 52 | 1. Set the **R Startup Script** contents to: | |
| 53 | ``` r | |
| 54 | source( 'library.R' ); | |
| 55 | ``` | |
| 56 | 1. Click **OK**. | |
| 57 | 1. Create a new file. | |
| 58 | 1. Set the contents to: | |
| 59 | ``` r | |
| 60 | `r#sum( 5, 5 )` | |
| 61 | ``` | |
| 62 | 1. Save the file as `sum.R`. | |
| 63 | ||
| 64 | The preview panel shows the result of calling the `sum` function: | |
| 65 | ||
| 66 | ``` | |
| 67 | 10.0 | |
| 68 | ``` | |
| 69 | ||
| 70 | This shows how the bootstrap script can load `library.R`, which defines | |
| 71 | a `sum` function that is called by name in the Markdown document. | |
| 72 | ||
| 73 | # Working directory | |
| 74 | ||
| 75 | R files may be sourced from any directory, not just the user's home | |
| 76 | directory. Accomplish this as follows: | |
| 77 | ||
| 78 | 1. Click **R → Directory**. | |
| 79 | 1. Set **Directory** to a different directory. | |
| 80 | 1. Click **OK**. | |
| 81 | 1. Create the directory if it does not exist. | |
| 82 | 1. Move `library.R` into the directory. | |
| 83 | 1. Append a new function to `library.R` as follows: | |
| 84 | ``` r | |
| 85 | mul <- function( a, b ) { | |
| 86 | a * b | |
| 87 | } | |
| 88 | ``` | |
| 89 | 1. Click **R → Script**. | |
| 90 | 1. Set the **R Startup Script** contents to: | |
| 91 | ``` r | |
| 92 | setwd( '$application.r.working.directory$' ); | |
| 93 | source( 'library.R' ); | |
| 94 | ``` | |
| 95 | 1. Change `sum.Rmd` to: | |
| 96 | ``` r | |
| 97 | `r#mul( 5, 5 )` | |
| 98 | ``` | |
| 99 | 1. Close the file `sum.Rmd`. | |
| 100 | 1. Confirm saving the file when prompted. | |
| 101 | 1. Re-open `sum.Rmd`. | |
| 102 | ||
| 103 | The preview panel shows: | |
| 104 | ||
| 105 | ``` | |
| 106 | 25.0 | |
| 107 | ``` | |
| 108 | ||
| 109 | Calling `setwd` using `'$application.r.working.directory$'` changes the | |
| 110 | working directory where the R engine searches for source files. | |
| 111 | ||
| 112 | # YAML definitions | |
| 113 | ||
| 114 | To see how variable definitions work in R, try the following: | |
| 115 | ||
| 116 | 1. Create a new file. | |
| 117 | 1. Change the contents to (use spaces not tabs): | |
| 118 | ``` yaml | |
| 119 | project: | |
| 120 | title: Project Title | |
| 121 | author: Author Name | |
| 122 | ``` | |
| 123 | 1. Save the file as `definitions.yaml`. | |
| 124 | 1. Click **File → Open**. | |
| 125 | 1. Set **Source Files** to **Definition Files**. | |
| 126 | 1. Select `definitions.yaml`. | |
| 127 | 1. Click **Open**. | |
| 128 | 1. Open `sum.Rmd` if it is not already open. | |
| 129 | 1. Type: `je` | |
| 130 | 1. Press `Ctrl+Space` | |
| 131 | ||
| 132 | The editor inserts the following text (matches `je` against Pro**je**ct): | |
| 133 | ||
| 134 | ``` r | |
| 135 | `r#x( v$project$title )` | |
| 136 | ``` | |
| 137 | ||
| 138 | The preview panel shows: | |
| 139 | ||
| 140 | ``` | |
| 141 | r#x( 'Project Title' ) | |
| 142 | ``` | |
| 143 | ||
| 144 | This is because the application inserts definition reference names based | |
| 145 | on the type of file being edited. By default, the R engine does not have | |
| 146 | a function named `x` defined. | |
| 147 | ||
| 148 | Continue as follows: | |
| 149 | ||
| 150 | 1. Click **R → Script**. | |
| 151 | 1. Append the following: | |
| 152 | ``` r | |
| 153 | x <- function( s ) { | |
| 154 | tryCatch( { | |
| 155 | r = eval( parse( text = s ) ) | |
| 156 | ||
| 157 | ifelse( is.atomic( r ), r, s ); | |
| 158 | }, | |
| 159 | warning = function( w ) { s }, | |
| 160 | error = function( e ) { s } ) | |
| 161 | } | |
| 162 | ``` | |
| 163 | 1. Click **OK**. | |
| 164 | 1. Close and re-open `sum.Rmd`. | |
| 165 | ||
| 166 | The preview panel shows: | |
| 167 | ||
| 168 | ``` | |
| 169 | 25.0 | |
| 170 | ||
| 171 | Project Title | |
| 172 | ``` | |
| 173 | ||
| 174 | The `x` function attempts to evaluate the expression defined by the YAML | |
| 175 | variable. This means that the YAML definitions can also include expressions | |
| 176 | that R is capable of evaluating. | |
| 177 | ||
| 178 | While the `x` function can be defined within the R Startup Script, it is | |
| 179 | better practice to put it into its own library so that it can be reused | |
| 180 | outside of the application. | |
| 181 | ||
| 182 | 1 |
| 1 | # Introduction | |
| 2 | ||
| 3 | The Scalable Vector Graphics (SVG) drawing software---[Batik](https://xmlgraphics.apache.org/batik/)---that's used by the application may be unable to read certain SVG files produced by [Inkscape](https://inkscape.org/). The result is that embedding the vector graphics files may trigger the following issues: | |
| 4 | ||
| 5 | * Unable to create nested element | |
| 6 | * Black blocks, no text displayed | |
| 7 | * Black text instead of coloured | |
| 8 | ||
| 9 | The remainder of this document explains these problems and how to fix them. | |
| 10 | ||
| 11 | # Nested element | |
| 12 | ||
| 13 | When referencing a vector graphic using Markdown, the status bar may show the following error: | |
| 14 | ||
| 15 | > The current document is unable to create an element of the requested type (namespace: http://www.w3.org/2000/svg, name: flowRoot). | |
| 16 | ||
| 17 | This error is due to a version mismatch of the `flowRoot` element that Inkscape creates. | |
| 18 | ||
| 19 | ## Fix | |
| 20 | ||
| 21 | Resolve the issue by changing the SVG version number as follows: | |
| 22 | ||
| 23 | 1. Edit the vector graphics file using any text editor. | |
| 24 | 1. Find `version="1.1"` and change it to `version="1.2"`. | |
| 25 | 1. Save the file. | |
| 26 | ||
| 27 | The SVG will now appear inside the application; however, the text may appear as black blocks. | |
| 28 | ||
| 29 | # Black blocks | |
| 30 | ||
| 31 | Depending on how text is added to a vector graphic in Inkscape, the text may be inserted within an element called a `flowRoot`. Although Batik recognizes `flowRoot` for SVG version 1.2, it cannot fully interpret the contents. Black blocks are drawn instead of the text, such as those depicted in the following figure: | |
| 32 | ||
| 33 |  | |
| 34 | ||
| 35 | ## Fix | |
| 36 | ||
| 37 | Resolve the issue by "unflowing" all text elements as follows: | |
| 38 | ||
| 39 | 1. Start Inkscape. | |
| 40 | 1. Load the SVG file. | |
| 41 | 1. Select all the text elements. | |
| 42 | 1. Click **Text → Unflow**. | |
| 43 | ||
| 44 | The text may change size and position; recreate the text without dragging using the text tool. After all the text areas have been recreated, continue as follows: | |
| 45 | ||
| 46 | 1. Click **Edit → XML Editor**. | |
| 47 | 1. Expand the **XML Editor** to see more elements. | |
| 48 | 1. Delete all elements named `svg:flowRoot`. | |
| 49 | 1. Save the file. | |
| 50 | ||
| 51 | When the illustration is reloaded, the black blocks will have disappeared, but the text elements ignore any assigned colour. | |
| 52 | ||
| 53 | # Black text | |
| 54 | ||
| 55 | When an SVG `style` attribute contains a reference to `-inkscape-font-specification`, Batik ignores all values that follow said reference. This results in black text, such as: | |
| 56 | ||
| 57 |  | |
| 58 | ||
| 59 | ## Fix | |
| 60 | ||
| 61 | Resolve the issue of colourless text as follows: | |
| 62 | ||
| 63 | 1. Open the SVG file in a plain text editor. | |
| 64 | 1. Remove all references `-inkscape-font-specification:'<FONT>';`, including the trailing (or leading) semicolon. | |
| 65 | 1. Save the file. | |
| 66 | ||
| 67 | When the illustration is reloaded, the colours will have reappeared, such as: | |
| 68 | ||
| 69 |  | |
| 70 | ||
| 71 | 1 |
| 1 | # Introduction | |
| 2 | ||
| 3 | This document describes how to use the application. | |
| 4 | ||
| 5 | # Variable definitions | |
| 6 | ||
| 7 | Variable definitions provide a way to insert key names having associated values into a document. The variable names and values are declared inside an external file using the [YAML](http://www.yaml.org/) file format. Simply put, variables are written in the file as follows: | |
| 8 | ||
| 9 | ``` | |
| 10 | key: value | |
| 11 | ``` | |
| 12 | ||
| 13 | Any number of variables can be defined, in any order: | |
| 14 | ||
| 15 | ``` | |
| 16 | key_1: Value 1 | |
| 17 | key_2: Value 2 | |
| 18 | ``` | |
| 19 | ||
| 20 | Variables can reference other variables by enclosing the key name within dollar symbols: | |
| 21 | ||
| 22 | ``` | |
| 23 | key: Value | |
| 24 | key_1: $key$ 1 | |
| 25 | key_2: $key$ 2 | |
| 26 | ``` | |
| 27 | ||
| 28 | Variables can use a nested structure to help group related information: | |
| 29 | ||
| 30 | ``` | |
| 31 | novel: | |
| 32 | title: Book Title | |
| 33 | author: Author Name | |
| 34 | isbn: 978-3-16-148410-0 | |
| 35 | ``` | |
| 36 | ||
| 37 | Use a period to reference nested keys, such as: | |
| 38 | ||
| 39 | ``` | |
| 40 | novel: | |
| 41 | author: Author Name | |
| 42 | copyright: | |
| 43 | owner: $novel.author$ | |
| 44 | ``` | |
| 45 | ||
| 46 | Save the variable definitions in a file having an extension of `.yaml` or `.yml`. | |
| 47 | ||
| 48 | # Document editing | |
| 49 | ||
| 50 | The application's purpose is to completely separate the document's content from its presentation. To achieve this, documents are composed using a [plain text](http://spec.commonmark.org/0.28/) format. | |
| 51 | ||
| 52 | ## Create document | |
| 53 | ||
| 54 | Start a new document as follows: | |
| 55 | ||
| 56 | 1. Start the application. | |
| 57 | 1. Click **File → New** to create an empty document to edit. | |
| 58 | 1. Click **File → Open** to open a variable definition file. | |
| 59 | 1. Change **Source Files** to **Definition Files** to list definition files. | |
| 60 | 1. Browse to and select a file saved with a `.yaml` or `.yml` extension. | |
| 61 | 1. Click **Open**. | |
| 62 | ||
| 63 | The variable definitions appear in the variable definition pane under the heading of **Definitions**. | |
| 64 | ||
| 65 | ## Edit document | |
| 66 | ||
| 67 | Edit the document as normal. Notice how the preview pane updates as new content is added. The toolbar shows various icons that perform different formatting operations. Try them to see how they appear in the preview pane. Other operations not shown on the toolbar include: | |
| 68 | ||
| 69 | * Struck text (enclose the words within `~~` and `~~`) | |
| 70 | * Horizontal rule (use `---` on an otherwise empty line). | |
| 71 | ||
| 72 | The preview pane shows one way to interpret and format the document, but many other presentations are possible. | |
| 73 | ||
| 74 | ## Insert variable | |
| 75 | ||
| 76 | Let's assume that the variable definitions loaded into the application include: | |
| 77 | ||
| 78 | ``` | |
| 79 | novel: | |
| 80 | title: Diary of $novel.author$ | |
| 81 | author: Anne Frank | |
| 82 | ``` | |
| 83 | ||
| 84 | To reference a variable, type in the key name enclosed within dollar symbols, such as: | |
| 85 | ||
| 86 | ``` | |
| 87 | The novel "$novel.title$" is one of the most widely read books in the world. | |
| 88 | ``` | |
| 89 | ||
| 90 | The preview pane shows: | |
| 91 | ||
| 92 | > The novel "Diary of Anne Frank" is one of the most widely read books in the world. | |
| 93 | ||
| 94 | As it is laborious to type in variable names, it is possible to inject the variable name using autocomplete. Accomplish this as follows: | |
| 95 | ||
| 96 | 1. Create a new file. | |
| 97 | 1. Type in a partial variable value, such as **Dia**. | |
| 98 | 1. Press `Ctrl+Space` (hold down the `Control` key and tap the spacebar). | |
| 99 | ||
| 100 | The editor shows: | |
| 101 | ||
| 102 | ``` | |
| 103 | $novel.title$ | |
| 104 | ``` | |
| 105 | ||
| 106 | The preview pane shows: | |
| 107 | ||
| 108 | ``` | |
| 109 | Diary of Anne Frank | |
| 110 | ``` | |
| 111 | ||
| 112 | The variable name is inserted into the document and the preview pane shows the variable's value. | |
| 113 | ||
| 114 | 1 |
| 173 | 173 | } |
| 174 | 174 | |
| 175 |
| 1 | ## Documents | |
| 2 | ||
| 3 | See the following documents for more information: | |
| 4 | ||
| 5 | * [definitions.md](definitions.md) -- Definitions and interpolation | |
| 6 | * [r.md](r.md) -- Call R functions within R Markdown documents | |
| 7 | * [svg.md](svg.md) -- Fix known issues with displaying SVG files | |
| 8 | * [credits.md](credits.md) -- Thanks to authors of contributing projects | |
| 9 | ||
| 1 | 10 |
| 1 | # Credits | |
| 2 | ||
| 3 | * Karl Tauber: [Markdown Writer FX](https://github.com/JFormDesigner/markdown-writer-fx) | |
| 4 | * Tomas Mikula: [RichTextFX](https://github.com/TomasMikula/RichTextFX), [ReactFX](https://github.com/TomasMikula/ReactFX), [WellBehavedFX](https://github.com/TomasMikula/WellBehavedFX), [Flowless](https://github.com/TomasMikula/Flowless), and [UndoFX](https://github.com/TomasMikula/UndoFX) | |
| 5 | * Mikael Grev: [MigLayout](http://www.miglayout.com/) | |
| 6 | * Tom Eugelink: [MigPane](https://github.com/mikaelgrev/miglayout/blob/master/javafx/src/main/java/org/tbee/javafx/scene/layout/fxml/MigPane.java) | |
| 7 | * Jens Deters: [FontAwesomeFX](https://bitbucket.org/Jerady/fontawesomefx) | |
| 8 | * Dieter Holz, [PreferencesFX](https://github.com/dlsc-software-consulting-gmbh/PreferencesFX) | |
| 9 | * David Croft, [File Preferences](http://www.davidc.net/programming/java/java-preferences-using-file-backing-store) | |
| 10 | * Alex Bertram, [Renjin](https://www.renjin.org/) | |
| 11 | * Vladimir Schneider: [flexmark](https://github.com/vsch/flexmark-java) | |
| 12 | * Michael Kay, [XSLT Processor](http://www.saxonica.com/) | |
| 13 | * Shy Shalom, Kohei Taketa: [juniversalchardet](https://github.com/takscape/juniversalchardet) | |
| 14 | ||
| 1 | 15 |
| 1 | # Introduction | |
| 2 | ||
| 3 | This document describes how to use the application. | |
| 4 | ||
| 5 | # Variable definitions | |
| 6 | ||
| 7 | Variable definitions provide a way to insert key names having associated values into a document. The variable names and values are declared inside an external file using the [YAML](http://www.yaml.org/) file format. Simply put, variables are written in the file as follows: | |
| 8 | ||
| 9 | ``` | |
| 10 | key: value | |
| 11 | ``` | |
| 12 | ||
| 13 | Any number of variables can be defined, in any order: | |
| 14 | ||
| 15 | ``` | |
| 16 | key_1: Value 1 | |
| 17 | key_2: Value 2 | |
| 18 | ``` | |
| 19 | ||
| 20 | Variables can reference other variables by enclosing the key name within dollar symbols: | |
| 21 | ||
| 22 | ``` | |
| 23 | key: Value | |
| 24 | key_1: $key$ 1 | |
| 25 | key_2: $key$ 2 | |
| 26 | ``` | |
| 27 | ||
| 28 | Variables can use a nested structure to help group related information: | |
| 29 | ||
| 30 | ``` | |
| 31 | novel: | |
| 32 | title: Book Title | |
| 33 | author: Author Name | |
| 34 | isbn: 978-3-16-148410-0 | |
| 35 | ``` | |
| 36 | ||
| 37 | Use a period to reference nested keys, such as: | |
| 38 | ||
| 39 | ``` | |
| 40 | novel: | |
| 41 | author: Author Name | |
| 42 | copyright: | |
| 43 | owner: $novel.author$ | |
| 44 | ``` | |
| 45 | ||
| 46 | Save the variable definitions in a file having an extension of `.yaml` or `.yml`. | |
| 47 | ||
| 48 | # Document editing | |
| 49 | ||
| 50 | The application's purpose is to completely separate the document's content from its presentation. To achieve this, documents are composed using a [plain text](http://spec.commonmark.org/0.28/) format. | |
| 51 | ||
| 52 | ## Create document | |
| 53 | ||
| 54 | Start a new document as follows: | |
| 55 | ||
| 56 | 1. Start the application. | |
| 57 | 1. Click **File → New** to create an empty document to edit. | |
| 58 | 1. Click **File → Open** to open a variable definition file. | |
| 59 | 1. Change **Source Files** to **Definition Files** to list definition files. | |
| 60 | 1. Browse to and select a file saved with a `.yaml` or `.yml` extension. | |
| 61 | 1. Click **Open**. | |
| 62 | ||
| 63 | The variable definitions appear in the variable definition pane under the heading of **Definitions**. | |
| 64 | ||
| 65 | ## Edit document | |
| 66 | ||
| 67 | Edit the document as normal. Notice how the preview pane updates as new content is added. The toolbar shows various icons that perform different formatting operations. Try them to see how they appear in the preview pane. Other operations not shown on the toolbar include: | |
| 68 | ||
| 69 | * Struck text (enclose the words within `~~` and `~~`) | |
| 70 | * Horizontal rule (use `---` on an otherwise empty line). | |
| 71 | ||
| 72 | The preview pane shows one way to interpret and format the document, but many other presentations are possible. | |
| 73 | ||
| 74 | ## Insert variable | |
| 75 | ||
| 76 | Let's assume that the variable definitions loaded into the application include: | |
| 77 | ||
| 78 | ``` | |
| 79 | novel: | |
| 80 | title: Diary of $novel.author$ | |
| 81 | author: Anne Frank | |
| 82 | ``` | |
| 83 | ||
| 84 | To reference a variable, type in the key name enclosed within dollar symbols, such as: | |
| 85 | ||
| 86 | ``` | |
| 87 | The novel "$novel.title$" is one of the most widely read books in the world. | |
| 88 | ``` | |
| 89 | ||
| 90 | The preview pane shows: | |
| 91 | ||
| 92 | > The novel "Diary of Anne Frank" is one of the most widely read books in the world. | |
| 93 | ||
| 94 | As it is laborious to type in variable names, it is possible to inject the variable name using autocomplete. Accomplish this as follows: | |
| 95 | ||
| 96 | 1. Create a new file. | |
| 97 | 1. Type in a partial variable value, such as **Dia**. | |
| 98 | 1. Press `Ctrl+Space` (hold down the `Control` key and tap the spacebar). | |
| 99 | ||
| 100 | The editor shows: | |
| 101 | ||
| 102 | ``` | |
| 103 | $novel.title$ | |
| 104 | ``` | |
| 105 | ||
| 106 | The preview pane shows: | |
| 107 | ||
| 108 | ``` | |
| 109 | Diary of Anne Frank | |
| 110 | ``` | |
| 111 | ||
| 112 | The variable name is inserted into the document and the preview pane shows the variable's value. | |
| 113 | ||
| 1 | 114 |
| 1 | # Introduction | |
| 2 | ||
| 3 | This document describes how to use the [R](https://www.r-project.org/) | |
| 4 | programming language from within the application. The application uses an | |
| 5 | interpreter known as [Renjin](https://www.renjin.org/) to integrate with R. | |
| 6 | ||
| 7 | # Hello world | |
| 8 | ||
| 9 | Complete the following steps to see R in action: | |
| 10 | ||
| 11 | 1. Start the application. | |
| 12 | 1. Click **File → New** to create a new file. | |
| 13 | 1. Click **File → Save As**. | |
| 14 | 1. Set **Name** to: `addition.Rmd` | |
| 15 | 1. Click **Save**. | |
| 16 | ||
| 17 | Setting the file name extension tells the application what processor to | |
| 18 | use when transforming the contents for display in the preview pane. Continue | |
| 19 | by typing in the following text, including the backticks: | |
| 20 | ||
| 21 | ```r | |
| 22 | `r#1 + 1` | |
| 23 | ``` | |
| 24 | ||
| 25 | The preview pane shows the result of `1` plus `1`: | |
| 26 | ||
| 27 | ``` | |
| 28 | 2.0 | |
| 29 | ``` | |
| 30 | ||
| 31 | # Bootstrap script | |
| 32 | ||
| 33 | Being able to run R code while editing an R Markdown document is convenient. | |
| 34 | Having the ability to call functions is where the power of R can be | |
| 35 | leveraged. | |
| 36 | ||
| 37 | Complete the following steps to call an R function from your own library: | |
| 38 | ||
| 39 | 1. Click **File → New** to create a new file. | |
| 40 | 1. Click **File → Save As**. | |
| 41 | 1. Browse to your home directory. | |
| 42 | 1. Set **Name** to: `library.R`. | |
| 43 | 1. Click **Save**. | |
| 44 | 1. Set the contents to: | |
| 45 | ``` r | |
| 46 | sum <- function( a, b ) { | |
| 47 | a + b | |
| 48 | } | |
| 49 | ``` | |
| 50 | 1. Click the **Save** icon. | |
| 51 | 1. Click **R → Script**. | |
| 52 | 1. Set the **R Startup Script** contents to: | |
| 53 | ``` r | |
| 54 | source( 'library.R' ); | |
| 55 | ``` | |
| 56 | 1. Click **OK**. | |
| 57 | 1. Create a new file. | |
| 58 | 1. Set the contents to: | |
| 59 | ``` r | |
| 60 | `r#sum( 5, 5 )` | |
| 61 | ``` | |
| 62 | 1. Save the file as `sum.R`. | |
| 63 | ||
| 64 | The preview panel shows the result of calling the `sum` function: | |
| 65 | ||
| 66 | ``` | |
| 67 | 10.0 | |
| 68 | ``` | |
| 69 | ||
| 70 | This shows how the bootstrap script can load `library.R`, which defines | |
| 71 | a `sum` function that is called by name in the Markdown document. | |
| 72 | ||
| 73 | # Working directory | |
| 74 | ||
| 75 | R files may be sourced from any directory, not just the user's home | |
| 76 | directory. Accomplish this as follows: | |
| 77 | ||
| 78 | 1. Click **R → Directory**. | |
| 79 | 1. Set **Directory** to a different directory. | |
| 80 | 1. Click **OK**. | |
| 81 | 1. Create the directory if it does not exist. | |
| 82 | 1. Move `library.R` into the directory. | |
| 83 | 1. Append a new function to `library.R` as follows: | |
| 84 | ``` r | |
| 85 | mul <- function( a, b ) { | |
| 86 | a * b | |
| 87 | } | |
| 88 | ``` | |
| 89 | 1. Click **R → Script**. | |
| 90 | 1. Set the **R Startup Script** contents to: | |
| 91 | ``` r | |
| 92 | setwd( '$application.r.working.directory$' ); | |
| 93 | source( 'library.R' ); | |
| 94 | ``` | |
| 95 | 1. Change `sum.Rmd` to: | |
| 96 | ``` r | |
| 97 | `r#mul( 5, 5 )` | |
| 98 | ``` | |
| 99 | 1. Close the file `sum.Rmd`. | |
| 100 | 1. Confirm saving the file when prompted. | |
| 101 | 1. Re-open `sum.Rmd`. | |
| 102 | ||
| 103 | The preview panel shows: | |
| 104 | ||
| 105 | ``` | |
| 106 | 25.0 | |
| 107 | ``` | |
| 108 | ||
| 109 | Calling `setwd` using `'$application.r.working.directory$'` changes the | |
| 110 | working directory where the R engine searches for source files. | |
| 111 | ||
| 112 | # YAML definitions | |
| 113 | ||
| 114 | To see how variable definitions work in R, try the following: | |
| 115 | ||
| 116 | 1. Create a new file. | |
| 117 | 1. Change the contents to (use spaces not tabs): | |
| 118 | ``` yaml | |
| 119 | project: | |
| 120 | title: Project Title | |
| 121 | author: Author Name | |
| 122 | ``` | |
| 123 | 1. Save the file as `definitions.yaml`. | |
| 124 | 1. Click **File → Open**. | |
| 125 | 1. Set **Source Files** to **Definition Files**. | |
| 126 | 1. Select `definitions.yaml`. | |
| 127 | 1. Click **Open**. | |
| 128 | 1. Open `sum.Rmd` if it is not already open. | |
| 129 | 1. Type: `je` | |
| 130 | 1. Press `Ctrl+Space` | |
| 131 | ||
| 132 | The editor inserts the following text (matches `je` against Pro**je**ct): | |
| 133 | ||
| 134 | ``` r | |
| 135 | `r#x( v$project$title )` | |
| 136 | ``` | |
| 137 | ||
| 138 | The preview panel shows: | |
| 139 | ||
| 140 | ``` | |
| 141 | r#x( 'Project Title' ) | |
| 142 | ``` | |
| 143 | ||
| 144 | This is because the application inserts definition reference names based | |
| 145 | on the type of file being edited. By default, the R engine does not have | |
| 146 | a function named `x` defined. | |
| 147 | ||
| 148 | Continue as follows: | |
| 149 | ||
| 150 | 1. Click **R → Script**. | |
| 151 | 1. Append the following: | |
| 152 | ``` r | |
| 153 | x <- function( s ) { | |
| 154 | tryCatch( { | |
| 155 | r = eval( parse( text = s ) ) | |
| 156 | ||
| 157 | ifelse( is.atomic( r ), r, s ); | |
| 158 | }, | |
| 159 | warning = function( w ) { s }, | |
| 160 | error = function( e ) { s } ) | |
| 161 | } | |
| 162 | ``` | |
| 163 | 1. Click **OK**. | |
| 164 | 1. Close and re-open `sum.Rmd`. | |
| 165 | ||
| 166 | The preview panel shows: | |
| 167 | ||
| 168 | ``` | |
| 169 | 25.0 | |
| 170 | ||
| 171 | Project Title | |
| 172 | ``` | |
| 173 | ||
| 174 | The `x` function attempts to evaluate the expression defined by the YAML | |
| 175 | variable. This means that the YAML definitions can also include expressions | |
| 176 | that R is capable of evaluating. | |
| 177 | ||
| 178 | While the `x` function can be defined within the R Startup Script, it is | |
| 179 | better practice to put it into its own library so that it can be reused | |
| 180 | outside of the application. | |
| 181 | ||
| 1 | 182 |
| 1 | # Introduction | |
| 2 | ||
| 3 | The Scalable Vector Graphics (SVG) drawing software---[Batik](https://xmlgraphics.apache.org/batik/)---that's used by the application may be unable to read certain SVG files produced by [Inkscape](https://inkscape.org/). The result is that embedding the vector graphics files may trigger the following issues: | |
| 4 | ||
| 5 | * Unable to create nested element | |
| 6 | * Black blocks, no text displayed | |
| 7 | * Black text instead of coloured | |
| 8 | ||
| 9 | The remainder of this document explains these problems and how to fix them. | |
| 10 | ||
| 11 | # Nested element | |
| 12 | ||
| 13 | When referencing a vector graphic using Markdown, the status bar may show the following error: | |
| 14 | ||
| 15 | > The current document is unable to create an element of the requested type (namespace: http://www.w3.org/2000/svg, name: flowRoot). | |
| 16 | ||
| 17 | This error is due to a version mismatch of the `flowRoot` element that Inkscape creates. | |
| 18 | ||
| 19 | ## Fix | |
| 20 | ||
| 21 | Resolve the issue by changing the SVG version number as follows: | |
| 22 | ||
| 23 | 1. Edit the vector graphics file using any text editor. | |
| 24 | 1. Find `version="1.1"` and change it to `version="1.2"`. | |
| 25 | 1. Save the file. | |
| 26 | ||
| 27 | The SVG will now appear inside the application; however, the text may appear as black blocks. | |
| 28 | ||
| 29 | # Black blocks | |
| 30 | ||
| 31 | Depending on how text is added to a vector graphic in Inkscape, the text may be inserted within an element called a `flowRoot`. Although Batik recognizes `flowRoot` for SVG version 1.2, it cannot fully interpret the contents. Black blocks are drawn instead of the text, such as those depicted in the following figure: | |
| 32 | ||
| 33 |  | |
| 34 | ||
| 35 | ## Fix | |
| 36 | ||
| 37 | Resolve the issue by "unflowing" all text elements as follows: | |
| 38 | ||
| 39 | 1. Start Inkscape. | |
| 40 | 1. Load the SVG file. | |
| 41 | 1. Select all the text elements. | |
| 42 | 1. Click **Text → Unflow**. | |
| 43 | ||
| 44 | The text may change size and position; recreate the text without dragging using the text tool. After all the text areas have been recreated, continue as follows: | |
| 45 | ||
| 46 | 1. Click **Edit → XML Editor**. | |
| 47 | 1. Expand the **XML Editor** to see more elements. | |
| 48 | 1. Delete all elements named `svg:flowRoot`. | |
| 49 | 1. Save the file. | |
| 50 | ||
| 51 | When the illustration is reloaded, the black blocks will have disappeared, but the text elements ignore any assigned colour. | |
| 52 | ||
| 53 | # Black text | |
| 54 | ||
| 55 | When an SVG `style` attribute contains a reference to `-inkscape-font-specification`, Batik ignores all values that follow said reference. This results in black text, such as: | |
| 56 | ||
| 57 |  | |
| 58 | ||
| 59 | ## Fix | |
| 60 | ||
| 61 | Resolve the issue of colourless text as follows: | |
| 62 | ||
| 63 | 1. Open the SVG file in a plain text editor. | |
| 64 | 1. Remove all references `-inkscape-font-specification:'<FONT>';`, including the trailing (or leading) semicolon. | |
| 65 | 1. Save the file. | |
| 66 | ||
| 67 | When the illustration is reloaded, the colours will have reappeared, such as: | |
| 68 | ||
| 69 |  | |
| 70 | ||
| 1 | 71 |
| 1 | *.class | |
| 1 | 2 |
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020 White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | # copy of this software and associated documentation files (the | |
| 6 | # "Software"), to deal in the Software without restriction, including | |
| 7 | # without limitation the rights to use, copy, modify, merge, publish, | |
| 8 | # distribute, sublicense, and/or sell copies of the Software, and to | |
| 9 | # permit persons to whom the Software is furnished to do so, subject to | |
| 10 | # the following conditions: | |
| 11 | # | |
| 12 | # The above copyright notice and this permission notice shall be included | |
| 13 | # in all copies or substantial portions of the Software. | |
| 14 | # | |
| 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 16 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| 18 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| 19 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
| 20 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
| 21 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | # ----------------------------------------------------------------------------- | |
| 23 | ||
| 24 | # ----------------------------------------------------------------------------- | |
| 25 | # This script introduces the editor and its purpose. | |
| 26 | # ----------------------------------------------------------------------------- | |
| 27 | import sys | |
| 28 | ||
| 29 | if not "../editor.sikuli" in sys.path: | |
| 30 | sys.path.append( "../editor.sikuli" ) | |
| 31 | ||
| 32 | from editor import * | |
| 33 | ||
| 34 | # --------------------------------------------------------------- | |
| 35 | # Fresh start | |
| 36 | # --------------------------------------------------------------- | |
| 37 | rm( app_home + "/variables.yaml" ) | |
| 38 | rm( app_home + "/untitled.md" ) | |
| 39 | rm( home + "/.scrivenvar" ) | |
| 40 | ||
| 41 | # --------------------------------------------------------------- | |
| 42 | # Wait for application to launch | |
| 43 | # --------------------------------------------------------------- | |
| 44 | openApp( "java -jar " + app_bin ) | |
| 45 | ||
| 46 | wait("1594187265140.png", 30) | |
| 47 | # --------------------------------------------------------------- | |
| 48 | # Introduction | |
| 49 | # --------------------------------------------------------------- | |
| 50 | set_typing_speed( 240 ) | |
| 51 | ||
| 52 | header( "What is this application?" ) | |
| 53 | typer( "Well, this application is a text editor that supports interpolated definitions, ") | |
| 54 | typer( "a few different text formats, real-time preview, spell check ") | |
| 55 | typer( "as you tipe" ) | |
| 56 | wait( 0.5 ) | |
| 57 | recur( 3, backspace ) | |
| 58 | typer( "ype, and R statements." ) | |
| 59 | paragraph() | |
| 60 | wait( 1 ) | |
| 61 | ||
| 62 | # --------------------------------------------------------------- | |
| 63 | # Definition demo | |
| 64 | # --------------------------------------------------------------- | |
| 65 | header( "What are definitions?" ) | |
| 66 | typer( "Watch. " ) | |
| 67 | wait( .5 ) | |
| 68 | ||
| 69 | # Focus the definition editor. | |
| 70 | click_create() | |
| 71 | recur( 4, tab ) | |
| 72 | ||
| 73 | wait( .5 ) | |
| 74 | rename_definition( "application" ) | |
| 75 | ||
| 76 | insert() | |
| 77 | rename_definition( "title" ) | |
| 78 | ||
| 79 | insert() | |
| 80 | rename_definition( "Scrivenvar" ) | |
| 81 | ||
| 82 | # Set focus to the text editor. | |
| 83 | tab() | |
| 84 | ||
| 85 | typer( "The left-hand pane contains a nested, folder-like structure of names " ) | |
| 86 | typer( "and values that are called *definitions*. " ) | |
| 87 | wait( .5 ) | |
| 88 | typer( "Such definitions can simplify updating documents. " ) | |
| 89 | wait( 1 ) | |
| 90 | ||
| 91 | edit_find( "this application" ) | |
| 92 | typer( "$application.title$" ) | |
| 93 | ||
| 94 | edit_find_next() | |
| 95 | typer( "$application.title$" ) | |
| 96 | ||
| 97 | type( Key.END, Key.CTRL ) | |
| 98 | ||
| 99 | typer( "The right-hand pane shows the result after having substituted definition " ) | |
| 100 | typer( "values into the document." ) | |
| 101 | wait( 2 ) | |
| 102 | paragraph() | |
| 103 | ||
| 104 | header( "What is interpolation?" ) | |
| 105 | typer( "Definition values can reference definition names. " ) | |
| 106 | wait( .5 ) | |
| 107 | typer( "The definition names act as placeholders. Substituting placeholders with " ) | |
| 108 | typer( "their defined value is called *interpolation*. Let's see how it works." ) | |
| 109 | wait( 2 ) | |
| 1 | 110 |
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020 White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | # copy of this software and associated documentation files (the | |
| 6 | # "Software"), to deal in the Software without restriction, including | |
| 7 | # without limitation the rights to use, copy, modify, merge, publish, | |
| 8 | # distribute, sublicense, and/or sell copies of the Software, and to | |
| 9 | # permit persons to whom the Software is furnished to do so, subject to | |
| 10 | # the following conditions: | |
| 11 | # | |
| 12 | # The above copyright notice and this permission notice shall be included | |
| 13 | # in all copies or substantial portions of the Software. | |
| 14 | # | |
| 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 16 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| 18 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| 19 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
| 20 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
| 21 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | # ----------------------------------------------------------------------------- | |
| 23 | ||
| 24 | # ----------------------------------------------------------------------------- | |
| 25 | # This script demonstrates how to use interpolated strings. | |
| 26 | # ----------------------------------------------------------------------------- | |
| 27 | import sys | |
| 28 | ||
| 29 | if not "../editor.sikuli" in sys.path: | |
| 30 | sys.path.append( "../editor.sikuli" ) | |
| 31 | ||
| 32 | from editor import * | |
| 33 | ||
| 34 | # ----------------------------------------------------------------------------- | |
| 35 | # Open sample chapter. | |
| 36 | # ----------------------------------------------------------------------------- | |
| 37 | file_open() | |
| 38 | type( Key.UP, Key.ALT ) | |
| 39 | wait( 1 ) | |
| 40 | typer( Key.END ) | |
| 41 | wait( 1 ) | |
| 42 | enter() | |
| 43 | wait( 0.5 ) | |
| 44 | enter() | |
| 45 | wait( 1 ) | |
| 46 | ||
| 47 | # ----------------------------------------------------------------------------- | |
| 48 | # Open the corresponding definition file. | |
| 49 | # ----------------------------------------------------------------------------- | |
| 50 | file_open() | |
| 51 | recur( 2, down ) | |
| 52 | wait( 1 ) | |
| 53 | enter() | |
| 54 | wait( 1 ) | |
| 55 | ||
| 56 | # ----------------------------------------------------------------------------- | |
| 57 | # Edit the sample document. | |
| 58 | # ----------------------------------------------------------------------------- | |
| 59 | set_typing_speed( 80 ) | |
| 60 | ||
| 61 | type( Key.HOME, Key.CTRL ) | |
| 62 | recur( 2, down ) | |
| 63 | ||
| 64 | # Grey | |
| 65 | recur( 3, skip_right ) | |
| 66 | autoinsert() | |
| 67 | ||
| 68 | # 34 | |
| 69 | recur( 4, skip_right ) | |
| 70 | autoinsert() | |
| 71 | ||
| 72 | # Central | |
| 73 | recur( 10, skip_right ) | |
| 74 | autoinsert() | |
| 75 | ||
| 76 | # London | |
| 77 | skip_right() | |
| 78 | autoinsert() | |
| 79 | ||
| 80 | # Hatchery | |
| 81 | skip_right() | |
| 82 | autoinsert() | |
| 83 | ||
| 84 | # and Conditioning | |
| 85 | recur( 2, select_word_right ) | |
| 86 | delete() | |
| 87 | ||
| 88 | # Centre | |
| 89 | skip_right() | |
| 90 | autoinsert() | |
| 91 | ||
| 92 | set_typing_speed( 220 ) | |
| 93 | ||
| 94 | typer( " Let's interpolate those four definitions instead!" ) | |
| 95 | wait( 4 ) | |
| 96 | recur( 13, type, Key.BACKSPACE, Key.CTRL ) | |
| 97 | recur( 9, backspace ) | |
| 98 | ||
| 99 | set_typing_speed( 60 ) | |
| 100 | ||
| 101 | typer( "name$" ) | |
| 102 | wait( 2 ) | |
| 103 | ||
| 104 | # Collapse all definitions | |
| 105 | tab() | |
| 106 | recur( 8, typer, Key.LEFT ) | |
| 107 | ||
| 108 | # Expand to city | |
| 109 | recur( 4, typer, Key.RIGHT ) | |
| 110 | ||
| 111 | # Jump to name | |
| 112 | recur( 2, down ) | |
| 113 | recur( 2, typer, Key.RIGHT ) | |
| 114 | ||
| 115 | # Open the text field to show the full value | |
| 116 | typer( Key.F2 ) | |
| 117 | ||
| 118 | # Traverse the text field | |
| 119 | home() | |
| 120 | recur( 16, type, Key.RIGHT, Key.CTRL ) | |
| 121 | esc() | |
| 122 | ||
| 123 | restore_typing_speed() | |
| 124 | ||
| 125 | tab() | |
| 126 | type( Key.HOME, Key.CTRL ) | |
| 127 | edit_find( "Director" ) | |
| 128 | autoinsert() | |
| 129 | ||
| 130 | edit_find_next() | |
| 131 | autoinsert() | |
| 132 | ||
| 133 | edit_find_next() | |
| 134 | typer( Key.RIGHT ) | |
| 135 | recur( 2, delete ) | |
| 136 | autoinsert() | |
| 137 | typer( "'s" ) | |
| 138 | ||
| 139 | edit_find( "Hatcheries" ) | |
| 140 | autoinsert() | |
| 141 | ||
| 142 | # and Conditioning | |
| 143 | recur( 2, select_word_right ) | |
| 144 | delete() | |
| 145 | ||
| 146 | edit_find( "Central" ) | |
| 147 | autoinsert() | |
| 148 | ||
| 149 | skip_right() | |
| 150 | autoinsert() | |
| 151 | ||
| 152 | typer( " How about a different city?" ) | |
| 153 | wait( 2 ) | |
| 154 | recur( 5, type, Key.BACKSPACE, Key.CTRL ) | |
| 155 | wait( 1 ) | |
| 156 | tab() | |
| 157 | typer( Key.F2 ) | |
| 158 | typer( "Seattle" ) | |
| 159 | enter() | |
| 160 | tab() | |
| 161 | wait( 2 ) | |
| 162 | ||
| 163 | type( Key.END, Key.CTRL ) | |
| 164 | paragraph() | |
| 165 | typer( "No?" ) | |
| 166 | paragraph() | |
| 167 | ||
| 168 | tab() | |
| 169 | typer( Key.F2 ) | |
| 170 | typer( "London" ) | |
| 171 | enter() | |
| 172 | ||
| 173 | tab() | |
| 174 | typer( "Organizing definitions is left to your ") | |
| 175 | typer( "doub" ) | |
| 176 | wait( .25 ) | |
| 177 | autoinsert() | |
| 178 | wait( 1 ) | |
| 179 | typer( " Good imagination." ) | |
| 180 | tab() | |
| 181 | ||
| 182 | # Jump to "char" definition | |
| 183 | home() | |
| 184 | ||
| 185 | # Jump to "char.a.primary.name" definition | |
| 186 | recur( 6, typer, Key.RIGHT ) | |
| 187 | ||
| 188 | # Jump to "char.a.primary.caste" definition | |
| 189 | down() | |
| 190 | typer( Key.RIGHT ) | |
| 191 | ||
| 192 | # Jump to root-level "caste" definition | |
| 193 | recur( 7, down ) | |
| 194 | ||
| 195 | # Reselect "super" | |
| 196 | recur( 5, typer, Key.RIGHT ) | |
| 197 | wait( 2 ) | |
| 198 | ||
| 199 | # Close the window, no save | |
| 200 | type( "w", Key.CTRL ) | |
| 201 | wait( 0.5 ) | |
| 202 | tab() | |
| 203 | wait( 0.5 ) | |
| 204 | typer( Key.SPACE ) | |
| 205 | wait( 1 ) | |
| 1 | 206 |
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020 White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | # copy of this software and associated documentation files (the | |
| 6 | # "Software"), to deal in the Software without restriction, including | |
| 7 | # without limitation the rights to use, copy, modify, merge, publish, | |
| 8 | # distribute, sublicense, and/or sell copies of the Software, and to | |
| 9 | # permit persons to whom the Software is furnished to do so, subject to | |
| 10 | # the following conditions: | |
| 11 | # | |
| 12 | # The above copyright notice and this permission notice shall be included | |
| 13 | # in all copies or substantial portions of the Software. | |
| 14 | # | |
| 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 16 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| 18 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| 19 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
| 20 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
| 21 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | # ----------------------------------------------------------------------------- | |
| 23 | ||
| 24 | # ----------------------------------------------------------------------------- | |
| 25 | # This script introduces images and R. | |
| 26 | # ----------------------------------------------------------------------------- | |
| 27 | import sys | |
| 28 | ||
| 29 | if not "../editor.sikuli" in sys.path: | |
| 30 | sys.path.append( "../editor.sikuli" ) | |
| 31 | ||
| 32 | from editor import * | |
| 33 | ||
| 34 | set_typing_speed( 80 ) | |
| 35 | file_open() | |
| 36 | type( Key.UP, Key.ALT ) | |
| 37 | wait( 0.5 ) | |
| 38 | home() | |
| 39 | wait( 0.25 ) | |
| 40 | enter() | |
| 41 | wait( 1 ) | |
| 42 | end() | |
| 43 | wait( 0.25 ) | |
| 44 | enter() | |
| 45 | wait( 1 ) | |
| 46 | ||
| 47 | set_typing_speed( 200 ) | |
| 48 | ||
| 49 | paragraph() | |
| 50 | header( "What text formats are supported?" ) | |
| 51 | ||
| 52 | typer( "Scr" ) | |
| 53 | autoinsert() | |
| 54 | typer( " supports Markdown, R Markdown, XML, and R XML; however, the software " ) | |
| 55 | typer( "architecture enables it to easily add new formats. The following figure " ) | |
| 56 | typer( "depicts the overall architecture: " ) | |
| 57 | paragraph() | |
| 58 | typer( "" ) | |
| 59 | paragraph() | |
| 60 | typer( "Most text editors read a single format and convert it to one other format. " ) | |
| 61 | typer( "With a little more effort, text editors can support many input and output " ) | |
| 62 | typer( "formats. Scr" ) | |
| 63 | autoinsert() | |
| 64 | typer( " goes one step further by introducing interpolated definitions." ) | |
| 65 | paragraph() | |
| 66 | typer( "Kitten interlude:" ) | |
| 67 | paragraph() | |
| 68 | typer( "" ) | |
| 69 | paragraph() | |
| 70 | ||
| 71 | header( "What is R?" ) | |
| 72 | typer( "R is a programming language. You might have noticed a few potential grammar " ) | |
| 73 | typer( "problems with direct substitution. Rules for possessive forms, numbers, and " ) | |
| 74 | typer( "other linguistic exceptions can be addressed using R. Let's take a look!" ) | |
| 1 | 75 |
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020 White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | # copy of this software and associated documentation files (the | |
| 6 | # "Software"), to deal in the Software without restriction, including | |
| 7 | # without limitation the rights to use, copy, modify, merge, publish, | |
| 8 | # distribute, sublicense, and/or sell copies of the Software, and to | |
| 9 | # permit persons to whom the Software is furnished to do so, subject to | |
| 10 | # the following conditions: | |
| 11 | # | |
| 12 | # The above copyright notice and this permission notice shall be included | |
| 13 | # in all copies or substantial portions of the Software. | |
| 14 | # | |
| 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 16 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| 18 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| 19 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
| 20 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
| 21 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | # ----------------------------------------------------------------------------- | |
| 23 | ||
| 24 | # ----------------------------------------------------------------------------- | |
| 25 | # This script demonstrates using R. | |
| 26 | # ----------------------------------------------------------------------------- | |
| 27 | import sys | |
| 28 | ||
| 29 | if not "../editor.sikuli" in sys.path: | |
| 30 | sys.path.append( "../editor.sikuli" ) | |
| 31 | ||
| 32 | from editor import * | |
| 33 | ||
| 34 | # ----------------------------------------------------------------------------- | |
| 35 | # Open the demo text. | |
| 36 | # ----------------------------------------------------------------------------- | |
| 37 | file_open() | |
| 38 | type( Key.UP, Key.ALT ) | |
| 39 | wait( 0.5 ) | |
| 40 | end() | |
| 41 | wait( 0.25 ) | |
| 42 | enter() | |
| 43 | wait( 0.5 ) | |
| 44 | down() | |
| 45 | wait( 0.25 ) | |
| 46 | enter() | |
| 47 | wait( 1 ) | |
| 48 | ||
| 49 | # ----------------------------------------------------------------------------- | |
| 50 | # Demo bootstrapping | |
| 51 | # ----------------------------------------------------------------------------- | |
| 52 | ||
| 53 | # Jump to the end. | |
| 54 | type( Key.END, Key.CTRL ) | |
| 55 | paragraph() | |
| 56 | ||
| 57 | type( "s", Key.CTRL + Key.ALT ) | |
| 58 | wait( 0.25 ) | |
| 59 | ||
| 60 | ||
| 61 | # ----------------------------------------------------------------------------- | |
| 62 | # Demo pluralization | |
| 63 | # ----------------------------------------------------------------------------- | |
| 64 | ||
| 65 | ||
| 66 | # ----------------------------------------------------------------------------- | |
| 67 | # Demo possessives (it, she, he, Ross) | |
| 68 | # ----------------------------------------------------------------------------- | |
| 69 | ||
| 70 | ||
| 71 | # ----------------------------------------------------------------------------- | |
| 72 | # Demo conversion, including ordinal numbers | |
| 73 | # ----------------------------------------------------------------------------- | |
| 74 | ||
| 75 | # ----------------------------------------------------------------------------- | |
| 76 | # Demo Chicago Manual of Style | |
| 77 | # ----------------------------------------------------------------------------- | |
| 78 | ||
| 79 | ||
| 80 | # ----------------------------------------------------------------------------- | |
| 81 | # Demo CSV file import | |
| 82 | # ----------------------------------------------------------------------------- | |
| 83 | ||
| 84 | ||
| 1 | 85 |
| 1 | # ----------------------------------------------------------------------------- | |
| 2 | # Copyright 2020 White Magic Software, Ltd. | |
| 3 | # | |
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 | # copy of this software and associated documentation files (the | |
| 6 | # "Software"), to deal in the Software without restriction, including | |
| 7 | # without limitation the rights to use, copy, modify, merge, publish, | |
| 8 | # distribute, sublicense, and/or sell copies of the Software, and to | |
| 9 | # permit persons to whom the Software is furnished to do so, subject to | |
| 10 | # the following conditions: | |
| 11 | # | |
| 12 | # The above copyright notice and this permission notice shall be included | |
| 13 | # in all copies or substantial portions of the Software. | |
| 14 | # | |
| 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 16 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 17 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| 18 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| 19 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
| 20 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
| 21 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 22 | # ----------------------------------------------------------------------------- | |
| 23 | ||
| 24 | # ----------------------------------------------------------------------------- | |
| 25 | # This script contains helper functions used by the other scripts. | |
| 26 | # | |
| 27 | # Do not run this script. | |
| 28 | # ----------------------------------------------------------------------------- | |
| 29 | ||
| 30 | from sikuli import * | |
| 31 | import sys | |
| 32 | import os | |
| 33 | from os.path import expanduser | |
| 34 | ||
| 35 | home = expanduser( "~" ) | |
| 36 | app_home = home + "/bin" | |
| 37 | app_bin = app_home + "/scrivenvar.jar" | |
| 38 | ||
| 39 | wpm_default_speed = 80 | |
| 40 | wpm_typing_speed = wpm_default_speed | |
| 41 | ||
| 42 | # ----------------------------------------------------------------------------- | |
| 43 | # Try to delete the file pointed to by the path variable. If there is no such | |
| 44 | # file, this will silently ignore the exception. | |
| 45 | # ----------------------------------------------------------------------------- | |
| 46 | def rm( path ): | |
| 47 | try: | |
| 48 | os.remove( path ) | |
| 49 | except: | |
| 50 | print "Ignored" | |
| 51 | ||
| 52 | # ----------------------------------------------------------------------------- | |
| 53 | # Changes the current typing speed, where speed is given in words per minute. | |
| 54 | # ----------------------------------------------------------------------------- | |
| 55 | def set_typing_speed( wpm ): | |
| 56 | global wpm_typing_speed | |
| 57 | wpm_typing_speed = wpm | |
| 58 | ||
| 59 | def restore_typing_speed(): | |
| 60 | set_typing_speed( wpm_default_speed ) | |
| 61 | ||
| 62 | # ----------------------------------------------------------------------------- | |
| 63 | # Creates a delay between keystrokes to emulate typing at a particular speed. | |
| 64 | # ----------------------------------------------------------------------------- | |
| 65 | def random_wait(): | |
| 66 | from time import sleep | |
| 67 | from random import uniform | |
| 68 | cpm = wpm_typing_speed * 5.1 | |
| 69 | cps = cpm / 60.0 | |
| 70 | ms_per_char = 1000.0 / cps | |
| 71 | ms_per_stroke = ms_per_char / 2.0 | |
| 72 | ||
| 73 | noise = uniform( 0, ms_per_stroke / 2 ) | |
| 74 | duration = (ms_per_stroke + noise ) / 1000 | |
| 75 | ||
| 76 | sleep( duration ) | |
| 77 | ||
| 78 | # ----------------------------------------------------------------------------- | |
| 79 | # Repeats a function call, f, n times. | |
| 80 | # ----------------------------------------------------------------------------- | |
| 81 | def recur( n, f, *args ): | |
| 82 | for i in range( n ): | |
| 83 | f(*args) | |
| 84 | random_wait() | |
| 85 | ||
| 86 | # ----------------------------------------------------------------------------- | |
| 87 | # Emulate a typist who is typing in the given text. | |
| 88 | # ----------------------------------------------------------------------------- | |
| 89 | def typer( text ): | |
| 90 | # ~25 is a reasonably realistic, fast typist. | |
| 91 | for c in text: | |
| 92 | type( c ) | |
| 93 | random_wait() | |
| 94 | ||
| 95 | # ----------------------------------------------------------------------------- | |
| 96 | # Injects a definition. | |
| 97 | # ----------------------------------------------------------------------------- | |
| 98 | def autoinsert(): | |
| 99 | type( Key.SPACE, Key.CTRL ) | |
| 100 | random_wait() | |
| 101 | ||
| 102 | # ----------------------------------------------------------------------------- | |
| 103 | # Types the TAB key. | |
| 104 | # ----------------------------------------------------------------------------- | |
| 105 | def tab(): | |
| 106 | typer( Key.TAB ) | |
| 107 | ||
| 108 | # ----------------------------------------------------------------------------- | |
| 109 | # Types the ENTER key. | |
| 110 | # ----------------------------------------------------------------------------- | |
| 111 | def enter(): | |
| 112 | typer( Key.ENTER ) | |
| 113 | ||
| 114 | # ----------------------------------------------------------------------------- | |
| 115 | # Types the ESC key. | |
| 116 | # ----------------------------------------------------------------------------- | |
| 117 | def esc(): | |
| 118 | typer( Key.ESC ) | |
| 119 | ||
| 120 | # ----------------------------------------------------------------------------- | |
| 121 | # Types the DOWN arrow key. | |
| 122 | # ----------------------------------------------------------------------------- | |
| 123 | def down(): | |
| 124 | typer( Key.DOWN ) | |
| 125 | ||
| 126 | # ----------------------------------------------------------------------------- | |
| 127 | # Types the HOME key. | |
| 128 | # ----------------------------------------------------------------------------- | |
| 129 | def home(): | |
| 130 | typer( Key.HOME ) | |
| 131 | ||
| 132 | # ----------------------------------------------------------------------------- | |
| 133 | # Types the END key. | |
| 134 | # ----------------------------------------------------------------------------- | |
| 135 | def end(): | |
| 136 | typer( Key.END ) | |
| 137 | ||
| 138 | # ----------------------------------------------------------------------------- | |
| 139 | # Types the BACKSPACE key. | |
| 140 | # ----------------------------------------------------------------------------- | |
| 141 | def backspace(): | |
| 142 | typer( Key.BACKSPACE ) | |
| 143 | ||
| 144 | # ----------------------------------------------------------------------------- | |
| 145 | # Types the INSERT key, often to insert a new definition. | |
| 146 | # ----------------------------------------------------------------------------- | |
| 147 | def insert(): | |
| 148 | typer( Key.INSERT ) | |
| 149 | ||
| 150 | # ----------------------------------------------------------------------------- | |
| 151 | # Types the DELETE key, often to remove selected text. | |
| 152 | # ----------------------------------------------------------------------------- | |
| 153 | def delete(): | |
| 154 | typer( Key.DELETE ) | |
| 155 | ||
| 156 | # ----------------------------------------------------------------------------- | |
| 157 | # Moves the cursor one word to the right. | |
| 158 | # ----------------------------------------------------------------------------- | |
| 159 | def skip_right(): | |
| 160 | type( Key.RIGHT, Key.CTRL ) | |
| 161 | random_wait() | |
| 162 | ||
| 163 | def select_word_right(): | |
| 164 | type( Key.RIGHT, Key.CTRL + Key.SHIFT ) | |
| 165 | random_wait() | |
| 166 | ||
| 167 | # ----------------------------------------------------------------------------- | |
| 168 | # Types ENTER twice to begin a new paragraph. | |
| 169 | # ----------------------------------------------------------------------------- | |
| 170 | def paragraph(): | |
| 171 | recur( 2, enter ) | |
| 172 | wait( 1.5 ) | |
| 173 | ||
| 174 | # ----------------------------------------------------------------------------- | |
| 175 | # Writes a heading to the document using the given text value as the content. | |
| 176 | # ----------------------------------------------------------------------------- | |
| 177 | def header( text ): | |
| 178 | typer( "# " + text ) | |
| 179 | paragraph() | |
| 180 | ||
| 181 | # ----------------------------------------------------------------------------- | |
| 182 | # Clicks the "Create" button to add a new definition. | |
| 183 | # ----------------------------------------------------------------------------- | |
| 184 | def click_create(): | |
| 185 | click("1594187923258.png") | |
| 186 | wait( .5 ) | |
| 187 | ||
| 188 | # ----------------------------------------------------------------------------- | |
| 189 | # Changes the text for the actively selected definition. | |
| 190 | # ----------------------------------------------------------------------------- | |
| 191 | def rename_definition( text ): | |
| 192 | typer( Key.F2 ) | |
| 193 | typer( text ) | |
| 194 | enter() | |
| 195 | wait( .5 ) | |
| 196 | ||
| 197 | # ----------------------------------------------------------------------------- | |
| 198 | # Searches for the given text within the document. | |
| 199 | # ----------------------------------------------------------------------------- | |
| 200 | def edit_find( text ): | |
| 201 | type( "f", Key.CTRL ) | |
| 202 | typer( text ) | |
| 203 | enter() | |
| 204 | wait( .25 ) | |
| 205 | esc() | |
| 206 | wait( .5 ) | |
| 207 | ||
| 208 | # ----------------------------------------------------------------------------- | |
| 209 | # Searches for the next occurrence of the previous search term. | |
| 210 | # ----------------------------------------------------------------------------- | |
| 211 | def edit_find_next(): | |
| 212 | typer( Key.F3 ) | |
| 213 | wait( .5 ) | |
| 214 | ||
| 215 | # ----------------------------------------------------------------------------- | |
| 216 | # Opens a dialog for selecting a file. | |
| 217 | # ----------------------------------------------------------------------------- | |
| 218 | def file_open(): | |
| 219 | type( "o", Key.CTRL ) | |
| 220 | wait( 1 ) | |
| 1 | 221 |
| 1106 | 1106 | .build(); |
| 1107 | 1107 | |
| 1108 | // Number of header actions (H1 ... H3) | |
| 1109 | final int HEADERS = 3; | |
| 1110 | final Action[] headers = new Action[ HEADERS ]; | |
| 1108 | // Number of heading actions (H1 ... H3) | |
| 1109 | final int HEADINGS = 3; | |
| 1110 | final Action[] headings = new Action[ HEADINGS ]; | |
| 1111 | 1111 | |
| 1112 | for( int i = 1; i <= HEADERS; i++ ) { | |
| 1112 | for( int i = 1; i <= HEADINGS; i++ ) { | |
| 1113 | 1113 | final String hashes = new String( new char[ i ] ).replace( "\0", "#" ); |
| 1114 | 1114 | final String markup = String.format( "%n%n%s ", hashes ); |
| 1115 | final String text = "Main.menu.insert.header." + i; | |
| 1115 | final String text = "Main.menu.insert.heading." + i; | |
| 1116 | 1116 | final String accelerator = "Shortcut+" + i; |
| 1117 | 1117 | final String prompt = text + ".prompt"; |
| 1118 | 1118 | |
| 1119 | headers[ i - 1 ] = new ActionBuilder() | |
| 1119 | headings[ i - 1 ] = new ActionBuilder() | |
| 1120 | 1120 | .setText( text ) |
| 1121 | 1121 | .setAccelerator( accelerator ) |
| ... | ||
| 1201 | 1201 | insertImageAction, |
| 1202 | 1202 | null, |
| 1203 | headers[ 0 ], | |
| 1204 | headers[ 1 ], | |
| 1205 | headers[ 2 ], | |
| 1203 | headings[ 0 ], | |
| 1204 | headings[ 1 ], | |
| 1205 | headings[ 2 ], | |
| 1206 | 1206 | null, |
| 1207 | 1207 | insertUnorderedListAction, |
| ... | ||
| 1243 | 1243 | insertImageAction, |
| 1244 | 1244 | null, |
| 1245 | headers[ 0 ], | |
| 1245 | headings[ 0 ], | |
| 1246 | 1246 | null, |
| 1247 | 1247 | insertUnorderedListAction, |
| 161 | 161 | * rendering on some platforms. |
| 162 | 162 | */ |
| 163 | private final static String HTML_HEADER = "<!DOCTYPE html>" | |
| 163 | private final static String HTML_PREFIX = "<!DOCTYPE html>" | |
| 164 | 164 | + "<html>" |
| 165 | 165 | + "<head>" |
| 166 | 166 | + "<link rel='stylesheet' href='" + |
| 167 | 167 | HTMLPreviewPane.class.getResource( STYLESHEET_PREVIEW ) + "'/>" |
| 168 | 168 | + "</head>" |
| 169 | 169 | + "<body>"; |
| 170 | 170 | |
| 171 | 171 | // Provide some extra space at the end for scrolling past the last line. |
| 172 | private final static String HTML_FOOTER = | |
| 172 | private final static String HTML_SUFFIX = | |
| 173 | 173 | "<p style='height=2em'> </p></body></html>"; |
| 174 | 174 | |
| ... | ||
| 195 | 195 | setStyle( "-fx-background-color: white;" ); |
| 196 | 196 | |
| 197 | // No need to append the header each time the HTML content is updated. | |
| 198 | mHtmlDocument.append( HTML_HEADER ); | |
| 197 | // No need to append same prefix each time the HTML content is updated. | |
| 198 | mHtmlDocument.append( HTML_PREFIX ); | |
| 199 | 199 | mHtmlPrefixLength = mHtmlDocument.length(); |
| 200 | 200 | |
| ... | ||
| 340 | 340 | |
| 341 | 341 | private String decorate( final String html ) { |
| 342 | // Trim the HTML back to the header. | |
| 342 | // Trim the HTML back to only the prefix. | |
| 343 | 343 | mHtmlDocument.setLength( mHtmlPrefixLength ); |
| 344 | 344 | |
| 345 | 345 | // Write the HTML body element followed by closing tags. |
| 346 | 346 | return mHtmlDocument.append( html ) |
| 347 | .append( HTML_FOOTER ) | |
| 347 | .append( HTML_SUFFIX ) | |
| 348 | 348 | .toString(); |
| 349 | 349 | } |
| 41 | 41 | Main.menu.insert.link=Link... |
| 42 | 42 | Main.menu.insert.image=Image... |
| 43 | Main.menu.insert.header.1=Header 1 | |
| 44 | Main.menu.insert.header.1.prompt=header 1 | |
| 45 | Main.menu.insert.header.2=Header 2 | |
| 46 | Main.menu.insert.header.2.prompt=header 2 | |
| 47 | Main.menu.insert.header.3=Header 3 | |
| 48 | Main.menu.insert.header.3.prompt=header 3 | |
| 43 | Main.menu.insert.heading.1=Heading 1 | |
| 44 | Main.menu.insert.heading.1.prompt=heading 1 | |
| 45 | Main.menu.insert.heading.2=Heading 2 | |
| 46 | Main.menu.insert.heading.2.prompt=heading 2 | |
| 47 | Main.menu.insert.heading.3=Heading 3 | |
| 48 | Main.menu.insert.heading.3.prompt=heading 3 | |
| 49 | 49 | Main.menu.insert.unordered_list=Unordered List |
| 50 | 50 | Main.menu.insert.ordered_list=Ordered List |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | /* HEADERS ***/ | |
| 29 | /* HEADINGS ***/ | |
| 30 | 30 | h1, h2, h3, h4, h5, h6 { |
| 31 | 31 | font-weight: bold; |