Dave Jarvis' Repositories

M .gitattributes
1111
#   Disable line ending normalize on checkin.
1212
13
*.blend binary
14
1315
*.bin binary
16
*.bmp binary
17
*.eps binary
1418
*.exe binary
1519
*.gif binary
1620
*.jar binary
21
*.jpg binary
22
*.mng binary
1723
*.png binary
1824
*.zip binary
19
*.ttf binary
2025
*.otf binary
21
*.blend binary
26
*.ttf binary
2227
2328
M .gitignore
1010
.classpath
1111
.idea
12
themes
1213
M BUILD.md
77
Download and install the following software packages:
88
9
* [OpenJDK 14.0.2](https://openjdk.java.net) (full JDK, including JavaFX)
10
* [Gradle 6.4](https://gradle.org/releases)
9
* [JDK 16](https://bell-sw.com/pages/downloads/?version=java-16) (Full JDK + JavaFX)
10
* [Gradle 7.0](https://services.gradle.org/distributions)
1111
* [Git 2.28.0](https://git-scm.com/downloads)
1212
...
3232
After the application is compiled, run it as follows:
3333
34
    java -jar build/libs/keenwrite.jar
34
    java --illegal-access=permit -jar build/libs/keenwrite.jar
3535
3636
On Windows:
3737
38
    java -jar build\libs\keenwrite.jar
38
    java --illegal-access=permit -jar build\libs\keenwrite.jar
3939
4040
# Integrated development environments
...
5959
The project is imported into the IDE.
6060
61
### Run
61
### Configure
6262
63
Run the application as follows:
63
Configure the IDE to run the application as follows:
6464
65
1. Ensure the **Project** is open.
66
1. Expand **src → main → java → com.keenwrite**.
67
1. Open **Launcher**.
68
1. Run **main**.
65
1. Click **Run → Edit Configurations**.
66
1. Click **+** to add a new configuration.
67
1. Set **Name** to: KeenWrite
68
1. Click **Modify Options → Add VM options**.
69
1. Set **VM options** field to: `--illegal-access=permit`
70
1. Click **OK** close the dialog.
6971
70
The application is launched.
72
The changes should resemble:
73
74
![Run Configuration](docs/images/app-ide.png)
75
76
### Run
77
78
Click **Run → KeenWrite** to launch the application.
7179
7280
# Installers
D PROGUARD.md
1
From https://github.com/greenrobot/EventBus#r8-proguard
2
3
	-keepattributes *Annotation*
4
	-keepclassmembers class * {
5
			@org.greenrobot.eventbus.Subscribe <methods>;
6
	}
7
	-keep enum org.greenrobot.eventbus.ThreadMode { *; }
8
	 
91
M README.md
3636
### Other
3737
38
Download and install a full version of [OpenJDK 15](https://bell-sw.com/pages/downloads/?version=java-15#mn) that includes JavaFX module support, then run:
38
Download and install a full version of [JDK 15](https://bell-sw.com/pages/downloads/?version=java-15) that includes JavaFX module support, then run:
3939
4040
``` bash
...
5252
* Real-time document statistics (with CJK word separation)
5353
* Diagrams: Mermaid, GraphViz, UML, sequence, timing, and more
54
* Dark, custom, and responsive themes
54
* Dark, custom, and responsive user interface skins
5555
* Integrated file manager
5656
* Interactive document outline
5757
* Internationalized font support (e.g., Chinese, Japanese, Korean, etc.)
58
* Support for Pandoc's fenced div extended attribute syntax
5859
* R integration
5960
* XML transformation using XSLT3 or older
6061
* Customizable user interface having detachable tabs
6162
* Platform-independent (Windows, Linux, MacOS)
6263
6364
## Usage
6465
6566
Read the [detailed documentation](docs/README.md) for using the application.
6667
67
### Themes
68
### Skins
6869
69
Read the [themes documentation](docs/themes.md) to learn about themes.
70
Read the [skins documentation](docs/skins.md) to learn about how to change
71
the user interface appearance.
7072
7173
## Screenshots
D build-template
1
#!/usr/bin/env bash
2
3
# -----------------------------------------------------------------------------
4
# Copyright 2020 Dave Jarvis
5
#
6
# Permission is hereby granted, free of charge, to any person obtaining a
7
# copy of this software and associated documentation files (the
8
# "Software"), to deal in the Software without restriction, including
9
# without limitation the rights to use, copy, modify, merge, publish,
10
# distribute, sublicense, and/or sell copies of the Software, and to
11
# permit persons to whom the Software is furnished to do so, subject to
12
# the following conditions:
13
#
14
# The above copyright notice and this permission notice shall be included
15
# in all copies or substantial portions of the Software.
16
#
17
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
# -----------------------------------------------------------------------------
25
26
set -o errexit
27
set -o nounset
28
29
readonly SCRIPT_SRC="$(dirname "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}")"
30
readonly SCRIPT_DIR="$(cd "${SCRIPT_SRC}" >/dev/null 2>&1 && pwd)"
31
readonly SCRIPT_NAME=$(basename "$0")
32
33
# -----------------------------------------------------------------------------
34
# The main entry point is responsible for parsing command-line arguments,
35
# changing to the appropriate directory, and running all commands requested
36
# by the user.
37
#
38
# $@ - Command-line arguments
39
# -----------------------------------------------------------------------------
40
main() {
41
  arguments "$@"
42
43
  $usage       && terminate 3
44
  requirements && terminate 4
45
  traps        && terminate 5
46
47
  directory    && terminate 6
48
  preprocess   && terminate 7
49
  execute      && terminate 8
50
  postprocess  && terminate 9
51
52
  terminate 0
53
}
54
55
# -----------------------------------------------------------------------------
56
# Perform all commands that the script requires.
57
#
58
# @return 0 - Indicate to terminate the script with non-zero exit level
59
# @return 1 - All tasks completed successfully (default)
60
# -----------------------------------------------------------------------------
61
execute() {
62
  return 1
63
}
64
65
# -----------------------------------------------------------------------------
66
# Changes to the script's working directory, provided it exists.
67
#
68
# @return 0 - Change directory failed
69
# @return 1 - Change directory succeeded
70
# -----------------------------------------------------------------------------
71
directory() {
72
  $log "Change directory"
73
  local result=1
74
75
  # Track whether change directory failed.
76
  cd "${SCRIPT_DIR}" > /dev/null 2>&1 || result=0
77
78
  return "${result}"
79
}
80
81
# -----------------------------------------------------------------------------
82
# Perform any initialization required prior to executing tasks.
83
#
84
# @return 0 - Preprocessing failed
85
# @return 1 - Preprocessing succeeded
86
# -----------------------------------------------------------------------------
87
preprocess() {
88
  $log "Preprocess"
89
90
  return 1
91
}
92
93
# -----------------------------------------------------------------------------
94
# Perform any clean up required prior to executing tasks.
95
#
96
# @return 0 - Postprocessing failed
97
# @return 1 - Postprocessing succeeded
98
# -----------------------------------------------------------------------------
99
postprocess() {
100
  $log "Postprocess"
101
102
  return 1
103
}
104
105
# -----------------------------------------------------------------------------
106
# Check that all required commands are available.
107
#
108
# @return 0 - At least one command is missing
109
# @return 1 - All commands are available
110
# -----------------------------------------------------------------------------
111
requirements() {
112
  $log "Verify requirements"
113
  local -r expected_count=${#DEPENDENCIES[@]}
114
  local total_count=0
115
116
  # Verify that each command exists.
117
  for dependency in "${DEPENDENCIES[@]}"; do
118
    # Extract the command name [0] and URL [1].
119
    IFS=',' read -ra dependent <<< "${dependency}"
120
121
    required "${dependent[0]}" "${dependent[1]}"
122
    total_count=$(( total_count + $? ))
123
  done
124
125
  unset IFS
126
127
  # Total dependencies found must match the expected number.
128
  # Integer-only division rounds down.
129
  return $(( total_count / expected_count ))
130
}
131
132
# -----------------------------------------------------------------------------
133
# Called before terminating the script.
134
# -----------------------------------------------------------------------------
135
cleanup() {
136
  $log "Cleanup"
137
}
138
139
# -----------------------------------------------------------------------------
140
# Terminates the program immediately.
141
# -----------------------------------------------------------------------------
142
trap_control_c() {
143
  $log "Interrupted"
144
  cleanup
145
  error "⯃"
146
  terminate 1
147
}
148
149
# -----------------------------------------------------------------------------
150
# Configure signal traps.
151
#
152
# @return 1 - Signal traps are set.
153
# -----------------------------------------------------------------------------
154
traps() {
155
  # Suppress echoing ^C if pressed.
156
  stty -echoctl
157
  trap trap_control_c INT
158
159
  return 1
160
}
161
162
# -----------------------------------------------------------------------------
163
# Check for a required command.
164
#
165
# $1 - Command or file to check for existence
166
# $2 - Command's website (e.g., download for binaries and source code)
167
#
168
# @return 0 - Command is missing
169
# @return 1 - Command exists
170
# -----------------------------------------------------------------------------
171
required() {
172
  local result=0
173
174
  test -f "$1" || \
175
  command -v "$1" > /dev/null 2>&1 && result=1 || \
176
    warning "Missing: $1 ($2)"
177
178
  return ${result}
179
}
180
181
# -----------------------------------------------------------------------------
182
# Show acceptable command-line arguments.
183
#
184
# @return 0 - Indicate script may not continue
185
# -----------------------------------------------------------------------------
186
utile_usage() {
187
  printf "Usage: %s [OPTIONS...]\n\n" "${SCRIPT_NAME}" >&2
188
189
  # Number of spaces to pad after the longest long argument.
190
  local -r PADDING=2
191
192
  # Determine the longest long argument to adjust spacing.
193
  local -r LEN=$(printf '%s\n' "${ARGUMENTS[@]}" | \
194
    awk -F"," '{print length($2)+'${PADDING}'}' | sort -n | tail -1)
195
196
  local duplicates
197
198
  for argument in "${ARGUMENTS[@]}"; do
199
    # Extract the short [0] and long [1] arguments and description [2].
200
    arg=("$(echo ${argument} | cut -d ',' -f1)" \
201
         "$(echo ${argument} | cut -d ',' -f2)" \
202
         "$(echo ${argument} | cut -d ',' -f3-)")
203
204
    duplicates+=("${arg[0]}")
205
206
    printf "  -%s, --%-${LEN}s%s\n" "${arg[0]}" "${arg[1]}" "${arg[2]}" >&2
207
  done
208
209
  # Sort the arguments to make sure no duplicates exist.
210
  duplicates=$(echo "${duplicates[@]}" | tr ' ' '\n' | sort | uniq -c -d)
211
212
  # Warn the developer that there's a duplicate command-line option.
213
  if [ -n "${duplicates}" ]; then
214
    # Trim all the whitespaces
215
    duplicates=$(echo "${duplicates}" | xargs echo -n)
216
    error "Duplicate command-line argument exists: ${duplicates}"
217
  fi
218
219
  return 0
220
}
221
222
# -----------------------------------------------------------------------------
223
# Write coloured text to standard output.
224
#
225
# $1 - Text to write
226
# $2 - Text's colour
227
# -----------------------------------------------------------------------------
228
coloured_text() {
229
  printf "%b%s%b\n" "$2" "$1" "${COLOUR_OFF}"
230
}
231
232
# -----------------------------------------------------------------------------
233
# Write a warning message to standard output.
234
#
235
# $1 - Text to write
236
# -----------------------------------------------------------------------------
237
warning() {
238
  coloured_text "$1" "${COLOUR_WARNING}"
239
}
240
241
# -----------------------------------------------------------------------------
242
# Write an error message to standard output.
243
#
244
# $1 - Text to write
245
# -----------------------------------------------------------------------------
246
error() {
247
  coloured_text "$1" "${COLOUR_ERROR}"
248
}
249
250
# -----------------------------------------------------------------------------
251
# Write a timestamp and message to standard output.
252
#
253
# $1 - Text to write
254
# -----------------------------------------------------------------------------
255
utile_log() {
256
  printf "[%s] " "$(date +%H:%M:%S.%4N)"
257
  coloured_text "$1" "${COLOUR_LOGGING}"
258
}
259
260
# -----------------------------------------------------------------------------
261
# Perform no operations.
262
#
263
# return 1 - Success
264
# -----------------------------------------------------------------------------
265
noop() {
266
  return 1
267
}
268
269
# -----------------------------------------------------------------------------
270
# Exit the program with a given exit code.
271
#
272
# $1 - Exit code
273
# -----------------------------------------------------------------------------
274
terminate() {
275
  exit "$1"
276
}
277
278
# -----------------------------------------------------------------------------
279
# Set global variables from command-line arguments.
280
# -----------------------------------------------------------------------------
281
arguments() {
282
  while [ "$#" -gt "0" ]; do
283
    local consume=1
284
285
    case "$1" in
286
      -V|--verbose)
287
        log=utile_log
288
      ;;
289
      -h|-\?|--help)
290
        usage=utile_usage
291
      ;;
292
      *)
293
        set +e
294
        argument "$@"
295
        consume=$?
296
        set -e
297
      ;;
298
    esac
299
300
    shift ${consume}
301
  done
302
}
303
304
# -----------------------------------------------------------------------------
305
# Parses a single command-line argument. This must return a value greater
306
# than or equal to 1, otherwise parsing the command-line arguments will
307
# loop indefinitely.
308
#
309
# @return The number of arguments to consume (1 by default).
310
# -----------------------------------------------------------------------------
311
argument() {
312
  return 1
313
}
314
315
# ANSI colour escape sequences.
316
readonly COLOUR_BLUE='\033[1;34m'
317
readonly COLOUR_PINK='\033[1;35m'
318
readonly COLOUR_DKGRAY='\033[30m'
319
readonly COLOUR_DKRED='\033[31m'
320
readonly COLOUR_LTRED='\033[1;31m'
321
readonly COLOUR_YELLOW='\033[1;33m'
322
readonly COLOUR_OFF='\033[0m'
323
324
# Colour definitions used by script.
325
COLOUR_LOGGING=${COLOUR_BLUE}
326
COLOUR_WARNING=${COLOUR_YELLOW}
327
COLOUR_ERROR=${COLOUR_LTRED}
328
329
# Define required commands to check when script starts.
330
DEPENDENCIES=(
331
  "awk,https://www.gnu.org/software/gawk/manual/gawk.html"
332
  "cut,https://www.gnu.org/software/coreutils"
333
)
334
335
# Define help for command-line arguments.
336
ARGUMENTS=(
337
  "V,verbose,Log messages while processing"
338
  "h,help,Show this help message then exit"
339
)
340
341
# These functions may be set to utile delegates while parsing arguments.
342
usage=noop
343
log=noop
344
3451
M build.gradle
11
plugins {
22
  id 'application'
3
  id 'org.openjfx.javafxplugin' version '0.0.9'
3
  id 'org.openjfx.javafxplugin' version '0.0.10'
44
  id 'com.palantir.git-version' version '0.12.3'
55
}
...
2828
  }
2929
}
30
31
def moduleSecurity = [
32
    "--add-opens=javafx.controls/javafx.scene.control=ALL-UNNAMED",
33
    "--add-opens=javafx.controls/javafx.scene.control.skin=ALL-UNNAMED",
34
    "--add-opens=javafx.graphics/javafx.scene.text=ALL-UNNAMED",
35
    "--add-opens=javafx.graphics/com.sun.javafx.css=ALL-UNNAMED",
36
    "--add-opens=javafx.graphics/com.sun.javafx.text=ALL-UNNAMED",
37
    "--add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED",
38
    "--add-exports=javafx.graphics/com.sun.javafx.application=ALL-UNNAMED",
39
    "--add-exports=javafx.graphics/com.sun.javafx.geom=ALL-UNNAMED",
40
    "--add-exports=javafx.graphics/com.sun.javafx.scene.traversal=ALL-UNNAMED",
41
    "--add-exports=javafx.graphics/com.sun.javafx.scene.traversal=ALL-UNNAMED",
42
    "--add-exports=javafx.graphics/com.sun.javafx.text=ALL-UNNAMED",
43
]
3044
3145
javafx {
32
  version = "15"
46
  version = "16"
3347
  modules = ['javafx.controls', 'javafx.swing']
3448
  configuration = 'compileOnly'
3549
}
3650
3751
dependencies {
38
  def v_junit = '5.5.2'
52
  def v_junit = '5.7.1'
3953
  def v_flexmark = '0.62.2'
40
  def v_jackson = '2.12.1'
54
  def v_jackson = '2.12.2'
4155
  def v_batik = '1.14'
56
  def v_wheatsheaf = '2.0.1'
4257
4358
  // JavaFX
44
  implementation 'org.controlsfx:controlsfx:11.0.3'
45
  implementation 'org.fxmisc.richtext:richtextfx:0.10.5'
59
  implementation 'org.controlsfx:controlsfx:11.1.0'
60
  implementation 'org.fxmisc.richtext:richtextfx:0.10.6'
4661
  implementation 'org.fxmisc.wellbehaved:wellbehavedfx:0.3.3'
4762
  implementation 'com.miglayout:miglayout-javafx:5.2'
48
  implementation('com.dlsc.preferencesfx:preferencesfx-core:11.7.0') {
49
    exclude group: 'org.openjfx'
50
  }
63
  implementation 'com.dlsc.preferencesfx:preferencesfx-core:11.8.0'
64
65
  // Pure JavaFX File Chooser
66
  implementation "com.io7m.jwheatsheaf:com.io7m.jwheatsheaf:${v_wheatsheaf}"
67
  implementation "com.io7m.jwheatsheaf:com.io7m.jwheatsheaf.api:${v_wheatsheaf}"
68
  implementation "com.io7m.jwheatsheaf:com.io7m.jwheatsheaf.ui:${v_wheatsheaf}"
5169
5270
  // Markdown
...
6886
  implementation 'com.ximpleware:vtd-xml:2.13.4'
6987
  implementation 'net.sf.saxon:Saxon-HE:10.3'
70
  //implementation 'xalan:xalan:2.7.2'
7188
7289
  // HTML parsing and rendering
...
90107
  implementation "org.apache.xmlgraphics:batik-svggen:${v_batik}"
91108
  implementation "org.apache.xmlgraphics:batik-transcoder:${v_batik}"
109
  implementation "org.apache.xmlgraphics:batik-rasterizer:${v_batik}"
92110
  implementation "org.apache.xmlgraphics:batik-util:${v_batik}"
93111
  implementation "org.apache.xmlgraphics:batik-xml:${v_batik}"
94112
95113
  // Misc.
96
  implementation 'org.ahocorasick:ahocorasick:0.4.0'
114
  implementation 'org.ahocorasick:ahocorasick:0.6.3'
97115
  implementation 'org.apache.commons:commons-configuration2:2.7'
98116
  implementation 'com.googlecode.juniversalchardet:juniversalchardet:1.0.3'
99117
  implementation 'javax.validation:validation-api:2.0.1.Final'
100118
  implementation 'org.greenrobot:eventbus:3.2.0'
101119
102
  // Configuration
120
  // Configuration: Update Workspace to use Jackson, instead could shave ~800kb
103121
  implementation 'org.apache.commons:commons-configuration2:2.7'
104122
  implementation 'commons-beanutils:commons-beanutils:1.9.4'
...
111129
  fx.each { fxitem ->
112130
    os.each { ositem ->
113
      println "org.openjfx:javafx-${fxitem}:${javafx.version}:${ositem}"
114
115131
      runtimeOnly "org.openjfx:javafx-${fxitem}:${javafx.version}:${ositem}"
116132
    }
117133
  }
118134
119
  testImplementation "org.junit.jupiter:junit-jupiter-engine:${v_junit}"
120135
  testImplementation "org.junit.jupiter:junit-jupiter-api:${v_junit}"
136
  testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
137
121138
  testImplementation "org.testfx:testfx-junit5:4.0.16-alpha"
122139
}
123140
124141
compileJava {
125142
  options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
126143
}
127144
128145
def resourceDir = sourceSets.main.resources.srcDirs[0]
129146
130
def config = new Properties()
131
file("${resourceDir}/bootstrap.properties").withInputStream {
132
  config.load(it)
133
}
147
final Properties config = new Properties()
148
final File configFile = file("${resourceDir}/bootstrap.properties")
149
final FileInputStream configStream = new FileInputStream(configFile)
150
config.load(configStream)
151
configStream.close()
134152
135
application {
136
  applicationName = config["application.title"].toLowerCase()
137
  mainClassName = "com.${applicationName}.Main"
153
final String applicationName = config.get("application.title").toString().toLowerCase()
154
final String applicationClass = "com.${applicationName}.Launcher"
138155
139
  applicationDefaultJvmArgs = [
140
      "--add-opens=javafx.controls/javafx.scene.control=ALL-UNNAMED",
141
      "--add-opens=javafx.controls/javafx.scene.control.skin=ALL-UNNAMED",
142
      "--add-opens=javafx.graphics/com.sun.javafx.css=ALL-UNNAMED",
143
  ]
156
application {
157
  mainClass.set(applicationClass)
158
  applicationDefaultJvmArgs = moduleSecurity
144159
}
145160
146161
version = gitVersion()
147
148
def launcherClassName = "com.${applicationName}.Launcher"
149162
150
def propertiesFile = new File("${resourceDir}/com/${applicationName}/app.properties")
163
final File propertiesFile = new File("${resourceDir}/com/${applicationName}/app.properties")
151164
propertiesFile.write("application.version=${version}")
152165
153166
jar {
154167
  duplicatesStrategy = DuplicatesStrategy.EXCLUDE
155168
156
  manifest {
157
    attributes 'Main-Class': launcherClassName
169
  doFirst {
170
    manifest {
171
      attributes 'Main-Class': applicationClass
172
    }
158173
  }
159174
...
183198
test {
184199
  useJUnitPlatform()
200
201
  doFirst {
202
    jvmArgs = moduleSecurity
203
  }
185204
186205
  testLogging {
M docs/README.md
1
## Documents
1
# Documentation
22
3
See the following documents for more information:
3
The following documents have additional details about using the editor:
44
5
* [i18n.md](i18n.md) -- Using internationalization features
5
* [div.md](div.md) -- Syntax for annotated text (fenced divs)
6
* [i18n.md](i18n.md) -- Internationalization features
7
* [r.md](r.md) -- R functions within R Markdown documents
8
* [samples](samples) -- Example documents
9
* [skins.md](skins.md) -- User interface customization
10
* [svg.md](svg.md) -- Resolve issues with some SVG files
11
* [typesetting.md](typesetting.md) -- Document typesetting
612
* [variables.md](variables.md) -- Variable definitions and interpolation
7
* [r.md](r.md) -- Call R functions within R Markdown documents
8
* [svg.md](svg.md) -- Fix known issues with displaying SVG files
9
* [themes.md](themes.md) -- Describes how to add and customize themes
13
14
# Contributions
15
1016
* [credits.md](credits.md) -- Thanks to authors of contributing projects
11
* [samples](samples) -- Contains example documents
17
* [licenses](licenses) -- Third-party licenses
1218
1319
A docs/development/proguard/README.md
1
From https://github.com/greenrobot/EventBus#r8-proguard
2
3
	-keepattributes *Annotation*
4
	-keepclassmembers class * {
5
			@org.greenrobot.eventbus.Subscribe <methods>;
6
	}
7
	-keep enum org.greenrobot.eventbus.ThreadMode { *; }
8
	 
19
A docs/div.md
1
# Fenced divs
2
3
This section describes the syntax to generate HTML `div` elements. The
4
syntax is known as a _fenced div_.
5
6
# Basic syntax
7
8
A fenced div has the following basic syntax:
9
10
``` markdown
11
::: name
12
Content
13
:::
14
```
15
16
To start a fenced div, begin a line with at least three colons (`:::`),
17
followed by at least one space, followed by any word. Content may follow
18
immediately on the next line. Terminate the fenced div with at least
19
three colons. The terminating colons needn't match in number to the starting
20
colons, but it's a good idea to maintain symmetry.
21
22
The HTML that is generated from the above fenced div will resemble:
23
24
``` html
25
<div class="name">
26
<p>Content</p>
27
</div>
28
```
29
30
# Extended syntax
31
32
A fenced div may use an extended syntax. The extended syntax can provide
33
a unique identifier, multiple class names, and key/value data pairs. For
34
example:
35
36
``` markdown
37
::: {#poem-01 .stanza author="Emily Dickinson" year=1890}
38
Because I could not stop for Death —
39
He kindly stopped for me —
40
The Carriage held but just Ourselves —
41
And Immortality.
42
:::
43
```
44
45
The above snippet produces:
46
47
``` html
48
<div id="poem-01" class="stanza" data-author="Emily Dickinson" data-year="1890">
49
<p>Because I could not stop for Death —
50
He kindly stopped for me —
51
The Carriage held but just Ourselves —
52
And Immortality.</p>
53
</div>
54
```
55
56
Note that when using the extended syntax, class styles must be prefixed with
57
a period (e.g., `.stanza` in the example).
58
59
# Nested syntax
60
61
Fenced divs may be nested, such as in the following example:
62
63
``` markdown
64
::: poem
65
:::::: stanza
66
Because I could not stop for Death —
67
He kindly stopped for me —
68
The Carriage held but just Ourselves —
69
And Immortality.
70
::::::
71
:::
72
```
73
74
The above example produces:
75
76
``` html
77
<div class="poem"><div class="stanza">
78
<p>Because I could not stop for Death —
79
He kindly stopped for me —
80
The Carriage held but just Ourselves —
81
And Immortality.</p>
82
</div></div>
83
```
84
185
A docs/images/app-ide.png
Binary file
A docs/images/screenshots/06.png
Binary file
A docs/images/screenshots/07.png
Binary file
A docs/licenses/BEAN-VALIDATION-API.md
11
2
                                 Apache License
3
                           Version 2.0, January 2004
4
                        http://www.apache.org/licenses/
5
6
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
8
   1. Definitions.
9
10
      "License" shall mean the terms and conditions for use, reproduction,
11
      and distribution as defined by Sections 1 through 9 of this document.
12
13
      "Licensor" shall mean the copyright owner or entity authorized by
14
      the copyright owner that is granting the License.
15
16
      "Legal Entity" shall mean the union of the acting entity and all
17
      other entities that control, are controlled by, or are under common
18
      control with that entity. For the purposes of this definition,
19
      "control" means (i) the power, direct or indirect, to cause the
20
      direction or management of such entity, whether by contract or
21
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
      outstanding shares, or (iii) beneficial ownership of such entity.
23
24
      "You" (or "Your") shall mean an individual or Legal Entity
25
      exercising permissions granted by this License.
26
27
      "Source" form shall mean the preferred form for making modifications,
28
      including but not limited to software source code, documentation
29
      source, and configuration files.
30
31
      "Object" form shall mean any form resulting from mechanical
32
      transformation or translation of a Source form, including but
33
      not limited to compiled object code, generated documentation,
34
      and conversions to other media types.
35
36
      "Work" shall mean the work of authorship, whether in Source or
37
      Object form, made available under the License, as indicated by a
38
      copyright notice that is included in or attached to the work
39
      (an example is provided in the Appendix below).
40
41
      "Derivative Works" shall mean any work, whether in Source or Object
42
      form, that is based on (or derived from) the Work and for which the
43
      editorial revisions, annotations, elaborations, or other modifications
44
      represent, as a whole, an original work of authorship. For the purposes
45
      of this License, Derivative Works shall not include works that remain
46
      separable from, or merely link (or bind by name) to the interfaces of,
47
      the Work and Derivative Works thereof.
48
49
      "Contribution" shall mean any work of authorship, including
50
      the original version of the Work and any modifications or additions
51
      to that Work or Derivative Works thereof, that is intentionally
52
      submitted to Licensor for inclusion in the Work by the copyright owner
53
      or by an individual or Legal Entity authorized to submit on behalf of
54
      the copyright owner. For the purposes of this definition, "submitted"
55
      means any form of electronic, verbal, or written communication sent
56
      to the Licensor or its representatives, including but not limited to
57
      communication on electronic mailing lists, source code control systems,
58
      and issue tracking systems that are managed by, or on behalf of, the
59
      Licensor for the purpose of discussing and improving the Work, but
60
      excluding communication that is conspicuously marked or otherwise
61
      designated in writing by the copyright owner as "Not a Contribution."
62
63
      "Contributor" shall mean Licensor and any individual or Legal Entity
64
      on behalf of whom a Contribution has been received by Licensor and
65
      subsequently incorporated within the Work.
66
67
   2. Grant of Copyright License. Subject to the terms and conditions of
68
      this License, each Contributor hereby grants to You a perpetual,
69
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
      copyright license to reproduce, prepare Derivative Works of,
71
      publicly display, publicly perform, sublicense, and distribute the
72
      Work and such Derivative Works in Source or Object form.
73
74
   3. Grant of Patent License. Subject to the terms and conditions of
75
      this License, each Contributor hereby grants to You a perpetual,
76
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
      (except as stated in this section) patent license to make, have made,
78
      use, offer to sell, sell, import, and otherwise transfer the Work,
79
      where such license applies only to those patent claims licensable
80
      by such Contributor that are necessarily infringed by their
81
      Contribution(s) alone or by combination of their Contribution(s)
82
      with the Work to which such Contribution(s) was submitted. If You
83
      institute patent litigation against any entity (including a
84
      cross-claim or counterclaim in a lawsuit) alleging that the Work
85
      or a Contribution incorporated within the Work constitutes direct
86
      or contributory patent infringement, then any patent licenses
87
      granted to You under this License for that Work shall terminate
88
      as of the date such litigation is filed.
89
90
   4. Redistribution. You may reproduce and distribute copies of the
91
      Work or Derivative Works thereof in any medium, with or without
92
      modifications, and in Source or Object form, provided that You
93
      meet the following conditions:
94
95
      (a) You must give any other recipients of the Work or
96
          Derivative Works a copy of this License; and
97
98
      (b) You must cause any modified files to carry prominent notices
99
          stating that You changed the files; and
100
101
      (c) You must retain, in the Source form of any Derivative Works
102
          that You distribute, all copyright, patent, trademark, and
103
          attribution notices from the Source form of the Work,
104
          excluding those notices that do not pertain to any part of
105
          the Derivative Works; and
106
107
      (d) If the Work includes a "NOTICE" text file as part of its
108
          distribution, then any Derivative Works that You distribute must
109
          include a readable copy of the attribution notices contained
110
          within such NOTICE file, excluding those notices that do not
111
          pertain to any part of the Derivative Works, in at least one
112
          of the following places: within a NOTICE text file distributed
113
          as part of the Derivative Works; within the Source form or
114
          documentation, if provided along with the Derivative Works; or,
115
          within a display generated by the Derivative Works, if and
116
          wherever such third-party notices normally appear. The contents
117
          of the NOTICE file are for informational purposes only and
118
          do not modify the License. You may add Your own attribution
119
          notices within Derivative Works that You distribute, alongside
120
          or as an addendum to the NOTICE text from the Work, provided
121
          that such additional attribution notices cannot be construed
122
          as modifying the License.
123
124
      You may add Your own copyright statement to Your modifications and
125
      may provide additional or different license terms and conditions
126
      for use, reproduction, or distribution of Your modifications, or
127
      for any such Derivative Works as a whole, provided Your use,
128
      reproduction, and distribution of the Work otherwise complies with
129
      the conditions stated in this License.
130
131
   5. Submission of Contributions. Unless You explicitly state otherwise,
132
      any Contribution intentionally submitted for inclusion in the Work
133
      by You to the Licensor shall be under the terms and conditions of
134
      this License, without any additional terms or conditions.
135
      Notwithstanding the above, nothing herein shall supersede or modify
136
      the terms of any separate license agreement you may have executed
137
      with Licensor regarding such Contributions.
138
139
   6. Trademarks. This License does not grant permission to use the trade
140
      names, trademarks, service marks, or product names of the Licensor,
141
      except as required for reasonable and customary use in describing the
142
      origin of the Work and reproducing the content of the NOTICE file.
143
144
   7. Disclaimer of Warranty. Unless required by applicable law or
145
      agreed to in writing, Licensor provides the Work (and each
146
      Contributor provides its Contributions) on an "AS IS" BASIS,
147
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
      implied, including, without limitation, any warranties or conditions
149
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
      PARTICULAR PURPOSE. You are solely responsible for determining the
151
      appropriateness of using or redistributing the Work and assume any
152
      risks associated with Your exercise of permissions under this License.
153
154
   8. Limitation of Liability. In no event and under no legal theory,
155
      whether in tort (including negligence), contract, or otherwise,
156
      unless required by applicable law (such as deliberate and grossly
157
      negligent acts) or agreed to in writing, shall any Contributor be
158
      liable to You for damages, including any direct, indirect, special,
159
      incidental, or consequential damages of any character arising as a
160
      result of this License or out of the use or inability to use the
161
      Work (including but not limited to damages for loss of goodwill,
162
      work stoppage, computer failure or malfunction, or any and all
163
      other commercial damages or losses), even if such Contributor
164
      has been advised of the possibility of such damages.
165
166
   9. Accepting Warranty or Additional Liability. While redistributing
167
      the Work or Derivative Works thereof, You may choose to offer,
168
      and charge a fee for, acceptance of support, warranty, indemnity,
169
      or other liability obligations and/or rights consistent with this
170
      License. However, in accepting such obligations, You may act only
171
      on Your own behalf and on Your sole responsibility, not on behalf
172
      of any other Contributor, and only if You agree to indemnify,
173
      defend, and hold each Contributor harmless for any liability
174
      incurred by, or claims asserted against, such Contributor by reason
175
      of your accepting any such warranty or additional liability.
176
177
   END OF TERMS AND CONDITIONS
178
179
   APPENDIX: How to apply the Apache License to your work.
180
181
      To apply the Apache License to your work, attach the following
182
      boilerplate notice, with the fields enclosed by brackets "[]"
183
      replaced with your own identifying information. (Don't include
184
      the brackets!)  The text should be enclosed in the appropriate
185
      comment syntax for the file format. We also recommend that a
186
      file or class name and description of purpose be included on the
187
      same "printed page" as the copyright notice for easier
188
      identification within third-party archives.
189
190
   Copyright [yyyy] [name of copyright owner]
191
192
   Licensed under the Apache License, Version 2.0 (the "License");
193
   you may not use this file except in compliance with the License.
194
   You may obtain a copy of the License at
195
196
       http://www.apache.org/licenses/LICENSE-2.0
197
198
   Unless required by applicable law or agreed to in writing, software
199
   distributed under the License is distributed on an "AS IS" BASIS,
200
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
   See the License for the specific language governing permissions and
202
   limitations under the License.
203
A docs/licenses/FILE-ICON-IMAGES.md
1
The MIT License (MIT)
2
3
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:
4
5
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7
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.
8
19
A docs/licenses/FILE-PREFERENCES.md
1
Released into the Public Domain by David Croft.
2
3
http://www.davidc.net/programming/java/java-preferences-using-file-backing-store
4
http://creativecommons.org/publicdomain/zero/1.0/
5
6
CC0 1.0 Universal (CC0 1.0)
7
8
Public Domain Dedication
9
10
This is a human-readable summary of the Legal Code (read the full text).
11
12
Disclaimer
13
14
No Copyright
15
16
* The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law.
17
18
* You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. See Other Information below.
19
20
This license is acceptable for Free Cultural Works.
21
22
Other Information
23
24
* In no way are the patent or trademark rights of any person affected by CC0, nor are the rights that other persons may have in the work or in how the work is used, such as publicity or privacy rights.
25
* Unless expressly stated otherwise, the person who associated a work with this deed makes no warranties about the work, and disclaims liability for all uses of the work, to the fullest extent permitted by applicable law.
26
* When using or citing the work, you should not imply endorsement by the author or the affirmer.
27
128
A docs/licenses/FLEXMARK.md
1
Copyright (c) 2015-2016, Atlassian Pty Ltd
2
All rights reserved.
3
4
Copyright (c) 2016-2018, Vladimir Schneider,
5
All rights reserved.
6
7
Redistribution and use in source and binary forms, with or without
8
modification, are permitted provided that the following conditions are met:
9
10
* Redistributions of source code must retain the above copyright notice, this
11
  list of conditions and the following disclaimer.
12
13
* Redistributions in binary form must reproduce the above copyright notice,
14
  this list of conditions and the following disclaimer in the documentation
15
  and/or other materials provided with the distribution.
16
17
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
127
A docs/licenses/FLOWLESS.md
1
Copyright (c) 2014, TomasMikula
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without
5
modification, are permitted provided that the following conditions are met:
6
7
* Redistributions of source code must retain the above copyright notice, this
8
  list of conditions and the following disclaimer.
9
10
* Redistributions in binary form must reproduce the above copyright notice,
11
  this list of conditions and the following disclaimer in the documentation
12
  and/or other materials provided with the distribution.
13
14
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
124
A docs/licenses/FONT-AWESOME-FX.txt
11
2
                                 Apache License
3
                           Version 2.0, January 2004
4
                        http://www.apache.org/licenses/
5
6
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
8
   1. Definitions.
9
10
      "License" shall mean the terms and conditions for use, reproduction,
11
      and distribution as defined by Sections 1 through 9 of this document.
12
13
      "Licensor" shall mean the copyright owner or entity authorized by
14
      the copyright owner that is granting the License.
15
16
      "Legal Entity" shall mean the union of the acting entity and all
17
      other entities that control, are controlled by, or are under common
18
      control with that entity. For the purposes of this definition,
19
      "control" means (i) the power, direct or indirect, to cause the
20
      direction or management of such entity, whether by contract or
21
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
      outstanding shares, or (iii) beneficial ownership of such entity.
23
24
      "You" (or "Your") shall mean an individual or Legal Entity
25
      exercising permissions granted by this License.
26
27
      "Source" form shall mean the preferred form for making modifications,
28
      including but not limited to software source code, documentation
29
      source, and configuration files.
30
31
      "Object" form shall mean any form resulting from mechanical
32
      transformation or translation of a Source form, including but
33
      not limited to compiled object code, generated documentation,
34
      and conversions to other media types.
35
36
      "Work" shall mean the work of authorship, whether in Source or
37
      Object form, made available under the License, as indicated by a
38
      copyright notice that is included in or attached to the work
39
      (an example is provided in the Appendix below).
40
41
      "Derivative Works" shall mean any work, whether in Source or Object
42
      form, that is based on (or derived from) the Work and for which the
43
      editorial revisions, annotations, elaborations, or other modifications
44
      represent, as a whole, an original work of authorship. For the purposes
45
      of this License, Derivative Works shall not include works that remain
46
      separable from, or merely link (or bind by name) to the interfaces of,
47
      the Work and Derivative Works thereof.
48
49
      "Contribution" shall mean any work of authorship, including
50
      the original version of the Work and any modifications or additions
51
      to that Work or Derivative Works thereof, that is intentionally
52
      submitted to Licensor for inclusion in the Work by the copyright owner
53
      or by an individual or Legal Entity authorized to submit on behalf of
54
      the copyright owner. For the purposes of this definition, "submitted"
55
      means any form of electronic, verbal, or written communication sent
56
      to the Licensor or its representatives, including but not limited to
57
      communication on electronic mailing lists, source code control systems,
58
      and issue tracking systems that are managed by, or on behalf of, the
59
      Licensor for the purpose of discussing and improving the Work, but
60
      excluding communication that is conspicuously marked or otherwise
61
      designated in writing by the copyright owner as "Not a Contribution."
62
63
      "Contributor" shall mean Licensor and any individual or Legal Entity
64
      on behalf of whom a Contribution has been received by Licensor and
65
      subsequently incorporated within the Work.
66
67
   2. Grant of Copyright License. Subject to the terms and conditions of
68
      this License, each Contributor hereby grants to You a perpetual,
69
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
      copyright license to reproduce, prepare Derivative Works of,
71
      publicly display, publicly perform, sublicense, and distribute the
72
      Work and such Derivative Works in Source or Object form.
73
74
   3. Grant of Patent License. Subject to the terms and conditions of
75
      this License, each Contributor hereby grants to You a perpetual,
76
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
      (except as stated in this section) patent license to make, have made,
78
      use, offer to sell, sell, import, and otherwise transfer the Work,
79
      where such license applies only to those patent claims licensable
80
      by such Contributor that are necessarily infringed by their
81
      Contribution(s) alone or by combination of their Contribution(s)
82
      with the Work to which such Contribution(s) was submitted. If You
83
      institute patent litigation against any entity (including a
84
      cross-claim or counterclaim in a lawsuit) alleging that the Work
85
      or a Contribution incorporated within the Work constitutes direct
86
      or contributory patent infringement, then any patent licenses
87
      granted to You under this License for that Work shall terminate
88
      as of the date such litigation is filed.
89
90
   4. Redistribution. You may reproduce and distribute copies of the
91
      Work or Derivative Works thereof in any medium, with or without
92
      modifications, and in Source or Object form, provided that You
93
      meet the following conditions:
94
95
      (a) You must give any other recipients of the Work or
96
          Derivative Works a copy of this License; and
97
98
      (b) You must cause any modified files to carry prominent notices
99
          stating that You changed the files; and
100
101
      (c) You must retain, in the Source form of any Derivative Works
102
          that You distribute, all copyright, patent, trademark, and
103
          attribution notices from the Source form of the Work,
104
          excluding those notices that do not pertain to any part of
105
          the Derivative Works; and
106
107
      (d) If the Work includes a "NOTICE" text file as part of its
108
          distribution, then any Derivative Works that You distribute must
109
          include a readable copy of the attribution notices contained
110
          within such NOTICE file, excluding those notices that do not
111
          pertain to any part of the Derivative Works, in at least one
112
          of the following places: within a NOTICE text file distributed
113
          as part of the Derivative Works; within the Source form or
114
          documentation, if provided along with the Derivative Works; or,
115
          within a display generated by the Derivative Works, if and
116
          wherever such third-party notices normally appear. The contents
117
          of the NOTICE file are for informational purposes only and
118
          do not modify the License. You may add Your own attribution
119
          notices within Derivative Works that You distribute, alongside
120
          or as an addendum to the NOTICE text from the Work, provided
121
          that such additional attribution notices cannot be construed
122
          as modifying the License.
123
124
      You may add Your own copyright statement to Your modifications and
125
      may provide additional or different license terms and conditions
126
      for use, reproduction, or distribution of Your modifications, or
127
      for any such Derivative Works as a whole, provided Your use,
128
      reproduction, and distribution of the Work otherwise complies with
129
      the conditions stated in this License.
130
131
   5. Submission of Contributions. Unless You explicitly state otherwise,
132
      any Contribution intentionally submitted for inclusion in the Work
133
      by You to the Licensor shall be under the terms and conditions of
134
      this License, without any additional terms or conditions.
135
      Notwithstanding the above, nothing herein shall supersede or modify
136
      the terms of any separate license agreement you may have executed
137
      with Licensor regarding such Contributions.
138
139
   6. Trademarks. This License does not grant permission to use the trade
140
      names, trademarks, service marks, or product names of the Licensor,
141
      except as required for reasonable and customary use in describing the
142
      origin of the Work and reproducing the content of the NOTICE file.
143
144
   7. Disclaimer of Warranty. Unless required by applicable law or
145
      agreed to in writing, Licensor provides the Work (and each
146
      Contributor provides its Contributions) on an "AS IS" BASIS,
147
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
      implied, including, without limitation, any warranties or conditions
149
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
      PARTICULAR PURPOSE. You are solely responsible for determining the
151
      appropriateness of using or redistributing the Work and assume any
152
      risks associated with Your exercise of permissions under this License.
153
154
   8. Limitation of Liability. In no event and under no legal theory,
155
      whether in tort (including negligence), contract, or otherwise,
156
      unless required by applicable law (such as deliberate and grossly
157
      negligent acts) or agreed to in writing, shall any Contributor be
158
      liable to You for damages, including any direct, indirect, special,
159
      incidental, or consequential damages of any character arising as a
160
      result of this License or out of the use or inability to use the
161
      Work (including but not limited to damages for loss of goodwill,
162
      work stoppage, computer failure or malfunction, or any and all
163
      other commercial damages or losses), even if such Contributor
164
      has been advised of the possibility of such damages.
165
166
   9. Accepting Warranty or Additional Liability. While redistributing
167
      the Work or Derivative Works thereof, You may choose to offer,
168
      and charge a fee for, acceptance of support, warranty, indemnity,
169
      or other liability obligations and/or rights consistent with this
170
      License. However, in accepting such obligations, You may act only
171
      on Your own behalf and on Your sole responsibility, not on behalf
172
      of any other Contributor, and only if You agree to indemnify,
173
      defend, and hold each Contributor harmless for any liability
174
      incurred by, or claims asserted against, such Contributor by reason
175
      of your accepting any such warranty or additional liability.
176
177
   END OF TERMS AND CONDITIONS
178
179
   APPENDIX: How to apply the Apache License to your work.
180
181
      To apply the Apache License to your work, attach the following
182
      boilerplate notice, with the fields enclosed by brackets "[]"
183
      replaced with your own identifying information. (Don't include
184
      the brackets!)  The text should be enclosed in the appropriate
185
      comment syntax for the file format. We also recommend that a
186
      file or class name and description of purpose be included on the
187
      same "printed page" as the copyright notice for easier
188
      identification within third-party archives.
189
190
   Copyright [yyyy] [name of copyright owner]
191
192
   Licensed under the Apache License, Version 2.0 (the "License");
193
   you may not use this file except in compliance with the License.
194
   You may obtain a copy of the License at
195
196
       http://www.apache.org/licenses/LICENSE-2.0
197
198
   Unless required by applicable law or agreed to in writing, software
199
   distributed under the License is distributed on an "AS IS" BASIS,
200
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
   See the License for the specific language governing permissions and
202
   limitations under the License.
203
A docs/licenses/JSYMSPELL.md
1
MIT License
2
3
Copyright (c) 2019 Raul Garcia
4
5
Permission is hereby granted, free of charge, to any person obtaining a copy
6
of this software and associated documentation files (the "Software"), to deal
7
in the Software without restriction, including without limitation the rights
8
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
copies of the Software, and to permit persons to whom the Software is
10
furnished to do so, subject to the following conditions:
11
12
The above copyright notice and this permission notice shall be included in all
13
copies or substantial portions of the Software.
14
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
SOFTWARE.
122
A docs/licenses/JUNIVERSAL-CHARDET.md
1
Version: MPL 1.1/GPL 2.0/LGPL 2.1
2
3
The contents of this file are subject to the Mozilla Public License Version
4
1.1 (the "License"); you may not use this file except in compliance with
5
the License. You may obtain a copy of the License at
6
http://www.mozilla.org/MPL/
7
8
Software distributed under the License is distributed on an "AS IS" basis,
9
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10
for the specific language governing rights and limitations under the
11
License.
12
13
The Original Code is Mozilla Universal charset detector code.
14
15
The Initial Developer of the Original Code is
16
Netscape Communications Corporation.
17
Portions created by the Initial Developer are Copyright (C) 2001
18
the Initial Developer. All Rights Reserved.
19
20
Contributor(s):
21
        Shy Shalom <shooshX@gmail.com>
22
        Kohei TAKETA <k-tak@void.in> (Java port)
23
24
Alternatively, the contents of this file may be used under the terms of
25
either the GNU General Public License Version 2 or later (the "GPL"), or
26
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
in which case the provisions of the GPL or the LGPL are applicable instead
28
of those above. If you wish to allow use of your version of this file only
29
under the terms of either the GPL or the LGPL, and not to allow others to
30
use your version of this file under the terms of the MPL, indicate your
31
decision by deleting the provisions above and replace them with the notice
32
and other provisions required by the GPL or the LGPL. If you do not delete
33
the provisions above, a recipient may use your version of this file under
34
the terms of any one of the MPL, the GPL or the LGPL.
35
136
A docs/licenses/JWHEATSHEAF.md
1
Copyright © 2020 Mark Raynsford <code@io7m.com> http://io7m.com
2
3
Permission to use, copy, modify, and/or distribute this software for any
4
purpose with or without fee is hereby granted, provided that the above
5
copyright notice and this permission notice appear in all copies.
6
7
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
114
A docs/licenses/MARKDOWN-WRITER-FX.md
1
Copyright (c) 2015 Karl Tauber <karl@jformdesigner.com>
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without
5
modification, are permitted provided that the following conditions are met:
6
7
* Redistributions of source code must retain the above copyright
8
  notice, this list of conditions and the following disclaimer.
9
10
* Redistributions in binary form must reproduce the above copyright
11
  notice, this list of conditions and the following disclaimer in the
12
  documentation and/or other materials provided with the distribution.
13
14
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
125
A docs/licenses/MIG-LAYOUT.md
1
Copyright (c) 2000 Mikael Grev
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without
5
modification, are permitted provided that the following conditions
6
are met:
7
1. Redistributions of source code must retain the above copyright
8
   notice, this list of conditions and the following disclaimer.
9
2. Redistributions in binary form must reproduce the above copyright
10
   notice, this list of conditions and the following disclaimer in the
11
   documentation and/or other materials provided with the distribution.
12
3. The name of the author may not be used to endorse or promote products
13
   derived from this software without specific prior written permission.
14
15
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
126
A docs/licenses/PREFERENCES-FX.txt
1
                                 Apache License
2
                           Version 2.0, January 2004
3
                        http://www.apache.org/licenses/
4
5
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7
   1. Definitions.
8
9
      "License" shall mean the terms and conditions for use, reproduction,
10
      and distribution as defined by Sections 1 through 9 of this document.
11
12
      "Licensor" shall mean the copyright owner or entity authorized by
13
      the copyright owner that is granting the License.
14
15
      "Legal Entity" shall mean the union of the acting entity and all
16
      other entities that control, are controlled by, or are under common
17
      control with that entity. For the purposes of this definition,
18
      "control" means (i) the power, direct or indirect, to cause the
19
      direction or management of such entity, whether by contract or
20
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
      outstanding shares, or (iii) beneficial ownership of such entity.
22
23
      "You" (or "Your") shall mean an individual or Legal Entity
24
      exercising permissions granted by this License.
25
26
      "Source" form shall mean the preferred form for making modifications,
27
      including but not limited to software source code, documentation
28
      source, and configuration files.
29
30
      "Object" form shall mean any form resulting from mechanical
31
      transformation or translation of a Source form, including but
32
      not limited to compiled object code, generated documentation,
33
      and conversions to other media types.
34
35
      "Work" shall mean the work of authorship, whether in Source or
36
      Object form, made available under the License, as indicated by a
37
      copyright notice that is included in or attached to the work
38
      (an example is provided in the Appendix below).
39
40
      "Derivative Works" shall mean any work, whether in Source or Object
41
      form, that is based on (or derived from) the Work and for which the
42
      editorial revisions, annotations, elaborations, or other modifications
43
      represent, as a whole, an original work of authorship. For the purposes
44
      of this License, Derivative Works shall not include works that remain
45
      separable from, or merely link (or bind by name) to the interfaces of,
46
      the Work and Derivative Works thereof.
47
48
      "Contribution" shall mean any work of authorship, including
49
      the original version of the Work and any modifications or additions
50
      to that Work or Derivative Works thereof, that is intentionally
51
      submitted to Licensor for inclusion in the Work by the copyright owner
52
      or by an individual or Legal Entity authorized to submit on behalf of
53
      the copyright owner. For the purposes of this definition, "submitted"
54
      means any form of electronic, verbal, or written communication sent
55
      to the Licensor or its representatives, including but not limited to
56
      communication on electronic mailing lists, source code control systems,
57
      and issue tracking systems that are managed by, or on behalf of, the
58
      Licensor for the purpose of discussing and improving the Work, but
59
      excluding communication that is conspicuously marked or otherwise
60
      designated in writing by the copyright owner as "Not a Contribution."
61
62
      "Contributor" shall mean Licensor and any individual or Legal Entity
63
      on behalf of whom a Contribution has been received by Licensor and
64
      subsequently incorporated within the Work.
65
66
   2. Grant of Copyright License. Subject to the terms and conditions of
67
      this License, each Contributor hereby grants to You a perpetual,
68
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
      copyright license to reproduce, prepare Derivative Works of,
70
      publicly display, publicly perform, sublicense, and distribute the
71
      Work and such Derivative Works in Source or Object form.
72
73
   3. Grant of Patent License. Subject to the terms and conditions of
74
      this License, each Contributor hereby grants to You a perpetual,
75
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
      (except as stated in this section) patent license to make, have made,
77
      use, offer to sell, sell, import, and otherwise transfer the Work,
78
      where such license applies only to those patent claims licensable
79
      by such Contributor that are necessarily infringed by their
80
      Contribution(s) alone or by combination of their Contribution(s)
81
      with the Work to which such Contribution(s) was submitted. If You
82
      institute patent litigation against any entity (including a
83
      cross-claim or counterclaim in a lawsuit) alleging that the Work
84
      or a Contribution incorporated within the Work constitutes direct
85
      or contributory patent infringement, then any patent licenses
86
      granted to You under this License for that Work shall terminate
87
      as of the date such litigation is filed.
88
89
   4. Redistribution. You may reproduce and distribute copies of the
90
      Work or Derivative Works thereof in any medium, with or without
91
      modifications, and in Source or Object form, provided that You
92
      meet the following conditions:
93
94
      (a) You must give any other recipients of the Work or
95
          Derivative Works a copy of this License; and
96
97
      (b) You must cause any modified files to carry prominent notices
98
          stating that You changed the files; and
99
100
      (c) You must retain, in the Source form of any Derivative Works
101
          that You distribute, all copyright, patent, trademark, and
102
          attribution notices from the Source form of the Work,
103
          excluding those notices that do not pertain to any part of
104
          the Derivative Works; and
105
106
      (d) If the Work includes a "NOTICE" text file as part of its
107
          distribution, then any Derivative Works that You distribute must
108
          include a readable copy of the attribution notices contained
109
          within such NOTICE file, excluding those notices that do not
110
          pertain to any part of the Derivative Works, in at least one
111
          of the following places: within a NOTICE text file distributed
112
          as part of the Derivative Works; within the Source form or
113
          documentation, if provided along with the Derivative Works; or,
114
          within a display generated by the Derivative Works, if and
115
          wherever such third-party notices normally appear. The contents
116
          of the NOTICE file are for informational purposes only and
117
          do not modify the License. You may add Your own attribution
118
          notices within Derivative Works that You distribute, alongside
119
          or as an addendum to the NOTICE text from the Work, provided
120
          that such additional attribution notices cannot be construed
121
          as modifying the License.
122
123
      You may add Your own copyright statement to Your modifications and
124
      may provide additional or different license terms and conditions
125
      for use, reproduction, or distribution of Your modifications, or
126
      for any such Derivative Works as a whole, provided Your use,
127
      reproduction, and distribution of the Work otherwise complies with
128
      the conditions stated in this License.
129
130
   5. Submission of Contributions. Unless You explicitly state otherwise,
131
      any Contribution intentionally submitted for inclusion in the Work
132
      by You to the Licensor shall be under the terms and conditions of
133
      this License, without any additional terms or conditions.
134
      Notwithstanding the above, nothing herein shall supersede or modify
135
      the terms of any separate license agreement you may have executed
136
      with Licensor regarding such Contributions.
137
138
   6. Trademarks. This License does not grant permission to use the trade
139
      names, trademarks, service marks, or product names of the Licensor,
140
      except as required for reasonable and customary use in describing the
141
      origin of the Work and reproducing the content of the NOTICE file.
142
143
   7. Disclaimer of Warranty. Unless required by applicable law or
144
      agreed to in writing, Licensor provides the Work (and each
145
      Contributor provides its Contributions) on an "AS IS" BASIS,
146
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
      implied, including, without limitation, any warranties or conditions
148
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
      PARTICULAR PURPOSE. You are solely responsible for determining the
150
      appropriateness of using or redistributing the Work and assume any
151
      risks associated with Your exercise of permissions under this License.
152
153
   8. Limitation of Liability. In no event and under no legal theory,
154
      whether in tort (including negligence), contract, or otherwise,
155
      unless required by applicable law (such as deliberate and grossly
156
      negligent acts) or agreed to in writing, shall any Contributor be
157
      liable to You for damages, including any direct, indirect, special,
158
      incidental, or consequential damages of any character arising as a
159
      result of this License or out of the use or inability to use the
160
      Work (including but not limited to damages for loss of goodwill,
161
      work stoppage, computer failure or malfunction, or any and all
162
      other commercial damages or losses), even if such Contributor
163
      has been advised of the possibility of such damages.
164
165
   9. Accepting Warranty or Additional Liability. While redistributing
166
      the Work or Derivative Works thereof, You may choose to offer,
167
      and charge a fee for, acceptance of support, warranty, indemnity,
168
      or other liability obligations and/or rights consistent with this
169
      License. However, in accepting such obligations, You may act only
170
      on Your own behalf and on Your sole responsibility, not on behalf
171
      of any other Contributor, and only if You agree to indemnify,
172
      defend, and hold each Contributor harmless for any liability
173
      incurred by, or claims asserted against, such Contributor by reason
174
      of your accepting any such warranty or additional liability.
175
176
   END OF TERMS AND CONDITIONS
177
178
   APPENDIX: How to apply the Apache License to your work.
179
180
      To apply the Apache License to your work, attach the following
181
      boilerplate notice, with the fields enclosed by brackets "{}"
182
      replaced with your own identifying information. (Don't include
183
      the brackets!)  The text should be enclosed in the appropriate
184
      comment syntax for the file format. We also recommend that a
185
      file or class name and description of purpose be included on the
186
      same "printed page" as the copyright notice for easier
187
      identification within third-party archives.
188
189
   Copyright {yyyy} {name of copyright owner}
190
191
   Licensed under the Apache License, Version 2.0 (the "License");
192
   you may not use this file except in compliance with the License.
193
   You may obtain a copy of the License at
194
195
       http://www.apache.org/licenses/LICENSE-2.0
196
197
   Unless required by applicable law or agreed to in writing, software
198
   distributed under the License is distributed on an "AS IS" BASIS,
199
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
   See the License for the specific language governing permissions and
201
   limitations under the License.
1202
A docs/licenses/REACT-FX.md
1
Copyright (c) 2013-2014, Tomas Mikula
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
6
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
8
2. 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.
9
10
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.
111
A docs/licenses/RENJIN.txt
1
		    GNU GENERAL PUBLIC LICENSE
2
		       Version 2, June 1991
3
4
 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5
                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
6
 Everyone is permitted to copy and distribute verbatim copies
7
 of this license document, but changing it is not allowed.
8
9
			    Preamble
10
11
  The licenses for most software are designed to take away your
12
freedom to share and change it.  By contrast, the GNU General Public
13
License is intended to guarantee your freedom to share and change free
14
software--to make sure the software is free for all its users.  This
15
General Public License applies to most of the Free Software
16
Foundation's software and to any other program whose authors commit to
17
using it.  (Some other Free Software Foundation software is covered by
18
the GNU Library General Public License instead.)  You can apply it to
19
your programs, too.
20
21
  When we speak of free software, we are referring to freedom, not
22
price.  Our General Public Licenses are designed to make sure that you
23
have the freedom to distribute copies of free software (and charge for
24
this service if you wish), that you receive source code or can get it
25
if you want it, that you can change the software or use pieces of it
26
in new free programs; and that you know you can do these things.
27
28
  To protect your rights, we need to make restrictions that forbid
29
anyone to deny you these rights or to ask you to surrender the rights.
30
These restrictions translate to certain responsibilities for you if you
31
distribute copies of the software, or if you modify it.
32
33
  For example, if you distribute copies of such a program, whether
34
gratis or for a fee, you must give the recipients all the rights that
35
you have.  You must make sure that they, too, receive or can get the
36
source code.  And you must show them these terms so they know their
37
rights.
38
39
  We protect your rights with two steps: (1) copyright the software, and
40
(2) offer you this license which gives you legal permission to copy,
41
distribute and/or modify the software.
42
43
  Also, for each author's protection and ours, we want to make certain
44
that everyone understands that there is no warranty for this free
45
software.  If the software is modified by someone else and passed on, we
46
want its recipients to know that what they have is not the original, so
47
that any problems introduced by others will not reflect on the original
48
authors' reputations.
49
50
  Finally, any free program is threatened constantly by software
51
patents.  We wish to avoid the danger that redistributors of a free
52
program will individually obtain patent licenses, in effect making the
53
program proprietary.  To prevent this, we have made it clear that any
54
patent must be licensed for everyone's free use or not licensed at all.
55
56
  The precise terms and conditions for copying, distribution and
57
modification follow.
58

59
		    GNU GENERAL PUBLIC LICENSE
60
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62
  0. This License applies to any program or other work which contains
63
a notice placed by the copyright holder saying it may be distributed
64
under the terms of this General Public License.  The "Program", below,
65
refers to any such program or work, and a "work based on the Program"
66
means either the Program or any derivative work under copyright law:
67
that is to say, a work containing the Program or a portion of it,
68
either verbatim or with modifications and/or translated into another
69
language.  (Hereinafter, translation is included without limitation in
70
the term "modification".)  Each licensee is addressed as "you".
71
72
Activities other than copying, distribution and modification are not
73
covered by this License; they are outside its scope.  The act of
74
running the Program is not restricted, and the output from the Program
75
is covered only if its contents constitute a work based on the
76
Program (independent of having been made by running the Program).
77
Whether that is true depends on what the Program does.
78
79
  1. You may copy and distribute verbatim copies of the Program's
80
source code as you receive it, in any medium, provided that you
81
conspicuously and appropriately publish on each copy an appropriate
82
copyright notice and disclaimer of warranty; keep intact all the
83
notices that refer to this License and to the absence of any warranty;
84
and give any other recipients of the Program a copy of this License
85
along with the Program.
86
87
You may charge a fee for the physical act of transferring a copy, and
88
you may at your option offer warranty protection in exchange for a fee.
89
90
  2. You may modify your copy or copies of the Program or any portion
91
of it, thus forming a work based on the Program, and copy and
92
distribute such modifications or work under the terms of Section 1
93
above, provided that you also meet all of these conditions:
94
95
    a) You must cause the modified files to carry prominent notices
96
    stating that you changed the files and the date of any change.
97
98
    b) You must cause any work that you distribute or publish, that in
99
    whole or in part contains or is derived from the Program or any
100
    part thereof, to be licensed as a whole at no charge to all third
101
    parties under the terms of this License.
102
103
    c) If the modified program normally reads commands interactively
104
    when run, you must cause it, when started running for such
105
    interactive use in the most ordinary way, to print or display an
106
    announcement including an appropriate copyright notice and a
107
    notice that there is no warranty (or else, saying that you provide
108
    a warranty) and that users may redistribute the program under
109
    these conditions, and telling the user how to view a copy of this
110
    License.  (Exception: if the Program itself is interactive but
111
    does not normally print such an announcement, your work based on
112
    the Program is not required to print an announcement.)
113

114
These requirements apply to the modified work as a whole.  If
115
identifiable sections of that work are not derived from the Program,
116
and can be reasonably considered independent and separate works in
117
themselves, then this License, and its terms, do not apply to those
118
sections when you distribute them as separate works.  But when you
119
distribute the same sections as part of a whole which is a work based
120
on the Program, the distribution of the whole must be on the terms of
121
this License, whose permissions for other licensees extend to the
122
entire whole, and thus to each and every part regardless of who wrote it.
123
124
Thus, it is not the intent of this section to claim rights or contest
125
your rights to work written entirely by you; rather, the intent is to
126
exercise the right to control the distribution of derivative or
127
collective works based on the Program.
128
129
In addition, mere aggregation of another work not based on the Program
130
with the Program (or with a work based on the Program) on a volume of
131
a storage or distribution medium does not bring the other work under
132
the scope of this License.
133
134
  3. You may copy and distribute the Program (or a work based on it,
135
under Section 2) in object code or executable form under the terms of
136
Sections 1 and 2 above provided that you also do one of the following:
137
138
    a) Accompany it with the complete corresponding machine-readable
139
    source code, which must be distributed under the terms of Sections
140
    1 and 2 above on a medium customarily used for software interchange; or,
141
142
    b) Accompany it with a written offer, valid for at least three
143
    years, to give any third party, for a charge no more than your
144
    cost of physically performing source distribution, a complete
145
    machine-readable copy of the corresponding source code, to be
146
    distributed under the terms of Sections 1 and 2 above on a medium
147
    customarily used for software interchange; or,
148
149
    c) Accompany it with the information you received as to the offer
150
    to distribute corresponding source code.  (This alternative is
151
    allowed only for noncommercial distribution and only if you
152
    received the program in object code or executable form with such
153
    an offer, in accord with Subsection b above.)
154
155
The source code for a work means the preferred form of the work for
156
making modifications to it.  For an executable work, complete source
157
code means all the source code for all modules it contains, plus any
158
associated interface definition files, plus the scripts used to
159
control compilation and installation of the executable.  However, as a
160
special exception, the source code distributed need not include
161
anything that is normally distributed (in either source or binary
162
form) with the major components (compiler, kernel, and so on) of the
163
operating system on which the executable runs, unless that component
164
itself accompanies the executable.
165
166
If distribution of executable or object code is made by offering
167
access to copy from a designated place, then offering equivalent
168
access to copy the source code from the same place counts as
169
distribution of the source code, even though third parties are not
170
compelled to copy the source along with the object code.
171

172
  4. You may not copy, modify, sublicense, or distribute the Program
173
except as expressly provided under this License.  Any attempt
174
otherwise to copy, modify, sublicense or distribute the Program is
175
void, and will automatically terminate your rights under this License.
176
However, parties who have received copies, or rights, from you under
177
this License will not have their licenses terminated so long as such
178
parties remain in full compliance.
179
180
  5. You are not required to accept this License, since you have not
181
signed it.  However, nothing else grants you permission to modify or
182
distribute the Program or its derivative works.  These actions are
183
prohibited by law if you do not accept this License.  Therefore, by
184
modifying or distributing the Program (or any work based on the
185
Program), you indicate your acceptance of this License to do so, and
186
all its terms and conditions for copying, distributing or modifying
187
the Program or works based on it.
188
189
  6. Each time you redistribute the Program (or any work based on the
190
Program), the recipient automatically receives a license from the
191
original licensor to copy, distribute or modify the Program subject to
192
these terms and conditions.  You may not impose any further
193
restrictions on the recipients' exercise of the rights granted herein.
194
You are not responsible for enforcing compliance by third parties to
195
this License.
196
197
  7. If, as a consequence of a court judgment or allegation of patent
198
infringement or for any other reason (not limited to patent issues),
199
conditions are imposed on you (whether by court order, agreement or
200
otherwise) that contradict the conditions of this License, they do not
201
excuse you from the conditions of this License.  If you cannot
202
distribute so as to satisfy simultaneously your obligations under this
203
License and any other pertinent obligations, then as a consequence you
204
may not distribute the Program at all.  For example, if a patent
205
license would not permit royalty-free redistribution of the Program by
206
all those who receive copies directly or indirectly through you, then
207
the only way you could satisfy both it and this License would be to
208
refrain entirely from distribution of the Program.
209
210
If any portion of this section is held invalid or unenforceable under
211
any particular circumstance, the balance of the section is intended to
212
apply and the section as a whole is intended to apply in other
213
circumstances.
214
215
It is not the purpose of this section to induce you to infringe any
216
patents or other property right claims or to contest validity of any
217
such claims; this section has the sole purpose of protecting the
218
integrity of the free software distribution system, which is
219
implemented by public license practices.  Many people have made
220
generous contributions to the wide range of software distributed
221
through that system in reliance on consistent application of that
222
system; it is up to the author/donor to decide if he or she is willing
223
to distribute software through any other system and a licensee cannot
224
impose that choice.
225
226
This section is intended to make thoroughly clear what is believed to
227
be a consequence of the rest of this License.
228

229
  8. If the distribution and/or use of the Program is restricted in
230
certain countries either by patents or by copyrighted interfaces, the
231
original copyright holder who places the Program under this License
232
may add an explicit geographical distribution limitation excluding
233
those countries, so that distribution is permitted only in or among
234
countries not thus excluded.  In such case, this License incorporates
235
the limitation as if written in the body of this License.
236
237
  9. The Free Software Foundation may publish revised and/or new versions
238
of the General Public License from time to time.  Such new versions will
239
be similar in spirit to the present version, but may differ in detail to
240
address new problems or concerns.
241
242
Each version is given a distinguishing version number.  If the Program
243
specifies a version number of this License which applies to it and "any
244
later version", you have the option of following the terms and conditions
245
either of that version or of any later version published by the Free
246
Software Foundation.  If the Program does not specify a version number of
247
this License, you may choose any version ever published by the Free Software
248
Foundation.
249
250
  10. If you wish to incorporate parts of the Program into other free
251
programs whose distribution conditions are different, write to the author
252
to ask for permission.  For software which is copyrighted by the Free
253
Software Foundation, write to the Free Software Foundation; we sometimes
254
make exceptions for this.  Our decision will be guided by the two goals
255
of preserving the free status of all derivatives of our free software and
256
of promoting the sharing and reuse of software generally.
257
258
			    NO WARRANTY
259
260
  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
262
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
266
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
267
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
REPAIR OR CORRECTION.
269
270
  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
POSSIBILITY OF SUCH DAMAGES.
279
280
		     END OF TERMS AND CONDITIONS
281

282
	    How to Apply These Terms to Your New Programs
283
284
  If you develop a new program, and you want it to be of the greatest
285
possible use to the public, the best way to achieve this is to make it
286
free software which everyone can redistribute and change under these terms.
287
288
  To do so, attach the following notices to the program.  It is safest
289
to attach them to the start of each source file to most effectively
290
convey the exclusion of warranty; and each file should have at least
291
the "copyright" line and a pointer to where the full notice is found.
292
293
    <one line to give the program's name and a brief idea of what it does.>
294
    Copyright (C) <year>  <name of author>
295
296
    This program is free software; you can redistribute it and/or modify
297
    it under the terms of the GNU General Public License as published by
298
    the Free Software Foundation; either version 2 of the License, or
299
    (at your option) any later version.
300
301
    This program is distributed in the hope that it will be useful,
302
    but WITHOUT ANY WARRANTY; without even the implied warranty of
303
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
304
    GNU General Public License for more details.
305
306
    You should have received a copy of the GNU General Public License
307
    along with this program; if not, write to the Free Software
308
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
309
310
311
Also add information on how to contact you by electronic and paper mail.
312
313
If the program is interactive, make it output a short notice like this
314
when it starts in an interactive mode:
315
316
    Gnomovision version 69, Copyright (C) year name of author
317
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318
    This is free software, and you are welcome to redistribute it
319
    under certain conditions; type `show c' for details.
320
321
The hypothetical commands `show w' and `show c' should show the appropriate
322
parts of the General Public License.  Of course, the commands you use may
323
be called something other than `show w' and `show c'; they could even be
324
mouse-clicks or menu items--whatever suits your program.
325
326
You should also get your employer (if you work as a programmer) or your
327
school, if any, to sign a "copyright disclaimer" for the program, if
328
necessary.  Here is a sample; alter the names:
329
330
  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331
  `Gnomovision' (which makes passes at compilers) written by James Hacker.
332
333
  <signature of Ty Coon>, 1 April 1989
334
  Ty Coon, President of Vice
335
336
This General Public License does not permit incorporating your program into
337
proprietary programs.  If your program is a subroutine library, you may
338
consider it more useful to permit linking proprietary applications with the
339
library.  If this is what you want to do, use the GNU Library General
340
Public License instead of this License.
1341
A docs/licenses/RICH-TEXT-FX.md
1
Copyright (c) 2013-2017, Tomas Mikula and contributors
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
6
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
8
2. 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.
9
10
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.
111
A docs/licenses/SAXON-HE.txt
1
                             Mozilla Public License
2
                                  Version 2.0
3
4
1. Definitions
5
6
   1.1. “Contributor”
7
          means each individual or legal entity that creates, contributes
8
          to the creation of, or owns Covered Software.
9
10
   1.2. “Contributor Version”
11
          means the combination of the Contributions of others (if any)
12
          used by a Contributor and that particular Contributor’s
13
          Contribution.
14
15
   1.3. “Contribution”
16
          means Covered Software of a particular Contributor.
17
18
   1.4. “Covered Software”
19
          means Source Code Form to which the initial Contributor has
20
          attached the notice in Exhibit A, the Executable Form of such
21
          Source Code Form, and Modifications of such Source Code Form, in
22
          each case including portions thereof.
23
24
   1.5. “Incompatible With Secondary Licenses”
25
          means
26
27
         a. that the initial Contributor has attached the notice described
28
            in Exhibit B to the Covered Software; or
29
         b. that the Covered Software was made available under the terms
30
            of version 1.1 or earlier of the License, but not also under
31
            the terms of a Secondary License.
32
33
   1.6. “Executable Form”
34
          means any form of the work other than Source Code Form.
35
36
   1.7. “Larger Work”
37
          means a work that combines Covered Software with other material,
38
          in a separate file or files, that is not Covered Software.
39
40
   1.8. “License”
41
          means this document.
42
43
   1.9. “Licensable”
44
          means having the right to grant, to the maximum extent possible,
45
          whether at the time of the initial grant or subsequently, any
46
          and all of the rights conveyed by this License.
47
48
   1.10. “Modifications”
49
          means any of the following:
50
51
         a. any file in Source Code Form that results from an addition to,
52
            deletion from, or modification of the contents of Covered
53
            Software; or
54
         b. any new file in Source Code Form that contains any Covered
55
            Software.
56
57
   1.11. “Patent Claims” of a Contributor
58
          means any patent claim(s), including without limitation, method,
59
          process, and apparatus claims, in any patent Licensable by such
60
          Contributor that would be infringed, but for the grant of the
61
          License, by the making, using, selling, offering for sale,
62
          having made, import, or transfer of either its Contributions or
63
          its Contributor Version.
64
65
   1.12. “Secondary License”
66
          means either the GNU General Public License, Version 2.0, the
67
          GNU Lesser General Public License, Version 2.1, the GNU Affero
68
          General Public License, Version 3.0, or any later versions of
69
          those licenses.
70
71
   1.13. “Source Code Form”
72
          means the form of the work preferred for making modifications.
73
74
   1.14. “You” (or “Your”)
75
          means an individual or a legal entity exercising rights under
76
          this License. For legal entities, “You” includes any entity that
77
          controls, is controlled by, or is under common control with You.
78
          For purposes of this definition, “control” means (a) the power,
79
          direct or indirect, to cause the direction or management of such
80
          entity, whether by contract or otherwise, or (b) ownership of
81
          more than fifty percent (50%) of the outstanding shares or
82
          beneficial ownership of such entity.
83
84
2. License Grants and Conditions
85
86
  2.1. Grants
87
88
   Each Contributor hereby grants You a world-wide, royalty-free,
89
   non-exclusive license:
90
    a. under intellectual property rights (other than patent or trademark)
91
       Licensable by such Contributor to use, reproduce, make available,
92
       modify, display, perform, distribute, and otherwise exploit its
93
       Contributions, either on an unmodified basis, with Modifications,
94
       or as part of a Larger Work; and
95
    b. under Patent Claims of such Contributor to make, use, sell, offer
96
       for sale, have made, import, and otherwise transfer either its
97
       Contributions or its Contributor Version.
98
99
  2.2. Effective Date
100
101
   The licenses granted in Section 2.1 with respect to any Contribution
102
   become effective for each Contribution on the date the Contributor
103
   first distributes such Contribution.
104
105
  2.3. Limitations on Grant Scope
106
107
   The licenses granted in this Section 2 are the only rights granted
108
   under this License. No additional rights or licenses will be implied
109
   from the distribution or licensing of Covered Software under this
110
   License. Notwithstanding Section 2.1(b) above, no patent license is
111
   granted by a Contributor:
112
    a. for any code that a Contributor has removed from Covered Software;
113
       or
114
    b. for infringements caused by: (i) Your and any other third party’s
115
       modifications of Covered Software, or (ii) the combination of its
116
       Contributions with other software (except as part of its
117
       Contributor Version); or
118
    c. under Patent Claims infringed by Covered Software in the absence of
119
       its Contributions.
120
121
   This License does not grant any rights in the trademarks, service
122
   marks, or logos of any Contributor (except as may be necessary to
123
   comply with the notice requirements in Section 3.4).
124
125
  2.4. Subsequent Licenses
126
127
   No Contributor makes additional grants as a result of Your choice to
128
   distribute the Covered Software under a subsequent version of this
129
   License (see Section 10.2) or under the terms of a Secondary License
130
   (if permitted under the terms of Section 3.3).
131
132
  2.5. Representation
133
134
   Each Contributor represents that the Contributor believes its
135
   Contributions are its original creation(s) or it has sufficient rights
136
   to grant the rights to its Contributions conveyed by this License.
137
138
  2.6. Fair Use
139
140
   This License is not intended to limit any rights You have under
141
   applicable copyright doctrines of fair use, fair dealing, or other
142
   equivalents.
143
144
  2.7. Conditions
145
146
   Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
147
   in Section 2.1.
148
149
3. Responsibilities
150
151
  3.1. Distribution of Source Form
152
153
   All distribution of Covered Software in Source Code Form, including any
154
   Modifications that You create or to which You contribute, must be under
155
   the terms of this License. You must inform recipients that the Source
156
   Code Form of the Covered Software is governed by the terms of this
157
   License, and how they can obtain a copy of this License. You may not
158
   attempt to alter or restrict the recipients’ rights in the Source Code
159
   Form.
160
161
  3.2. Distribution of Executable Form
162
163
   If You distribute Covered Software in Executable Form then:
164
    a. such Covered Software must also be made available in Source Code
165
       Form, as described in Section 3.1, and You must inform recipients
166
       of the Executable Form how they can obtain a copy of such Source
167
       Code Form by reasonable means in a timely manner, at a charge no
168
       more than the cost of distribution to the recipient; and
169
    b. You may distribute such Executable Form under the terms of this
170
       License, or sublicense it under different terms, provided that the
171
       license for the Executable Form does not attempt to limit or alter
172
       the recipients’ rights in the Source Code Form under this License.
173
174
  3.3. Distribution of a Larger Work
175
176
   You may create and distribute a Larger Work under terms of Your choice,
177
   provided that You also comply with the requirements of this License for
178
   the Covered Software. If the Larger Work is a combination of Covered
179
   Software with a work governed by one or more Secondary Licenses, and
180
   the Covered Software is not Incompatible With Secondary Licenses, this
181
   License permits You to additionally distribute such Covered Software
182
   under the terms of such Secondary License(s), so that the recipient of
183
   the Larger Work may, at their option, further distribute the Covered
184
   Software under the terms of either this License or such Secondary
185
   License(s).
186
187
  3.4. Notices
188
189
   You may not remove or alter the substance of any license notices
190
   (including copyright notices, patent notices, disclaimers of warranty,
191
   or limitations of liability) contained within the Source Code Form of
192
   the Covered Software, except that You may alter any license notices to
193
   the extent required to remedy known factual inaccuracies.
194
195
  3.5. Application of Additional Terms
196
197
   You may choose to offer, and to charge a fee for, warranty, support,
198
   indemnity or liability obligations to one or more recipients of Covered
199
   Software. However, You may do so only on Your own behalf, and not on
200
   behalf of any Contributor. You must make it absolutely clear that any
201
   such warranty, support, indemnity, or liability obligation is offered
202
   by You alone, and You hereby agree to indemnify every Contributor for
203
   any liability incurred by such Contributor as a result of warranty,
204
   support, indemnity or liability terms You offer. You may include
205
   additional disclaimers of warranty and limitations of liability
206
   specific to any jurisdiction.
207
208
4. Inability to Comply Due to Statute or Regulation
209
210
   If it is impossible for You to comply with any of the terms of this
211
   License with respect to some or all of the Covered Software due to
212
   statute, judicial order, or regulation then You must: (a) comply with
213
   the terms of this License to the maximum extent possible; and (b)
214
   describe the limitations and the code they affect. Such description
215
   must be placed in a text file included with all distributions of the
216
   Covered Software under this License. Except to the extent prohibited by
217
   statute or regulation, such description must be sufficiently detailed
218
   for a recipient of ordinary skill to be able to understand it.
219
220
5. Termination
221
222
   5.1. The rights granted under this License will terminate automatically
223
   if You fail to comply with any of its terms. However, if You become
224
   compliant, then the rights granted under this License from a particular
225
   Contributor are reinstated (a) provisionally, unless and until such
226
   Contributor explicitly and finally terminates Your grants, and (b) on
227
   an ongoing basis, if such Contributor fails to notify You of the
228
   non-compliance by some reasonable means prior to 60 days after You have
229
   come back into compliance. Moreover, Your grants from a particular
230
   Contributor are reinstated on an ongoing basis if such Contributor
231
   notifies You of the non-compliance by some reasonable means, this is
232
   the first time You have received notice of non-compliance with this
233
   License from such Contributor, and You become compliant prior to 30
234
   days after Your receipt of the notice.
235
236
   5.2. If You initiate litigation against any entity by asserting a
237
   patent infringement claim (excluding declaratory judgment actions,
238
   counter-claims, and cross-claims) alleging that a Contributor Version
239
   directly or indirectly infringes any patent, then the rights granted to
240
   You by any and all Contributors for the Covered Software under
241
   Section 2.1 of this License shall terminate.
242
243
   5.3. In the event of termination under Sections 5.1 or 5.2 above, all
244
   end user license agreements (excluding distributors and resellers)
245
   which have been validly granted by You or Your distributors under this
246
   License prior to termination shall survive termination.
247
248
6. Disclaimer of Warranty
249
250
   Covered Software is provided under this License on an “as is” basis,
251
   without warranty of any kind, either expressed, implied, or statutory,
252
   including, without limitation, warranties that the Covered Software is
253
   free of defects, merchantable, fit for a particular purpose or
254
   non-infringing. The entire risk as to the quality and performance of
255
   the Covered Software is with You. Should any Covered Software prove
256
   defective in any respect, You (not any Contributor) assume the cost of
257
   any necessary servicing, repair, or correction. This disclaimer of
258
   warranty constitutes an essential part of this License. No use of any
259
   Covered Software is authorized under this License except under this
260
   disclaimer.
261
262
7. Limitation of Liability
263
264
   Under no circumstances and under no legal theory, whether tort
265
   (including negligence), contract, or otherwise, shall any Contributor,
266
   or anyone who distributes Covered Software as permitted above, be
267
   liable to You for any direct, indirect, special, incidental, or
268
   consequential damages of any character including, without limitation,
269
   damages for lost profits, loss of goodwill, work stoppage, computer
270
   failure or malfunction, or any and all other commercial damages or
271
   losses, even if such party shall have been informed of the possibility
272
   of such damages. This limitation of liability shall not apply to
273
   liability for death or personal injury resulting from such party’s
274
   negligence to the extent applicable law prohibits such limitation. Some
275
   jurisdictions do not allow the exclusion or limitation of incidental or
276
   consequential damages, so this exclusion and limitation may not apply
277
   to You.
278
279
8. Litigation
280
281
   Any litigation relating to this License may be brought only in the
282
   courts of a jurisdiction where the defendant maintains its principal
283
   place of business and such litigation shall be governed by laws of that
284
   jurisdiction, without reference to its conflict-of-law provisions.
285
   Nothing in this Section shall prevent a party’s ability to bring
286
   cross-claims or counter-claims.
287
288
9. Miscellaneous
289
290
   This License represents the complete agreement concerning the subject
291
   matter hereof. If any provision of this License is held to be
292
   unenforceable, such provision shall be reformed only to the extent
293
   necessary to make it enforceable. Any law or regulation which provides
294
   that the language of a contract shall be construed against the drafter
295
   shall not be used to construe this License against a Contributor.
296
297
10. Versions of the License
298
299
  10.1. New Versions
300
301
   Mozilla Foundation is the license steward. Except as provided in
302
   Section 10.3, no one other than the license steward has the right to
303
   modify or publish new versions of this License. Each version will be
304
   given a distinguishing version number.
305
306
  10.2. Effect of New Versions
307
308
   You may distribute the Covered Software under the terms of the version
309
   of the License under which You originally received the Covered
310
   Software, or under the terms of any subsequent version published by the
311
   license steward.
312
313
  10.3. Modified Versions
314
315
   If you create software not governed by this License, and you want to
316
   create a new license for such software, you may create and use a
317
   modified version of this License if you rename the license and remove
318
   any references to the name of the license steward (except to note that
319
   such modified license differs from this License).
320
321
  10.4. Distributing Source Code Form that is Incompatible With Secondary
322
  Licenses
323
324
   If You choose to distribute Source Code Form that is Incompatible With
325
   Secondary Licenses under the terms of this version of the License, the
326
   notice described in Exhibit B of this License must be attached.
327
328
Exhibit A - Source Code Form License Notice
329
330
     This Source Code Form is subject to the terms of the Mozilla Public
331
     License, v. 2.0. If a copy of the MPL was not distributed with this
332
     file, You can obtain one at https://mozilla.org/MPL/2.0/.
333
334
   If it is not possible or desirable to put the notice in a particular
335
   file, then You may include the notice in a location (such as a LICENSE
336
   file in a relevant directory) where a recipient would be likely to look
337
   for such a notice.
338
339
   You may add additional accurate notices of copyright ownership.
340
341
Exhibit B - “Incompatible With Secondary Licenses” Notice
342
343
     This Source Code Form is “Incompatible With Secondary Licenses”, as
344
     defined by the Mozilla Public License, v. 2.0.
1345
A docs/licenses/UNDO-FX.md
1
Copyright (c) 2014, TomasMikula
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without modification,
5
are permitted provided that the following conditions are met:
6
7
* Redistributions of source code must retain the above copyright notice, this
8
  list of conditions and the following disclaimer.
9
10
* Redistributions in binary form must reproduce the above copyright notice, this
11
  list of conditions and the following disclaimer in the documentation and/or
12
  other materials provided with the distribution.
113
14
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
A docs/licenses/WELL-BEHAVED-FX.md
1
Copyright (c) 2014, TomasMikula
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without
5
modification, are permitted provided that the following conditions are met:
6
7
* Redistributions of source code must retain the above copyright notice, this
8
  list of conditions and the following disclaimer.
9
10
* Redistributions in binary form must reproduce the above copyright notice,
11
  this list of conditions and the following disclaimer in the documentation
12
  and/or other materials provided with the distribution.
13
14
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
125
A docs/licenses/fonts/NOTO-CJK.md
1
URL: https://github.com/googlefonts/noto-cjk
2
3
Version: 1.002 or later
4
5
License: SIL Open Font License v1.1
6
7
License File: LICENSE
8
9
Note: prior releases of the CJK fonts were issued under the Apache 2
10
license. This was changed to the SIL OFL v1.1 starting with Version 1.002.
11
12
Description:
13
Noto CJK fonts, supporting Simplified Chinese, Traditional Chinese,
14
Japanese, and Korean. The supported scripts are Han, Hiragana, Katakana,
15
Hangul, and Bopomofo. Latin, Greek, Cyrillic, and various symbols are also
16
supported for compatibility with CJK standards.
17
18
The fonts in this directory are developed by Google and Adobe and are
19
released as open source under the Apache license version 2.0. The copyright
20
is held by Adobe, while the trademarks on the names are held by Google.
21
22
A README-formats file has been added explaining the different formats
23
provided and their features and limitations.
124
A docs/licenses/fonts/NOTO-SANS.md
11
2
                                 Apache License
3
                           Version 2.0, January 2004
4
                        http://www.apache.org/licenses/
5
6
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
8
   1. Definitions.
9
10
      "License" shall mean the terms and conditions for use, reproduction,
11
      and distribution as defined by Sections 1 through 9 of this document.
12
13
      "Licensor" shall mean the copyright owner or entity authorized by
14
      the copyright owner that is granting the License.
15
16
      "Legal Entity" shall mean the union of the acting entity and all
17
      other entities that control, are controlled by, or are under common
18
      control with that entity. For the purposes of this definition,
19
      "control" means (i) the power, direct or indirect, to cause the
20
      direction or management of such entity, whether by contract or
21
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
      outstanding shares, or (iii) beneficial ownership of such entity.
23
24
      "You" (or "Your") shall mean an individual or Legal Entity
25
      exercising permissions granted by this License.
26
27
      "Source" form shall mean the preferred form for making modifications,
28
      including but not limited to software source code, documentation
29
      source, and configuration files.
30
31
      "Object" form shall mean any form resulting from mechanical
32
      transformation or translation of a Source form, including but
33
      not limited to compiled object code, generated documentation,
34
      and conversions to other media types.
35
36
      "Work" shall mean the work of authorship, whether in Source or
37
      Object form, made available under the License, as indicated by a
38
      copyright notice that is included in or attached to the work
39
      (an example is provided in the Appendix below).
40
41
      "Derivative Works" shall mean any work, whether in Source or Object
42
      form, that is based on (or derived from) the Work and for which the
43
      editorial revisions, annotations, elaborations, or other modifications
44
      represent, as a whole, an original work of authorship. For the purposes
45
      of this License, Derivative Works shall not include works that remain
46
      separable from, or merely link (or bind by name) to the interfaces of,
47
      the Work and Derivative Works thereof.
48
49
      "Contribution" shall mean any work of authorship, including
50
      the original version of the Work and any modifications or additions
51
      to that Work or Derivative Works thereof, that is intentionally
52
      submitted to Licensor for inclusion in the Work by the copyright owner
53
      or by an individual or Legal Entity authorized to submit on behalf of
54
      the copyright owner. For the purposes of this definition, "submitted"
55
      means any form of electronic, verbal, or written communication sent
56
      to the Licensor or its representatives, including but not limited to
57
      communication on electronic mailing lists, source code control systems,
58
      and issue tracking systems that are managed by, or on behalf of, the
59
      Licensor for the purpose of discussing and improving the Work, but
60
      excluding communication that is conspicuously marked or otherwise
61
      designated in writing by the copyright owner as "Not a Contribution."
62
63
      "Contributor" shall mean Licensor and any individual or Legal Entity
64
      on behalf of whom a Contribution has been received by Licensor and
65
      subsequently incorporated within the Work.
66
67
   2. Grant of Copyright License. Subject to the terms and conditions of
68
      this License, each Contributor hereby grants to You a perpetual,
69
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
      copyright license to reproduce, prepare Derivative Works of,
71
      publicly display, publicly perform, sublicense, and distribute the
72
      Work and such Derivative Works in Source or Object form.
73
74
   3. Grant of Patent License. Subject to the terms and conditions of
75
      this License, each Contributor hereby grants to You a perpetual,
76
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
      (except as stated in this section) patent license to make, have made,
78
      use, offer to sell, sell, import, and otherwise transfer the Work,
79
      where such license applies only to those patent claims licensable
80
      by such Contributor that are necessarily infringed by their
81
      Contribution(s) alone or by combination of their Contribution(s)
82
      with the Work to which such Contribution(s) was submitted. If You
83
      institute patent litigation against any entity (including a
84
      cross-claim or counterclaim in a lawsuit) alleging that the Work
85
      or a Contribution incorporated within the Work constitutes direct
86
      or contributory patent infringement, then any patent licenses
87
      granted to You under this License for that Work shall terminate
88
      as of the date such litigation is filed.
89
90
   4. Redistribution. You may reproduce and distribute copies of the
91
      Work or Derivative Works thereof in any medium, with or without
92
      modifications, and in Source or Object form, provided that You
93
      meet the following conditions:
94
95
      (a) You must give any other recipients of the Work or
96
          Derivative Works a copy of this License; and
97
98
      (b) You must cause any modified files to carry prominent notices
99
          stating that You changed the files; and
100
101
      (c) You must retain, in the Source form of any Derivative Works
102
          that You distribute, all copyright, patent, trademark, and
103
          attribution notices from the Source form of the Work,
104
          excluding those notices that do not pertain to any part of
105
          the Derivative Works; and
106
107
      (d) If the Work includes a "NOTICE" text file as part of its
108
          distribution, then any Derivative Works that You distribute must
109
          include a readable copy of the attribution notices contained
110
          within such NOTICE file, excluding those notices that do not
111
          pertain to any part of the Derivative Works, in at least one
112
          of the following places: within a NOTICE text file distributed
113
          as part of the Derivative Works; within the Source form or
114
          documentation, if provided along with the Derivative Works; or,
115
          within a display generated by the Derivative Works, if and
116
          wherever such third-party notices normally appear. The contents
117
          of the NOTICE file are for informational purposes only and
118
          do not modify the License. You may add Your own attribution
119
          notices within Derivative Works that You distribute, alongside
120
          or as an addendum to the NOTICE text from the Work, provided
121
          that such additional attribution notices cannot be construed
122
          as modifying the License.
123
124
      You may add Your own copyright statement to Your modifications and
125
      may provide additional or different license terms and conditions
126
      for use, reproduction, or distribution of Your modifications, or
127
      for any such Derivative Works as a whole, provided Your use,
128
      reproduction, and distribution of the Work otherwise complies with
129
      the conditions stated in this License.
130
131
   5. Submission of Contributions. Unless You explicitly state otherwise,
132
      any Contribution intentionally submitted for inclusion in the Work
133
      by You to the Licensor shall be under the terms and conditions of
134
      this License, without any additional terms or conditions.
135
      Notwithstanding the above, nothing herein shall supersede or modify
136
      the terms of any separate license agreement you may have executed
137
      with Licensor regarding such Contributions.
138
139
   6. Trademarks. This License does not grant permission to use the trade
140
      names, trademarks, service marks, or product names of the Licensor,
141
      except as required for reasonable and customary use in describing the
142
      origin of the Work and reproducing the content of the NOTICE file.
143
144
   7. Disclaimer of Warranty. Unless required by applicable law or
145
      agreed to in writing, Licensor provides the Work (and each
146
      Contributor provides its Contributions) on an "AS IS" BASIS,
147
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
      implied, including, without limitation, any warranties or conditions
149
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
      PARTICULAR PURPOSE. You are solely responsible for determining the
151
      appropriateness of using or redistributing the Work and assume any
152
      risks associated with Your exercise of permissions under this License.
153
154
   8. Limitation of Liability. In no event and under no legal theory,
155
      whether in tort (including negligence), contract, or otherwise,
156
      unless required by applicable law (such as deliberate and grossly
157
      negligent acts) or agreed to in writing, shall any Contributor be
158
      liable to You for damages, including any direct, indirect, special,
159
      incidental, or consequential damages of any character arising as a
160
      result of this License or out of the use or inability to use the
161
      Work (including but not limited to damages for loss of goodwill,
162
      work stoppage, computer failure or malfunction, or any and all
163
      other commercial damages or losses), even if such Contributor
164
      has been advised of the possibility of such damages.
165
166
   9. Accepting Warranty or Additional Liability. While redistributing
167
      the Work or Derivative Works thereof, You may choose to offer,
168
      and charge a fee for, acceptance of support, warranty, indemnity,
169
      or other liability obligations and/or rights consistent with this
170
      License. However, in accepting such obligations, You may act only
171
      on Your own behalf and on Your sole responsibility, not on behalf
172
      of any other Contributor, and only if You agree to indemnify,
173
      defend, and hold each Contributor harmless for any liability
174
      incurred by, or claims asserted against, such Contributor by reason
175
      of your accepting any such warranty or additional liability.
176
177
   END OF TERMS AND CONDITIONS
178
179
   APPENDIX: How to apply the Apache License to your work.
180
181
      To apply the Apache License to your work, attach the following
182
      boilerplate notice, with the fields enclosed by brackets "[]"
183
      replaced with your own identifying information. (Don't include
184
      the brackets!)  The text should be enclosed in the appropriate
185
      comment syntax for the file format. We also recommend that a
186
      file or class name and description of purpose be included on the
187
      same "printed page" as the copyright notice for easier
188
      identification within third-party archives.
189
190
   Copyright [yyyy] [name of copyright owner]
191
192
   Licensed under the Apache License, Version 2.0 (the "License");
193
   you may not use this file except in compliance with the License.
194
   You may obtain a copy of the License at
195
196
       http://www.apache.org/licenses/LICENSE-2.0
197
198
   Unless required by applicable law or agreed to in writing, software
199
   distributed under the License is distributed on an "AS IS" BASIS,
200
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
   See the License for the specific language governing permissions and
202
   limitations under the License.
203
A docs/licenses/fonts/NOTO.md
1
Copyright 2018 The Noto Project Authors (https://github.com/googlei18n/noto-fonts)
2
3
This Font Software is licensed under the SIL Open Font License,
4
Version 1.1.
5
6
This license is copied below, and is also available with a FAQ at:
7
http://scripts.sil.org/OFL
8
9
-----------------------------------------------------------
10
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
11
-----------------------------------------------------------
12
13
PREAMBLE
14
The goals of the Open Font License (OFL) are to stimulate worldwide
15
development of collaborative font projects, to support the font
16
creation efforts of academic and linguistic communities, and to
17
provide a free and open framework in which fonts may be shared and
18
improved in partnership with others.
19
20
The OFL allows the licensed fonts to be used, studied, modified and
21
redistributed freely as long as they are not sold by themselves. The
22
fonts, including any derivative works, can be bundled, embedded,
23
redistributed and/or sold with any software provided that any reserved
24
names are not used by derivative works. The fonts and derivatives,
25
however, cannot be released under any other type of license. The
26
requirement for fonts to remain under this license does not apply to
27
any document created using the fonts or their derivatives.
28
29
DEFINITIONS
30
"Font Software" refers to the set of files released by the Copyright
31
Holder(s) under this license and clearly marked as such. This may
32
include source files, build scripts and documentation.
33
34
"Reserved Font Name" refers to any names specified as such after the
35
copyright statement(s).
36
37
"Original Version" refers to the collection of Font Software
38
components as distributed by the Copyright Holder(s).
39
40
"Modified Version" refers to any derivative made by adding to,
41
deleting, or substituting -- in part or in whole -- any of the
42
components of the Original Version, by changing formats or by porting
43
the Font Software to a new environment.
44
45
"Author" refers to any designer, engineer, programmer, technical
46
writer or other person who contributed to the Font Software.
47
48
PERMISSION & CONDITIONS
49
Permission is hereby granted, free of charge, to any person obtaining
50
a copy of the Font Software, to use, study, copy, merge, embed,
51
modify, redistribute, and sell modified and unmodified copies of the
52
Font Software, subject to the following conditions:
53
54
1) Neither the Font Software nor any of its individual components, in
55
Original or Modified Versions, may be sold by itself.
56
57
2) Original or Modified Versions of the Font Software may be bundled,
58
redistributed and/or sold with any software, provided that each copy
59
contains the above copyright notice and this license. These can be
60
included either as stand-alone text files, human-readable headers or
61
in the appropriate machine-readable metadata fields within text or
62
binary files as long as those fields can be easily viewed by the user.
63
64
3) No Modified Version of the Font Software may use the Reserved Font
65
Name(s) unless explicit written permission is granted by the
66
corresponding Copyright Holder. This restriction only applies to the
67
primary font name as presented to the users.
68
69
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
70
Software shall not be used to promote, endorse or advertise any
71
Modified Version, except to acknowledge the contribution(s) of the
72
Copyright Holder(s) and the Author(s) or with their explicit written
73
permission.
74
75
5) The Font Software, modified or unmodified, in part or in whole,
76
must be distributed entirely under this license, and must not be
77
distributed under any other license. The requirement for fonts to
78
remain under this license does not apply to any document created using
79
the Font Software.
80
81
TERMINATION
82
This license becomes null and void if any of the above conditions are
83
not met.
84
85
DISCLAIMER
86
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
87
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
88
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
89
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
90
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
91
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
92
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
93
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
94
OTHER DEALINGS IN THE FONT SOFTWARE.
195
A docs/licenses/fonts/SOURCE-CODE-PRO.md
1
Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
2
3
This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
This license is copied below, and is also available with a FAQ at:
5
http://scripts.sil.org/OFL
6
7
8
-----------------------------------------------------------
9
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
-----------------------------------------------------------
11
12
PREAMBLE
13
The goals of the Open Font License (OFL) are to stimulate worldwide
14
development of collaborative font projects, to support the font creation
15
efforts of academic and linguistic communities, and to provide a free and
16
open framework in which fonts may be shared and improved in partnership
17
with others.
18
19
The OFL allows the licensed fonts to be used, studied, modified and
20
redistributed freely as long as they are not sold by themselves. The
21
fonts, including any derivative works, can be bundled, embedded, 
22
redistributed and/or sold with any software provided that any reserved
23
names are not used by derivative works. The fonts and derivatives,
24
however, cannot be released under any other type of license. The
25
requirement for fonts to remain under this license does not apply
26
to any document created using the fonts or their derivatives.
27
28
DEFINITIONS
29
"Font Software" refers to the set of files released by the Copyright
30
Holder(s) under this license and clearly marked as such. This may
31
include source files, build scripts and documentation.
32
33
"Reserved Font Name" refers to any names specified as such after the
34
copyright statement(s).
35
36
"Original Version" refers to the collection of Font Software components as
37
distributed by the Copyright Holder(s).
38
39
"Modified Version" refers to any derivative made by adding to, deleting,
40
or substituting -- in part or in whole -- any of the components of the
41
Original Version, by changing formats or by porting the Font Software to a
42
new environment.
43
44
"Author" refers to any designer, engineer, programmer, technical
45
writer or other person who contributed to the Font Software.
46
47
PERMISSION & CONDITIONS
48
Permission is hereby granted, free of charge, to any person obtaining
49
a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
redistribute, and sell modified and unmodified copies of the Font
51
Software, subject to the following conditions:
52
53
1) Neither the Font Software nor any of its individual components,
54
in Original or Modified Versions, may be sold by itself.
55
56
2) Original or Modified Versions of the Font Software may be bundled,
57
redistributed and/or sold with any software, provided that each copy
58
contains the above copyright notice and this license. These can be
59
included either as stand-alone text files, human-readable headers or
60
in the appropriate machine-readable metadata fields within text or
61
binary files as long as those fields can be easily viewed by the user.
62
63
3) No Modified Version of the Font Software may use the Reserved Font
64
Name(s) unless explicit written permission is granted by the corresponding
65
Copyright Holder. This restriction only applies to the primary font name as
66
presented to the users.
67
68
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
Software shall not be used to promote, endorse or advertise any
70
Modified Version, except to acknowledge the contribution(s) of the
71
Copyright Holder(s) and the Author(s) or with their explicit written
72
permission.
73
74
5) The Font Software, modified or unmodified, in part or in whole,
75
must be distributed entirely under this license, and must not be
76
distributed under any other license. The requirement for fonts to
77
remain under this license does not apply to any document created
78
using the Font Software.
79
80
TERMINATION
81
This license becomes null and void if any of the above conditions are
82
not met.
83
84
DISCLAIMER
85
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
OTHER DEALINGS IN THE FONT SOFTWARE.
194
A docs/licenses/fonts/SOURCE-SERIF-4.md
1
Copyright 2014-2019 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries.
2
3
This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
5
This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
6
7
8
-----------------------------------------------------------
9
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
-----------------------------------------------------------
11
12
PREAMBLE
13
The goals of the Open Font License (OFL) are to stimulate worldwide
14
development of collaborative font projects, to support the font creation
15
efforts of academic and linguistic communities, and to provide a free and
16
open framework in which fonts may be shared and improved in partnership
17
with others.
18
19
The OFL allows the licensed fonts to be used, studied, modified and
20
redistributed freely as long as they are not sold by themselves. The
21
fonts, including any derivative works, can be bundled, embedded,
22
redistributed and/or sold with any software provided that any reserved
23
names are not used by derivative works. The fonts and derivatives,
24
however, cannot be released under any other type of license. The
25
requirement for fonts to remain under this license does not apply
26
to any document created using the fonts or their derivatives.
27
28
DEFINITIONS
29
"Font Software" refers to the set of files released by the Copyright
30
Holder(s) under this license and clearly marked as such. This may
31
include source files, build scripts and documentation.
32
33
"Reserved Font Name" refers to any names specified as such after the
34
copyright statement(s).
35
36
"Original Version" refers to the collection of Font Software components as
37
distributed by the Copyright Holder(s).
38
39
"Modified Version" refers to any derivative made by adding to, deleting,
40
or substituting -- in part or in whole -- any of the components of the
41
Original Version, by changing formats or by porting the Font Software to a
42
new environment.
43
44
"Author" refers to any designer, engineer, programmer, technical
45
writer or other person who contributed to the Font Software.
46
47
PERMISSION & CONDITIONS
48
Permission is hereby granted, free of charge, to any person obtaining
49
a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
redistribute, and sell modified and unmodified copies of the Font
51
Software, subject to the following conditions:
52
53
1) Neither the Font Software nor any of its individual components,
54
in Original or Modified Versions, may be sold by itself.
55
56
2) Original or Modified Versions of the Font Software may be bundled,
57
redistributed and/or sold with any software, provided that each copy
58
contains the above copyright notice and this license. These can be
59
included either as stand-alone text files, human-readable headers or
60
in the appropriate machine-readable metadata fields within text or
61
binary files as long as those fields can be easily viewed by the user.
62
63
3) No Modified Version of the Font Software may use the Reserved Font
64
Name(s) unless explicit written permission is granted by the corresponding
65
Copyright Holder. This restriction only applies to the primary font name as
66
presented to the users.
67
68
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
Software shall not be used to promote, endorse or advertise any
70
Modified Version, except to acknowledge the contribution(s) of the
71
Copyright Holder(s) and the Author(s) or with their explicit written
72
permission.
73
74
5) The Font Software, modified or unmodified, in part or in whole,
75
must be distributed entirely under this license, and must not be
76
distributed under any other license. The requirement for fonts to
77
remain under this license does not apply to any document created
78
using the Font Software.
79
80
TERMINATION
81
This license becomes null and void if any of the above conditions are
82
not met.
83
84
DISCLAIMER
85
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
OTHER DEALINGS IN THE FONT SOFTWARE.
194
A docs/skins.md
1
# Skins
2
3
The application provides bundled skins and the ability to add custom
4
skins. This document describes the interplay between bundled skins
5
and building your own look and feel.
6
7
A skin is a set of styles, similar to cascading style sheet classes,
8
that configures the user interface colours, fonts, spacing, highlights,
9
drop-shadows, gradients, and more.
10
11
For more information on CSS, see the [W3C CSS tutorial](https://www.w3.org/Style/Examples/011/firstcss).
12
13
# Order
14
15
The order that stylesheets are applied matters so that stylesheets can
16
override styles defined previously. The application's user interface
17
is made up of the following stylesheets, applied in the order listed:
18
19
* **scene.css** --- Defines toolbar styling.
20
* **markdown.css** --- Defines text editor styling.
21
* **skins/skin_name.css** --- Bundled skin selected in preferences.
22
* **custom.css** --- User-defined file set in preferences.
23
24
# Customization
25
26
Create a custom skin as follows:
27
28
1. Start the application.
29
1. Click **File → New** to create a new file.
30
1. Click **File → Save As** to rename the file.
31
1. Save the file as `custom.css`.
32
1. Change the content to the following:
33
``` css
34
.root {
35
  -fx-base: rgb( 30, 30, 30 );
36
  -fx-background: -fx-base;
37
}
38
```
39
40
Next, apply the skin as follows:
41
42
1. Click **Edit → Preferences** to open the preferences dialog.
43
1. Click **Skins** to view the available options.
44
1. Click **Browse** to select a custom file.
45
1. Browse to and select `custom.css`, created previously.
46
1. Click **Open**.
47
1. Click **Apply**.
48
49
The user interface immediately changes to a dark mode. Continue:
50
51
1. Click **OK** to close the dialog.
52
1. Change the **rgb** numbers in **custom.css** from `30` to `60`.
53
1. Click **File → Save** to save the CSS file.
54
55
The user interface immediately changes colour.
56
57
# Classes
58
59
When creating your own skin, there many classes that can be styled. The
60
previous section showed how to set up a rudimentary skin. Instead, start
61
with a template that already has a number of classes defined so that you
62
can tweak them to your taste. Accomplish this as follows:
63
64
1. Visit the [skin](https://github.com/DaveJarvis/keenwrite/tree/master/src/main/resources/com/keenwrite/skins) repository directory
65
1. Click one of the files (e.g., `haunted_grey.css`).
66
1. Click **Raw**.
67
1. Copy the entire text.
68
1. Return to `custom.css`.
69
1. Delete the contents.
70
1. Paste the copied text.
71
1. Save the file.
72
73
To see how the CSS styles are applied to the text editor, open
74
[markdown.css](https://github.com/DaveJarvis/keenwrite/blob/master/src/main/resources/com/keenwrite/editor/markdown.css), which is also in the repository.
75
76
# Modena
77
78
The basic look used by the application is _Modena Light_. Typically we
79
only need to override a few classes to completely change the application's
80
look and feel. For a full listing of available styles see the OpenJDK's
81
[Modena CSS file](https://github.com/openjdk/jfx/blob/master/modules/javafx.controls/src/main/resources/com/sun/javafx/scene/control/skin/modena/modena.css).
82
83
# JavaFX CSS
84
85
The [Java CSS Reference Guide](https://openjfx.io/javadoc/11/javafx.graphics/javafx/scene/doc-files/cssref.html) is exhaustive. In addition to showing many
86
differences between JavaFX CSS and W3C CSS, the guide introduces numerous
87
helpful functions for manipulating colours and gradients using existing
88
colour definitions.
89
90
# RichTextFX
91
92
The application uses RichTextFX to render the text editor. Styling various
93
text editor classes can require using the prefix `-rtfx` instead of the
94
regular JavaFX `-fx`.
95
96
# Submit
97
98
If you have a look that you'd like to contribute to the project, do pass
99
it along. Either open a new issue in the [issue tracker](https://github.com/DaveJarvis/keenwrite/issues) that contains the CSS file or submit a pull request.
100
1101
D docs/themes.md
1
# Themes
2
3
The application provides bundled themes and the ability to add custom
4
themes. This document describes the interplay between bundled themes
5
and building your own theme.
6
7
A theme is a set of styles, similar to cascading style sheet classes,
8
that instruct the user interface on how to apply colours, fonts, spacing,
9
highlights, drop-shadows, gradients, and so forth.
10
11
For more information on CSS, see the [W3C CSS tutorial](https://www.w3.org/Style/Examples/011/firstcss).
12
13
# Order
14
15
The order that stylesheets are applied matters so that stylesheets can
16
override styles defined previously. The application's user interface
17
is made up of the following stylesheets, applied in the order listed:
18
19
* **scene.css** --- Defines toolbar styling.
20
* **markdown.css** --- Defines text editor styling.
21
* **themes/theme_name.css** --- Bundled theme selected in preferences.
22
* **custom.css** --- User-defined file set in preferences.
23
24
# Customization
25
26
Create a custom theme as follows:
27
28
1. Start the application.
29
1. Click **File → New** to create a new file.
30
1. Click **File → Save As** to rename the file.
31
1. Save the file as `custom.css`.
32
1. Change the content to the following:
33
``` css
34
.root {
35
  -fx-base: rgb( 30, 30, 30 );
36
  -fx-background: -fx-base;
37
}
38
```
39
40
Next, apply the theme as follows:
41
42
1. Click **Edit → Preferences** to open the preferences dialog.
43
1. Click **Themes** to view the theme options.
44
1. Click **Browse** to select a custom theme file.
45
1. Browse to and select `custom.css`, created previously.
46
1. Click **Open**.
47
1. Click **Apply**.
48
49
The user interface immediately changes to a dark mode. Continue:
50
51
1. Click **OK** to close the dialog.
52
1. Change the **rgb** numbers in **custom.css** from `30` to `60`.
53
1. Click **File → Save** to save the CSS file.
54
55
The user interface immediately changes colour.
56
57
# Classes
58
59
When creating your own theme, there many classes that can be styled. The
60
previous section showed how to set up a rudimentary theme. Instead, start
61
with a template that already has a number of classes defined so that you
62
can tweak them to your taste. Accomplish this as follows:
63
64
1. Visit the [themes](https://github.com/DaveJarvis/keenwrite/tree/master/src/main/resources/com/keenwrite/themes) repository directory
65
1. Click one of the themes (e.g., `haunted_grey.css`).
66
1. Click **Raw**.
67
1. Copy the entire text.
68
1. Return to `custom.css`.
69
1. Delete the contents.
70
1. Paste the copied text.
71
1. Save the file.
72
73
To see how the CSS styles are applied to the text editor, open
74
[markdown.css](https://github.com/DaveJarvis/keenwrite/blob/master/src/main/resources/com/keenwrite/editor/markdown.css), which is also in the repository.
75
76
# Modena
77
78
The basic theme used by the application is _Modena Light_. Typically we
79
only need to override a few classes to completely change the application's
80
look and feel. For a full listing of available styles see the OpenJDK's
81
[Modena CSS file](https://github.com/openjdk/jfx/blob/master/modules/javafx.controls/src/main/resources/com/sun/javafx/scene/control/skin/modena/modena.css).
82
83
# JavaFX CSS
84
85
The [Java CSS Reference Guide](https://openjfx.io/javadoc/11/javafx.graphics/javafx/scene/doc-files/cssref.html) is exhaustive. In addition to showing many
86
differences between JavaFX CSS and W3C CSS, the guide introduces numerous
87
helpful functions for manipulating colours and gradients using existing
88
colour definitions.
89
90
# RichTextFX
91
92
The application uses RichTextFX to render the text editor. Styling various
93
text editor classes can require using the prefix `-rtfx` instead of the
94
regular JavaFX `-fx`.
95
96
# Submit
97
98
Send in your themes! If you have a theme you'd like to contribute to the
99
project, or improvements to an existing theme, do pass it along. Either open a new issue in the [issue tracker](https://github.com/DaveJarvis/keenwrite/issues) that contains the CSS file or submit a pull request.
100
1011
A docs/typesetting.md
1
# Overview
2
3
Typesetting PDF files entails the following:
4
5
* Download and install typesetting software
6
* Download a theme pack
7
8
These are described in the subsequent sections. Once the requirements have been met, continue reading to learn how to typeset a document.
9
10
# Download typesetter
11
12
Download the typesetting software as follows:
13
14
1. Start the text editor.
15
1. Click **File → Export As → PDF**.
16
    * Note the following details (e.g., Windows X86 64-bit):
17
        * operating system name;
18
        * instruction set; and
19
        * architecture.
20
1. Click the [link](https://wiki.contextgarden.net/Installation) in the dialog.
21
1. Download the appropriate archive file.
22
23
# Install typesetter
24
25
This section describes the installation steps for various platforms. Follow the steps that apply to the computer's operating system:
26
27
* [Windows](#windows) (includes Windows 7, Windows 10, and similar)
28
* [Unix](#unix) (includes MacOS, FreeBSD, Linux, and similar)
29
30
## Windows
31
32
Proceed with a Windows installation of typesetting software as follows:
33
34
1. Extract the `.zip` file into `C:\Users\%USERNAME%\AppData\Local\context` (the "root" directory)
35
1. Run **install.bat** to download and install the software.
36
    * If prompted, click **Run anyway** (or click **More info** first).
37
1. Right-click <a href="https://github.com/DaveJarvis/keenwrite/raw/master/scripts/localpath.bat">localpath.bat</a>.
38
1. Select **Save Link As** (or similar).
39
1. Save the file to the typesetting software's "root" directory.
40
1. Rename `localpath.bat.txt` to `localpath.bat`, if necessary.
41
1. Run `localpath.bat` (to set and save the `PATH` environment variable).
42
43
Installation is complete. Verify the installation as follows:
44
45
1. Type: `context --version`
46
1. Press `Enter`.
47
48
If version information is displayed then the software is installed correctly.
49
50
Continue by installing a [theme pack](#theme-pack).
51
52
## Unix
53
54
For Linux, MacOS, FreeBSD, and similar operating systems, proceed as follows:
55
56
1. Create `$HOME/.local/bin/context`
57
1. Extract the `.zip` file within `$HOME/.local/bin/context`
58
1. Run `sh install.sh`
59
1. Add `export PATH=$PATH:$HOME/.local/bin/context/tex/texmf-linux-64/bin` to the login script.
60
61
Installation is complete. Verify the installation as follows:
62
63
1. Open a new terminal (to export the new PATH setting).
64
1. Type: `context --version`
65
1. Press `Enter`.
66
67
If version information is displayed then the software is installed correctly.
68
69
Continue by installing a [theme pack](#theme-pack).
70
71
# Theme pack
72
73
A theme pack is a set of themes that define how documents appear when typeset. Broadly, themes are applied as follows:
74
75
* Install a theme pack
76
* Configure individual themes
77
78
## Install theme pack
79
80
Install and configure the default theme pack as follows:
81
82
1. Download the <a href="https://github.com/DaveJarvis/keenwrite-themes/raw/main/theme-pack.zip">theme-pack.zip</a> archive.
83
1. Extract archive into a known location.
84
1. Start the text editor, if not already running.
85
1. Click **Edit → Preferences**.
86
1. Click **Typesetting**.
87
1. Click **Browse** beside **Themes**.
88
1. Navigate to the `themes` directory.
89
1. Click **Open**.
90
1. Click **OK**.
91
92
The theme pack is installed.
93
94
Each theme has its own requirements, described below. 
95
96
## Configure Boschet theme
97
98
Download and install the following font families:
99
100
* [Libre Baskerville](https://fonts.google.com/specimen/Libre+Baskerville)
101
* [Archivo Narrow](https://fonts.google.com/specimen/Archivo+Narrow)
102
* [Inconsolata](https://fonts.google.com/specimen/Inconsolata)
103
104
The theme is configured.
105
106
# Typeset document
107
108
Typeset a document as follows:
109
110
1. Start the text editor, if not already running.
111
1. Click **File → New** (or type `Ctrl+n`).
112
1. Type in some text.
113
1. Click **File → Export As → PDF** (or type `Ctrl+p`).
114
1. Select a theme from the drop-down list.
115
1. Click **OK** (or press `Enter`).
116
1. Set the **File name** to the PDF file name.
117
1. Click **Save**.
118
119
The document is typeset; open the PDF file in a PDF reader to view the result.
120
121
# Background 
122
123
This text editor helps keep content separated from presentation. Plain text documents will remain readable long after proprietary formats have become obsolete. However, we've come to expect much more in what we read than mere text: from hyperlinked tables of contents to indexes, from footers to footnotes, from mathematical expressions to complex graphics, modern documents are nuanced and multifaceted.
124
125
## History
126
127
Before computer-based typesetting, much of mathematics was put to page by hand. Professional typesetters, who were often expensive and usually not mathematicians, would inadvertently introduce typographic errors into equations. Phototypesetting technology improved upon hand-typesetting, but well-known computer scientist Donald Knuth---whose third volume of *The Art of Computer Programming* was phototypeset in 1976---expressed dissatisfaction with its typographic quality. He set himself two goals: let anyone create high-quality books without much effort and provide software that typesets consistently on all capable computers. Two years later, he released a typesetting system and a font description language: TeX and METAFONT, respectively.
128
129
In short, TeX is software that helps typeset plain text documents.
130
131
## ConTeXt
132
133
Programming computers to typeset internationalized text automatically at the level we've become accustomed takes decades of development effort. Many free and open source software solutions can typeset text, including: ConTeXt, LaTeX, Sile, and others. ConTeXt, which builds upon TeX, is ideal for typesetting plain text into beautiful documents because it is developed with a notion of *setups*. These setups can wholly describe how text is to be typeset and---by being external to the text itself---configuring setups provides ample control over the document's final appearance without changing the prose.
134
135
# Further reading
136
137
Here are a few documents that introduce the typesetting system:
138
139
* *What is ConTeXt?* ([English](https://www.pragma-ade.com/general/manuals/what-is-context.pdf))
140
* *A not so short introduction to ConTeXt* ([English](https://github.com/contextgarden/not-so-short-introduction-to-context/raw/main/en/introCTX_eng.pdf) or [Spanish](https://raw.githubusercontent.com/contextgarden/not-so-short-introduction-to-context/main/es/introCTX_esp.pdf))
141
* *Dealing with XML in ConTeXt MKIV* ([English](https://pragma-ade.com/general/manuals/xml-mkiv.pdf))
142
* *Typographic Programming* ([English](https://www.pragma-ade.com/general/manuals/style.pdf))
143
144
The [documentation library](https://wiki.contextgarden.net/Documentation) includes the following gems:
145
146
* [ConTeXt Manual](https://www.pragma-ade.nl/general/manuals/ma-cb-en.pdf)
147
* [ConTeXt command reference](https://www.pragma-ade.nl/general/qrcs/setup-en.pdf)
148
* [METAFUN Manual](https://www.pragma-ade.nl/general/manuals/metafun-p.pdf)
149
* [It's in the Details](https://www.pragma-ade.nl/general/manuals/details.pdf)
150
* [Fonts out of ConTeXt](https://www.pragma-ade.com/general/manuals/fonts-mkiv.pdf)
151
152
Expert-level documentation includes the [LuaTeX Reference Manual](https://www.pragma-ade.nl/general/manuals/luatex.pdf).
153
1154
A docs/video/.gitignore
1
*.avi
2
*.wav
3
*.png
4
*.mp4
5
*.mp3
6
17
A docs/video/title.blend
Binary file
A docs/video/traced-text.svg
1
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
<svg
3
   xmlns:dc="http://purl.org/dc/elements/1.1/"
4
   xmlns:cc="http://creativecommons.org/ns#"
5
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
6
   xmlns:svg="http://www.w3.org/2000/svg"
7
   xmlns="http://www.w3.org/2000/svg"
8
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
9
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
10
   width="211.87125mm"
11
   height="56.576mm"
12
   viewBox="0 0 211.87125 56.576"
13
   version="1.1"
14
   id="svg8"
15
   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
16
   sodipodi:docname="traced-text.svg">
17
  <defs
18
     id="defs2" />
19
  <sodipodi:namedview
20
     id="base"
21
     pagecolor="#ffffff"
22
     bordercolor="#666666"
23
     borderopacity="1.0"
24
     inkscape:pageopacity="0.0"
25
     inkscape:pageshadow="2"
26
     inkscape:zoom="1.4142136"
27
     inkscape:cx="367.6429"
28
     inkscape:cy="129.23348"
29
     inkscape:document-units="mm"
30
     inkscape:current-layer="layer1"
31
     inkscape:document-rotation="0"
32
     showgrid="false"
33
     fit-margin-top="10"
34
     fit-margin-left="10"
35
     fit-margin-right="10"
36
     fit-margin-bottom="10" />
37
  <metadata
38
     id="metadata5">
39
    <rdf:RDF>
40
      <cc:Work
41
         rdf:about="">
42
        <dc:format>image/svg+xml</dc:format>
43
        <dc:type
44
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
45
        <dc:title></dc:title>
46
      </cc:Work>
47
    </rdf:RDF>
48
  </metadata>
49
  <g
50
     inkscape:label="Layer 1"
51
     inkscape:groupmode="layer"
52
     id="layer1"
53
     transform="translate(-1.4263456,-106.05539)">
54
    <text
55
       xml:space="preserve"
56
       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.8px;line-height:1.25;font-family:'Alex Brush';-inkscape-font-specification:'Alex Brush, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
57
       x="12.289946"
58
       y="147.80539"
59
       id="text835"><tspan
60
         sodipodi:role="line"
61
         id="tspan833"
62
         x="12.289946"
63
         y="147.80539"
64
         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.8px;font-family:'Alex Brush';-inkscape-font-specification:'Alex Brush, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.264583">Scrivenvar</tspan></text>
65
    <path
66
       sodipodi:nodetypes="cssssc"
67
       id="path859"
68
       d="m 47.37594,126.25759 c 5.878995,0.58684 8.108819,-2.8906 6.991897,-5.39049 -4.163299,-9.31827 -26.104298,-1.57165 -26.47428,4.67958 -0.290066,4.90098 4.329286,5.69691 9.138161,6.81221 4.75698,1.10326 9.980125,1.72503 10.138085,4.5281 0.511551,9.07772 -11.28247,13.50974 -21.577969,13.14767"
69
       style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#4eb059;stroke-width:0.132292;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
70
    <path
71
       sodipodi:nodetypes="cssc"
72
       id="path861"
73
       d="m 61.538159,137.91416 c 8.229745,-12.05206 -9.227635,-1.22793 -10.272792,5.40306 -0.929347,5.89623 4.566953,5.63307 9.024721,2.11036 5.095939,-4.02702 8.706628,-8.11599 12.031905,-13.9409"
74
       style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#4eb059;stroke-width:0.132292;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
75
    <path
76
       sodipodi:nodetypes="ccssc"
77
       id="path863"
78
       d="m 72.321991,131.48668 c 3.834665,-5.91801 -1.131419,0.83402 0.75311,2.48796 2.189872,1.94816 6.580549,-2.11016 5.400159,-0.72958 -0.854851,0.99983 -9.857527,10.41157 -5.126492,13.80621 2.461609,1.76627 8.936925,-2.58857 11.751532,-5.5313"
79
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
80
    <path
81
       sodipodi:nodetypes="csssc"
82
       id="path963"
83
       d="m 85.1003,141.51997 c 0,0 6.754775,-9.24626 6.743495,-8.01563 -0.01328,1.44899 -5.040946,6.68411 -6.63123,10.08427 -0.90584,1.93677 -0.626402,4.68995 2.447111,4.25184 1.468017,-0.20926 5.212094,-2.44913 10.029682,-7.66684"
84
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
85
    <path
86
       sodipodi:nodetypes="csccc"
87
       id="path965"
88
       d="m 97.689357,140.17361 c 0,0 3.797813,-8.42805 4.594353,-7.95573 0.58723,0.34822 -6.526154,13.32545 -5.477472,14.50806 2.435753,1.7862 19.064212,-11.51107 15.563042,-16.73913 -0.73409,-1.34256 -3.18033,-1.99148 -3.18033,-1.99148"
89
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
90
    <path
91
       sodipodi:nodetypes="csssc"
92
       d="m 113.37707,141.34636 c 4.23091,0.29831 11.94363,-4.90618 10.94354,-7.7799 -1.29105,-3.70978 -8.05529,1.78774 -9.69006,3.68511 -4.97668,5.77609 -4.11733,10.31478 -0.92228,10.61275 3.436,0.32045 8.83724,-3.13085 13.69698,-9.62574"
93
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
94
       id="path967" />
95
    <path
96
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
97
       d="m 146.49943,140.17361 c 0,0 3.79781,-8.42805 4.59435,-7.95573 0.58723,0.34822 -6.52616,13.32545 -5.47747,14.50806 2.43575,1.7862 19.06421,-11.51107 15.56304,-16.73913 -0.73409,-1.34256 -3.10123,-1.96263 -3.10123,-1.96263"
98
       id="path970"
99
       sodipodi:nodetypes="csccc" />
100
    <path
101
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
102
       d="m 188.80833,131.36316 c 3.83466,-5.91801 -1.13142,0.83402 0.75311,2.48796 2.18987,1.94816 6.58055,-2.11016 5.40016,-0.72958 -0.85485,0.99983 -9.98962,10.60367 -5.12649,13.80621 2.8329,1.86556 9.63808,-2.25455 13.61435,-8.05051"
103
       id="path987"
104
       sodipodi:nodetypes="ccssc" />
105
    <path
106
       sodipodi:nodetypes="ccsssccc"
107
       d="m 127.40525,138.23858 c 1.53961,-1.23511 5.06979,-6.4876 5.94375,-5.82833 -1.7832,2.5949 -8.95273,13.68991 -7.1105,13.94503 1.19011,0.16482 7.25976,-8.00422 10.87675,-10.901 1.83151,-1.46682 4.35069,-3.49971 5.94917,-3.73267 1.66376,-0.24247 -1.93803,2.90472 -3.80099,5.77097 -1.36327,2.14988 -4.92421,8.02816 -2.69839,9.35481 3.0826,1.21137 7.35116,-4.27566 9.93439,-6.67382"
108
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
109
       id="path989" />
110
    <path
111
       sodipodi:nodetypes="csscsc"
112
       id="path992"
113
       d="m 176.85645,132.78853 c -3.26879,-6.24001 -16.43513,7.99373 -16.14879,12.14556 0.1378,1.99804 2.16776,3.14653 3.8818,2.44798 4.44909,-1.8132 11.93103,-13.58278 13.4413,-14.18515 -6.97685,9.84354 -7.04537,13.29844 -4.02229,13.83262 2.49715,0.44125 8.94275,-6.11484 14.79986,-15.66638"
114
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
115
  </g>
116
</svg>
1117
D font-names
1
#!/usr/bin/env bash
2
3
# Outputs font names for all font files.
4
5
find src/main/resources/fonts -type f \( -name "*otf" -o -name "*ttf" \) -exec \
6
  fc-scan --format "%{foundry}: %{family}\n" {} \; | uniq | sort
7
81
D installer
1
#!/usr/bin/env bash
2
3
# ---------------------------------------------------------------------------
4
# This script cross-compiles application launchers for different platforms.
5
#
6
# The application binaries are self-contained launchers that do not need
7
# to be installed.
8
# ---------------------------------------------------------------------------
9
10
source $HOME/bin/build-template
11
12
readonly APP_NAME=$(find "${SCRIPT_DIR}/src" -type f -name "settings.properties" -exec cat {} \; | grep "application.title=" | cut -d'=' -f2)
13
readonly FILE_APP_JAR="${APP_NAME}.jar"
14
15
ARG_JAVA_OS="linux"
16
ARG_JAVA_ARCH="amd64"
17
ARG_JAVA_VERSION="15.0.2"
18
ARG_JAVA_UPDATE="10"
19
ARG_JAVA_DIR="java"
20
21
ARG_DIR_DIST="dist"
22
23
FILE_DIST_EXEC="run.sh"
24
25
ARG_PATH_DIST_JAR="${SCRIPT_DIR}/build/libs/${FILE_APP_JAR}"
26
27
DEPENDENCIES=(
28
  "gradle,https://gradle.org"
29
  "warp-packer,https://github.com/dgiagio/warp"
30
  "tar,https://www.gnu.org/software/tar"
31
  "unzip,http://infozip.sourceforge.net"
32
)
33
34
ARGUMENTS+=(
35
  "a,arch,Target operating system architecture (amd64)"
36
  "o,os,Target operating system (linux, windows, mac)"
37
  "u,update,Java update version number (${ARG_JAVA_UPDATE})"
38
  "v,version,Full Java version (${ARG_JAVA_VERSION})"
39
)
40
41
ARCHIVE_EXT="tar.gz"
42
ARCHIVE_APP="tar xf"
43
APP_EXTENSION="bin"
44
45
# ---------------------------------------------------------------------------
46
# Generates
47
# ---------------------------------------------------------------------------
48
execute() {
49
  $do_configure_target
50
  $do_build
51
  $do_clean
52
53
  pushd "${ARG_DIR_DIST}" > /dev/null 2>&1
54
55
  $do_extract_java
56
  $do_create_launch_script
57
  $do_copy_archive
58
59
  popd > /dev/null 2>&1
60
61
  $do_create_launcher
62
63
  return 1
64
}
65
66
# ---------------------------------------------------------------------------
67
# Configure platform-specific commands and file names.
68
# ---------------------------------------------------------------------------
69
utile_configure_target() {
70
  if [ "${ARG_JAVA_OS}" = "windows" ]; then
71
    ARCHIVE_EXT="zip"
72
    ARCHIVE_APP="unzip -qq"
73
    FILE_DIST_EXEC="run.bat"
74
    APP_EXTENSION="exe"
75
    do_create_launch_script=utile_create_launch_script_windows
76
  fi
77
}
78
79
# ---------------------------------------------------------------------------
80
# Build platform-specific überjar.
81
# ---------------------------------------------------------------------------
82
utile_build() {
83
  $log "Delete ${ARG_PATH_DIST_JAR}"
84
  rm -f "${ARG_PATH_DIST_JAR}"
85
86
  $log "Build application for ${ARG_JAVA_OS}"
87
  gradle clean jar -PtargetOs="${ARG_JAVA_OS}"
88
}
89
90
# ---------------------------------------------------------------------------
91
# Purges the existing distribution directory to recreate the launcher.
92
# This refreshes the JRE from the downloaded archive.
93
# ---------------------------------------------------------------------------
94
utile_clean() {
95
  $log "Recreate ${ARG_DIR_DIST}"
96
  rm -rf "${ARG_DIR_DIST}"
97
  mkdir -p "${ARG_DIR_DIST}"
98
}
99
100
# ---------------------------------------------------------------------------
101
# Extract platform-specific Java Runtime Environment. This will download
102
# and cache the required Java Runtime Environment for the target platform.
103
# On subsequent runs, the cached version is used, instead of issuing another
104
# download.
105
# ---------------------------------------------------------------------------
106
utile_extract_java() {
107
  $log "Extract Java"
108
  local -r java_vm="jre"
109
  local -r java_version="${ARG_JAVA_VERSION}+${ARG_JAVA_UPDATE}"
110
  local -r url_java="https://download.bell-sw.com/java/${java_version}/bellsoft-${java_vm}${java_version}-${ARG_JAVA_OS}-${ARG_JAVA_ARCH}-full.${ARCHIVE_EXT}"
111
112
  local -r file_java="${java_vm}-${java_version}-${ARG_JAVA_OS}-${ARG_JAVA_ARCH}.${ARCHIVE_EXT}"
113
  local -r path_java="/tmp/${file_java}"
114
115
  # File must have contents.
116
  if [ ! -s ${path_java} ]; then
117
    $log "Download ${url_java} to ${path_java}"
118
    wget -q "${url_java}" -O "${path_java}"
119
  fi
120
121
  $log "Unpack ${path_java}"
122
  $ARCHIVE_APP "${path_java}"
123
124
  local -r dir_java="${java_vm}-${ARG_JAVA_VERSION}-full"
125
126
  $log "Rename ${dir_java} to ${ARG_JAVA_DIR}"
127
  mv "${dir_java}" "${ARG_JAVA_DIR}"
128
}
129
130
# ---------------------------------------------------------------------------
131
# Create Linux-specific launch script.
132
# ---------------------------------------------------------------------------
133
utile_create_launch_script_linux() {
134
  $log "Create Linux launch script"
135
136
  cat > "${FILE_DIST_EXEC}" << __EOT
137
#!/usr/bin/env bash
138
139
readonly SCRIPT_SRC="\$(dirname "\${BASH_SOURCE[\${#BASH_SOURCE[@]} - 1]}")"
140
141
"\${SCRIPT_SRC}/${ARG_JAVA_DIR}/bin/java" -jar "\${SCRIPT_SRC}/${FILE_APP_JAR}" "\$@" 2>&1 >/dev/null &
142
__EOT
143
144
  chmod +x "${FILE_DIST_EXEC}"
145
}
146
147
# ---------------------------------------------------------------------------
148
# Create Windows-specific launch script.
149
# ---------------------------------------------------------------------------
150
utile_create_launch_script_windows() {
151
  $log "Create Windows launch script"
152
153
  cat > "${FILE_DIST_EXEC}" << __EOT
154
@echo off
155
156
set SCRIPT_DIR=%~dp0
157
"%SCRIPT_DIR%\\${ARG_JAVA_DIR}\\bin\\java" -jar "%SCRIPT_DIR%\\${APP_NAME}.jar" %*
158
__EOT
159
160
  # Convert Unix end of line characters (\n) to Windows format (\r\n).
161
  # This avoids any potential line conversion issues with the repository.
162
  sed -i 's/$/\r/' "${FILE_DIST_EXEC}"
163
}
164
165
# ---------------------------------------------------------------------------
166
# Copy application überjar.
167
# ---------------------------------------------------------------------------
168
utile_copy_archive() {
169
  $log "Create copy of ${FILE_APP_JAR}"
170
  cp "${ARG_PATH_DIST_JAR}" "${FILE_APP_JAR}"
171
}
172
173
# ---------------------------------------------------------------------------
174
# Create platform-specific launcher binary.
175
# ---------------------------------------------------------------------------
176
utile_create_launcher() {
177
  local -r FILE_APP_NAME="${APP_NAME}.${APP_EXTENSION}"
178
  $log "Create ${FILE_APP_NAME}"
179
180
  # Warp-packer does not seem to overwrite the file.
181
  rm -f "${FILE_APP_NAME}"
182
183
  # Download uses amd64, but warp-packer differs.
184
  if [ "${ARG_JAVA_ARCH}" = "amd64" ]; then
185
    ARG_JAVA_ARCH="x64"
186
  fi
187
188
  warp-packer \
189
    --arch "${ARG_JAVA_OS}-${ARG_JAVA_ARCH}" \
190
    --input_dir "${ARG_DIR_DIST}" \
191
    --exec "${FILE_DIST_EXEC}" \
192
    --output "${FILE_APP_NAME}" > /dev/null
193
194
  chmod +x "${FILE_APP_NAME}"
195
}
196
197
argument() {
198
  local consume=2
199
200
  case "$1" in
201
    -a|--arch)
202
    ARG_JAVA_ARCH="$2"
203
    ;;
204
    -o|--os)
205
    ARG_JAVA_OS="$2"
206
    ;;
207
    -u|--update)
208
    ARG_JAVA_UPDATE="$2"
209
    ;;
210
    -v|--version)
211
    ARG_JAVA_VERSION="$2"
212
    ;;
213
  esac
214
215
  return ${consume}
216
}
217
218
do_configure_target=utile_configure_target
219
do_build=utile_build
220
do_clean=utile_clean
221
do_extract_java=utile_extract_java
222
do_create_launch_script=utile_create_launch_script_linux
223
do_copy_archive=utile_copy_archive
224
do_create_launcher=utile_create_launcher
225
226
main "$@"
227
2281
A installer.sh
1
#!/usr/bin/env bash
2
3
# ---------------------------------------------------------------------------
4
# This script cross-compiles application launchers for different platforms.
5
#
6
# The application binaries are self-contained launchers that do not need
7
# to be installed.
8
# ---------------------------------------------------------------------------
9
10
source $HOME/bin/build-template
11
12
readonly APP_NAME=$(find "${SCRIPT_DIR}/src" -type f -name "settings.properties" -exec cat {} \; | grep "application.title=" | cut -d'=' -f2)
13
readonly FILE_APP_JAR="${APP_NAME}.jar"
14
15
# JDK 16 work-around until RichTextFX is fixed.
16
# See: https://github.com/FXMisc/RichTextFX/issues/1013
17
readonly OPT_JAVA="--illegal-access=permit"
18
19
ARG_JAVA_OS="linux"
20
ARG_JAVA_ARCH="amd64"
21
ARG_JAVA_VERSION="16.0.1"
22
ARG_JAVA_UPDATE="9"
23
ARG_JAVA_DIR="java"
24
25
ARG_DIR_DIST="dist"
26
27
FILE_DIST_EXEC="run.sh"
28
29
ARG_PATH_DIST_JAR="${SCRIPT_DIR}/build/libs/${FILE_APP_JAR}"
30
31
DEPENDENCIES=(
32
  "gradle,https://gradle.org"
33
  "warp-packer,https://github.com/dgiagio/warp"
34
  "tar,https://www.gnu.org/software/tar"
35
  "unzip,http://infozip.sourceforge.net"
36
)
37
38
ARGUMENTS+=(
39
  "a,arch,Target operating system architecture (amd64)"
40
  "o,os,Target operating system (linux, windows, mac)"
41
  "u,update,Java update version number (${ARG_JAVA_UPDATE})"
42
  "v,version,Full Java version (${ARG_JAVA_VERSION})"
43
)
44
45
ARCHIVE_EXT="tar.gz"
46
ARCHIVE_APP="tar xf"
47
APP_EXTENSION="bin"
48
49
# ---------------------------------------------------------------------------
50
# Generates
51
# ---------------------------------------------------------------------------
52
execute() {
53
  $do_configure_target
54
  $do_build
55
  $do_clean
56
57
  pushd "${ARG_DIR_DIST}" > /dev/null 2>&1
58
59
  $do_extract_java
60
  $do_create_launch_script
61
  $do_copy_archive
62
63
  popd > /dev/null 2>&1
64
65
  $do_create_launcher
66
67
  return 1
68
}
69
70
# ---------------------------------------------------------------------------
71
# Configure platform-specific commands and file names.
72
# ---------------------------------------------------------------------------
73
utile_configure_target() {
74
  if [ "${ARG_JAVA_OS}" = "windows" ]; then
75
    ARCHIVE_EXT="zip"
76
    ARCHIVE_APP="unzip -qq"
77
    FILE_DIST_EXEC="run.bat"
78
    APP_EXTENSION="exe"
79
    do_create_launch_script=utile_create_launch_script_windows
80
  fi
81
}
82
83
# ---------------------------------------------------------------------------
84
# Build platform-specific überjar.
85
# ---------------------------------------------------------------------------
86
utile_build() {
87
  $log "Delete ${ARG_PATH_DIST_JAR}"
88
  rm -f "${ARG_PATH_DIST_JAR}"
89
90
  $log "Build application for ${ARG_JAVA_OS}"
91
  gradle clean jar -PtargetOs="${ARG_JAVA_OS}"
92
}
93
94
# ---------------------------------------------------------------------------
95
# Purges the existing distribution directory to recreate the launcher.
96
# This refreshes the JRE from the downloaded archive.
97
# ---------------------------------------------------------------------------
98
utile_clean() {
99
  $log "Recreate ${ARG_DIR_DIST}"
100
  rm -rf "${ARG_DIR_DIST}"
101
  mkdir -p "${ARG_DIR_DIST}"
102
}
103
104
# ---------------------------------------------------------------------------
105
# Extract platform-specific Java Runtime Environment. This will download
106
# and cache the required Java Runtime Environment for the target platform.
107
# On subsequent runs, the cached version is used, instead of issuing another
108
# download.
109
# ---------------------------------------------------------------------------
110
utile_extract_java() {
111
  $log "Extract Java"
112
  local -r java_vm="jre"
113
  local -r java_version="${ARG_JAVA_VERSION}+${ARG_JAVA_UPDATE}"
114
  local -r url_java="https://download.bell-sw.com/java/${java_version}/bellsoft-${java_vm}${java_version}-${ARG_JAVA_OS}-${ARG_JAVA_ARCH}-full.${ARCHIVE_EXT}"
115
116
  local -r file_java="${java_vm}-${java_version}-${ARG_JAVA_OS}-${ARG_JAVA_ARCH}.${ARCHIVE_EXT}"
117
  local -r path_java="/tmp/${file_java}"
118
119
  # File must have contents.
120
  if [ ! -s ${path_java} ]; then
121
    $log "Download ${url_java} to ${path_java}"
122
    wget -q "${url_java}" -O "${path_java}"
123
  fi
124
125
  $log "Unpack ${path_java}"
126
  $ARCHIVE_APP "${path_java}"
127
128
  local -r dir_java="${java_vm}-${ARG_JAVA_VERSION}-full"
129
130
  $log "Rename ${dir_java} to ${ARG_JAVA_DIR}"
131
  mv "${dir_java}" "${ARG_JAVA_DIR}"
132
}
133
134
# ---------------------------------------------------------------------------
135
# Create Linux-specific launch script.
136
# ---------------------------------------------------------------------------
137
utile_create_launch_script_linux() {
138
  $log "Create Linux launch script"
139
140
  cat > "${FILE_DIST_EXEC}" << __EOT
141
#!/usr/bin/env bash
142
143
readonly SCRIPT_SRC="\$(dirname "\${BASH_SOURCE[\${#BASH_SOURCE[@]} - 1]}")"
144
145
"\${SCRIPT_SRC}/${ARG_JAVA_DIR}/bin/java" ${OPT_JAVA} -jar "\${SCRIPT_SRC}/${FILE_APP_JAR}" "\$@" 2>&1 >/dev/null &
146
__EOT
147
148
  chmod +x "${FILE_DIST_EXEC}"
149
}
150
151
# ---------------------------------------------------------------------------
152
# Create Windows-specific launch script.
153
# ---------------------------------------------------------------------------
154
utile_create_launch_script_windows() {
155
  $log "Create Windows launch script"
156
157
  cat > "${FILE_DIST_EXEC}" << __EOT
158
@echo off
159
160
set SCRIPT_DIR=%~dp0
161
"%SCRIPT_DIR%\\${ARG_JAVA_DIR}\\bin\\java" ${OPT_JAVA} -jar "%SCRIPT_DIR%\\${APP_NAME}.jar" %*
162
__EOT
163
164
  # Convert Unix end of line characters (\n) to Windows format (\r\n).
165
  # This avoids any potential line conversion issues with the repository.
166
  sed -i 's/$/\r/' "${FILE_DIST_EXEC}"
167
}
168
169
# ---------------------------------------------------------------------------
170
# Copy application überjar.
171
# ---------------------------------------------------------------------------
172
utile_copy_archive() {
173
  $log "Create copy of ${FILE_APP_JAR}"
174
  cp "${ARG_PATH_DIST_JAR}" "${FILE_APP_JAR}"
175
}
176
177
# ---------------------------------------------------------------------------
178
# Create platform-specific launcher binary.
179
# ---------------------------------------------------------------------------
180
utile_create_launcher() {
181
  local -r FILE_APP_NAME="${APP_NAME}.${APP_EXTENSION}"
182
  $log "Create ${FILE_APP_NAME}"
183
184
  # Warp-packer does not seem to overwrite the file.
185
  rm -f "${FILE_APP_NAME}"
186
187
  # Download uses amd64, but warp-packer differs.
188
  if [ "${ARG_JAVA_ARCH}" = "amd64" ]; then
189
    ARG_JAVA_ARCH="x64"
190
  fi
191
192
  warp-packer \
193
    --arch "${ARG_JAVA_OS}-${ARG_JAVA_ARCH}" \
194
    --input_dir "${ARG_DIR_DIST}" \
195
    --exec "${FILE_DIST_EXEC}" \
196
    --output "${FILE_APP_NAME}" > /dev/null
197
198
  chmod +x "${FILE_APP_NAME}"
199
}
200
201
argument() {
202
  local consume=2
203
204
  case "$1" in
205
    -a|--arch)
206
    ARG_JAVA_ARCH="$2"
207
    ;;
208
    -o|--os)
209
    ARG_JAVA_OS="$2"
210
    ;;
211
    -u|--update)
212
    ARG_JAVA_UPDATE="$2"
213
    ;;
214
    -v|--version)
215
    ARG_JAVA_VERSION="$2"
216
    ;;
217
  esac
218
219
  return ${consume}
220
}
221
222
do_configure_target=utile_configure_target
223
do_build=utile_build
224
do_clean=utile_clean
225
do_extract_java=utile_extract_java
226
do_create_launch_script=utile_create_launch_script_linux
227
do_copy_archive=utile_copy_archive
228
do_create_launcher=utile_create_launcher
229
230
main "$@"
231
1232
A keenwrite.sh
1
#!/usr/bin/env bash
2
3
java --illegal-access=permit -jar build/libs/keenwrite.jar 2> /dev/null
4
15
D licenses/BEAN-VALIDATION-API.md
11
2
                                 Apache License
3
                           Version 2.0, January 2004
4
                        http://www.apache.org/licenses/
5
6
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
8
   1. Definitions.
9
10
      "License" shall mean the terms and conditions for use, reproduction,
11
      and distribution as defined by Sections 1 through 9 of this document.
12
13
      "Licensor" shall mean the copyright owner or entity authorized by
14
      the copyright owner that is granting the License.
15
16
      "Legal Entity" shall mean the union of the acting entity and all
17
      other entities that control, are controlled by, or are under common
18
      control with that entity. For the purposes of this definition,
19
      "control" means (i) the power, direct or indirect, to cause the
20
      direction or management of such entity, whether by contract or
21
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
      outstanding shares, or (iii) beneficial ownership of such entity.
23
24
      "You" (or "Your") shall mean an individual or Legal Entity
25
      exercising permissions granted by this License.
26
27
      "Source" form shall mean the preferred form for making modifications,
28
      including but not limited to software source code, documentation
29
      source, and configuration files.
30
31
      "Object" form shall mean any form resulting from mechanical
32
      transformation or translation of a Source form, including but
33
      not limited to compiled object code, generated documentation,
34
      and conversions to other media types.
35
36
      "Work" shall mean the work of authorship, whether in Source or
37
      Object form, made available under the License, as indicated by a
38
      copyright notice that is included in or attached to the work
39
      (an example is provided in the Appendix below).
40
41
      "Derivative Works" shall mean any work, whether in Source or Object
42
      form, that is based on (or derived from) the Work and for which the
43
      editorial revisions, annotations, elaborations, or other modifications
44
      represent, as a whole, an original work of authorship. For the purposes
45
      of this License, Derivative Works shall not include works that remain
46
      separable from, or merely link (or bind by name) to the interfaces of,
47
      the Work and Derivative Works thereof.
48
49
      "Contribution" shall mean any work of authorship, including
50
      the original version of the Work and any modifications or additions
51
      to that Work or Derivative Works thereof, that is intentionally
52
      submitted to Licensor for inclusion in the Work by the copyright owner
53
      or by an individual or Legal Entity authorized to submit on behalf of
54
      the copyright owner. For the purposes of this definition, "submitted"
55
      means any form of electronic, verbal, or written communication sent
56
      to the Licensor or its representatives, including but not limited to
57
      communication on electronic mailing lists, source code control systems,
58
      and issue tracking systems that are managed by, or on behalf of, the
59
      Licensor for the purpose of discussing and improving the Work, but
60
      excluding communication that is conspicuously marked or otherwise
61
      designated in writing by the copyright owner as "Not a Contribution."
62
63
      "Contributor" shall mean Licensor and any individual or Legal Entity
64
      on behalf of whom a Contribution has been received by Licensor and
65
      subsequently incorporated within the Work.
66
67
   2. Grant of Copyright License. Subject to the terms and conditions of
68
      this License, each Contributor hereby grants to You a perpetual,
69
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
      copyright license to reproduce, prepare Derivative Works of,
71
      publicly display, publicly perform, sublicense, and distribute the
72
      Work and such Derivative Works in Source or Object form.
73
74
   3. Grant of Patent License. Subject to the terms and conditions of
75
      this License, each Contributor hereby grants to You a perpetual,
76
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
      (except as stated in this section) patent license to make, have made,
78
      use, offer to sell, sell, import, and otherwise transfer the Work,
79
      where such license applies only to those patent claims licensable
80
      by such Contributor that are necessarily infringed by their
81
      Contribution(s) alone or by combination of their Contribution(s)
82
      with the Work to which such Contribution(s) was submitted. If You
83
      institute patent litigation against any entity (including a
84
      cross-claim or counterclaim in a lawsuit) alleging that the Work
85
      or a Contribution incorporated within the Work constitutes direct
86
      or contributory patent infringement, then any patent licenses
87
      granted to You under this License for that Work shall terminate
88
      as of the date such litigation is filed.
89
90
   4. Redistribution. You may reproduce and distribute copies of the
91
      Work or Derivative Works thereof in any medium, with or without
92
      modifications, and in Source or Object form, provided that You
93
      meet the following conditions:
94
95
      (a) You must give any other recipients of the Work or
96
          Derivative Works a copy of this License; and
97
98
      (b) You must cause any modified files to carry prominent notices
99
          stating that You changed the files; and
100
101
      (c) You must retain, in the Source form of any Derivative Works
102
          that You distribute, all copyright, patent, trademark, and
103
          attribution notices from the Source form of the Work,
104
          excluding those notices that do not pertain to any part of
105
          the Derivative Works; and
106
107
      (d) If the Work includes a "NOTICE" text file as part of its
108
          distribution, then any Derivative Works that You distribute must
109
          include a readable copy of the attribution notices contained
110
          within such NOTICE file, excluding those notices that do not
111
          pertain to any part of the Derivative Works, in at least one
112
          of the following places: within a NOTICE text file distributed
113
          as part of the Derivative Works; within the Source form or
114
          documentation, if provided along with the Derivative Works; or,
115
          within a display generated by the Derivative Works, if and
116
          wherever such third-party notices normally appear. The contents
117
          of the NOTICE file are for informational purposes only and
118
          do not modify the License. You may add Your own attribution
119
          notices within Derivative Works that You distribute, alongside
120
          or as an addendum to the NOTICE text from the Work, provided
121
          that such additional attribution notices cannot be construed
122
          as modifying the License.
123
124
      You may add Your own copyright statement to Your modifications and
125
      may provide additional or different license terms and conditions
126
      for use, reproduction, or distribution of Your modifications, or
127
      for any such Derivative Works as a whole, provided Your use,
128
      reproduction, and distribution of the Work otherwise complies with
129
      the conditions stated in this License.
130
131
   5. Submission of Contributions. Unless You explicitly state otherwise,
132
      any Contribution intentionally submitted for inclusion in the Work
133
      by You to the Licensor shall be under the terms and conditions of
134
      this License, without any additional terms or conditions.
135
      Notwithstanding the above, nothing herein shall supersede or modify
136
      the terms of any separate license agreement you may have executed
137
      with Licensor regarding such Contributions.
138
139
   6. Trademarks. This License does not grant permission to use the trade
140
      names, trademarks, service marks, or product names of the Licensor,
141
      except as required for reasonable and customary use in describing the
142
      origin of the Work and reproducing the content of the NOTICE file.
143
144
   7. Disclaimer of Warranty. Unless required by applicable law or
145
      agreed to in writing, Licensor provides the Work (and each
146
      Contributor provides its Contributions) on an "AS IS" BASIS,
147
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
      implied, including, without limitation, any warranties or conditions
149
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
      PARTICULAR PURPOSE. You are solely responsible for determining the
151
      appropriateness of using or redistributing the Work and assume any
152
      risks associated with Your exercise of permissions under this License.
153
154
   8. Limitation of Liability. In no event and under no legal theory,
155
      whether in tort (including negligence), contract, or otherwise,
156
      unless required by applicable law (such as deliberate and grossly
157
      negligent acts) or agreed to in writing, shall any Contributor be
158
      liable to You for damages, including any direct, indirect, special,
159
      incidental, or consequential damages of any character arising as a
160
      result of this License or out of the use or inability to use the
161
      Work (including but not limited to damages for loss of goodwill,
162
      work stoppage, computer failure or malfunction, or any and all
163
      other commercial damages or losses), even if such Contributor
164
      has been advised of the possibility of such damages.
165
166
   9. Accepting Warranty or Additional Liability. While redistributing
167
      the Work or Derivative Works thereof, You may choose to offer,
168
      and charge a fee for, acceptance of support, warranty, indemnity,
169
      or other liability obligations and/or rights consistent with this
170
      License. However, in accepting such obligations, You may act only
171
      on Your own behalf and on Your sole responsibility, not on behalf
172
      of any other Contributor, and only if You agree to indemnify,
173
      defend, and hold each Contributor harmless for any liability
174
      incurred by, or claims asserted against, such Contributor by reason
175
      of your accepting any such warranty or additional liability.
176
177
   END OF TERMS AND CONDITIONS
178
179
   APPENDIX: How to apply the Apache License to your work.
180
181
      To apply the Apache License to your work, attach the following
182
      boilerplate notice, with the fields enclosed by brackets "[]"
183
      replaced with your own identifying information. (Don't include
184
      the brackets!)  The text should be enclosed in the appropriate
185
      comment syntax for the file format. We also recommend that a
186
      file or class name and description of purpose be included on the
187
      same "printed page" as the copyright notice for easier
188
      identification within third-party archives.
189
190
   Copyright [yyyy] [name of copyright owner]
191
192
   Licensed under the Apache License, Version 2.0 (the "License");
193
   you may not use this file except in compliance with the License.
194
   You may obtain a copy of the License at
195
196
       http://www.apache.org/licenses/LICENSE-2.0
197
198
   Unless required by applicable law or agreed to in writing, software
199
   distributed under the License is distributed on an "AS IS" BASIS,
200
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
   See the License for the specific language governing permissions and
202
   limitations under the License.
203
D licenses/FILE-ICON-IMAGES.md
1
The MIT License (MIT)
2
3
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:
4
5
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7
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.
8
91
D licenses/FILE-PREFERENCES.md
1
Released into the Public Domain by David Croft.
2
3
http://www.davidc.net/programming/java/java-preferences-using-file-backing-store
4
http://creativecommons.org/publicdomain/zero/1.0/
5
6
CC0 1.0 Universal (CC0 1.0)
7
8
Public Domain Dedication
9
10
This is a human-readable summary of the Legal Code (read the full text).
11
12
Disclaimer
13
14
No Copyright
15
16
* The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law.
17
18
* You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. See Other Information below.
19
20
This license is acceptable for Free Cultural Works.
21
22
Other Information
23
24
* In no way are the patent or trademark rights of any person affected by CC0, nor are the rights that other persons may have in the work or in how the work is used, such as publicity or privacy rights.
25
* Unless expressly stated otherwise, the person who associated a work with this deed makes no warranties about the work, and disclaims liability for all uses of the work, to the fullest extent permitted by applicable law.
26
* When using or citing the work, you should not imply endorsement by the author or the affirmer.
27
281
D licenses/FLEXMARK.md
1
Copyright (c) 2015-2016, Atlassian Pty Ltd
2
All rights reserved.
3
4
Copyright (c) 2016-2018, Vladimir Schneider,
5
All rights reserved.
6
7
Redistribution and use in source and binary forms, with or without
8
modification, are permitted provided that the following conditions are met:
9
10
* Redistributions of source code must retain the above copyright notice, this
11
  list of conditions and the following disclaimer.
12
13
* Redistributions in binary form must reproduce the above copyright notice,
14
  this list of conditions and the following disclaimer in the documentation
15
  and/or other materials provided with the distribution.
16
17
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271
D licenses/FLOWLESS.md
1
Copyright (c) 2014, TomasMikula
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without
5
modification, are permitted provided that the following conditions are met:
6
7
* Redistributions of source code must retain the above copyright notice, this
8
  list of conditions and the following disclaimer.
9
10
* Redistributions in binary form must reproduce the above copyright notice,
11
  this list of conditions and the following disclaimer in the documentation
12
  and/or other materials provided with the distribution.
13
14
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
241
D licenses/FONT-AWESOME-FX.txt
11
2
                                 Apache License
3
                           Version 2.0, January 2004
4
                        http://www.apache.org/licenses/
5
6
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
8
   1. Definitions.
9
10
      "License" shall mean the terms and conditions for use, reproduction,
11
      and distribution as defined by Sections 1 through 9 of this document.
12
13
      "Licensor" shall mean the copyright owner or entity authorized by
14
      the copyright owner that is granting the License.
15
16
      "Legal Entity" shall mean the union of the acting entity and all
17
      other entities that control, are controlled by, or are under common
18
      control with that entity. For the purposes of this definition,
19
      "control" means (i) the power, direct or indirect, to cause the
20
      direction or management of such entity, whether by contract or
21
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
      outstanding shares, or (iii) beneficial ownership of such entity.
23
24
      "You" (or "Your") shall mean an individual or Legal Entity
25
      exercising permissions granted by this License.
26
27
      "Source" form shall mean the preferred form for making modifications,
28
      including but not limited to software source code, documentation
29
      source, and configuration files.
30
31
      "Object" form shall mean any form resulting from mechanical
32
      transformation or translation of a Source form, including but
33
      not limited to compiled object code, generated documentation,
34
      and conversions to other media types.
35
36
      "Work" shall mean the work of authorship, whether in Source or
37
      Object form, made available under the License, as indicated by a
38
      copyright notice that is included in or attached to the work
39
      (an example is provided in the Appendix below).
40
41
      "Derivative Works" shall mean any work, whether in Source or Object
42
      form, that is based on (or derived from) the Work and for which the
43
      editorial revisions, annotations, elaborations, or other modifications
44
      represent, as a whole, an original work of authorship. For the purposes
45
      of this License, Derivative Works shall not include works that remain
46
      separable from, or merely link (or bind by name) to the interfaces of,
47
      the Work and Derivative Works thereof.
48
49
      "Contribution" shall mean any work of authorship, including
50
      the original version of the Work and any modifications or additions
51
      to that Work or Derivative Works thereof, that is intentionally
52
      submitted to Licensor for inclusion in the Work by the copyright owner
53
      or by an individual or Legal Entity authorized to submit on behalf of
54
      the copyright owner. For the purposes of this definition, "submitted"
55
      means any form of electronic, verbal, or written communication sent
56
      to the Licensor or its representatives, including but not limited to
57
      communication on electronic mailing lists, source code control systems,
58
      and issue tracking systems that are managed by, or on behalf of, the
59
      Licensor for the purpose of discussing and improving the Work, but
60
      excluding communication that is conspicuously marked or otherwise
61
      designated in writing by the copyright owner as "Not a Contribution."
62
63
      "Contributor" shall mean Licensor and any individual or Legal Entity
64
      on behalf of whom a Contribution has been received by Licensor and
65
      subsequently incorporated within the Work.
66
67
   2. Grant of Copyright License. Subject to the terms and conditions of
68
      this License, each Contributor hereby grants to You a perpetual,
69
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
      copyright license to reproduce, prepare Derivative Works of,
71
      publicly display, publicly perform, sublicense, and distribute the
72
      Work and such Derivative Works in Source or Object form.
73
74
   3. Grant of Patent License. Subject to the terms and conditions of
75
      this License, each Contributor hereby grants to You a perpetual,
76
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
      (except as stated in this section) patent license to make, have made,
78
      use, offer to sell, sell, import, and otherwise transfer the Work,
79
      where such license applies only to those patent claims licensable
80
      by such Contributor that are necessarily infringed by their
81
      Contribution(s) alone or by combination of their Contribution(s)
82
      with the Work to which such Contribution(s) was submitted. If You
83
      institute patent litigation against any entity (including a
84
      cross-claim or counterclaim in a lawsuit) alleging that the Work
85
      or a Contribution incorporated within the Work constitutes direct
86
      or contributory patent infringement, then any patent licenses
87
      granted to You under this License for that Work shall terminate
88
      as of the date such litigation is filed.
89
90
   4. Redistribution. You may reproduce and distribute copies of the
91
      Work or Derivative Works thereof in any medium, with or without
92
      modifications, and in Source or Object form, provided that You
93
      meet the following conditions:
94
95
      (a) You must give any other recipients of the Work or
96
          Derivative Works a copy of this License; and
97
98
      (b) You must cause any modified files to carry prominent notices
99
          stating that You changed the files; and
100
101
      (c) You must retain, in the Source form of any Derivative Works
102
          that You distribute, all copyright, patent, trademark, and
103
          attribution notices from the Source form of the Work,
104
          excluding those notices that do not pertain to any part of
105
          the Derivative Works; and
106
107
      (d) If the Work includes a "NOTICE" text file as part of its
108
          distribution, then any Derivative Works that You distribute must
109
          include a readable copy of the attribution notices contained
110
          within such NOTICE file, excluding those notices that do not
111
          pertain to any part of the Derivative Works, in at least one
112
          of the following places: within a NOTICE text file distributed
113
          as part of the Derivative Works; within the Source form or
114
          documentation, if provided along with the Derivative Works; or,
115
          within a display generated by the Derivative Works, if and
116
          wherever such third-party notices normally appear. The contents
117
          of the NOTICE file are for informational purposes only and
118
          do not modify the License. You may add Your own attribution
119
          notices within Derivative Works that You distribute, alongside
120
          or as an addendum to the NOTICE text from the Work, provided
121
          that such additional attribution notices cannot be construed
122
          as modifying the License.
123
124
      You may add Your own copyright statement to Your modifications and
125
      may provide additional or different license terms and conditions
126
      for use, reproduction, or distribution of Your modifications, or
127
      for any such Derivative Works as a whole, provided Your use,
128
      reproduction, and distribution of the Work otherwise complies with
129
      the conditions stated in this License.
130
131
   5. Submission of Contributions. Unless You explicitly state otherwise,
132
      any Contribution intentionally submitted for inclusion in the Work
133
      by You to the Licensor shall be under the terms and conditions of
134
      this License, without any additional terms or conditions.
135
      Notwithstanding the above, nothing herein shall supersede or modify
136
      the terms of any separate license agreement you may have executed
137
      with Licensor regarding such Contributions.
138
139
   6. Trademarks. This License does not grant permission to use the trade
140
      names, trademarks, service marks, or product names of the Licensor,
141
      except as required for reasonable and customary use in describing the
142
      origin of the Work and reproducing the content of the NOTICE file.
143
144
   7. Disclaimer of Warranty. Unless required by applicable law or
145
      agreed to in writing, Licensor provides the Work (and each
146
      Contributor provides its Contributions) on an "AS IS" BASIS,
147
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
      implied, including, without limitation, any warranties or conditions
149
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
      PARTICULAR PURPOSE. You are solely responsible for determining the
151
      appropriateness of using or redistributing the Work and assume any
152
      risks associated with Your exercise of permissions under this License.
153
154
   8. Limitation of Liability. In no event and under no legal theory,
155
      whether in tort (including negligence), contract, or otherwise,
156
      unless required by applicable law (such as deliberate and grossly
157
      negligent acts) or agreed to in writing, shall any Contributor be
158
      liable to You for damages, including any direct, indirect, special,
159
      incidental, or consequential damages of any character arising as a
160
      result of this License or out of the use or inability to use the
161
      Work (including but not limited to damages for loss of goodwill,
162
      work stoppage, computer failure or malfunction, or any and all
163
      other commercial damages or losses), even if such Contributor
164
      has been advised of the possibility of such damages.
165
166
   9. Accepting Warranty or Additional Liability. While redistributing
167
      the Work or Derivative Works thereof, You may choose to offer,
168
      and charge a fee for, acceptance of support, warranty, indemnity,
169
      or other liability obligations and/or rights consistent with this
170
      License. However, in accepting such obligations, You may act only
171
      on Your own behalf and on Your sole responsibility, not on behalf
172
      of any other Contributor, and only if You agree to indemnify,
173
      defend, and hold each Contributor harmless for any liability
174
      incurred by, or claims asserted against, such Contributor by reason
175
      of your accepting any such warranty or additional liability.
176
177
   END OF TERMS AND CONDITIONS
178
179
   APPENDIX: How to apply the Apache License to your work.
180
181
      To apply the Apache License to your work, attach the following
182
      boilerplate notice, with the fields enclosed by brackets "[]"
183
      replaced with your own identifying information. (Don't include
184
      the brackets!)  The text should be enclosed in the appropriate
185
      comment syntax for the file format. We also recommend that a
186
      file or class name and description of purpose be included on the
187
      same "printed page" as the copyright notice for easier
188
      identification within third-party archives.
189
190
   Copyright [yyyy] [name of copyright owner]
191
192
   Licensed under the Apache License, Version 2.0 (the "License");
193
   you may not use this file except in compliance with the License.
194
   You may obtain a copy of the License at
195
196
       http://www.apache.org/licenses/LICENSE-2.0
197
198
   Unless required by applicable law or agreed to in writing, software
199
   distributed under the License is distributed on an "AS IS" BASIS,
200
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
   See the License for the specific language governing permissions and
202
   limitations under the License.
203
D licenses/JSYMSPELL.md
1
MIT License
2
3
Copyright (c) 2019 Raul Garcia
4
5
Permission is hereby granted, free of charge, to any person obtaining a copy
6
of this software and associated documentation files (the "Software"), to deal
7
in the Software without restriction, including without limitation the rights
8
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
copies of the Software, and to permit persons to whom the Software is
10
furnished to do so, subject to the following conditions:
11
12
The above copyright notice and this permission notice shall be included in all
13
copies or substantial portions of the Software.
14
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
SOFTWARE.
221
D licenses/JUNIVERSAL-CHARDET.md
1
Version: MPL 1.1/GPL 2.0/LGPL 2.1
2
3
The contents of this file are subject to the Mozilla Public License Version
4
1.1 (the "License"); you may not use this file except in compliance with
5
the License. You may obtain a copy of the License at
6
http://www.mozilla.org/MPL/
7
8
Software distributed under the License is distributed on an "AS IS" basis,
9
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10
for the specific language governing rights and limitations under the
11
License.
12
13
The Original Code is Mozilla Universal charset detector code.
14
15
The Initial Developer of the Original Code is
16
Netscape Communications Corporation.
17
Portions created by the Initial Developer are Copyright (C) 2001
18
the Initial Developer. All Rights Reserved.
19
20
Contributor(s):
21
        Shy Shalom <shooshX@gmail.com>
22
        Kohei TAKETA <k-tak@void.in> (Java port)
23
24
Alternatively, the contents of this file may be used under the terms of
25
either the GNU General Public License Version 2 or later (the "GPL"), or
26
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
in which case the provisions of the GPL or the LGPL are applicable instead
28
of those above. If you wish to allow use of your version of this file only
29
under the terms of either the GPL or the LGPL, and not to allow others to
30
use your version of this file under the terms of the MPL, indicate your
31
decision by deleting the provisions above and replace them with the notice
32
and other provisions required by the GPL or the LGPL. If you do not delete
33
the provisions above, a recipient may use your version of this file under
34
the terms of any one of the MPL, the GPL or the LGPL.
35
361
D licenses/MARKDOWN-WRITER-FX.md
1
Copyright (c) 2015 Karl Tauber <karl@jformdesigner.com>
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without
5
modification, are permitted provided that the following conditions are met:
6
7
* Redistributions of source code must retain the above copyright
8
  notice, this list of conditions and the following disclaimer.
9
10
* Redistributions in binary form must reproduce the above copyright
11
  notice, this list of conditions and the following disclaimer in the
12
  documentation and/or other materials provided with the distribution.
13
14
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
251
D licenses/MIG-LAYOUT.md
1
Copyright (c) 2000 Mikael Grev
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without
5
modification, are permitted provided that the following conditions
6
are met:
7
1. Redistributions of source code must retain the above copyright
8
   notice, this list of conditions and the following disclaimer.
9
2. Redistributions in binary form must reproduce the above copyright
10
   notice, this list of conditions and the following disclaimer in the
11
   documentation and/or other materials provided with the distribution.
12
3. The name of the author may not be used to endorse or promote products
13
   derived from this software without specific prior written permission.
14
15
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
261
D licenses/PREFERENCES-FX.txt
1
                                 Apache License
2
                           Version 2.0, January 2004
3
                        http://www.apache.org/licenses/
4
5
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7
   1. Definitions.
8
9
      "License" shall mean the terms and conditions for use, reproduction,
10
      and distribution as defined by Sections 1 through 9 of this document.
11
12
      "Licensor" shall mean the copyright owner or entity authorized by
13
      the copyright owner that is granting the License.
14
15
      "Legal Entity" shall mean the union of the acting entity and all
16
      other entities that control, are controlled by, or are under common
17
      control with that entity. For the purposes of this definition,
18
      "control" means (i) the power, direct or indirect, to cause the
19
      direction or management of such entity, whether by contract or
20
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
      outstanding shares, or (iii) beneficial ownership of such entity.
22
23
      "You" (or "Your") shall mean an individual or Legal Entity
24
      exercising permissions granted by this License.
25
26
      "Source" form shall mean the preferred form for making modifications,
27
      including but not limited to software source code, documentation
28
      source, and configuration files.
29
30
      "Object" form shall mean any form resulting from mechanical
31
      transformation or translation of a Source form, including but
32
      not limited to compiled object code, generated documentation,
33
      and conversions to other media types.
34
35
      "Work" shall mean the work of authorship, whether in Source or
36
      Object form, made available under the License, as indicated by a
37
      copyright notice that is included in or attached to the work
38
      (an example is provided in the Appendix below).
39
40
      "Derivative Works" shall mean any work, whether in Source or Object
41
      form, that is based on (or derived from) the Work and for which the
42
      editorial revisions, annotations, elaborations, or other modifications
43
      represent, as a whole, an original work of authorship. For the purposes
44
      of this License, Derivative Works shall not include works that remain
45
      separable from, or merely link (or bind by name) to the interfaces of,
46
      the Work and Derivative Works thereof.
47
48
      "Contribution" shall mean any work of authorship, including
49
      the original version of the Work and any modifications or additions
50
      to that Work or Derivative Works thereof, that is intentionally
51
      submitted to Licensor for inclusion in the Work by the copyright owner
52
      or by an individual or Legal Entity authorized to submit on behalf of
53
      the copyright owner. For the purposes of this definition, "submitted"
54
      means any form of electronic, verbal, or written communication sent
55
      to the Licensor or its representatives, including but not limited to
56
      communication on electronic mailing lists, source code control systems,
57
      and issue tracking systems that are managed by, or on behalf of, the
58
      Licensor for the purpose of discussing and improving the Work, but
59
      excluding communication that is conspicuously marked or otherwise
60
      designated in writing by the copyright owner as "Not a Contribution."
61
62
      "Contributor" shall mean Licensor and any individual or Legal Entity
63
      on behalf of whom a Contribution has been received by Licensor and
64
      subsequently incorporated within the Work.
65
66
   2. Grant of Copyright License. Subject to the terms and conditions of
67
      this License, each Contributor hereby grants to You a perpetual,
68
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
      copyright license to reproduce, prepare Derivative Works of,
70
      publicly display, publicly perform, sublicense, and distribute the
71
      Work and such Derivative Works in Source or Object form.
72
73
   3. Grant of Patent License. Subject to the terms and conditions of
74
      this License, each Contributor hereby grants to You a perpetual,
75
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
      (except as stated in this section) patent license to make, have made,
77
      use, offer to sell, sell, import, and otherwise transfer the Work,
78
      where such license applies only to those patent claims licensable
79
      by such Contributor that are necessarily infringed by their
80
      Contribution(s) alone or by combination of their Contribution(s)
81
      with the Work to which such Contribution(s) was submitted. If You
82
      institute patent litigation against any entity (including a
83
      cross-claim or counterclaim in a lawsuit) alleging that the Work
84
      or a Contribution incorporated within the Work constitutes direct
85
      or contributory patent infringement, then any patent licenses
86
      granted to You under this License for that Work shall terminate
87
      as of the date such litigation is filed.
88
89
   4. Redistribution. You may reproduce and distribute copies of the
90
      Work or Derivative Works thereof in any medium, with or without
91
      modifications, and in Source or Object form, provided that You
92
      meet the following conditions:
93
94
      (a) You must give any other recipients of the Work or
95
          Derivative Works a copy of this License; and
96
97
      (b) You must cause any modified files to carry prominent notices
98
          stating that You changed the files; and
99
100
      (c) You must retain, in the Source form of any Derivative Works
101
          that You distribute, all copyright, patent, trademark, and
102
          attribution notices from the Source form of the Work,
103
          excluding those notices that do not pertain to any part of
104
          the Derivative Works; and
105
106
      (d) If the Work includes a "NOTICE" text file as part of its
107
          distribution, then any Derivative Works that You distribute must
108
          include a readable copy of the attribution notices contained
109
          within such NOTICE file, excluding those notices that do not
110
          pertain to any part of the Derivative Works, in at least one
111
          of the following places: within a NOTICE text file distributed
112
          as part of the Derivative Works; within the Source form or
113
          documentation, if provided along with the Derivative Works; or,
114
          within a display generated by the Derivative Works, if and
115
          wherever such third-party notices normally appear. The contents
116
          of the NOTICE file are for informational purposes only and
117
          do not modify the License. You may add Your own attribution
118
          notices within Derivative Works that You distribute, alongside
119
          or as an addendum to the NOTICE text from the Work, provided
120
          that such additional attribution notices cannot be construed
121
          as modifying the License.
122
123
      You may add Your own copyright statement to Your modifications and
124
      may provide additional or different license terms and conditions
125
      for use, reproduction, or distribution of Your modifications, or
126
      for any such Derivative Works as a whole, provided Your use,
127
      reproduction, and distribution of the Work otherwise complies with
128
      the conditions stated in this License.
129
130
   5. Submission of Contributions. Unless You explicitly state otherwise,
131
      any Contribution intentionally submitted for inclusion in the Work
132
      by You to the Licensor shall be under the terms and conditions of
133
      this License, without any additional terms or conditions.
134
      Notwithstanding the above, nothing herein shall supersede or modify
135
      the terms of any separate license agreement you may have executed
136
      with Licensor regarding such Contributions.
137
138
   6. Trademarks. This License does not grant permission to use the trade
139
      names, trademarks, service marks, or product names of the Licensor,
140
      except as required for reasonable and customary use in describing the
141
      origin of the Work and reproducing the content of the NOTICE file.
142
143
   7. Disclaimer of Warranty. Unless required by applicable law or
144
      agreed to in writing, Licensor provides the Work (and each
145
      Contributor provides its Contributions) on an "AS IS" BASIS,
146
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
      implied, including, without limitation, any warranties or conditions
148
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
      PARTICULAR PURPOSE. You are solely responsible for determining the
150
      appropriateness of using or redistributing the Work and assume any
151
      risks associated with Your exercise of permissions under this License.
152
153
   8. Limitation of Liability. In no event and under no legal theory,
154
      whether in tort (including negligence), contract, or otherwise,
155
      unless required by applicable law (such as deliberate and grossly
156
      negligent acts) or agreed to in writing, shall any Contributor be
157
      liable to You for damages, including any direct, indirect, special,
158
      incidental, or consequential damages of any character arising as a
159
      result of this License or out of the use or inability to use the
160
      Work (including but not limited to damages for loss of goodwill,
161
      work stoppage, computer failure or malfunction, or any and all
162
      other commercial damages or losses), even if such Contributor
163
      has been advised of the possibility of such damages.
164
165
   9. Accepting Warranty or Additional Liability. While redistributing
166
      the Work or Derivative Works thereof, You may choose to offer,
167
      and charge a fee for, acceptance of support, warranty, indemnity,
168
      or other liability obligations and/or rights consistent with this
169
      License. However, in accepting such obligations, You may act only
170
      on Your own behalf and on Your sole responsibility, not on behalf
171
      of any other Contributor, and only if You agree to indemnify,
172
      defend, and hold each Contributor harmless for any liability
173
      incurred by, or claims asserted against, such Contributor by reason
174
      of your accepting any such warranty or additional liability.
175
176
   END OF TERMS AND CONDITIONS
177
178
   APPENDIX: How to apply the Apache License to your work.
179
180
      To apply the Apache License to your work, attach the following
181
      boilerplate notice, with the fields enclosed by brackets "{}"
182
      replaced with your own identifying information. (Don't include
183
      the brackets!)  The text should be enclosed in the appropriate
184
      comment syntax for the file format. We also recommend that a
185
      file or class name and description of purpose be included on the
186
      same "printed page" as the copyright notice for easier
187
      identification within third-party archives.
188
189
   Copyright {yyyy} {name of copyright owner}
190
191
   Licensed under the Apache License, Version 2.0 (the "License");
192
   you may not use this file except in compliance with the License.
193
   You may obtain a copy of the License at
194
195
       http://www.apache.org/licenses/LICENSE-2.0
196
197
   Unless required by applicable law or agreed to in writing, software
198
   distributed under the License is distributed on an "AS IS" BASIS,
199
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
   See the License for the specific language governing permissions and
201
   limitations under the License.
2021
D licenses/REACT-FX.md
1
Copyright (c) 2013-2014, Tomas Mikula
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
6
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
8
2. 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.
9
10
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.
111
D licenses/RENJIN.txt
1
		    GNU GENERAL PUBLIC LICENSE
2
		       Version 2, June 1991
3
4
 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5
                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
6
 Everyone is permitted to copy and distribute verbatim copies
7
 of this license document, but changing it is not allowed.
8
9
			    Preamble
10
11
  The licenses for most software are designed to take away your
12
freedom to share and change it.  By contrast, the GNU General Public
13
License is intended to guarantee your freedom to share and change free
14
software--to make sure the software is free for all its users.  This
15
General Public License applies to most of the Free Software
16
Foundation's software and to any other program whose authors commit to
17
using it.  (Some other Free Software Foundation software is covered by
18
the GNU Library General Public License instead.)  You can apply it to
19
your programs, too.
20
21
  When we speak of free software, we are referring to freedom, not
22
price.  Our General Public Licenses are designed to make sure that you
23
have the freedom to distribute copies of free software (and charge for
24
this service if you wish), that you receive source code or can get it
25
if you want it, that you can change the software or use pieces of it
26
in new free programs; and that you know you can do these things.
27
28
  To protect your rights, we need to make restrictions that forbid
29
anyone to deny you these rights or to ask you to surrender the rights.
30
These restrictions translate to certain responsibilities for you if you
31
distribute copies of the software, or if you modify it.
32
33
  For example, if you distribute copies of such a program, whether
34
gratis or for a fee, you must give the recipients all the rights that
35
you have.  You must make sure that they, too, receive or can get the
36
source code.  And you must show them these terms so they know their
37
rights.
38
39
  We protect your rights with two steps: (1) copyright the software, and
40
(2) offer you this license which gives you legal permission to copy,
41
distribute and/or modify the software.
42
43
  Also, for each author's protection and ours, we want to make certain
44
that everyone understands that there is no warranty for this free
45
software.  If the software is modified by someone else and passed on, we
46
want its recipients to know that what they have is not the original, so
47
that any problems introduced by others will not reflect on the original
48
authors' reputations.
49
50
  Finally, any free program is threatened constantly by software
51
patents.  We wish to avoid the danger that redistributors of a free
52
program will individually obtain patent licenses, in effect making the
53
program proprietary.  To prevent this, we have made it clear that any
54
patent must be licensed for everyone's free use or not licensed at all.
55
56
  The precise terms and conditions for copying, distribution and
57
modification follow.
58

59
		    GNU GENERAL PUBLIC LICENSE
60
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62
  0. This License applies to any program or other work which contains
63
a notice placed by the copyright holder saying it may be distributed
64
under the terms of this General Public License.  The "Program", below,
65
refers to any such program or work, and a "work based on the Program"
66
means either the Program or any derivative work under copyright law:
67
that is to say, a work containing the Program or a portion of it,
68
either verbatim or with modifications and/or translated into another
69
language.  (Hereinafter, translation is included without limitation in
70
the term "modification".)  Each licensee is addressed as "you".
71
72
Activities other than copying, distribution and modification are not
73
covered by this License; they are outside its scope.  The act of
74
running the Program is not restricted, and the output from the Program
75
is covered only if its contents constitute a work based on the
76
Program (independent of having been made by running the Program).
77
Whether that is true depends on what the Program does.
78
79
  1. You may copy and distribute verbatim copies of the Program's
80
source code as you receive it, in any medium, provided that you
81
conspicuously and appropriately publish on each copy an appropriate
82
copyright notice and disclaimer of warranty; keep intact all the
83
notices that refer to this License and to the absence of any warranty;
84
and give any other recipients of the Program a copy of this License
85
along with the Program.
86
87
You may charge a fee for the physical act of transferring a copy, and
88
you may at your option offer warranty protection in exchange for a fee.
89
90
  2. You may modify your copy or copies of the Program or any portion
91
of it, thus forming a work based on the Program, and copy and
92
distribute such modifications or work under the terms of Section 1
93
above, provided that you also meet all of these conditions:
94
95
    a) You must cause the modified files to carry prominent notices
96
    stating that you changed the files and the date of any change.
97
98
    b) You must cause any work that you distribute or publish, that in
99
    whole or in part contains or is derived from the Program or any
100
    part thereof, to be licensed as a whole at no charge to all third
101
    parties under the terms of this License.
102
103
    c) If the modified program normally reads commands interactively
104
    when run, you must cause it, when started running for such
105
    interactive use in the most ordinary way, to print or display an
106
    announcement including an appropriate copyright notice and a
107
    notice that there is no warranty (or else, saying that you provide
108
    a warranty) and that users may redistribute the program under
109
    these conditions, and telling the user how to view a copy of this
110
    License.  (Exception: if the Program itself is interactive but
111
    does not normally print such an announcement, your work based on
112
    the Program is not required to print an announcement.)
113

114
These requirements apply to the modified work as a whole.  If
115
identifiable sections of that work are not derived from the Program,
116
and can be reasonably considered independent and separate works in
117
themselves, then this License, and its terms, do not apply to those
118
sections when you distribute them as separate works.  But when you
119
distribute the same sections as part of a whole which is a work based
120
on the Program, the distribution of the whole must be on the terms of
121
this License, whose permissions for other licensees extend to the
122
entire whole, and thus to each and every part regardless of who wrote it.
123
124
Thus, it is not the intent of this section to claim rights or contest
125
your rights to work written entirely by you; rather, the intent is to
126
exercise the right to control the distribution of derivative or
127
collective works based on the Program.
128
129
In addition, mere aggregation of another work not based on the Program
130
with the Program (or with a work based on the Program) on a volume of
131
a storage or distribution medium does not bring the other work under
132
the scope of this License.
133
134
  3. You may copy and distribute the Program (or a work based on it,
135
under Section 2) in object code or executable form under the terms of
136
Sections 1 and 2 above provided that you also do one of the following:
137
138
    a) Accompany it with the complete corresponding machine-readable
139
    source code, which must be distributed under the terms of Sections
140
    1 and 2 above on a medium customarily used for software interchange; or,
141
142
    b) Accompany it with a written offer, valid for at least three
143
    years, to give any third party, for a charge no more than your
144
    cost of physically performing source distribution, a complete
145
    machine-readable copy of the corresponding source code, to be
146
    distributed under the terms of Sections 1 and 2 above on a medium
147
    customarily used for software interchange; or,
148
149
    c) Accompany it with the information you received as to the offer
150
    to distribute corresponding source code.  (This alternative is
151
    allowed only for noncommercial distribution and only if you
152
    received the program in object code or executable form with such
153
    an offer, in accord with Subsection b above.)
154
155
The source code for a work means the preferred form of the work for
156
making modifications to it.  For an executable work, complete source
157
code means all the source code for all modules it contains, plus any
158
associated interface definition files, plus the scripts used to
159
control compilation and installation of the executable.  However, as a
160
special exception, the source code distributed need not include
161
anything that is normally distributed (in either source or binary
162
form) with the major components (compiler, kernel, and so on) of the
163
operating system on which the executable runs, unless that component
164
itself accompanies the executable.
165
166
If distribution of executable or object code is made by offering
167
access to copy from a designated place, then offering equivalent
168
access to copy the source code from the same place counts as
169
distribution of the source code, even though third parties are not
170
compelled to copy the source along with the object code.
171

172
  4. You may not copy, modify, sublicense, or distribute the Program
173
except as expressly provided under this License.  Any attempt
174
otherwise to copy, modify, sublicense or distribute the Program is
175
void, and will automatically terminate your rights under this License.
176
However, parties who have received copies, or rights, from you under
177
this License will not have their licenses terminated so long as such
178
parties remain in full compliance.
179
180
  5. You are not required to accept this License, since you have not
181
signed it.  However, nothing else grants you permission to modify or
182
distribute the Program or its derivative works.  These actions are
183
prohibited by law if you do not accept this License.  Therefore, by
184
modifying or distributing the Program (or any work based on the
185
Program), you indicate your acceptance of this License to do so, and
186
all its terms and conditions for copying, distributing or modifying
187
the Program or works based on it.
188
189
  6. Each time you redistribute the Program (or any work based on the
190
Program), the recipient automatically receives a license from the
191
original licensor to copy, distribute or modify the Program subject to
192
these terms and conditions.  You may not impose any further
193
restrictions on the recipients' exercise of the rights granted herein.
194
You are not responsible for enforcing compliance by third parties to
195
this License.
196
197
  7. If, as a consequence of a court judgment or allegation of patent
198
infringement or for any other reason (not limited to patent issues),
199
conditions are imposed on you (whether by court order, agreement or
200
otherwise) that contradict the conditions of this License, they do not
201
excuse you from the conditions of this License.  If you cannot
202
distribute so as to satisfy simultaneously your obligations under this
203
License and any other pertinent obligations, then as a consequence you
204
may not distribute the Program at all.  For example, if a patent
205
license would not permit royalty-free redistribution of the Program by
206
all those who receive copies directly or indirectly through you, then
207
the only way you could satisfy both it and this License would be to
208
refrain entirely from distribution of the Program.
209
210
If any portion of this section is held invalid or unenforceable under
211
any particular circumstance, the balance of the section is intended to
212
apply and the section as a whole is intended to apply in other
213
circumstances.
214
215
It is not the purpose of this section to induce you to infringe any
216
patents or other property right claims or to contest validity of any
217
such claims; this section has the sole purpose of protecting the
218
integrity of the free software distribution system, which is
219
implemented by public license practices.  Many people have made
220
generous contributions to the wide range of software distributed
221
through that system in reliance on consistent application of that
222
system; it is up to the author/donor to decide if he or she is willing
223
to distribute software through any other system and a licensee cannot
224
impose that choice.
225
226
This section is intended to make thoroughly clear what is believed to
227
be a consequence of the rest of this License.
228

229
  8. If the distribution and/or use of the Program is restricted in
230
certain countries either by patents or by copyrighted interfaces, the
231
original copyright holder who places the Program under this License
232
may add an explicit geographical distribution limitation excluding
233
those countries, so that distribution is permitted only in or among
234
countries not thus excluded.  In such case, this License incorporates
235
the limitation as if written in the body of this License.
236
237
  9. The Free Software Foundation may publish revised and/or new versions
238
of the General Public License from time to time.  Such new versions will
239
be similar in spirit to the present version, but may differ in detail to
240
address new problems or concerns.
241
242
Each version is given a distinguishing version number.  If the Program
243
specifies a version number of this License which applies to it and "any
244
later version", you have the option of following the terms and conditions
245
either of that version or of any later version published by the Free
246
Software Foundation.  If the Program does not specify a version number of
247
this License, you may choose any version ever published by the Free Software
248
Foundation.
249
250
  10. If you wish to incorporate parts of the Program into other free
251
programs whose distribution conditions are different, write to the author
252
to ask for permission.  For software which is copyrighted by the Free
253
Software Foundation, write to the Free Software Foundation; we sometimes
254
make exceptions for this.  Our decision will be guided by the two goals
255
of preserving the free status of all derivatives of our free software and
256
of promoting the sharing and reuse of software generally.
257
258
			    NO WARRANTY
259
260
  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
262
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
266
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
267
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
REPAIR OR CORRECTION.
269
270
  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
POSSIBILITY OF SUCH DAMAGES.
279
280
		     END OF TERMS AND CONDITIONS
281

282
	    How to Apply These Terms to Your New Programs
283
284
  If you develop a new program, and you want it to be of the greatest
285
possible use to the public, the best way to achieve this is to make it
286
free software which everyone can redistribute and change under these terms.
287
288
  To do so, attach the following notices to the program.  It is safest
289
to attach them to the start of each source file to most effectively
290
convey the exclusion of warranty; and each file should have at least
291
the "copyright" line and a pointer to where the full notice is found.
292
293
    <one line to give the program's name and a brief idea of what it does.>
294
    Copyright (C) <year>  <name of author>
295
296
    This program is free software; you can redistribute it and/or modify
297
    it under the terms of the GNU General Public License as published by
298
    the Free Software Foundation; either version 2 of the License, or
299
    (at your option) any later version.
300
301
    This program is distributed in the hope that it will be useful,
302
    but WITHOUT ANY WARRANTY; without even the implied warranty of
303
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
304
    GNU General Public License for more details.
305
306
    You should have received a copy of the GNU General Public License
307
    along with this program; if not, write to the Free Software
308
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
309
310
311
Also add information on how to contact you by electronic and paper mail.
312
313
If the program is interactive, make it output a short notice like this
314
when it starts in an interactive mode:
315
316
    Gnomovision version 69, Copyright (C) year name of author
317
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318
    This is free software, and you are welcome to redistribute it
319
    under certain conditions; type `show c' for details.
320
321
The hypothetical commands `show w' and `show c' should show the appropriate
322
parts of the General Public License.  Of course, the commands you use may
323
be called something other than `show w' and `show c'; they could even be
324
mouse-clicks or menu items--whatever suits your program.
325
326
You should also get your employer (if you work as a programmer) or your
327
school, if any, to sign a "copyright disclaimer" for the program, if
328
necessary.  Here is a sample; alter the names:
329
330
  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331
  `Gnomovision' (which makes passes at compilers) written by James Hacker.
332
333
  <signature of Ty Coon>, 1 April 1989
334
  Ty Coon, President of Vice
335
336
This General Public License does not permit incorporating your program into
337
proprietary programs.  If your program is a subroutine library, you may
338
consider it more useful to permit linking proprietary applications with the
339
library.  If this is what you want to do, use the GNU Library General
340
Public License instead of this License.
3411
D licenses/RICH-TEXT-FX.md
1
Copyright (c) 2013-2017, Tomas Mikula and contributors
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
6
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
8
2. 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.
9
10
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.
111
D licenses/SAXON-HE.txt
1
                             Mozilla Public License
2
                                  Version 2.0
3
4
1. Definitions
5
6
   1.1. “Contributor”
7
          means each individual or legal entity that creates, contributes
8
          to the creation of, or owns Covered Software.
9
10
   1.2. “Contributor Version”
11
          means the combination of the Contributions of others (if any)
12
          used by a Contributor and that particular Contributor’s
13
          Contribution.
14
15
   1.3. “Contribution”
16
          means Covered Software of a particular Contributor.
17
18
   1.4. “Covered Software”
19
          means Source Code Form to which the initial Contributor has
20
          attached the notice in Exhibit A, the Executable Form of such
21
          Source Code Form, and Modifications of such Source Code Form, in
22
          each case including portions thereof.
23
24
   1.5. “Incompatible With Secondary Licenses”
25
          means
26
27
         a. that the initial Contributor has attached the notice described
28
            in Exhibit B to the Covered Software; or
29
         b. that the Covered Software was made available under the terms
30
            of version 1.1 or earlier of the License, but not also under
31
            the terms of a Secondary License.
32
33
   1.6. “Executable Form”
34
          means any form of the work other than Source Code Form.
35
36
   1.7. “Larger Work”
37
          means a work that combines Covered Software with other material,
38
          in a separate file or files, that is not Covered Software.
39
40
   1.8. “License”
41
          means this document.
42
43
   1.9. “Licensable”
44
          means having the right to grant, to the maximum extent possible,
45
          whether at the time of the initial grant or subsequently, any
46
          and all of the rights conveyed by this License.
47
48
   1.10. “Modifications”
49
          means any of the following:
50
51
         a. any file in Source Code Form that results from an addition to,
52
            deletion from, or modification of the contents of Covered
53
            Software; or
54
         b. any new file in Source Code Form that contains any Covered
55
            Software.
56
57
   1.11. “Patent Claims” of a Contributor
58
          means any patent claim(s), including without limitation, method,
59
          process, and apparatus claims, in any patent Licensable by such
60
          Contributor that would be infringed, but for the grant of the
61
          License, by the making, using, selling, offering for sale,
62
          having made, import, or transfer of either its Contributions or
63
          its Contributor Version.
64
65
   1.12. “Secondary License”
66
          means either the GNU General Public License, Version 2.0, the
67
          GNU Lesser General Public License, Version 2.1, the GNU Affero
68
          General Public License, Version 3.0, or any later versions of
69
          those licenses.
70
71
   1.13. “Source Code Form”
72
          means the form of the work preferred for making modifications.
73
74
   1.14. “You” (or “Your”)
75
          means an individual or a legal entity exercising rights under
76
          this License. For legal entities, “You” includes any entity that
77
          controls, is controlled by, or is under common control with You.
78
          For purposes of this definition, “control” means (a) the power,
79
          direct or indirect, to cause the direction or management of such
80
          entity, whether by contract or otherwise, or (b) ownership of
81
          more than fifty percent (50%) of the outstanding shares or
82
          beneficial ownership of such entity.
83
84
2. License Grants and Conditions
85
86
  2.1. Grants
87
88
   Each Contributor hereby grants You a world-wide, royalty-free,
89
   non-exclusive license:
90
    a. under intellectual property rights (other than patent or trademark)
91
       Licensable by such Contributor to use, reproduce, make available,
92
       modify, display, perform, distribute, and otherwise exploit its
93
       Contributions, either on an unmodified basis, with Modifications,
94
       or as part of a Larger Work; and
95
    b. under Patent Claims of such Contributor to make, use, sell, offer
96
       for sale, have made, import, and otherwise transfer either its
97
       Contributions or its Contributor Version.
98
99
  2.2. Effective Date
100
101
   The licenses granted in Section 2.1 with respect to any Contribution
102
   become effective for each Contribution on the date the Contributor
103
   first distributes such Contribution.
104
105
  2.3. Limitations on Grant Scope
106
107
   The licenses granted in this Section 2 are the only rights granted
108
   under this License. No additional rights or licenses will be implied
109
   from the distribution or licensing of Covered Software under this
110
   License. Notwithstanding Section 2.1(b) above, no patent license is
111
   granted by a Contributor:
112
    a. for any code that a Contributor has removed from Covered Software;
113
       or
114
    b. for infringements caused by: (i) Your and any other third party’s
115
       modifications of Covered Software, or (ii) the combination of its
116
       Contributions with other software (except as part of its
117
       Contributor Version); or
118
    c. under Patent Claims infringed by Covered Software in the absence of
119
       its Contributions.
120
121
   This License does not grant any rights in the trademarks, service
122
   marks, or logos of any Contributor (except as may be necessary to
123
   comply with the notice requirements in Section 3.4).
124
125
  2.4. Subsequent Licenses
126
127
   No Contributor makes additional grants as a result of Your choice to
128
   distribute the Covered Software under a subsequent version of this
129
   License (see Section 10.2) or under the terms of a Secondary License
130
   (if permitted under the terms of Section 3.3).
131
132
  2.5. Representation
133
134
   Each Contributor represents that the Contributor believes its
135
   Contributions are its original creation(s) or it has sufficient rights
136
   to grant the rights to its Contributions conveyed by this License.
137
138
  2.6. Fair Use
139
140
   This License is not intended to limit any rights You have under
141
   applicable copyright doctrines of fair use, fair dealing, or other
142
   equivalents.
143
144
  2.7. Conditions
145
146
   Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
147
   in Section 2.1.
148
149
3. Responsibilities
150
151
  3.1. Distribution of Source Form
152
153
   All distribution of Covered Software in Source Code Form, including any
154
   Modifications that You create or to which You contribute, must be under
155
   the terms of this License. You must inform recipients that the Source
156
   Code Form of the Covered Software is governed by the terms of this
157
   License, and how they can obtain a copy of this License. You may not
158
   attempt to alter or restrict the recipients’ rights in the Source Code
159
   Form.
160
161
  3.2. Distribution of Executable Form
162
163
   If You distribute Covered Software in Executable Form then:
164
    a. such Covered Software must also be made available in Source Code
165
       Form, as described in Section 3.1, and You must inform recipients
166
       of the Executable Form how they can obtain a copy of such Source
167
       Code Form by reasonable means in a timely manner, at a charge no
168
       more than the cost of distribution to the recipient; and
169
    b. You may distribute such Executable Form under the terms of this
170
       License, or sublicense it under different terms, provided that the
171
       license for the Executable Form does not attempt to limit or alter
172
       the recipients’ rights in the Source Code Form under this License.
173
174
  3.3. Distribution of a Larger Work
175
176
   You may create and distribute a Larger Work under terms of Your choice,
177
   provided that You also comply with the requirements of this License for
178
   the Covered Software. If the Larger Work is a combination of Covered
179
   Software with a work governed by one or more Secondary Licenses, and
180
   the Covered Software is not Incompatible With Secondary Licenses, this
181
   License permits You to additionally distribute such Covered Software
182
   under the terms of such Secondary License(s), so that the recipient of
183
   the Larger Work may, at their option, further distribute the Covered
184
   Software under the terms of either this License or such Secondary
185
   License(s).
186
187
  3.4. Notices
188
189
   You may not remove or alter the substance of any license notices
190
   (including copyright notices, patent notices, disclaimers of warranty,
191
   or limitations of liability) contained within the Source Code Form of
192
   the Covered Software, except that You may alter any license notices to
193
   the extent required to remedy known factual inaccuracies.
194
195
  3.5. Application of Additional Terms
196
197
   You may choose to offer, and to charge a fee for, warranty, support,
198
   indemnity or liability obligations to one or more recipients of Covered
199
   Software. However, You may do so only on Your own behalf, and not on
200
   behalf of any Contributor. You must make it absolutely clear that any
201
   such warranty, support, indemnity, or liability obligation is offered
202
   by You alone, and You hereby agree to indemnify every Contributor for
203
   any liability incurred by such Contributor as a result of warranty,
204
   support, indemnity or liability terms You offer. You may include
205
   additional disclaimers of warranty and limitations of liability
206
   specific to any jurisdiction.
207
208
4. Inability to Comply Due to Statute or Regulation
209
210
   If it is impossible for You to comply with any of the terms of this
211
   License with respect to some or all of the Covered Software due to
212
   statute, judicial order, or regulation then You must: (a) comply with
213
   the terms of this License to the maximum extent possible; and (b)
214
   describe the limitations and the code they affect. Such description
215
   must be placed in a text file included with all distributions of the
216
   Covered Software under this License. Except to the extent prohibited by
217
   statute or regulation, such description must be sufficiently detailed
218
   for a recipient of ordinary skill to be able to understand it.
219
220
5. Termination
221
222
   5.1. The rights granted under this License will terminate automatically
223
   if You fail to comply with any of its terms. However, if You become
224
   compliant, then the rights granted under this License from a particular
225
   Contributor are reinstated (a) provisionally, unless and until such
226
   Contributor explicitly and finally terminates Your grants, and (b) on
227
   an ongoing basis, if such Contributor fails to notify You of the
228
   non-compliance by some reasonable means prior to 60 days after You have
229
   come back into compliance. Moreover, Your grants from a particular
230
   Contributor are reinstated on an ongoing basis if such Contributor
231
   notifies You of the non-compliance by some reasonable means, this is
232
   the first time You have received notice of non-compliance with this
233
   License from such Contributor, and You become compliant prior to 30
234
   days after Your receipt of the notice.
235
236
   5.2. If You initiate litigation against any entity by asserting a
237
   patent infringement claim (excluding declaratory judgment actions,
238
   counter-claims, and cross-claims) alleging that a Contributor Version
239
   directly or indirectly infringes any patent, then the rights granted to
240
   You by any and all Contributors for the Covered Software under
241
   Section 2.1 of this License shall terminate.
242
243
   5.3. In the event of termination under Sections 5.1 or 5.2 above, all
244
   end user license agreements (excluding distributors and resellers)
245
   which have been validly granted by You or Your distributors under this
246
   License prior to termination shall survive termination.
247
248
6. Disclaimer of Warranty
249
250
   Covered Software is provided under this License on an “as is” basis,
251
   without warranty of any kind, either expressed, implied, or statutory,
252
   including, without limitation, warranties that the Covered Software is
253
   free of defects, merchantable, fit for a particular purpose or
254
   non-infringing. The entire risk as to the quality and performance of
255
   the Covered Software is with You. Should any Covered Software prove
256
   defective in any respect, You (not any Contributor) assume the cost of
257
   any necessary servicing, repair, or correction. This disclaimer of
258
   warranty constitutes an essential part of this License. No use of any
259
   Covered Software is authorized under this License except under this
260
   disclaimer.
261
262
7. Limitation of Liability
263
264
   Under no circumstances and under no legal theory, whether tort
265
   (including negligence), contract, or otherwise, shall any Contributor,
266
   or anyone who distributes Covered Software as permitted above, be
267
   liable to You for any direct, indirect, special, incidental, or
268
   consequential damages of any character including, without limitation,
269
   damages for lost profits, loss of goodwill, work stoppage, computer
270
   failure or malfunction, or any and all other commercial damages or
271
   losses, even if such party shall have been informed of the possibility
272
   of such damages. This limitation of liability shall not apply to
273
   liability for death or personal injury resulting from such party’s
274
   negligence to the extent applicable law prohibits such limitation. Some
275
   jurisdictions do not allow the exclusion or limitation of incidental or
276
   consequential damages, so this exclusion and limitation may not apply
277
   to You.
278
279
8. Litigation
280
281
   Any litigation relating to this License may be brought only in the
282
   courts of a jurisdiction where the defendant maintains its principal
283
   place of business and such litigation shall be governed by laws of that
284
   jurisdiction, without reference to its conflict-of-law provisions.
285
   Nothing in this Section shall prevent a party’s ability to bring
286
   cross-claims or counter-claims.
287
288
9. Miscellaneous
289
290
   This License represents the complete agreement concerning the subject
291
   matter hereof. If any provision of this License is held to be
292
   unenforceable, such provision shall be reformed only to the extent
293
   necessary to make it enforceable. Any law or regulation which provides
294
   that the language of a contract shall be construed against the drafter
295
   shall not be used to construe this License against a Contributor.
296
297
10. Versions of the License
298
299
  10.1. New Versions
300
301
   Mozilla Foundation is the license steward. Except as provided in
302
   Section 10.3, no one other than the license steward has the right to
303
   modify or publish new versions of this License. Each version will be
304
   given a distinguishing version number.
305
306
  10.2. Effect of New Versions
307
308
   You may distribute the Covered Software under the terms of the version
309
   of the License under which You originally received the Covered
310
   Software, or under the terms of any subsequent version published by the
311
   license steward.
312
313
  10.3. Modified Versions
314
315
   If you create software not governed by this License, and you want to
316
   create a new license for such software, you may create and use a
317
   modified version of this License if you rename the license and remove
318
   any references to the name of the license steward (except to note that
319
   such modified license differs from this License).
320
321
  10.4. Distributing Source Code Form that is Incompatible With Secondary
322
  Licenses
323
324
   If You choose to distribute Source Code Form that is Incompatible With
325
   Secondary Licenses under the terms of this version of the License, the
326
   notice described in Exhibit B of this License must be attached.
327
328
Exhibit A - Source Code Form License Notice
329
330
     This Source Code Form is subject to the terms of the Mozilla Public
331
     License, v. 2.0. If a copy of the MPL was not distributed with this
332
     file, You can obtain one at https://mozilla.org/MPL/2.0/.
333
334
   If it is not possible or desirable to put the notice in a particular
335
   file, then You may include the notice in a location (such as a LICENSE
336
   file in a relevant directory) where a recipient would be likely to look
337
   for such a notice.
338
339
   You may add additional accurate notices of copyright ownership.
340
341
Exhibit B - “Incompatible With Secondary Licenses” Notice
342
343
     This Source Code Form is “Incompatible With Secondary Licenses”, as
344
     defined by the Mozilla Public License, v. 2.0.
3451
D licenses/UNDO-FX.md
1
Copyright (c) 2014, TomasMikula
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without modification,
5
are permitted provided that the following conditions are met:
6
7
* Redistributions of source code must retain the above copyright notice, this
8
  list of conditions and the following disclaimer.
9
10
* Redistributions in binary form must reproduce the above copyright notice, this
11
  list of conditions and the following disclaimer in the documentation and/or
12
  other materials provided with the distribution.
131
14
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
D licenses/WELL-BEHAVED-FX.md
1
Copyright (c) 2014, TomasMikula
2
All rights reserved.
3
4
Redistribution and use in source and binary forms, with or without
5
modification, are permitted provided that the following conditions are met:
6
7
* Redistributions of source code must retain the above copyright notice, this
8
  list of conditions and the following disclaimer.
9
10
* Redistributions in binary form must reproduce the above copyright notice,
11
  this list of conditions and the following disclaimer in the documentation
12
  and/or other materials provided with the distribution.
13
14
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
251
D licenses/fonts/NOTO-CJK.md
1
URL: https://github.com/googlefonts/noto-cjk
2
3
Version: 1.002 or later
4
5
License: SIL Open Font License v1.1
6
7
License File: LICENSE
8
9
Note: prior releases of the CJK fonts were issued under the Apache 2
10
license. This was changed to the SIL OFL v1.1 starting with Version 1.002.
11
12
Description:
13
Noto CJK fonts, supporting Simplified Chinese, Traditional Chinese,
14
Japanese, and Korean. The supported scripts are Han, Hiragana, Katakana,
15
Hangul, and Bopomofo. Latin, Greek, Cyrillic, and various symbols are also
16
supported for compatibility with CJK standards.
17
18
The fonts in this directory are developed by Google and Adobe and are
19
released as open source under the Apache license version 2.0. The copyright
20
is held by Adobe, while the trademarks on the names are held by Google.
21
22
A README-formats file has been added explaining the different formats
23
provided and their features and limitations.
241
D licenses/fonts/NOTO-SANS.md
11
2
                                 Apache License
3
                           Version 2.0, January 2004
4
                        http://www.apache.org/licenses/
5
6
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
8
   1. Definitions.
9
10
      "License" shall mean the terms and conditions for use, reproduction,
11
      and distribution as defined by Sections 1 through 9 of this document.
12
13
      "Licensor" shall mean the copyright owner or entity authorized by
14
      the copyright owner that is granting the License.
15
16
      "Legal Entity" shall mean the union of the acting entity and all
17
      other entities that control, are controlled by, or are under common
18
      control with that entity. For the purposes of this definition,
19
      "control" means (i) the power, direct or indirect, to cause the
20
      direction or management of such entity, whether by contract or
21
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
      outstanding shares, or (iii) beneficial ownership of such entity.
23
24
      "You" (or "Your") shall mean an individual or Legal Entity
25
      exercising permissions granted by this License.
26
27
      "Source" form shall mean the preferred form for making modifications,
28
      including but not limited to software source code, documentation
29
      source, and configuration files.
30
31
      "Object" form shall mean any form resulting from mechanical
32
      transformation or translation of a Source form, including but
33
      not limited to compiled object code, generated documentation,
34
      and conversions to other media types.
35
36
      "Work" shall mean the work of authorship, whether in Source or
37
      Object form, made available under the License, as indicated by a
38
      copyright notice that is included in or attached to the work
39
      (an example is provided in the Appendix below).
40
41
      "Derivative Works" shall mean any work, whether in Source or Object
42
      form, that is based on (or derived from) the Work and for which the
43
      editorial revisions, annotations, elaborations, or other modifications
44
      represent, as a whole, an original work of authorship. For the purposes
45
      of this License, Derivative Works shall not include works that remain
46
      separable from, or merely link (or bind by name) to the interfaces of,
47
      the Work and Derivative Works thereof.
48
49
      "Contribution" shall mean any work of authorship, including
50
      the original version of the Work and any modifications or additions
51
      to that Work or Derivative Works thereof, that is intentionally
52
      submitted to Licensor for inclusion in the Work by the copyright owner
53
      or by an individual or Legal Entity authorized to submit on behalf of
54
      the copyright owner. For the purposes of this definition, "submitted"
55
      means any form of electronic, verbal, or written communication sent
56
      to the Licensor or its representatives, including but not limited to
57
      communication on electronic mailing lists, source code control systems,
58
      and issue tracking systems that are managed by, or on behalf of, the
59
      Licensor for the purpose of discussing and improving the Work, but
60
      excluding communication that is conspicuously marked or otherwise
61
      designated in writing by the copyright owner as "Not a Contribution."
62
63
      "Contributor" shall mean Licensor and any individual or Legal Entity
64
      on behalf of whom a Contribution has been received by Licensor and
65
      subsequently incorporated within the Work.
66
67
   2. Grant of Copyright License. Subject to the terms and conditions of
68
      this License, each Contributor hereby grants to You a perpetual,
69
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
      copyright license to reproduce, prepare Derivative Works of,
71
      publicly display, publicly perform, sublicense, and distribute the
72
      Work and such Derivative Works in Source or Object form.
73
74
   3. Grant of Patent License. Subject to the terms and conditions of
75
      this License, each Contributor hereby grants to You a perpetual,
76
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
      (except as stated in this section) patent license to make, have made,
78
      use, offer to sell, sell, import, and otherwise transfer the Work,
79
      where such license applies only to those patent claims licensable
80
      by such Contributor that are necessarily infringed by their
81
      Contribution(s) alone or by combination of their Contribution(s)
82
      with the Work to which such Contribution(s) was submitted. If You
83
      institute patent litigation against any entity (including a
84
      cross-claim or counterclaim in a lawsuit) alleging that the Work
85
      or a Contribution incorporated within the Work constitutes direct
86
      or contributory patent infringement, then any patent licenses
87
      granted to You under this License for that Work shall terminate
88
      as of the date such litigation is filed.
89
90
   4. Redistribution. You may reproduce and distribute copies of the
91
      Work or Derivative Works thereof in any medium, with or without
92
      modifications, and in Source or Object form, provided that You
93
      meet the following conditions:
94
95
      (a) You must give any other recipients of the Work or
96
          Derivative Works a copy of this License; and
97
98
      (b) You must cause any modified files to carry prominent notices
99
          stating that You changed the files; and
100
101
      (c) You must retain, in the Source form of any Derivative Works
102
          that You distribute, all copyright, patent, trademark, and
103
          attribution notices from the Source form of the Work,
104
          excluding those notices that do not pertain to any part of
105
          the Derivative Works; and
106
107
      (d) If the Work includes a "NOTICE" text file as part of its
108
          distribution, then any Derivative Works that You distribute must
109
          include a readable copy of the attribution notices contained
110
          within such NOTICE file, excluding those notices that do not
111
          pertain to any part of the Derivative Works, in at least one
112
          of the following places: within a NOTICE text file distributed
113
          as part of the Derivative Works; within the Source form or
114
          documentation, if provided along with the Derivative Works; or,
115
          within a display generated by the Derivative Works, if and
116
          wherever such third-party notices normally appear. The contents
117
          of the NOTICE file are for informational purposes only and
118
          do not modify the License. You may add Your own attribution
119
          notices within Derivative Works that You distribute, alongside
120
          or as an addendum to the NOTICE text from the Work, provided
121
          that such additional attribution notices cannot be construed
122
          as modifying the License.
123
124
      You may add Your own copyright statement to Your modifications and
125
      may provide additional or different license terms and conditions
126
      for use, reproduction, or distribution of Your modifications, or
127
      for any such Derivative Works as a whole, provided Your use,
128
      reproduction, and distribution of the Work otherwise complies with
129
      the conditions stated in this License.
130
131
   5. Submission of Contributions. Unless You explicitly state otherwise,
132
      any Contribution intentionally submitted for inclusion in the Work
133
      by You to the Licensor shall be under the terms and conditions of
134
      this License, without any additional terms or conditions.
135
      Notwithstanding the above, nothing herein shall supersede or modify
136
      the terms of any separate license agreement you may have executed
137
      with Licensor regarding such Contributions.
138
139
   6. Trademarks. This License does not grant permission to use the trade
140
      names, trademarks, service marks, or product names of the Licensor,
141
      except as required for reasonable and customary use in describing the
142
      origin of the Work and reproducing the content of the NOTICE file.
143
144
   7. Disclaimer of Warranty. Unless required by applicable law or
145
      agreed to in writing, Licensor provides the Work (and each
146
      Contributor provides its Contributions) on an "AS IS" BASIS,
147
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
      implied, including, without limitation, any warranties or conditions
149
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
      PARTICULAR PURPOSE. You are solely responsible for determining the
151
      appropriateness of using or redistributing the Work and assume any
152
      risks associated with Your exercise of permissions under this License.
153
154
   8. Limitation of Liability. In no event and under no legal theory,
155
      whether in tort (including negligence), contract, or otherwise,
156
      unless required by applicable law (such as deliberate and grossly
157
      negligent acts) or agreed to in writing, shall any Contributor be
158
      liable to You for damages, including any direct, indirect, special,
159
      incidental, or consequential damages of any character arising as a
160
      result of this License or out of the use or inability to use the
161
      Work (including but not limited to damages for loss of goodwill,
162
      work stoppage, computer failure or malfunction, or any and all
163
      other commercial damages or losses), even if such Contributor
164
      has been advised of the possibility of such damages.
165
166
   9. Accepting Warranty or Additional Liability. While redistributing
167
      the Work or Derivative Works thereof, You may choose to offer,
168
      and charge a fee for, acceptance of support, warranty, indemnity,
169
      or other liability obligations and/or rights consistent with this
170
      License. However, in accepting such obligations, You may act only
171
      on Your own behalf and on Your sole responsibility, not on behalf
172
      of any other Contributor, and only if You agree to indemnify,
173
      defend, and hold each Contributor harmless for any liability
174
      incurred by, or claims asserted against, such Contributor by reason
175
      of your accepting any such warranty or additional liability.
176
177
   END OF TERMS AND CONDITIONS
178
179
   APPENDIX: How to apply the Apache License to your work.
180
181
      To apply the Apache License to your work, attach the following
182
      boilerplate notice, with the fields enclosed by brackets "[]"
183
      replaced with your own identifying information. (Don't include
184
      the brackets!)  The text should be enclosed in the appropriate
185
      comment syntax for the file format. We also recommend that a
186
      file or class name and description of purpose be included on the
187
      same "printed page" as the copyright notice for easier
188
      identification within third-party archives.
189
190
   Copyright [yyyy] [name of copyright owner]
191
192
   Licensed under the Apache License, Version 2.0 (the "License");
193
   you may not use this file except in compliance with the License.
194
   You may obtain a copy of the License at
195
196
       http://www.apache.org/licenses/LICENSE-2.0
197
198
   Unless required by applicable law or agreed to in writing, software
199
   distributed under the License is distributed on an "AS IS" BASIS,
200
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
   See the License for the specific language governing permissions and
202
   limitations under the License.
203
D licenses/fonts/NOTO.md
1
Copyright 2018 The Noto Project Authors (https://github.com/googlei18n/noto-fonts)
2
3
This Font Software is licensed under the SIL Open Font License,
4
Version 1.1.
5
6
This license is copied below, and is also available with a FAQ at:
7
http://scripts.sil.org/OFL
8
9
-----------------------------------------------------------
10
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
11
-----------------------------------------------------------
12
13
PREAMBLE
14
The goals of the Open Font License (OFL) are to stimulate worldwide
15
development of collaborative font projects, to support the font
16
creation efforts of academic and linguistic communities, and to
17
provide a free and open framework in which fonts may be shared and
18
improved in partnership with others.
19
20
The OFL allows the licensed fonts to be used, studied, modified and
21
redistributed freely as long as they are not sold by themselves. The
22
fonts, including any derivative works, can be bundled, embedded,
23
redistributed and/or sold with any software provided that any reserved
24
names are not used by derivative works. The fonts and derivatives,
25
however, cannot be released under any other type of license. The
26
requirement for fonts to remain under this license does not apply to
27
any document created using the fonts or their derivatives.
28
29
DEFINITIONS
30
"Font Software" refers to the set of files released by the Copyright
31
Holder(s) under this license and clearly marked as such. This may
32
include source files, build scripts and documentation.
33
34
"Reserved Font Name" refers to any names specified as such after the
35
copyright statement(s).
36
37
"Original Version" refers to the collection of Font Software
38
components as distributed by the Copyright Holder(s).
39
40
"Modified Version" refers to any derivative made by adding to,
41
deleting, or substituting -- in part or in whole -- any of the
42
components of the Original Version, by changing formats or by porting
43
the Font Software to a new environment.
44
45
"Author" refers to any designer, engineer, programmer, technical
46
writer or other person who contributed to the Font Software.
47
48
PERMISSION & CONDITIONS
49
Permission is hereby granted, free of charge, to any person obtaining
50
a copy of the Font Software, to use, study, copy, merge, embed,
51
modify, redistribute, and sell modified and unmodified copies of the
52
Font Software, subject to the following conditions:
53
54
1) Neither the Font Software nor any of its individual components, in
55
Original or Modified Versions, may be sold by itself.
56
57
2) Original or Modified Versions of the Font Software may be bundled,
58
redistributed and/or sold with any software, provided that each copy
59
contains the above copyright notice and this license. These can be
60
included either as stand-alone text files, human-readable headers or
61
in the appropriate machine-readable metadata fields within text or
62
binary files as long as those fields can be easily viewed by the user.
63
64
3) No Modified Version of the Font Software may use the Reserved Font
65
Name(s) unless explicit written permission is granted by the
66
corresponding Copyright Holder. This restriction only applies to the
67
primary font name as presented to the users.
68
69
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
70
Software shall not be used to promote, endorse or advertise any
71
Modified Version, except to acknowledge the contribution(s) of the
72
Copyright Holder(s) and the Author(s) or with their explicit written
73
permission.
74
75
5) The Font Software, modified or unmodified, in part or in whole,
76
must be distributed entirely under this license, and must not be
77
distributed under any other license. The requirement for fonts to
78
remain under this license does not apply to any document created using
79
the Font Software.
80
81
TERMINATION
82
This license becomes null and void if any of the above conditions are
83
not met.
84
85
DISCLAIMER
86
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
87
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
88
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
89
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
90
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
91
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
92
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
93
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
94
OTHER DEALINGS IN THE FONT SOFTWARE.
951
D licenses/fonts/SOURCE-CODE-PRO.md
1
Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
2
3
This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
This license is copied below, and is also available with a FAQ at:
5
http://scripts.sil.org/OFL
6
7
8
-----------------------------------------------------------
9
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
-----------------------------------------------------------
11
12
PREAMBLE
13
The goals of the Open Font License (OFL) are to stimulate worldwide
14
development of collaborative font projects, to support the font creation
15
efforts of academic and linguistic communities, and to provide a free and
16
open framework in which fonts may be shared and improved in partnership
17
with others.
18
19
The OFL allows the licensed fonts to be used, studied, modified and
20
redistributed freely as long as they are not sold by themselves. The
21
fonts, including any derivative works, can be bundled, embedded, 
22
redistributed and/or sold with any software provided that any reserved
23
names are not used by derivative works. The fonts and derivatives,
24
however, cannot be released under any other type of license. The
25
requirement for fonts to remain under this license does not apply
26
to any document created using the fonts or their derivatives.
27
28
DEFINITIONS
29
"Font Software" refers to the set of files released by the Copyright
30
Holder(s) under this license and clearly marked as such. This may
31
include source files, build scripts and documentation.
32
33
"Reserved Font Name" refers to any names specified as such after the
34
copyright statement(s).
35
36
"Original Version" refers to the collection of Font Software components as
37
distributed by the Copyright Holder(s).
38
39
"Modified Version" refers to any derivative made by adding to, deleting,
40
or substituting -- in part or in whole -- any of the components of the
41
Original Version, by changing formats or by porting the Font Software to a
42
new environment.
43
44
"Author" refers to any designer, engineer, programmer, technical
45
writer or other person who contributed to the Font Software.
46
47
PERMISSION & CONDITIONS
48
Permission is hereby granted, free of charge, to any person obtaining
49
a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
redistribute, and sell modified and unmodified copies of the Font
51
Software, subject to the following conditions:
52
53
1) Neither the Font Software nor any of its individual components,
54
in Original or Modified Versions, may be sold by itself.
55
56
2) Original or Modified Versions of the Font Software may be bundled,
57
redistributed and/or sold with any software, provided that each copy
58
contains the above copyright notice and this license. These can be
59
included either as stand-alone text files, human-readable headers or
60
in the appropriate machine-readable metadata fields within text or
61
binary files as long as those fields can be easily viewed by the user.
62
63
3) No Modified Version of the Font Software may use the Reserved Font
64
Name(s) unless explicit written permission is granted by the corresponding
65
Copyright Holder. This restriction only applies to the primary font name as
66
presented to the users.
67
68
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
Software shall not be used to promote, endorse or advertise any
70
Modified Version, except to acknowledge the contribution(s) of the
71
Copyright Holder(s) and the Author(s) or with their explicit written
72
permission.
73
74
5) The Font Software, modified or unmodified, in part or in whole,
75
must be distributed entirely under this license, and must not be
76
distributed under any other license. The requirement for fonts to
77
remain under this license does not apply to any document created
78
using the Font Software.
79
80
TERMINATION
81
This license becomes null and void if any of the above conditions are
82
not met.
83
84
DISCLAIMER
85
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
OTHER DEALINGS IN THE FONT SOFTWARE.
941
D licenses/fonts/SOURCE-SERIF-4.md
1
Copyright 2014-2019 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries.
2
3
This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
5
This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
6
7
8
-----------------------------------------------------------
9
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
-----------------------------------------------------------
11
12
PREAMBLE
13
The goals of the Open Font License (OFL) are to stimulate worldwide
14
development of collaborative font projects, to support the font creation
15
efforts of academic and linguistic communities, and to provide a free and
16
open framework in which fonts may be shared and improved in partnership
17
with others.
18
19
The OFL allows the licensed fonts to be used, studied, modified and
20
redistributed freely as long as they are not sold by themselves. The
21
fonts, including any derivative works, can be bundled, embedded,
22
redistributed and/or sold with any software provided that any reserved
23
names are not used by derivative works. The fonts and derivatives,
24
however, cannot be released under any other type of license. The
25
requirement for fonts to remain under this license does not apply
26
to any document created using the fonts or their derivatives.
27
28
DEFINITIONS
29
"Font Software" refers to the set of files released by the Copyright
30
Holder(s) under this license and clearly marked as such. This may
31
include source files, build scripts and documentation.
32
33
"Reserved Font Name" refers to any names specified as such after the
34
copyright statement(s).
35
36
"Original Version" refers to the collection of Font Software components as
37
distributed by the Copyright Holder(s).
38
39
"Modified Version" refers to any derivative made by adding to, deleting,
40
or substituting -- in part or in whole -- any of the components of the
41
Original Version, by changing formats or by porting the Font Software to a
42
new environment.
43
44
"Author" refers to any designer, engineer, programmer, technical
45
writer or other person who contributed to the Font Software.
46
47
PERMISSION & CONDITIONS
48
Permission is hereby granted, free of charge, to any person obtaining
49
a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
redistribute, and sell modified and unmodified copies of the Font
51
Software, subject to the following conditions:
52
53
1) Neither the Font Software nor any of its individual components,
54
in Original or Modified Versions, may be sold by itself.
55
56
2) Original or Modified Versions of the Font Software may be bundled,
57
redistributed and/or sold with any software, provided that each copy
58
contains the above copyright notice and this license. These can be
59
included either as stand-alone text files, human-readable headers or
60
in the appropriate machine-readable metadata fields within text or
61
binary files as long as those fields can be easily viewed by the user.
62
63
3) No Modified Version of the Font Software may use the Reserved Font
64
Name(s) unless explicit written permission is granted by the corresponding
65
Copyright Holder. This restriction only applies to the primary font name as
66
presented to the users.
67
68
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
Software shall not be used to promote, endorse or advertise any
70
Modified Version, except to acknowledge the contribution(s) of the
71
Copyright Holder(s) and the Author(s) or with their explicit written
72
permission.
73
74
5) The Font Software, modified or unmodified, in part or in whole,
75
must be distributed entirely under this license, and must not be
76
distributed under any other license. The requirement for fonts to
77
remain under this license does not apply to any document created
78
using the Font Software.
79
80
TERMINATION
81
This license becomes null and void if any of the above conditions are
82
not met.
83
84
DISCLAIMER
85
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
OTHER DEALINGS IN THE FONT SOFTWARE.
941
D logging/Main.java
1
package com.github.javaparser;
2
3
import com.github.javaparser.ast.CompilationUnit;
4
import com.github.javaparser.ast.body.MethodDeclaration;
5
import com.github.javaparser.ast.body.TypeDeclaration;
6
import com.github.javaparser.ast.stmt.BlockStmt;
7
import com.github.javaparser.ast.stmt.Statement;
8
9
import java.io.File;
10
import java.io.FileNotFoundException;
11
import java.util.List;
12
import java.util.Optional;
13
14
import static com.github.javaparser.StaticJavaParser.parseStatement;
15
import static java.lang.String.format;
16
17
public class Main {
18
  public static void main( final String[] args ) throws FileNotFoundException {
19
    final File sourceFile = new File( args[ 0 ] );
20
    final JavaParser parser = new JavaParser();
21
    final ParseResult<CompilationUnit> pr = parser.parse( sourceFile );
22
    final Optional<CompilationUnit> ocu = pr.getResult();
23
24
    if( ocu.isPresent() ) {
25
      final CompilationUnit cu = ocu.get();
26
      final List<TypeDeclaration<?>> types = cu.getTypes();
27
28
      for( final TypeDeclaration<?> type : types ) {
29
        final List<MethodDeclaration> methods = type.getMethods();
30
31
        for( final MethodDeclaration method : methods ) {
32
          final Optional<BlockStmt> body = method.getBody();
33
          final String m = format( "%s::%s( %s )",
34
                                   type.getNameAsString(),
35
                                   method.getNameAsString(),
36
                                   method.getParameters().toString() );
37
38
          final String mBegan = format(
39
              "System.out.println(\"BEGAN %s\");", m );
40
          final String mEnded = format(
41
              "System.out.println(\"ENDED %s\");", m );
42
43
          final Statement sBegan = parseStatement( mBegan );
44
          final Statement sEnded = parseStatement( mEnded );
45
46
          body.ifPresent( ( b ) -> {
47
            final int i = b.getStatements().size();
48
49
            b.addStatement( 0, sBegan );
50
51
            // Insert before any "return" statement.
52
            b.addStatement( i, sEnded );
53
          } );
54
        }
55
56
        System.out.println( cu.toString() );
57
      }
58
    }
59
  }
60
}
611
D logging/README.md
1
# Logging
2
3
The files in this directory can be used to log the entry/exit to every
4
method for debugging purposes. These changes are not meant to be pushed
5
onto the mainline branch (i.e., not for production use).
6
7
The instructions are relative to the directory containing these instructions.
8
9
# Build
10
11
If modifications to the existing JAR are needed, rebuild the changes
12
as follows:
13
14
    git clone https://github.com/javaparser/javaparser
15
    cd javaparser
16
    cp Main.java ./javaparser-core/src/main/java/com/github/javaparser/.
17
    mvn package -Dmaven.test.skip=true
18
    cp javaparser-core/target/javaparser-core-3.16.2-SNAPSHOT.jar jp.jar
19
20
The file `jp.jar` is built with `Main.class`.
21
22
# Usage
23
24
Run the `inject` script to replace the original files with the logging
25
versions.
26
27
# Revert
28
29
When finished building a debug version of the application, reset the repo
30
as follows:
31
32
    git reset --hard HEAD
33
341
D logging/inject
1
#!/usr/bin/env bash
2
3
echo "Parsing"
4
find ../src/main/java -type f -name "*.java" -exec \
5
  sh -c 'echo {}; java -cp jp.jar com.github.javaparser.Main {} > {}.jp' \;
6
7
echo "Renaming"
8
# The +10c ensures that files without code are skipped.
9
find ../src/main/java -type f -name "*.jp" -size +10c -exec \
10
  sh -c 'echo {}; mv {} $(dirname {})/$(basename {} .jp)' \;
11
121
D logging/jp.jar
Binary file
D release
1
#!/usr/bin/env bash
2
3
# ---------------------------------------------------------------------------
4
# This script builds Windows, Linux, and Java archive binaries for a
5
# release.
6
# ---------------------------------------------------------------------------
7
8
source $HOME/bin/build-template
9
10
readonly FILE_PROPERTIES="${SCRIPT_DIR}/src/main/resources/bootstrap.properties"
11
readonly BIN_INSTALLER="${SCRIPT_DIR}/installer"
12
13
DEPENDENCIES=(
14
  "gradle,https://gradle.org"
15
  "${FILE_PROPERTIES},File containing application name"
16
)
17
18
execute() {
19
  $log "Build Windows installer binary"
20
  ${BIN_INSTALLER} -o windows
21
22
  $log "Build Linux installer binary"
23
  ${BIN_INSTALLER} -o linux
24
25
  $log "Build Java archive"
26
  gradle clean jar
27
  mv "build/libs/${application_title}.jar" .
28
}
29
30
preprocess() {
31
  while IFS='=' read -r key value; do
32
    if [[ "${key}" = "" || "${key}" = "#"* ]]; then
33
      continue
34
    fi
35
36
    key=$(echo $key | tr '.' '_')
37
    eval ${key}=\${value}
38
  done < "${FILE_PROPERTIES}"
39
40
  application_title="${application_title,,}"
41
42
  return 1
43
}
44
45
main "$@"
46
471
A release.sh
1
#!/usr/bin/env bash
2
3
# ---------------------------------------------------------------------------
4
# This script builds Windows, Linux, and Java archive binaries for a
5
# release.
6
# ---------------------------------------------------------------------------
7
8
source $HOME/bin/build-template
9
10
readonly FILE_PROPERTIES="${SCRIPT_DIR}/src/main/resources/bootstrap.properties"
11
readonly BIN_INSTALLER="${SCRIPT_DIR}/installer.sh"
12
13
DEPENDENCIES=(
14
  "gradle,https://gradle.org"
15
  "zip,http://infozip.sourceforge.net"
16
  "${FILE_PROPERTIES},File containing application name"
17
)
18
19
execute() {
20
  $log "Build Windows installer binary"
21
  ${BIN_INSTALLER} -o windows
22
23
  $log "Build Linux installer binary"
24
  ${BIN_INSTALLER} -o linux
25
26
  $log "Build Java archive"
27
  gradle clean jar
28
  mv "build/libs/${application_title}.jar" .
29
}
30
31
preprocess() {
32
  while IFS='=' read -r key value; do
33
    if [[ "${key}" = "" || "${key}" = "#"* ]]; then
34
      continue
35
    fi
36
37
    key=$(echo $key | tr '.' '_')
38
    eval ${key}=\${value}
39
  done < "${FILE_PROPERTIES}"
40
41
  application_title="${application_title,,}"
42
43
  return 1
44
}
45
46
main "$@"
47
148
A scripts/bash-template
1
#!/usr/bin/env bash
2
3
# -----------------------------------------------------------------------------
4
# Copyright 2020 Dave Jarvis
5
#
6
# Permission is hereby granted, free of charge, to any person obtaining a
7
# copy of this software and associated documentation files (the
8
# "Software"), to deal in the Software without restriction, including
9
# without limitation the rights to use, copy, modify, merge, publish,
10
# distribute, sublicense, and/or sell copies of the Software, and to
11
# permit persons to whom the Software is furnished to do so, subject to
12
# the following conditions:
13
#
14
# The above copyright notice and this permission notice shall be included
15
# in all copies or substantial portions of the Software.
16
#
17
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
# -----------------------------------------------------------------------------
25
26
set -o errexit
27
set -o nounset
28
29
readonly SCRIPT_SRC="$(dirname "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}")"
30
readonly SCRIPT_DIR="$(cd "${SCRIPT_SRC}" >/dev/null 2>&1 && pwd)"
31
readonly SCRIPT_NAME=$(basename "$0")
32
33
# -----------------------------------------------------------------------------
34
# The main entry point is responsible for parsing command-line arguments,
35
# changing to the appropriate directory, and running all commands requested
36
# by the user.
37
#
38
# $@ - Command-line arguments
39
# -----------------------------------------------------------------------------
40
main() {
41
  arguments "$@"
42
43
  $usage       && terminate 3
44
  requirements && terminate 4
45
  traps        && terminate 5
46
47
  directory    && terminate 6
48
  preprocess   && terminate 7
49
  execute      && terminate 8
50
  postprocess  && terminate 9
51
52
  terminate 0
53
}
54
55
# -----------------------------------------------------------------------------
56
# Perform all commands that the script requires.
57
#
58
# @return 0 - Indicate to terminate the script with non-zero exit level
59
# @return 1 - All tasks completed successfully (default)
60
# -----------------------------------------------------------------------------
61
execute() {
62
  return 1
63
}
64
65
# -----------------------------------------------------------------------------
66
# Changes to the script's working directory, provided it exists.
67
#
68
# @return 0 - Change directory failed
69
# @return 1 - Change directory succeeded
70
# -----------------------------------------------------------------------------
71
directory() {
72
  $log "Change directory"
73
  local result=1
74
75
  # Track whether change directory failed.
76
  cd "${SCRIPT_DIR}" > /dev/null 2>&1 || result=0
77
78
  return "${result}"
79
}
80
81
# -----------------------------------------------------------------------------
82
# Perform any initialization required prior to executing tasks.
83
#
84
# @return 0 - Preprocessing failed
85
# @return 1 - Preprocessing succeeded
86
# -----------------------------------------------------------------------------
87
preprocess() {
88
  $log "Preprocess"
89
90
  return 1
91
}
92
93
# -----------------------------------------------------------------------------
94
# Perform any clean up required prior to executing tasks.
95
#
96
# @return 0 - Postprocessing failed
97
# @return 1 - Postprocessing succeeded
98
# -----------------------------------------------------------------------------
99
postprocess() {
100
  $log "Postprocess"
101
102
  return 1
103
}
104
105
# -----------------------------------------------------------------------------
106
# Check that all required commands are available.
107
#
108
# @return 0 - At least one command is missing
109
# @return 1 - All commands are available
110
# -----------------------------------------------------------------------------
111
requirements() {
112
  $log "Verify requirements"
113
  local -r expected_count=${#DEPENDENCIES[@]}
114
  local total_count=0
115
116
  # Verify that each command exists.
117
  for dependency in "${DEPENDENCIES[@]}"; do
118
    # Extract the command name [0] and URL [1].
119
    IFS=',' read -ra dependent <<< "${dependency}"
120
121
    required "${dependent[0]}" "${dependent[1]}"
122
    total_count=$(( total_count + $? ))
123
  done
124
125
  unset IFS
126
127
  # Total dependencies found must match the expected number.
128
  # Integer-only division rounds down.
129
  return $(( total_count / expected_count ))
130
}
131
132
# -----------------------------------------------------------------------------
133
# Called before terminating the script.
134
# -----------------------------------------------------------------------------
135
cleanup() {
136
  $log "Cleanup"
137
}
138
139
# -----------------------------------------------------------------------------
140
# Terminates the program immediately.
141
# -----------------------------------------------------------------------------
142
trap_control_c() {
143
  $log "Interrupted"
144
  cleanup
145
  error "⯃"
146
  terminate 1
147
}
148
149
# -----------------------------------------------------------------------------
150
# Configure signal traps.
151
#
152
# @return 1 - Signal traps are set.
153
# -----------------------------------------------------------------------------
154
traps() {
155
  # Suppress echoing ^C if pressed.
156
  stty -echoctl
157
  trap trap_control_c INT
158
159
  return 1
160
}
161
162
# -----------------------------------------------------------------------------
163
# Check for a required command.
164
#
165
# $1 - Command or file to check for existence
166
# $2 - Command's website (e.g., download for binaries and source code)
167
#
168
# @return 0 - Command is missing
169
# @return 1 - Command exists
170
# -----------------------------------------------------------------------------
171
required() {
172
  local result=0
173
174
  test -f "$1" || \
175
  command -v "$1" > /dev/null 2>&1 && result=1 || \
176
    warning "Missing: $1 ($2)"
177
178
  return ${result}
179
}
180
181
# -----------------------------------------------------------------------------
182
# Show acceptable command-line arguments.
183
#
184
# @return 0 - Indicate script may not continue
185
# -----------------------------------------------------------------------------
186
utile_usage() {
187
  printf "Usage: %s [OPTIONS...]\n\n" "${SCRIPT_NAME}" >&2
188
189
  # Number of spaces to pad after the longest long argument.
190
  local -r PADDING=2
191
192
  # Determine the longest long argument to adjust spacing.
193
  local -r LEN=$(printf '%s\n' "${ARGUMENTS[@]}" | \
194
    awk -F"," '{print length($2)+'${PADDING}'}' | sort -n | tail -1)
195
196
  local duplicates
197
198
  for argument in "${ARGUMENTS[@]}"; do
199
    # Extract the short [0] and long [1] arguments and description [2].
200
    arg=("$(echo ${argument} | cut -d ',' -f1)" \
201
         "$(echo ${argument} | cut -d ',' -f2)" \
202
         "$(echo ${argument} | cut -d ',' -f3-)")
203
204
    duplicates+=("${arg[0]}")
205
206
    printf "  -%s, --%-${LEN}s%s\n" "${arg[0]}" "${arg[1]}" "${arg[2]}" >&2
207
  done
208
209
  # Sort the arguments to make sure no duplicates exist.
210
  duplicates=$(echo "${duplicates[@]}" | tr ' ' '\n' | sort | uniq -c -d)
211
212
  # Warn the developer that there's a duplicate command-line option.
213
  if [ -n "${duplicates}" ]; then
214
    # Trim all the whitespaces
215
    duplicates=$(echo "${duplicates}" | xargs echo -n)
216
    error "Duplicate command-line argument exists: ${duplicates}"
217
  fi
218
219
  return 0
220
}
221
222
# -----------------------------------------------------------------------------
223
# Write coloured text to standard output.
224
#
225
# $1 - Text to write
226
# $2 - Text's colour
227
# -----------------------------------------------------------------------------
228
coloured_text() {
229
  printf "%b%s%b\n" "$2" "$1" "${COLOUR_OFF}"
230
}
231
232
# -----------------------------------------------------------------------------
233
# Write a warning message to standard output.
234
#
235
# $1 - Text to write
236
# -----------------------------------------------------------------------------
237
warning() {
238
  coloured_text "$1" "${COLOUR_WARNING}"
239
}
240
241
# -----------------------------------------------------------------------------
242
# Write an error message to standard output.
243
#
244
# $1 - Text to write
245
# -----------------------------------------------------------------------------
246
error() {
247
  coloured_text "$1" "${COLOUR_ERROR}"
248
}
249
250
# -----------------------------------------------------------------------------
251
# Write a timestamp and message to standard output.
252
#
253
# $1 - Text to write
254
# -----------------------------------------------------------------------------
255
utile_log() {
256
  printf "[%s] " "$(date +%H:%M:%S.%4N)"
257
  coloured_text "$1" "${COLOUR_LOGGING}"
258
}
259
260
# -----------------------------------------------------------------------------
261
# Perform no operations.
262
#
263
# return 1 - Success
264
# -----------------------------------------------------------------------------
265
noop() {
266
  return 1
267
}
268
269
# -----------------------------------------------------------------------------
270
# Exit the program with a given exit code.
271
#
272
# $1 - Exit code
273
# -----------------------------------------------------------------------------
274
terminate() {
275
  exit "$1"
276
}
277
278
# -----------------------------------------------------------------------------
279
# Set global variables from command-line arguments.
280
# -----------------------------------------------------------------------------
281
arguments() {
282
  while [ "$#" -gt "0" ]; do
283
    local consume=1
284
285
    case "$1" in
286
      -V|--verbose)
287
        log=utile_log
288
      ;;
289
      -h|-\?|--help)
290
        usage=utile_usage
291
      ;;
292
      *)
293
        set +e
294
        argument "$@"
295
        consume=$?
296
        set -e
297
      ;;
298
    esac
299
300
    shift ${consume}
301
  done
302
}
303
304
# -----------------------------------------------------------------------------
305
# Parses a single command-line argument. This must return a value greater
306
# than or equal to 1, otherwise parsing the command-line arguments will
307
# loop indefinitely.
308
#
309
# @return The number of arguments to consume (1 by default).
310
# -----------------------------------------------------------------------------
311
argument() {
312
  return 1
313
}
314
315
# ANSI colour escape sequences.
316
readonly COLOUR_BLUE='\033[1;34m'
317
readonly COLOUR_PINK='\033[1;35m'
318
readonly COLOUR_DKGRAY='\033[30m'
319
readonly COLOUR_DKRED='\033[31m'
320
readonly COLOUR_LTRED='\033[1;31m'
321
readonly COLOUR_YELLOW='\033[1;33m'
322
readonly COLOUR_OFF='\033[0m'
323
324
# Colour definitions used by script.
325
COLOUR_LOGGING=${COLOUR_BLUE}
326
COLOUR_WARNING=${COLOUR_YELLOW}
327
COLOUR_ERROR=${COLOUR_LTRED}
328
329
# Define required commands to check when script starts.
330
DEPENDENCIES=(
331
  "awk,https://www.gnu.org/software/gawk/manual/gawk.html"
332
  "cut,https://www.gnu.org/software/coreutils"
333
)
334
335
# Define help for command-line arguments.
336
ARGUMENTS=(
337
  "V,verbose,Log messages while processing"
338
  "h,help,Show this help message then exit"
339
)
340
341
# These functions may be set to utile delegates while parsing arguments.
342
usage=noop
343
log=noop
344
1345
A scripts/font-names.sh
1
#!/usr/bin/env bash
2
3
# Outputs font names for all font files.
4
5
find src/main/resources/fonts -type f \( -name "*otf" -o -name "*ttf" \) -exec \
6
  fc-scan --format "%{foundry}: %{family}\n" {} \; | uniq | sort
7
18
A scripts/localpath.bat
1
@echo off
2
set "OWNPATH=%~dp0"
3
set "PLATFORM=mswin"
4
5
if defined ProgramFiles(x86)                        set "PLATFORM=win64"
6
if "%PROCESSOR_ARCHITECTURE%"=="AMD64"              set "PLATFORM=win64"
7
if exist "%OWNPATH%tex\texmf-mswin\bin\context.exe" set "PLATFORM=mswin"
8
if exist "%OWNPATH%tex\texmf-win64\bin\context.exe" set "PLATFORM=win64"
9
10
set "TeXPath=%OWNPATH%tex\texmf-%PLATFORM%\bin"
11
12
echo %PATH% | findstr "texmf-%PLATFORM%" > nul
13
14
rem Only update the PATH if not previously updated
15
if ERRORLEVEL 1 (
16
  setlocal enabledelayedexpansion
17
  set "Exists=false"
18
  set "Key=HKCU\Environment"
19
  
20
  for /F "USEBACKQ tokens=2*" %%A in (`reg query %%Key%% /v PATH 2^>nul`) do (
21
    if not "%%~B" == "" (
22
      set "Exists=true"
23
24
      rem Preserve the existing PATH
25
      echo %%B > currpath.txt
26
27
      rem Change the PATH environment variable
28
      setx PATH "%%B;%TeXPath%"
29
    )
30
  )
31
32
  rem The user-defined PATH does not exist, create it
33
  if "!Exists!" == "false" (
34
    rem Change the user PATH environment variable
35
    setx PATH "%TeXPath%"
36
  )
37
38
  endlocal
39
  
40
  rem Update the current session
41
  set "PATH=%PATH%;%TeXPath%"
42
)
43
144
M src/main/java/com/keenwrite/AbstractFileFactory.java
66
import java.nio.file.Path;
77
8
import static com.keenwrite.Constants.GLOB_PREFIX_FILE;
9
import static com.keenwrite.Constants.sSettings;
8
import static com.keenwrite.constants.Constants.GLOB_PREFIX_FILE;
9
import static com.keenwrite.constants.Constants.sSettings;
1010
import static com.keenwrite.io.FileType.UNKNOWN;
1111
import static com.keenwrite.predicates.PredicateFactory.createFileTypePredicate;
M src/main/java/com/keenwrite/Bootstrap.java
22
package com.keenwrite;
33
4
import com.keenwrite.constants.Constants;
5
46
import java.io.InputStream;
57
import java.util.Calendar;
M src/main/java/com/keenwrite/Caret.java
1010
import java.util.Collection;
1111
12
import static com.keenwrite.Constants.STATUS_BAR_LINE;
12
import static com.keenwrite.constants.Constants.STATUS_BAR_LINE;
1313
import static com.keenwrite.Messages.get;
1414
D src/main/java/com/keenwrite/Constants.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite;
3
4
import com.keenwrite.service.Settings;
5
import javafx.scene.image.Image;
6
import javafx.scene.image.ImageView;
7
8
import java.io.File;
9
import java.nio.charset.Charset;
10
import java.nio.file.Path;
11
import java.util.ArrayList;
12
import java.util.List;
13
import java.util.Locale;
14
15
import static com.keenwrite.Bootstrap.APP_TITLE_LOWERCASE;
16
import static com.keenwrite.preferences.LocaleScripts.withScript;
17
import static java.io.File.separator;
18
import static java.lang.String.format;
19
import static java.lang.System.getProperty;
20
21
/**
22
 * Defines application-wide default values.
23
 */
24
public final class Constants {
25
26
  /**
27
   * Used by the default settings to load the {@link Settings} service. This
28
   * must come before any attempt is made to create a {@link Settings} object.
29
   * The reference to {@link Bootstrap#APP_TITLE_LOWERCASE} should cause the
30
   * JVM to load {@link Bootstrap} prior to proceeding. Loading that class
31
   * beforehand will read the bootstrap properties file to determine the
32
   * application name, which is then used to locate the settings properties.
33
   */
34
  public static final String PATH_PROPERTIES_SETTINGS =
35
    format( "/com/%s/settings.properties", APP_TITLE_LOWERCASE );
36
37
  /**
38
   * The {@link Settings} uses {@link #PATH_PROPERTIES_SETTINGS}.
39
   */
40
  public static final Settings sSettings = Services.load( Settings.class );
41
42
  public static final double WINDOW_X_DEFAULT = 0;
43
  public static final double WINDOW_Y_DEFAULT = 0;
44
  public static final double WINDOW_W_DEFAULT = 1200;
45
  public static final double WINDOW_H_DEFAULT = 800;
46
47
  public static final File DOCUMENT_DEFAULT = getFile( "document" );
48
  public static final File DEFINITION_DEFAULT = getFile( "definition" );
49
50
  public static final String APP_BUNDLE_NAME = get( "application.messages" );
51
52
  public static final String STYLESHEET_APPLICATION_BASE =
53
    get( "file.stylesheet.application.base" );
54
  public static final String STYLESHEET_APPLICATION_THEME =
55
    get( "file.stylesheet.application.theme" );
56
  public static final String STYLESHEET_MARKDOWN =
57
    get( "file.stylesheet.markdown" );
58
  public static final String STYLESHEET_MARKDOWN_LOCALE =
59
    "file.stylesheet.markdown.locale";
60
  public static final String STYLESHEET_PREVIEW =
61
    get( "file.stylesheet.preview" );
62
  public static final String STYLESHEET_PREVIEW_LOCALE =
63
    "file.stylesheet.preview.locale";
64
65
  public static final List<Image> LOGOS = createImages(
66
    "file.logo.16",
67
    "file.logo.32",
68
    "file.logo.128",
69
    "file.logo.256",
70
    "file.logo.512"
71
  );
72
73
  public static final Image ICON_DIALOG = LOGOS.get( 1 );
74
  public static final ImageView ICON_DIALOG_NODE = new ImageView( ICON_DIALOG );
75
76
  public static final String FILE_PREFERENCES = getPreferencesFilename();
77
78
  /**
79
   * Refer to file name extension settings in the configuration file. Do not
80
   * terminate with a period.
81
   */
82
  public static final String GLOB_PREFIX_FILE = "file.ext";
83
84
  /**
85
   * Three parameters: line number, column number, and offset.
86
   */
87
  public static final String STATUS_BAR_LINE = "Main.status.line";
88
89
  public static final String STATUS_BAR_OK = "Main.status.state.default";
90
91
  /**
92
   * Used to show an error while parsing, usually syntactical.
93
   */
94
  public static final String STATUS_PARSE_ERROR = "Main.status.error.parse";
95
  public static final String STATUS_DEFINITION_BLANK =
96
    "Main.status.error.def.blank";
97
  public static final String STATUS_DEFINITION_EMPTY =
98
    "Main.status.error.def.empty";
99
100
  /**
101
   * One parameter: the word under the cursor that could not be found.
102
   */
103
  public static final String STATUS_DEFINITION_MISSING =
104
    "Main.status.error.def.missing";
105
106
  /**
107
   * Used when creating flat maps relating to resolved variables.
108
   */
109
  public static final int MAP_SIZE_DEFAULT = 128;
110
111
  /**
112
   * Default image extension order to use when scanning.
113
   */
114
  public static final String PERSIST_IMAGES_DEFAULT =
115
    get( "file.ext.image.order" );
116
117
  /**
118
   * Default working directory to use for R startup script.
119
   */
120
  public static final File USER_DIRECTORY =
121
    new File( System.getProperty( "user.dir" ) );
122
123
  public static final String NEWLINE = System.lineSeparator();
124
125
  /**
126
   * Default path to use for an untitled (pathless) file.
127
   */
128
  public static final Path DEFAULT_DIRECTORY = USER_DIRECTORY.toPath();
129
130
  /**
131
   * Default character set to use when reading/writing files.
132
   */
133
  public static final Charset DEFAULT_CHARSET = Charset.defaultCharset();
134
135
  /**
136
   * Default starting delimiter for definition variables. This value must
137
   * not overlap math delimiters, so do not use $ tokens as the first
138
   * delimiter.
139
   */
140
  public static final String DEF_DELIM_BEGAN_DEFAULT = "{{";
141
142
  /**
143
   * Default ending delimiter for definition variables.
144
   */
145
  public static final String DEF_DELIM_ENDED_DEFAULT = "}}";
146
147
  /**
148
   * Default starting delimiter when inserting R variables.
149
   */
150
  public static final String R_DELIM_BEGAN_DEFAULT = "x( ";
151
152
  /**
153
   * Default ending delimiter when inserting R variables.
154
   */
155
  public static final String R_DELIM_ENDED_DEFAULT = " )";
156
157
  /**
158
   * Resource directory where different language lexicons are located.
159
   */
160
  public static final String LEXICONS_DIRECTORY = "lexicons";
161
162
  /**
163
   * Absolute location of true type font files within the Java archive file.
164
   */
165
  public static final String FONT_DIRECTORY = "/fonts";
166
167
  /**
168
   * Default text editor font name.
169
   */
170
  public static final String FONT_NAME_EDITOR_DEFAULT = "Noto Sans Regular";
171
172
  /**
173
   * Default text editor font size, in points.
174
   */
175
  public static final float FONT_SIZE_EDITOR_DEFAULT = 12f;
176
177
  /**
178
   * Default preview font name.
179
   */
180
  public static final String FONT_NAME_PREVIEW_DEFAULT = "Source Serif 4";
181
182
  /**
183
   * Default preview font size, in points.
184
   */
185
  public static final float FONT_SIZE_PREVIEW_DEFAULT = 13f;
186
187
  /**
188
   * Default monospace preview font name.
189
   */
190
  public static final String FONT_NAME_PREVIEW_MONO_NAME_DEFAULT =
191
    "Source Code Pro";
192
193
  /**
194
   * Default monospace preview font size, in points.
195
   */
196
  public static final float FONT_SIZE_PREVIEW_MONO_SIZE_DEFAULT = 13f;
197
198
  /**
199
   * Default locale for font loading, including ISO 15924 alpha-4 script code.
200
   */
201
  public static final Locale LOCALE_DEFAULT = withScript( Locale.getDefault() );
202
203
  /**
204
   * Default CSS theme to apply (resolves to a minimal implementation).
205
   */
206
  public static final String THEME_DEFAULT = "Modena Light";
207
208
  /**
209
   * Custom CSS theme to apply.
210
   */
211
  public static final File THEME_CUSTOM_DEFAULT = null;
212
213
  /**
214
   * Default identifier to use for synchronized scrolling.
215
   */
216
  public static final String CARET_ID = "caret";
217
218
  /**
219
   * Default spacing for UI items (e.g., toolbars).
220
   */
221
  public static final int UI_CONTROL_SPACING = 10;
222
223
  /**
224
   * Default server name for rendering diagrams.
225
   * <p>
226
   * TODO: Make this a preference so that local installs are possible.
227
   */
228
  public static final String DIAGRAM_SERVER_NAME = "kroki.io";
229
230
  /**
231
   * Application action messages properties prefix.
232
   */
233
  public static final String ACTION_PREFIX = "Action.";
234
235
  /**
236
   * Prevent instantiation.
237
   */
238
  private Constants() {
239
  }
240
241
  /**
242
   * Converts from points to pixels because FlyingSaucer cannot handle points
243
   * properly. This is used to convert font sizes.
244
   *
245
   * @param points The points to convert to pixels.
246
   * @return The given number of points in equivalent pixels.
247
   */
248
  public static int toPixels( final double points ) {
249
    return (int) (points * (1 + 1 / 3f));
250
  }
251
252
  private static String get( final String key ) {
253
    return sSettings.getSetting( key, "" );
254
  }
255
256
  /**
257
   * Returns a default {@link File} instance based on the given key suffix.
258
   *
259
   * @param suffix Appended to {@code "file.default."}.
260
   * @return A new {@link File} instance that references the settings file name.
261
   */
262
  private static File getFile( final String suffix ) {
263
    return new File( get( "file.default." + suffix ) );
264
  }
265
266
  /**
267
   * Returns the equivalent of {@code $HOME/.filename.xml}.
268
   */
269
  private static String getPreferencesFilename() {
270
    return format(
271
      "%s%s.%s.xml",
272
      getProperty( "user.home" ),
273
      separator,
274
      APP_TITLE_LOWERCASE
275
    );
276
  }
277
278
  /**
279
   * Converts the given file names to images, such as application icons.
280
   *
281
   * @param keys The file names to convert to images.
282
   * @return The images loaded from the file name references.
283
   */
284
  private static List<Image> createImages( final String... keys ) {
285
    final List<Image> images = new ArrayList<>( keys.length );
286
287
    for( final var key : keys ) {
288
      images.add( new Image( get( key ) ) );
289
    }
290
291
    return images;
292
  }
293
}
2941
M src/main/java/com/keenwrite/DefinitionNameInjector.java
77
import com.keenwrite.sigils.SigilOperator;
88
9
import static com.keenwrite.Constants.*;
9
import static com.keenwrite.constants.Constants.*;
1010
import static com.keenwrite.events.StatusEvent.clue;
1111
M src/main/java/com/keenwrite/ExportFormat.java
2525
2626
  /**
27
   * For XHTML exports, encode TeX using {@code $} delimiters.
28
   */
29
  XHTML_TEX( ".xml" ),
30
31
  /**
2732
   * Indicates that the processors should export to a Markdown format.
2833
   * Treat image links relatively.
2934
   */
3035
  MARKDOWN_PLAIN( ".out.md" ),
36
37
  /**
38
   * Exports as PDF file format.
39
   */
40
  APPLICATION_PDF( ".pdf" ),
3141
3242
  /**
M src/main/java/com/keenwrite/MainApp.java
22
package com.keenwrite;
33
4
import com.keenwrite.events.HyperlinkOpenEvent;
45
import com.keenwrite.preferences.Workspace;
56
import javafx.application.Application;
67
import javafx.event.Event;
78
import javafx.event.EventType;
89
import javafx.scene.input.KeyCode;
910
import javafx.scene.input.KeyEvent;
1011
import javafx.stage.Stage;
12
import org.greenrobot.eventbus.Subscribe;
1113
1214
import java.util.function.BooleanSupplier;
1315
import java.util.logging.LogManager;
1416
1517
import static com.keenwrite.Bootstrap.APP_TITLE;
16
import static com.keenwrite.Constants.LOGOS;
18
import static com.keenwrite.constants.GraphicsConstants.LOGOS;
19
import static com.keenwrite.events.Bus.register;
1720
import static com.keenwrite.preferences.WorkspaceKeys.*;
1821
import static com.keenwrite.util.FontLoader.initFonts;
...
6770
6871
    stage.show();
72
    register( this );
6973
  }
7074
...
120124
    mMainScene = new MainScene( mWorkspace );
121125
    stage.setScene( mMainScene.getScene() );
126
  }
127
128
  /**
129
   * When a hyperlink website URL is clicked, this method is called to launch
130
   * the default browser to the event's location.
131
   *
132
   * @param event The event called when a hyperlink was clicked.
133
   */
134
  @Subscribe
135
  public void handle( final HyperlinkOpenEvent event ) {
136
    getHostServices().showDocument( event.getUri().toString() );
122137
  }
123138
M src/main/java/com/keenwrite/MainPane.java
99
import com.keenwrite.editors.definition.yaml.YamlTreeTransformer;
1010
import com.keenwrite.editors.markdown.MarkdownEditor;
11
import com.keenwrite.events.CaretNavigationEvent;
12
import com.keenwrite.events.FileOpenEvent;
13
import com.keenwrite.events.TextDefinitionFocusEvent;
14
import com.keenwrite.events.TextEditorFocusEvent;
15
import com.keenwrite.io.MediaType;
16
import com.keenwrite.preferences.Key;
17
import com.keenwrite.preferences.Workspace;
18
import com.keenwrite.preview.HtmlPanel;
19
import com.keenwrite.preview.HtmlPreview;
20
import com.keenwrite.processors.Processor;
21
import com.keenwrite.processors.ProcessorContext;
22
import com.keenwrite.processors.ProcessorFactory;
23
import com.keenwrite.processors.markdown.extensions.CaretExtension;
24
import com.keenwrite.service.events.Notifier;
25
import com.keenwrite.sigils.RSigilOperator;
26
import com.keenwrite.sigils.SigilOperator;
27
import com.keenwrite.sigils.Tokens;
28
import com.keenwrite.sigils.YamlSigilOperator;
29
import com.keenwrite.ui.explorer.FilesView;
30
import com.keenwrite.ui.heuristics.DocumentStatistics;
31
import com.keenwrite.ui.outline.DocumentOutline;
32
import com.panemu.tiwulfx.control.dock.DetachableTab;
33
import com.panemu.tiwulfx.control.dock.DetachableTabPane;
34
import javafx.application.Platform;
35
import javafx.beans.property.*;
36
import javafx.collections.ListChangeListener;
37
import javafx.event.ActionEvent;
38
import javafx.event.Event;
39
import javafx.event.EventHandler;
40
import javafx.scene.Node;
41
import javafx.scene.Scene;
42
import javafx.scene.control.SplitPane;
43
import javafx.scene.control.Tab;
44
import javafx.scene.control.TabPane;
45
import javafx.scene.control.Tooltip;
46
import javafx.scene.control.TreeItem.TreeModificationEvent;
47
import javafx.scene.input.KeyEvent;
48
import javafx.stage.Stage;
49
import javafx.stage.Window;
50
import org.greenrobot.eventbus.Subscribe;
51
52
import java.io.File;
53
import java.io.FileNotFoundException;
54
import java.nio.file.Path;
55
import java.util.*;
56
import java.util.concurrent.atomic.AtomicBoolean;
57
import java.util.function.Function;
58
import java.util.stream.Collectors;
59
60
import static com.keenwrite.Constants.*;
61
import static com.keenwrite.ExportFormat.NONE;
62
import static com.keenwrite.Messages.get;
63
import static com.keenwrite.events.Bus.register;
64
import static com.keenwrite.events.StatusEvent.clue;
65
import static com.keenwrite.io.MediaType.*;
66
import static com.keenwrite.preferences.WorkspaceKeys.*;
67
import static com.keenwrite.processors.IdentityProcessor.IDENTITY;
68
import static com.keenwrite.processors.ProcessorFactory.createProcessors;
69
import static java.util.stream.Collectors.groupingBy;
70
import static javafx.application.Platform.runLater;
71
import static javafx.scene.control.ButtonType.NO;
72
import static javafx.scene.control.ButtonType.YES;
73
import static javafx.scene.control.TabPane.TabClosingPolicy.ALL_TABS;
74
import static javafx.scene.input.KeyCode.SPACE;
75
import static javafx.scene.input.KeyCombination.CONTROL_DOWN;
76
import static javafx.util.Duration.millis;
77
import static javax.swing.SwingUtilities.invokeLater;
78
import static org.fxmisc.wellbehaved.event.EventPattern.keyPressed;
79
80
/**
81
 * Responsible for wiring together the main application components for a
82
 * particular workspace (project). These include the definition views,
83
 * text editors, and preview pane along with any corresponding controllers.
84
 */
85
public final class MainPane extends SplitPane {
86
  private static final Notifier sNotifier = Services.load( Notifier.class );
87
88
  /**
89
   * Used when opening files to determine how each file should be binned and
90
   * therefore what tab pane to be opened within.
91
   */
92
  private static final Set<MediaType> PLAIN_TEXT_FORMAT = Set.of(
93
    TEXT_MARKDOWN, TEXT_R_MARKDOWN, TEXT_R_XML, UNDEFINED
94
  );
95
96
  /**
97
   * Prevents re-instantiation of processing classes.
98
   */
99
  private final Map<TextResource, Processor<String>> mProcessors =
100
    new HashMap<>();
101
102
  private final Workspace mWorkspace;
103
104
  /**
105
   * Groups similar file type tabs together.
106
   */
107
  private final Map<MediaType, TabPane> mTabPanes = new HashMap<>();
108
109
  /**
110
   * Stores definition names and values.
111
   */
112
  private final Map<String, String> mResolvedMap =
113
    new HashMap<>( MAP_SIZE_DEFAULT );
114
115
  /**
116
   * Renders the actively selected plain text editor tab.
117
   */
118
  private final HtmlPreview mPreview;
119
120
  /**
121
   * Provides an interactive document outline.
122
   */
123
  private final DocumentOutline mOutline = new DocumentOutline();
124
125
  /**
126
   * Changing the active editor fires the value changed event. This allows
127
   * refreshes to happen when external definitions are modified and need to
128
   * trigger the processing chain.
129
   */
130
  private final ObjectProperty<TextEditor> mActiveTextEditor =
131
    createActiveTextEditor();
132
133
  /**
134
   * Changing the active definition editor fires the value changed event. This
135
   * allows refreshes to happen when external definitions are modified and need
136
   * to trigger the processing chain.
137
   */
138
  private final ObjectProperty<TextDefinition> mActiveDefinitionEditor =
139
    createActiveDefinitionEditor( mActiveTextEditor );
140
141
  /**
142
   * Tracks the number of detached tab panels opened into their own windows,
143
   * which allows unique identification of subordinate windows by their title.
144
   * It is doubtful more than 128 windows, much less 256, will be created.
145
   */
146
  private byte mWindowCount;
147
148
  /**
149
   * Called when the definition data is changed.
150
   */
151
  private final EventHandler<TreeModificationEvent<Event>> mTreeHandler =
152
    event -> {
153
      final var editor = mActiveDefinitionEditor.get();
154
155
      resolve( editor );
156
      process( getActiveTextEditor() );
157
      save( editor );
158
    };
159
160
  private final DocumentStatistics mStatistics;
161
162
  /**
163
   * Adds all content panels to the main user interface. This will load the
164
   * configuration settings from the workspace to reproduce the settings from
165
   * a previous session.
166
   */
167
  public MainPane( final Workspace workspace ) {
168
    mWorkspace = workspace;
169
    mPreview = new HtmlPreview( workspace );
170
    mStatistics = new DocumentStatistics( workspace );
171
172
    open( bin( getRecentFiles() ) );
173
    viewPreview();
174
    setDividerPositions( calculateDividerPositions() );
175
176
    // Once the main scene's window regains focus, update the active definition
177
    // editor to the currently selected tab.
178
    runLater(
179
      () -> getWindow().setOnCloseRequest( ( event ) -> {
180
        // Order matters here. We want to close all the tabs to ensure each
181
        // is saved, but after they are closed, the workspace should still
182
        // retain the list of files that were open. If this line came after
183
        // closing, then restarting the application would list no files.
184
        mWorkspace.save();
185
186
        if( closeAll() ) {
187
          Platform.exit();
188
          System.exit( 0 );
189
        }
190
        else {
191
          event.consume();
192
        }
193
      } )
194
    );
195
196
    register( this );
197
  }
198
199
  @Subscribe
200
  public void handle( final TextEditorFocusEvent event ) {
201
    mActiveTextEditor.set( event.get() );
202
  }
203
204
  @Subscribe
205
  public void handle( final TextDefinitionFocusEvent event ) {
206
    mActiveDefinitionEditor.set( event.get() );
207
  }
208
209
  /**
210
   * Typically called when a file name is clicked in the {@link HtmlPanel}.
211
   *
212
   * @param event The event to process, must contain a valid file reference.
213
   */
214
  @Subscribe
215
  public void handle( final FileOpenEvent event ) {
216
    final File eventFile;
217
    final var eventUri = event.getUri();
218
219
    if( eventUri.isAbsolute() ) {
220
      eventFile = new File( eventUri.getPath() );
221
    }
222
    else {
223
      final var activeFile = getActiveTextEditor().getFile();
224
      final var parent = activeFile.getParentFile();
225
226
      if( parent == null ) {
227
        clue( new FileNotFoundException( eventUri.getPath() ) );
228
        return;
229
      }
230
      else {
231
        final var parentPath = parent.getAbsolutePath();
232
        eventFile = Path.of( parentPath, eventUri.getPath() ).toFile();
233
      }
234
    }
235
236
    runLater( () -> open( eventFile ) );
237
  }
238
239
  @Subscribe
240
  public void handle( final CaretNavigationEvent event ) {
241
    runLater( () -> {
242
      final var textArea = getActiveTextEditor().getTextArea();
243
      textArea.moveTo( event.getOffset() );
244
      textArea.requestFollowCaret();
245
      textArea.requestFocus();
246
    } );
247
  }
248
249
  /**
250
   * TODO: Load divider positions from exported settings, see bin() comment.
251
   */
252
  private double[] calculateDividerPositions() {
253
    final var ratio = 100f / getItems().size() / 100;
254
    final var positions = getDividerPositions();
255
256
    for( int i = 0; i < positions.length; i++ ) {
257
      positions[ i ] = ratio * i;
258
    }
259
260
    return positions;
261
  }
262
263
  /**
264
   * Opens all the files into the application, provided the paths are unique.
265
   * This may only be called for any type of files that a user can edit
266
   * (i.e., update and persist), such as definitions and text files.
267
   *
268
   * @param files The list of files to open.
269
   */
270
  public void open( final List<File> files ) {
271
    files.forEach( this::open );
272
  }
273
274
  /**
275
   * This opens the given file. Since the preview pane is not a file that
276
   * can be opened, it is safe to add a listener to the detachable pane.
277
   *
278
   * @param file The file to open.
279
   */
280
  private void open( final File file ) {
281
    final var tab = createTab( file );
282
    final var node = tab.getContent();
283
    final var mediaType = MediaType.valueFrom( file );
284
    final var tabPane = obtainTabPane( mediaType );
285
286
    tab.setTooltip( createTooltip( file ) );
287
    tabPane.setFocusTraversable( false );
288
    tabPane.setTabClosingPolicy( ALL_TABS );
289
    tabPane.getTabs().add( tab );
290
291
    // Attach the tab scene factory for new tab panes.
292
    if( !getItems().contains( tabPane ) ) {
293
      addTabPane(
294
        node instanceof TextDefinition ? 0 : getItems().size(), tabPane
295
      );
296
    }
297
298
    getRecentFiles().add( file.getAbsolutePath() );
299
  }
300
301
  /**
302
   * Opens a new text editor document using the default document file name.
303
   */
304
  public void newTextEditor() {
305
    open( DOCUMENT_DEFAULT );
306
  }
307
308
  /**
309
   * Opens a new definition editor document using the default definition
310
   * file name.
311
   */
312
  public void newDefinitionEditor() {
313
    open( DEFINITION_DEFAULT );
314
  }
315
316
  /**
317
   * Iterates over all tab panes to find all {@link TextEditor}s and request
318
   * that they save themselves.
319
   */
320
  public void saveAll() {
321
    mTabPanes.forEach(
322
      ( mt, tp ) -> tp.getTabs().forEach( ( tab ) -> {
323
        final var node = tab.getContent();
324
        if( node instanceof TextEditor ) {
325
          save( ((TextEditor) node) );
326
        }
327
      } )
328
    );
329
  }
330
331
  /**
332
   * Requests that the active {@link TextEditor} saves itself. Don't bother
333
   * checking if modified first because if the user swaps external media from
334
   * an external source (e.g., USB thumb drive), save should not second-guess
335
   * the user: save always re-saves. Also, it's less code.
336
   */
337
  public void save() {
338
    save( getActiveTextEditor() );
339
  }
340
341
  /**
342
   * Saves the active {@link TextEditor} under a new name.
343
   *
344
   * @param file The new active editor {@link File} reference.
345
   */
346
  public void saveAs( final File file ) {
347
    assert file != null;
348
    final var editor = getActiveTextEditor();
349
    final var tab = getTab( editor );
350
351
    editor.rename( file );
352
    tab.ifPresent( t -> {
353
      t.setText( editor.getFilename() );
354
      t.setTooltip( createTooltip( file ) );
355
    } );
356
357
    save();
358
  }
359
360
  /**
361
   * Saves the given {@link TextResource} to a file. This is typically used
362
   * to save either an instance of {@link TextEditor} or {@link TextDefinition}.
363
   *
364
   * @param resource The resource to export.
365
   */
366
  private void save( final TextResource resource ) {
367
    try {
368
      resource.save();
369
    } catch( final Exception ex ) {
370
      clue( ex );
371
      sNotifier.alert(
372
        getWindow(), resource.getPath(), "TextResource.saveFailed", ex
373
      );
374
    }
375
  }
376
377
  /**
378
   * Closes all open {@link TextEditor}s; all {@link TextDefinition}s stay open.
379
   *
380
   * @return {@code true} when all editors, modified or otherwise, were
381
   * permitted to close; {@code false} when one or more editors were modified
382
   * and the user requested no closing.
383
   */
384
  public boolean closeAll() {
385
    var closable = true;
386
387
    for( final var entry : mTabPanes.entrySet() ) {
388
      final var tabPane = entry.getValue();
389
      final var tabIterator = tabPane.getTabs().iterator();
390
391
      while( tabIterator.hasNext() ) {
392
        final var tab = tabIterator.next();
393
        final var resource = tab.getContent();
394
395
        // The definition panes auto-save, so being specific here prevents
396
        // closing the definitions in the situation where the user wants to
397
        // continue editing (i.e., possibly save unsaved work).
398
        if( !(resource instanceof TextEditor) ) {
399
          continue;
400
        }
401
402
        if( canClose( (TextEditor) resource ) ) {
403
          tabIterator.remove();
404
          close( tab );
405
        }
406
        else {
407
          closable = false;
408
        }
409
      }
410
    }
411
412
    return closable;
413
  }
414
415
  /**
416
   * Calls the tab's {@link Tab#getOnClosed()} handler to carry out a close
417
   * event.
418
   *
419
   * @param tab The {@link Tab} that was closed.
420
   */
421
  private void close( final Tab tab ) {
422
    final var handler = tab.getOnClosed();
423
424
    if( handler != null ) {
425
      handler.handle( new ActionEvent() );
426
    }
427
  }
428
429
  /**
430
   * Closes the active tab; delegates to {@link #canClose(TextResource)}.
431
   */
432
  public void close() {
433
    final var editor = getActiveTextEditor();
434
435
    if( canClose( editor ) ) {
436
      close( editor );
437
    }
438
  }
439
440
  /**
441
   * Closes the given {@link TextResource}. This must not be called from within
442
   * a loop that iterates over the tab panes using {@code forEach}, lest a
443
   * concurrent modification exception be thrown.
444
   *
445
   * @param resource The {@link TextResource} to close, without confirming with
446
   *                 the user.
447
   */
448
  private void close( final TextResource resource ) {
449
    getTab( resource ).ifPresent(
450
      ( tab ) -> {
451
        tab.getTabPane().getTabs().remove( tab );
452
        close( tab );
453
      }
454
    );
455
  }
456
457
  /**
458
   * Answers whether the given {@link TextResource} may be closed.
459
   *
460
   * @param editor The {@link TextResource} to try closing.
461
   * @return {@code true} when the editor may be closed; {@code false} when
462
   * the user has requested to keep the editor open.
463
   */
464
  private boolean canClose( final TextResource editor ) {
465
    final var editorTab = getTab( editor );
466
    final var canClose = new AtomicBoolean( true );
467
468
    if( editor.isModified() ) {
469
      final var filename = new StringBuilder();
470
      editorTab.ifPresent( ( tab ) -> filename.append( tab.getText() ) );
471
472
      final var message = sNotifier.createNotification(
473
        Messages.get( "Alert.file.close.title" ),
474
        Messages.get( "Alert.file.close.text" ),
475
        filename.toString()
476
      );
477
478
      final var dialog = sNotifier.createConfirmation( getWindow(), message );
479
480
      dialog.showAndWait().ifPresent(
481
        save -> canClose.set( save == YES ? editor.save() : save == NO )
482
      );
483
    }
484
485
    return canClose.get();
486
  }
487
488
  private ObjectProperty<TextEditor> createActiveTextEditor() {
489
    final var editor = new SimpleObjectProperty<TextEditor>();
490
491
    editor.addListener( ( c, o, n ) -> {
492
      if( n != null ) {
493
        mPreview.setBaseUri( n.getPath() );
494
        process( n );
495
      }
496
    } );
497
498
    return editor;
499
  }
500
501
  /**
502
   * Adds the HTML preview tab to its own, singular tab pane.
503
   */
504
  public void viewPreview() {
505
    viewTab( mPreview, TEXT_HTML, "Pane.preview.title" );
506
  }
507
508
  /**
509
   * Adds the document outline tab to its own, singular tab pane.
510
   */
511
  public void viewOutline() {
512
    viewTab( mOutline, APP_DOCUMENT_OUTLINE, "Pane.outline.title" );
513
  }
514
515
  public void viewStatistics() {
516
    viewTab( mStatistics, APP_DOCUMENT_STATISTICS, "Pane.statistics.title" );
517
  }
518
519
  public void viewFiles() {
520
    try {
521
      final var fileManager = new FilesView( mWorkspace );
522
      viewTab( fileManager, APP_FILE_MANAGER, "Pane.files.title" );
523
    } catch( final Exception ex ) {
524
      clue( ex );
525
    }
526
  }
527
528
  private void viewTab(
529
    final Node node, final MediaType mediaType, final String key ) {
530
    final var tabPane = obtainTabPane( mediaType );
531
532
    for( final var tab : tabPane.getTabs() ) {
533
      if( tab.getContent() == node ) {
534
        return;
535
      }
536
    }
537
538
    tabPane.getTabs().add( createTab( get( key ), node ) );
539
    addTabPane( tabPane );
540
  }
541
542
  public void viewRefresh() {
543
    mPreview.refresh();
544
  }
545
546
  /**
547
   * Returns the tab that contains the given {@link TextEditor}.
548
   *
549
   * @param editor The {@link TextEditor} instance to find amongst the tabs.
550
   * @return The first tab having content that matches the given tab.
551
   */
552
  private Optional<Tab> getTab( final TextResource editor ) {
553
    return mTabPanes.values()
554
                    .stream()
555
                    .flatMap( pane -> pane.getTabs().stream() )
556
                    .filter( tab -> editor.equals( tab.getContent() ) )
557
                    .findFirst();
558
  }
559
560
  /**
561
   * Creates a new {@link DefinitionEditor} wrapped in a listener that
562
   * is used to detect when the active {@link DefinitionEditor} has changed.
563
   * Upon changing, the {@link #mResolvedMap} is updated and the active
564
   * text editor is refreshed.
565
   *
566
   * @param editor Text editor to update with the revised resolved map.
567
   * @return A newly configured property that represents the active
568
   * {@link DefinitionEditor}, never null.
569
   */
570
  private ObjectProperty<TextDefinition> createActiveDefinitionEditor(
571
    final ObjectProperty<TextEditor> editor ) {
572
    final var definitions = new SimpleObjectProperty<TextDefinition>();
573
    definitions.addListener( ( c, o, n ) -> {
574
      resolve( n == null ? createDefinitionEditor() : n );
575
      process( editor.get() );
576
    } );
577
578
    return definitions;
579
  }
580
581
  private Tab createTab( final String filename, final Node node ) {
582
    return new DetachableTab( filename, node );
583
  }
584
585
  private Tab createTab( final File file ) {
586
    final var r = createTextResource( file );
587
    final var tab = createTab( r.getFilename(), r.getNode() );
588
589
    r.modifiedProperty().addListener(
590
      ( c, o, n ) -> tab.setText( r.getFilename() + (n ? "*" : "") )
591
    );
592
593
    // This is called when either the tab is closed by the user clicking on
594
    // the tab's close icon or when closing (all) from the file menu.
595
    tab.setOnClosed(
596
      ( __ ) -> getRecentFiles().remove( file.getAbsolutePath() )
597
    );
598
599
    tab.tabPaneProperty().addListener( ( cPane, oPane, nPane ) -> {
600
      if( nPane != null ) {
601
        nPane.focusedProperty().addListener( ( c, o, n ) -> {
602
          if( n != null && n ) {
603
            final var selected = nPane.getSelectionModel().getSelectedItem();
604
            final var node = selected.getContent();
605
            node.requestFocus();
606
          }
607
        } );
608
      }
609
    } );
610
611
    return tab;
612
  }
613
614
  /**
615
   * Creates bins for the different {@link MediaType}s, which eventually are
616
   * added to the UI as separate tab panes. If ever a general-purpose scene
617
   * exporter is developed to serialize a scene to an FXML file, this could
618
   * be replaced by such a class.
619
   * <p>
620
   * When binning the files, this makes sure that at least one file exists
621
   * for every type. If the user has opted to close a particular type (such
622
   * as the definition pane), the view will suppressed elsewhere.
623
   * </p>
624
   * <p>
625
   * The order that the binned files are returned will be reflected in the
626
   * order that the corresponding panes are rendered in the UI.
627
   * </p>
628
   *
629
   * @param paths The file paths to bin according to their type.
630
   * @return An in-order list of files, first by structured definition files,
631
   * then by plain text documents.
632
   */
633
  private List<File> bin( final SetProperty<String> paths ) {
634
    // Treat all files destined for the text editor as plain text documents
635
    // so that they are added to the same pane. Grouping by TEXT_PLAIN is a
636
    // bit arbitrary, but means explicitly capturing TEXT_PLAIN isn't needed.
637
    final Function<MediaType, MediaType> bin =
638
      m -> PLAIN_TEXT_FORMAT.contains( m ) ? TEXT_PLAIN : m;
639
640
    // Create two groups: YAML files and plain text files.
641
    final var bins = paths
642
      .stream()
643
      .collect(
644
        groupingBy( path -> bin.apply( MediaType.valueFrom( path ) ) )
645
      );
646
647
    bins.putIfAbsent( TEXT_YAML, List.of( DEFINITION_DEFAULT.toString() ) );
648
    bins.putIfAbsent( TEXT_PLAIN, List.of( DOCUMENT_DEFAULT.toString() ) );
649
650
    final var result = new ArrayList<File>( paths.size() );
651
652
    // Ensure that the same types are listed together (keep insertion order).
653
    bins.forEach( ( mediaType, files ) -> result.addAll(
654
      files.stream().map( File::new ).collect( Collectors.toList() ) )
655
    );
656
657
    return result;
658
  }
659
660
  /**
661
   * Uses the given {@link TextDefinition} instance to update the
662
   * {@link #mResolvedMap}.
663
   *
664
   * @param editor A non-null, possibly empty definition editor.
665
   */
666
  private void resolve( final TextDefinition editor ) {
667
    assert editor != null;
668
669
    final var tokens = createDefinitionTokens();
670
    final var operator = new YamlSigilOperator( tokens );
671
    final var map = new HashMap<String, String>();
672
673
    editor.toMap().forEach( ( k, v ) -> map.put( operator.entoken( k ), v ) );
674
675
    mResolvedMap.clear();
676
    mResolvedMap.putAll( editor.interpolate( map, tokens ) );
677
  }
678
679
  /**
680
   * Force the active editor to update, which will cause the processor
681
   * to re-evaluate the interpolated definition map thereby updating the
682
   * preview pane.
683
   *
684
   * @param editor Contains the source document to update in the preview pane.
685
   */
686
  private void process( final TextEditor editor ) {
687
    // Ensure that these are run from within the Swing event dispatch thread
688
    // so that the text editor thread is immediately freed for caret movement.
689
    // This means that the preview will have a slight delay when catching up
690
    // to the caret position.
691
    invokeLater( () -> {
692
      final var processor = mProcessors.getOrDefault( editor, IDENTITY );
693
      processor.apply( editor == null ? "" : editor.getText() );
694
      mPreview.scrollTo( CARET_ID );
695
    } );
696
  }
697
698
  /**
699
   * Lazily creates a {@link TabPane} configured to listen for tab select
700
   * events. The tab pane is associated with a given media type so that
701
   * similar files can be grouped together.
702
   *
703
   * @param mediaType The media type to associate with the tab pane.
704
   * @return An instance of {@link TabPane} that will handle tab docking.
705
   */
706
  private TabPane obtainTabPane( final MediaType mediaType ) {
707
    return mTabPanes.computeIfAbsent(
708
      mediaType, ( mt ) -> createTabPane()
709
    );
710
  }
711
712
  /**
713
   * Creates an initialized {@link TabPane} instance.
714
   *
715
   * @return A new {@link TabPane} with all listeners configured.
716
   */
717
  private TabPane createTabPane() {
718
    final var tabPane = new DetachableTabPane();
719
720
    initStageOwnerFactory( tabPane );
721
    initTabListener( tabPane );
722
723
    return tabPane;
724
  }
725
726
  /**
727
   * When any {@link DetachableTabPane} is detached from the main window,
728
   * the stage owner factory must be given its parent window, which will
729
   * own the child window. The parent window is the {@link MainPane}'s
730
   * {@link Scene}'s {@link Window} instance.
731
   *
732
   * <p>
733
   * This will derives the new title from the main window title, incrementing
734
   * the window count to help uniquely identify the child windows.
735
   * </p>
736
   *
737
   * @param tabPane A new {@link DetachableTabPane} to configure.
738
   */
739
  private void initStageOwnerFactory( final DetachableTabPane tabPane ) {
740
    tabPane.setStageOwnerFactory( ( stage ) -> {
741
      final var title = get(
742
        "Detach.tab.title",
743
        ((Stage) getWindow()).getTitle(), ++mWindowCount
744
      );
745
      stage.setTitle( title );
746
747
      return getScene().getWindow();
748
    } );
749
  }
750
751
  /**
752
   * Responsible for configuring the content of each {@link DetachableTab} when
753
   * it is added to the given {@link DetachableTabPane} instance.
754
   * <p>
755
   * For {@link TextEditor} contents, an instance of {@link ScrollEventHandler}
756
   * is initialized to perform synchronized scrolling between the editor and
757
   * its preview window. Additionally, the last tab in the tab pane's list of
758
   * tabs is given focus.
759
   * </p>
760
   * <p>
761
   * Note that multiple tabs can be added simultaneously.
762
   * </p>
763
   *
764
   * @param tabPane A new {@link TabPane} to configure.
765
   */
766
  private void initTabListener( final TabPane tabPane ) {
767
    tabPane.getTabs().addListener(
768
      ( final ListChangeListener.Change<? extends Tab> listener ) -> {
769
        while( listener.next() ) {
770
          if( listener.wasAdded() ) {
771
            final var tabs = listener.getAddedSubList();
772
773
            tabs.forEach( ( tab ) -> {
774
              final var node = tab.getContent();
775
776
              if( node instanceof TextEditor ) {
777
                initScrollEventListener( tab );
778
              }
779
            } );
780
781
            // Select and give focus to the last tab opened.
782
            final var index = tabs.size() - 1;
783
            if( index >= 0 ) {
784
              final var tab = tabs.get( index );
785
              tabPane.getSelectionModel().select( tab );
786
              tab.getContent().requestFocus();
787
            }
788
          }
789
        }
790
      }
791
    );
792
  }
793
794
  /**
795
   * Synchronizes scrollbar positions between the given {@link Tab} that
796
   * contains an instance of {@link TextEditor} and {@link HtmlPreview} pane.
797
   *
798
   * @param tab The container for an instance of {@link TextEditor}.
799
   */
800
  private void initScrollEventListener( final Tab tab ) {
801
    final var editor = (TextEditor) tab.getContent();
802
    final var scrollPane = editor.getScrollPane();
803
    final var scrollBar = mPreview.getVerticalScrollBar();
804
    final var handler = new ScrollEventHandler( scrollPane, scrollBar );
805
    handler.enabledProperty().bind( tab.selectedProperty() );
806
  }
807
808
  private void addTabPane( final int index, final TabPane tabPane ) {
809
    final var items = getItems();
810
    if( !items.contains( tabPane ) ) {
811
      items.add( index, tabPane );
812
    }
813
  }
814
815
  private void addTabPane( final TabPane tabPane ) {
816
    addTabPane( getItems().size(), tabPane );
817
  }
818
819
  public ProcessorContext createProcessorContext() {
820
    return createProcessorContext( NONE );
821
  }
822
823
  public ProcessorContext createProcessorContext( final ExportFormat format ) {
824
    final var editor = getActiveTextEditor();
825
    return createProcessorContext(
826
      editor.getPath(), editor.getCaret(), format );
827
  }
828
829
  /**
830
   * @param path  Used by {@link ProcessorFactory} to determine
831
   *              {@link Processor} type to create based on file type.
832
   * @param caret Used by {@link CaretExtension} to add ID attribute into
833
   *              preview document for scrollbar synchronization.
834
   * @return A new {@link ProcessorContext} to use when creating an instance of
835
   * {@link Processor}.
836
   */
837
  private ProcessorContext createProcessorContext(
838
    final Path path, final Caret caret, final ExportFormat format ) {
839
    return new ProcessorContext(
840
      mPreview, mResolvedMap, path, caret, format, mWorkspace
841
    );
842
  }
843
844
  private TextResource createTextResource( final File file ) {
845
    // TODO: Create PlainTextEditor that's returned by default.
846
    return MediaType.valueFrom( file ) == TEXT_YAML
847
      ? createDefinitionEditor( file )
848
      : createMarkdownEditor( file );
849
  }
850
851
  /**
852
   * Creates an instance of {@link MarkdownEditor} that listens for both
853
   * caret change events and text change events. Text change events must
854
   * take priority over caret change events because it's possible to change
855
   * the text without moving the caret (e.g., delete selected text).
856
   *
857
   * @param file The file containing contents for the text editor.
858
   * @return A non-null text editor.
859
   */
860
  private TextResource createMarkdownEditor( final File file ) {
861
    final var path = file.toPath();
862
    final var editor = new MarkdownEditor( file, getWorkspace() );
863
    final var caret = editor.getCaret();
864
    final var context = createProcessorContext( path, caret, NONE );
865
866
    mProcessors.computeIfAbsent( editor, p -> createProcessors( context ) );
867
868
    editor.addDirtyListener( ( c, o, n ) -> {
869
      if( n ) {
870
        // Reset the status to OK after changing the text.
871
        clue();
872
873
        // Processing the text will update the status bar.
11
import com.keenwrite.events.*;
12
import com.keenwrite.io.MediaType;
13
import com.keenwrite.preferences.Key;
14
import com.keenwrite.preferences.Workspace;
15
import com.keenwrite.preview.HtmlPanel;
16
import com.keenwrite.preview.HtmlPreview;
17
import com.keenwrite.processors.Processor;
18
import com.keenwrite.processors.ProcessorContext;
19
import com.keenwrite.processors.ProcessorFactory;
20
import com.keenwrite.processors.markdown.extensions.CaretExtension;
21
import com.keenwrite.service.events.Notifier;
22
import com.keenwrite.sigils.RSigilOperator;
23
import com.keenwrite.sigils.SigilOperator;
24
import com.keenwrite.sigils.Tokens;
25
import com.keenwrite.sigils.YamlSigilOperator;
26
import com.keenwrite.ui.explorer.FilePickerFactory;
27
import com.keenwrite.ui.heuristics.DocumentStatistics;
28
import com.keenwrite.ui.outline.DocumentOutline;
29
import com.panemu.tiwulfx.control.dock.DetachableTab;
30
import com.panemu.tiwulfx.control.dock.DetachableTabPane;
31
import javafx.application.Platform;
32
import javafx.beans.property.*;
33
import javafx.collections.ListChangeListener;
34
import javafx.concurrent.Task;
35
import javafx.event.ActionEvent;
36
import javafx.event.Event;
37
import javafx.event.EventHandler;
38
import javafx.scene.Node;
39
import javafx.scene.Scene;
40
import javafx.scene.control.*;
41
import javafx.scene.control.TreeItem.TreeModificationEvent;
42
import javafx.scene.input.KeyEvent;
43
import javafx.scene.layout.FlowPane;
44
import javafx.stage.Stage;
45
import javafx.stage.Window;
46
import org.greenrobot.eventbus.Subscribe;
47
48
import java.io.File;
49
import java.io.FileNotFoundException;
50
import java.nio.file.Path;
51
import java.util.*;
52
import java.util.concurrent.ExecutorService;
53
import java.util.concurrent.atomic.AtomicBoolean;
54
import java.util.function.Function;
55
import java.util.stream.Collectors;
56
57
import static com.keenwrite.ExportFormat.NONE;
58
import static com.keenwrite.Messages.get;
59
import static com.keenwrite.constants.Constants.*;
60
import static com.keenwrite.constants.GraphicsConstants.ICON_DIALOG_NODE;
61
import static com.keenwrite.events.Bus.register;
62
import static com.keenwrite.events.HyperlinkOpenEvent.fireHyperlinkOpenEvent;
63
import static com.keenwrite.events.StatusEvent.clue;
64
import static com.keenwrite.io.MediaType.*;
65
import static com.keenwrite.preferences.WorkspaceKeys.*;
66
import static com.keenwrite.processors.IdentityProcessor.IDENTITY;
67
import static com.keenwrite.processors.ProcessorFactory.createProcessors;
68
import static java.lang.String.format;
69
import static java.lang.System.getProperty;
70
import static java.util.concurrent.Executors.newFixedThreadPool;
71
import static java.util.stream.Collectors.groupingBy;
72
import static javafx.application.Platform.runLater;
73
import static javafx.scene.control.Alert.AlertType.ERROR;
74
import static javafx.scene.control.ButtonType.*;
75
import static javafx.scene.control.TabPane.TabClosingPolicy.ALL_TABS;
76
import static javafx.scene.input.KeyCode.SPACE;
77
import static javafx.scene.input.KeyCombination.CONTROL_DOWN;
78
import static javafx.util.Duration.millis;
79
import static javax.swing.SwingUtilities.invokeLater;
80
import static org.fxmisc.wellbehaved.event.EventPattern.keyPressed;
81
82
/**
83
 * Responsible for wiring together the main application components for a
84
 * particular workspace (project). These include the definition views,
85
 * text editors, and preview pane along with any corresponding controllers.
86
 */
87
public final class MainPane extends SplitPane {
88
  private static final ExecutorService sExecutor = newFixedThreadPool( 1 );
89
90
  private static final Notifier sNotifier = Services.load( Notifier.class );
91
92
  /**
93
   * Used when opening files to determine how each file should be binned and
94
   * therefore what tab pane to be opened within.
95
   */
96
  private static final Set<MediaType> PLAIN_TEXT_FORMAT = Set.of(
97
    TEXT_MARKDOWN, TEXT_R_MARKDOWN, TEXT_R_XML, UNDEFINED
98
  );
99
100
  /**
101
   * Prevents re-instantiation of processing classes.
102
   */
103
  private final Map<TextResource, Processor<String>> mProcessors =
104
    new HashMap<>();
105
106
  private final Workspace mWorkspace;
107
108
  /**
109
   * Groups similar file type tabs together.
110
   */
111
  private final Map<MediaType, TabPane> mTabPanes = new HashMap<>();
112
113
  /**
114
   * Stores definition names and values.
115
   */
116
  private final Map<String, String> mResolvedMap =
117
    new HashMap<>( MAP_SIZE_DEFAULT );
118
119
  /**
120
   * Renders the actively selected plain text editor tab.
121
   */
122
  private final HtmlPreview mPreview;
123
124
  /**
125
   * Provides an interactive document outline.
126
   */
127
  private final DocumentOutline mOutline = new DocumentOutline();
128
129
  /**
130
   * Changing the active editor fires the value changed event. This allows
131
   * refreshes to happen when external definitions are modified and need to
132
   * trigger the processing chain.
133
   */
134
  private final ObjectProperty<TextEditor> mActiveTextEditor =
135
    createActiveTextEditor();
136
137
  /**
138
   * Changing the active definition editor fires the value changed event. This
139
   * allows refreshes to happen when external definitions are modified and need
140
   * to trigger the processing chain.
141
   */
142
  private final ObjectProperty<TextDefinition> mActiveDefinitionEditor =
143
    createActiveDefinitionEditor( mActiveTextEditor );
144
145
  /**
146
   * Tracks the number of detached tab panels opened into their own windows,
147
   * which allows unique identification of subordinate windows by their title.
148
   * It is doubtful more than 128 windows, much less 256, will be created.
149
   */
150
  private byte mWindowCount;
151
152
  /**
153
   * Called when the definition data is changed.
154
   */
155
  private final EventHandler<TreeModificationEvent<Event>> mTreeHandler =
156
    event -> {
157
      final var editor = mActiveDefinitionEditor.get();
158
159
      resolve( editor );
160
      process( getActiveTextEditor() );
161
      save( editor );
162
    };
163
164
  private final DocumentStatistics mStatistics;
165
166
  /**
167
   * Adds all content panels to the main user interface. This will load the
168
   * configuration settings from the workspace to reproduce the settings from
169
   * a previous session.
170
   */
171
  public MainPane( final Workspace workspace ) {
172
    mWorkspace = workspace;
173
    mPreview = new HtmlPreview( workspace );
174
    mStatistics = new DocumentStatistics( workspace );
175
176
    open( bin( getRecentFiles() ) );
177
    viewPreview();
178
    setDividerPositions( calculateDividerPositions() );
179
180
    // Once the main scene's window regains focus, update the active definition
181
    // editor to the currently selected tab.
182
    runLater(
183
      () -> getWindow().setOnCloseRequest( ( event ) -> {
184
        // Order matters here. We want to close all the tabs to ensure each
185
        // is saved, but after they are closed, the workspace should still
186
        // retain the list of files that were open. If this line came after
187
        // closing, then restarting the application would list no files.
188
        mWorkspace.save();
189
190
        if( closeAll() ) {
191
          Platform.exit();
192
          System.exit( 0 );
193
        }
194
        else {
195
          event.consume();
196
        }
197
      } )
198
    );
199
200
    register( this );
201
  }
202
203
  @Subscribe
204
  public void handle( final TextEditorFocusEvent event ) {
205
    mActiveTextEditor.set( event.get() );
206
  }
207
208
  @Subscribe
209
  public void handle( final TextDefinitionFocusEvent event ) {
210
    mActiveDefinitionEditor.set( event.get() );
211
  }
212
213
  /**
214
   * Typically called when a file name is clicked in the {@link HtmlPanel}.
215
   *
216
   * @param event The event to process, must contain a valid file reference.
217
   */
218
  @Subscribe
219
  public void handle( final FileOpenEvent event ) {
220
    final File eventFile;
221
    final var eventUri = event.getUri();
222
223
    if( eventUri.isAbsolute() ) {
224
      eventFile = new File( eventUri.getPath() );
225
    }
226
    else {
227
      final var activeFile = getActiveTextEditor().getFile();
228
      final var parent = activeFile.getParentFile();
229
230
      if( parent == null ) {
231
        clue( new FileNotFoundException( eventUri.getPath() ) );
232
        return;
233
      }
234
      else {
235
        final var parentPath = parent.getAbsolutePath();
236
        eventFile = Path.of( parentPath, eventUri.getPath() ).toFile();
237
      }
238
    }
239
240
    runLater( () -> open( eventFile ) );
241
  }
242
243
  @Subscribe
244
  public void handle( final CaretNavigationEvent event ) {
245
    runLater( () -> {
246
      final var textArea = getActiveTextEditor().getTextArea();
247
      textArea.moveTo( event.getOffset() );
248
      textArea.requestFollowCaret();
249
      textArea.requestFocus();
250
    } );
251
  }
252
253
  @Subscribe
254
  @SuppressWarnings( "unused" )
255
  public void handle( final ExportFailedEvent event ) {
256
    final var os = getProperty( "os.name" );
257
    final var arch = getProperty( "os.arch" ).toLowerCase();
258
    final var bits = getProperty( "sun.arch.data.model" );
259
260
    final var title = Messages.get( "Alert.typesetter.missing.title" );
261
    final var header = Messages.get( "Alert.typesetter.missing.header" );
262
    final var version = Messages.get(
263
      "Alert.typesetter.missing.version",
264
      os,
265
      arch
266
        .replaceAll( "amd.*|i.*|x86.*", "X86" )
267
        .replaceAll( "mips.*", "MIPS" )
268
        .replaceAll( "armv.*", "ARM" ),
269
      bits );
270
    final var text = Messages.get( "Alert.typesetter.missing.installer.text" );
271
272
    // Download and install ConTeXt for {0} {1} {2}-bit
273
    final var content = format( "%s %s", text, version );
274
    final var flowPane = new FlowPane();
275
    final var link = new Hyperlink( text );
276
    final var label = new Label( version );
277
    flowPane.getChildren().addAll( link, label );
278
279
    final var alert = new Alert( ERROR, content, OK );
280
    alert.setTitle( title );
281
    alert.setHeaderText( header );
282
    alert.getDialogPane().contentProperty().set( flowPane );
283
    alert.setGraphic( ICON_DIALOG_NODE );
284
285
    link.setOnAction( ( e ) -> {
286
      alert.close();
287
      final var url = Messages.get( "Alert.typesetter.missing.installer.url" );
288
      runLater( () -> fireHyperlinkOpenEvent( url ) );
289
    } );
290
291
    alert.showAndWait();
292
  }
293
294
  /**
295
   * TODO: Load divider positions from exported settings, see bin() comment.
296
   */
297
  private double[] calculateDividerPositions() {
298
    final var ratio = 100f / getItems().size() / 100;
299
    final var positions = getDividerPositions();
300
301
    for( int i = 0; i < positions.length; i++ ) {
302
      positions[ i ] = ratio * i;
303
    }
304
305
    return positions;
306
  }
307
308
  /**
309
   * Opens all the files into the application, provided the paths are unique.
310
   * This may only be called for any type of files that a user can edit
311
   * (i.e., update and persist), such as definitions and text files.
312
   *
313
   * @param files The list of files to open.
314
   */
315
  public void open( final List<File> files ) {
316
    files.forEach( this::open );
317
  }
318
319
  /**
320
   * This opens the given file. Since the preview pane is not a file that
321
   * can be opened, it is safe to add a listener to the detachable pane.
322
   *
323
   * @param file The file to open.
324
   */
325
  private void open( final File file ) {
326
    final var tab = createTab( file );
327
    final var node = tab.getContent();
328
    final var mediaType = MediaType.valueFrom( file );
329
    final var tabPane = obtainTabPane( mediaType );
330
331
    tab.setTooltip( createTooltip( file ) );
332
    tabPane.setFocusTraversable( false );
333
    tabPane.setTabClosingPolicy( ALL_TABS );
334
    tabPane.getTabs().add( tab );
335
336
    // Attach the tab scene factory for new tab panes.
337
    if( !getItems().contains( tabPane ) ) {
338
      addTabPane(
339
        node instanceof TextDefinition ? 0 : getItems().size(), tabPane
340
      );
341
    }
342
343
    getRecentFiles().add( file.getAbsolutePath() );
344
  }
345
346
  /**
347
   * Opens a new text editor document using the default document file name.
348
   */
349
  public void newTextEditor() {
350
    open( DOCUMENT_DEFAULT );
351
  }
352
353
  /**
354
   * Opens a new definition editor document using the default definition
355
   * file name.
356
   */
357
  public void newDefinitionEditor() {
358
    open( DEFINITION_DEFAULT );
359
  }
360
361
  /**
362
   * Iterates over all tab panes to find all {@link TextEditor}s and request
363
   * that they save themselves.
364
   */
365
  public void saveAll() {
366
    mTabPanes.forEach(
367
      ( mt, tp ) -> tp.getTabs().forEach( ( tab ) -> {
368
        final var node = tab.getContent();
369
        if( node instanceof TextEditor ) {
370
          save( ((TextEditor) node) );
371
        }
372
      } )
373
    );
374
  }
375
376
  /**
377
   * Requests that the active {@link TextEditor} saves itself. Don't bother
378
   * checking if modified first because if the user swaps external media from
379
   * an external source (e.g., USB thumb drive), save should not second-guess
380
   * the user: save always re-saves. Also, it's less code.
381
   */
382
  public void save() {
383
    save( getActiveTextEditor() );
384
  }
385
386
  /**
387
   * Saves the active {@link TextEditor} under a new name.
388
   *
389
   * @param files The new active editor {@link File} reference, must contain
390
   *              at least one element.
391
   */
392
  public void saveAs( final List<File> files ) {
393
    assert files != null;
394
    assert !files.isEmpty();
395
    final var editor = getActiveTextEditor();
396
    final var tab = getTab( editor );
397
    final var file = files.get( 0 );
398
399
    editor.rename( file );
400
    tab.ifPresent( t -> {
401
      t.setText( editor.getFilename() );
402
      t.setTooltip( createTooltip( file ) );
403
    } );
404
405
    save();
406
  }
407
408
  /**
409
   * Saves the given {@link TextResource} to a file. This is typically used
410
   * to save either an instance of {@link TextEditor} or {@link TextDefinition}.
411
   *
412
   * @param resource The resource to export.
413
   */
414
  private void save( final TextResource resource ) {
415
    try {
416
      resource.save();
417
    } catch( final Exception ex ) {
418
      clue( ex );
419
      sNotifier.alert(
420
        getWindow(), resource.getPath(), "TextResource.saveFailed", ex
421
      );
422
    }
423
  }
424
425
  /**
426
   * Closes all open {@link TextEditor}s; all {@link TextDefinition}s stay open.
427
   *
428
   * @return {@code true} when all editors, modified or otherwise, were
429
   * permitted to close; {@code false} when one or more editors were modified
430
   * and the user requested no closing.
431
   */
432
  public boolean closeAll() {
433
    var closable = true;
434
435
    for( final var entry : mTabPanes.entrySet() ) {
436
      final var tabPane = entry.getValue();
437
      final var tabIterator = tabPane.getTabs().iterator();
438
439
      while( tabIterator.hasNext() ) {
440
        final var tab = tabIterator.next();
441
        final var resource = tab.getContent();
442
443
        // The definition panes auto-save, so being specific here prevents
444
        // closing the definitions in the situation where the user wants to
445
        // continue editing (i.e., possibly save unsaved work).
446
        if( !(resource instanceof TextEditor) ) {
447
          continue;
448
        }
449
450
        if( canClose( (TextEditor) resource ) ) {
451
          tabIterator.remove();
452
          close( tab );
453
        }
454
        else {
455
          closable = false;
456
        }
457
      }
458
    }
459
460
    return closable;
461
  }
462
463
  /**
464
   * Calls the tab's {@link Tab#getOnClosed()} handler to carry out a close
465
   * event.
466
   *
467
   * @param tab The {@link Tab} that was closed.
468
   */
469
  private void close( final Tab tab ) {
470
    final var handler = tab.getOnClosed();
471
472
    if( handler != null ) {
473
      handler.handle( new ActionEvent() );
474
    }
475
  }
476
477
  /**
478
   * Closes the active tab; delegates to {@link #canClose(TextResource)}.
479
   */
480
  public void close() {
481
    final var editor = getActiveTextEditor();
482
483
    if( canClose( editor ) ) {
484
      close( editor );
485
    }
486
  }
487
488
  /**
489
   * Closes the given {@link TextResource}. This must not be called from within
490
   * a loop that iterates over the tab panes using {@code forEach}, lest a
491
   * concurrent modification exception be thrown.
492
   *
493
   * @param resource The {@link TextResource} to close, without confirming with
494
   *                 the user.
495
   */
496
  private void close( final TextResource resource ) {
497
    getTab( resource ).ifPresent(
498
      ( tab ) -> {
499
        tab.getTabPane().getTabs().remove( tab );
500
        close( tab );
501
      }
502
    );
503
  }
504
505
  /**
506
   * Answers whether the given {@link TextResource} may be closed.
507
   *
508
   * @param editor The {@link TextResource} to try closing.
509
   * @return {@code true} when the editor may be closed; {@code false} when
510
   * the user has requested to keep the editor open.
511
   */
512
  private boolean canClose( final TextResource editor ) {
513
    final var editorTab = getTab( editor );
514
    final var canClose = new AtomicBoolean( true );
515
516
    if( editor.isModified() ) {
517
      final var filename = new StringBuilder();
518
      editorTab.ifPresent( ( tab ) -> filename.append( tab.getText() ) );
519
520
      final var message = sNotifier.createNotification(
521
        Messages.get( "Alert.file.close.title" ),
522
        Messages.get( "Alert.file.close.text" ),
523
        filename.toString()
524
      );
525
526
      final var dialog = sNotifier.createConfirmation( getWindow(), message );
527
528
      dialog.showAndWait().ifPresent(
529
        save -> canClose.set( save == YES ? editor.save() : save == NO )
530
      );
531
    }
532
533
    return canClose.get();
534
  }
535
536
  private ObjectProperty<TextEditor> createActiveTextEditor() {
537
    final var editor = new SimpleObjectProperty<TextEditor>();
538
539
    editor.addListener( ( c, o, n ) -> {
540
      if( n != null ) {
541
        mPreview.setBaseUri( n.getPath() );
542
        process( n );
543
      }
544
    } );
545
546
    return editor;
547
  }
548
549
  /**
550
   * Adds the HTML preview tab to its own, singular tab pane.
551
   */
552
  public void viewPreview() {
553
    viewTab( mPreview, TEXT_HTML, "Pane.preview.title" );
554
  }
555
556
  /**
557
   * Adds the document outline tab to its own, singular tab pane.
558
   */
559
  public void viewOutline() {
560
    viewTab( mOutline, APP_DOCUMENT_OUTLINE, "Pane.outline.title" );
561
  }
562
563
  public void viewStatistics() {
564
    viewTab( mStatistics, APP_DOCUMENT_STATISTICS, "Pane.statistics.title" );
565
  }
566
567
  public void viewFiles() {
568
    try {
569
      final var factory = new FilePickerFactory( mWorkspace );
570
      final var fileManager = factory.createModeless();
571
      viewTab( fileManager, APP_FILE_MANAGER, "Pane.files.title" );
572
    } catch( final Exception ex ) {
573
      clue( ex );
574
    }
575
  }
576
577
  private void viewTab(
578
    final Node node, final MediaType mediaType, final String key ) {
579
    final var tabPane = obtainTabPane( mediaType );
580
581
    for( final var tab : tabPane.getTabs() ) {
582
      if( tab.getContent() == node ) {
583
        return;
584
      }
585
    }
586
587
    tabPane.getTabs().add( createTab( get( key ), node ) );
588
    addTabPane( tabPane );
589
  }
590
591
  public void viewRefresh() {
592
    mPreview.refresh();
593
  }
594
595
  /**
596
   * Returns the tab that contains the given {@link TextEditor}.
597
   *
598
   * @param editor The {@link TextEditor} instance to find amongst the tabs.
599
   * @return The first tab having content that matches the given tab.
600
   */
601
  private Optional<Tab> getTab( final TextResource editor ) {
602
    return mTabPanes.values()
603
                    .stream()
604
                    .flatMap( pane -> pane.getTabs().stream() )
605
                    .filter( tab -> editor.equals( tab.getContent() ) )
606
                    .findFirst();
607
  }
608
609
  /**
610
   * Creates a new {@link DefinitionEditor} wrapped in a listener that
611
   * is used to detect when the active {@link DefinitionEditor} has changed.
612
   * Upon changing, the {@link #mResolvedMap} is updated and the active
613
   * text editor is refreshed.
614
   *
615
   * @param editor Text editor to update with the revised resolved map.
616
   * @return A newly configured property that represents the active
617
   * {@link DefinitionEditor}, never null.
618
   */
619
  private ObjectProperty<TextDefinition> createActiveDefinitionEditor(
620
    final ObjectProperty<TextEditor> editor ) {
621
    final var definitions = new SimpleObjectProperty<TextDefinition>();
622
    definitions.addListener( ( c, o, n ) -> {
623
      resolve( n == null ? createDefinitionEditor() : n );
624
      process( editor.get() );
625
    } );
626
627
    return definitions;
628
  }
629
630
  private Tab createTab( final String filename, final Node node ) {
631
    return new DetachableTab( filename, node );
632
  }
633
634
  private Tab createTab( final File file ) {
635
    final var r = createTextResource( file );
636
    final var tab = createTab( r.getFilename(), r.getNode() );
637
638
    r.modifiedProperty().addListener(
639
      ( c, o, n ) -> tab.setText( r.getFilename() + (n ? "*" : "") )
640
    );
641
642
    // This is called when either the tab is closed by the user clicking on
643
    // the tab's close icon or when closing (all) from the file menu.
644
    tab.setOnClosed(
645
      ( __ ) -> getRecentFiles().remove( file.getAbsolutePath() )
646
    );
647
648
    tab.tabPaneProperty().addListener( ( cPane, oPane, nPane ) -> {
649
      if( nPane != null ) {
650
        nPane.focusedProperty().addListener( ( c, o, n ) -> {
651
          if( n != null && n ) {
652
            final var selected = nPane.getSelectionModel().getSelectedItem();
653
            final var node = selected.getContent();
654
            node.requestFocus();
655
          }
656
        } );
657
      }
658
    } );
659
660
    return tab;
661
  }
662
663
  /**
664
   * Creates bins for the different {@link MediaType}s, which eventually are
665
   * added to the UI as separate tab panes. If ever a general-purpose scene
666
   * exporter is developed to serialize a scene to an FXML file, this could
667
   * be replaced by such a class.
668
   * <p>
669
   * When binning the files, this makes sure that at least one file exists
670
   * for every type. If the user has opted to close a particular type (such
671
   * as the definition pane), the view will suppressed elsewhere.
672
   * </p>
673
   * <p>
674
   * The order that the binned files are returned will be reflected in the
675
   * order that the corresponding panes are rendered in the UI.
676
   * </p>
677
   *
678
   * @param paths The file paths to bin according to their type.
679
   * @return An in-order list of files, first by structured definition files,
680
   * then by plain text documents.
681
   */
682
  private List<File> bin( final SetProperty<String> paths ) {
683
    // Treat all files destined for the text editor as plain text documents
684
    // so that they are added to the same pane. Grouping by TEXT_PLAIN is a
685
    // bit arbitrary, but means explicitly capturing TEXT_PLAIN isn't needed.
686
    final Function<MediaType, MediaType> bin =
687
      m -> PLAIN_TEXT_FORMAT.contains( m ) ? TEXT_PLAIN : m;
688
689
    // Create two groups: YAML files and plain text files.
690
    final var bins = paths
691
      .stream()
692
      .collect(
693
        groupingBy( path -> bin.apply( MediaType.fromFilename( path ) ) )
694
      );
695
696
    bins.putIfAbsent( TEXT_YAML, List.of( DEFINITION_DEFAULT.toString() ) );
697
    bins.putIfAbsent( TEXT_PLAIN, List.of( DOCUMENT_DEFAULT.toString() ) );
698
699
    final var result = new ArrayList<File>( paths.size() );
700
701
    // Ensure that the same types are listed together (keep insertion order).
702
    bins.forEach( ( mediaType, files ) -> result.addAll(
703
      files.stream().map( File::new ).collect( Collectors.toList() ) )
704
    );
705
706
    return result;
707
  }
708
709
  /**
710
   * Uses the given {@link TextDefinition} instance to update the
711
   * {@link #mResolvedMap}.
712
   *
713
   * @param editor A non-null, possibly empty definition editor.
714
   */
715
  private void resolve( final TextDefinition editor ) {
716
    assert editor != null;
717
718
    final var tokens = createDefinitionTokens();
719
    final var operator = new YamlSigilOperator( tokens );
720
    final var map = new HashMap<String, String>();
721
722
    editor.toMap().forEach( ( k, v ) -> map.put( operator.entoken( k ), v ) );
723
724
    mResolvedMap.clear();
725
    mResolvedMap.putAll( editor.interpolate( map, tokens ) );
726
  }
727
728
  /**
729
   * Force the active editor to update, which will cause the processor
730
   * to re-evaluate the interpolated definition map thereby updating the
731
   * preview pane.
732
   *
733
   * @param editor Contains the source document to update in the preview pane.
734
   */
735
  private void process( final TextEditor editor ) {
736
    // Ensure processing does not run on the JavaFX thread, which frees the
737
    // text editor immediately for caret movement. The preview will have a
738
    // slight delay when catching up to the caret position.
739
    final var task = new Task<Void>() {
740
      @Override
741
      public Void call() {
742
        try {
743
          final var p = mProcessors.getOrDefault( editor, IDENTITY );
744
          p.apply( editor == null ? "" : editor.getText() );
745
        } catch( final Exception ex ) {
746
          clue( ex );
747
        }
748
749
        return null;
750
      }
751
    };
752
753
    task.setOnSucceeded(
754
      e -> invokeLater( () -> mPreview.scrollTo( CARET_ID ) )
755
    );
756
757
    // Prevents multiple process requests from executing simultaneously (due
758
    // to having a restricted queue size).
759
    sExecutor.execute( task );
760
  }
761
762
  /**
763
   * Lazily creates a {@link TabPane} configured to listen for tab select
764
   * events. The tab pane is associated with a given media type so that
765
   * similar files can be grouped together.
766
   *
767
   * @param mediaType The media type to associate with the tab pane.
768
   * @return An instance of {@link TabPane} that will handle tab docking.
769
   */
770
  private TabPane obtainTabPane( final MediaType mediaType ) {
771
    return mTabPanes.computeIfAbsent(
772
      mediaType, ( mt ) -> createTabPane()
773
    );
774
  }
775
776
  /**
777
   * Creates an initialized {@link TabPane} instance.
778
   *
779
   * @return A new {@link TabPane} with all listeners configured.
780
   */
781
  private TabPane createTabPane() {
782
    final var tabPane = new DetachableTabPane();
783
784
    initStageOwnerFactory( tabPane );
785
    initTabListener( tabPane );
786
787
    return tabPane;
788
  }
789
790
  /**
791
   * When any {@link DetachableTabPane} is detached from the main window,
792
   * the stage owner factory must be given its parent window, which will
793
   * own the child window. The parent window is the {@link MainPane}'s
794
   * {@link Scene}'s {@link Window} instance.
795
   *
796
   * <p>
797
   * This will derives the new title from the main window title, incrementing
798
   * the window count to help uniquely identify the child windows.
799
   * </p>
800
   *
801
   * @param tabPane A new {@link DetachableTabPane} to configure.
802
   */
803
  private void initStageOwnerFactory( final DetachableTabPane tabPane ) {
804
    tabPane.setStageOwnerFactory( ( stage ) -> {
805
      final var title = get(
806
        "Detach.tab.title",
807
        ((Stage) getWindow()).getTitle(), ++mWindowCount
808
      );
809
      stage.setTitle( title );
810
811
      return getScene().getWindow();
812
    } );
813
  }
814
815
  /**
816
   * Responsible for configuring the content of each {@link DetachableTab} when
817
   * it is added to the given {@link DetachableTabPane} instance.
818
   * <p>
819
   * For {@link TextEditor} contents, an instance of {@link ScrollEventHandler}
820
   * is initialized to perform synchronized scrolling between the editor and
821
   * its preview window. Additionally, the last tab in the tab pane's list of
822
   * tabs is given focus.
823
   * </p>
824
   * <p>
825
   * Note that multiple tabs can be added simultaneously.
826
   * </p>
827
   *
828
   * @param tabPane A new {@link TabPane} to configure.
829
   */
830
  private void initTabListener( final TabPane tabPane ) {
831
    tabPane.getTabs().addListener(
832
      ( final ListChangeListener.Change<? extends Tab> listener ) -> {
833
        while( listener.next() ) {
834
          if( listener.wasAdded() ) {
835
            final var tabs = listener.getAddedSubList();
836
837
            tabs.forEach( ( tab ) -> {
838
              final var node = tab.getContent();
839
840
              if( node instanceof TextEditor ) {
841
                initScrollEventListener( tab );
842
              }
843
            } );
844
845
            // Select and give focus to the last tab opened.
846
            final var index = tabs.size() - 1;
847
            if( index >= 0 ) {
848
              final var tab = tabs.get( index );
849
              tabPane.getSelectionModel().select( tab );
850
              tab.getContent().requestFocus();
851
            }
852
          }
853
        }
854
      }
855
    );
856
  }
857
858
  /**
859
   * Synchronizes scrollbar positions between the given {@link Tab} that
860
   * contains an instance of {@link TextEditor} and {@link HtmlPreview} pane.
861
   *
862
   * @param tab The container for an instance of {@link TextEditor}.
863
   */
864
  private void initScrollEventListener( final Tab tab ) {
865
    final var editor = (TextEditor) tab.getContent();
866
    final var scrollPane = editor.getScrollPane();
867
    final var scrollBar = mPreview.getVerticalScrollBar();
868
    final var handler = new ScrollEventHandler( scrollPane, scrollBar );
869
    handler.enabledProperty().bind( tab.selectedProperty() );
870
  }
871
872
  private void addTabPane( final int index, final TabPane tabPane ) {
873
    final var items = getItems();
874
    if( !items.contains( tabPane ) ) {
875
      items.add( index, tabPane );
876
    }
877
  }
878
879
  private void addTabPane( final TabPane tabPane ) {
880
    addTabPane( getItems().size(), tabPane );
881
  }
882
883
  public ProcessorContext createProcessorContext() {
884
    return createProcessorContext( null, NONE );
885
  }
886
887
  public ProcessorContext createProcessorContext(
888
    final Path exportPath, final ExportFormat format ) {
889
    final var editor = getActiveTextEditor();
890
    return createProcessorContext(
891
      editor.getPath(), exportPath, format, editor.getCaret() );
892
  }
893
894
  private ProcessorContext createProcessorContext(
895
    final Path path, final Caret caret ) {
896
    return createProcessorContext( path, null, ExportFormat.NONE, caret );
897
  }
898
899
  /**
900
   * @param path       Used by {@link ProcessorFactory} to determine
901
   *                   {@link Processor} type to create based on file type.
902
   * @param exportPath Used when exporting to a PDF file (binary).
903
   * @param format     Used when processors export to a new text format.
904
   * @param caret      Used by {@link CaretExtension} to add ID attribute into
905
   *                   preview document for scrollbar synchronization.
906
   * @return A new {@link ProcessorContext} to use when creating an instance of
907
   * {@link Processor}.
908
   */
909
  private ProcessorContext createProcessorContext(
910
    final Path path, final Path exportPath, final ExportFormat format,
911
    final Caret caret ) {
912
    return new ProcessorContext(
913
      mPreview, mResolvedMap, path, exportPath, format, mWorkspace, caret
914
    );
915
  }
916
917
  private TextResource createTextResource( final File file ) {
918
    // TODO: Create PlainTextEditor that's returned by default.
919
    return MediaType.valueFrom( file ) == TEXT_YAML
920
      ? createDefinitionEditor( file )
921
      : createMarkdownEditor( file );
922
  }
923
924
  /**
925
   * Creates an instance of {@link MarkdownEditor} that listens for both
926
   * caret change events and text change events. Text change events must
927
   * take priority over caret change events because it's possible to change
928
   * the text without moving the caret (e.g., delete selected text).
929
   *
930
   * @param file The file containing contents for the text editor.
931
   * @return A non-null text editor.
932
   */
933
  private TextResource createMarkdownEditor( final File file ) {
934
    final var path = file.toPath();
935
    final var editor = new MarkdownEditor( file, getWorkspace() );
936
    final var caret = editor.getCaret();
937
    final var context = createProcessorContext( path, caret );
938
939
    mProcessors.computeIfAbsent( editor, p -> createProcessors( context ) );
940
941
    editor.addDirtyListener( ( c, o, n ) -> {
942
      if( n ) {
943
        // Reset the status to OK after changing the text.
944
        clue();
945
946
        // Processing the text may update the status bar.
874947
        process( getActiveTextEditor() );
875948
      }
M src/main/java/com/keenwrite/MainScene.java
1717
import java.io.File;
1818
19
import static com.keenwrite.Constants.*;
2019
import static com.keenwrite.Messages.get;
20
import static com.keenwrite.constants.Constants.*;
2121
import static com.keenwrite.events.ScrollLockEvent.fireScrollLockEvent;
2222
import static com.keenwrite.events.StatusEvent.clue;
23
import static com.keenwrite.preferences.ThemeProperty.toFilename;
24
import static com.keenwrite.preferences.WorkspaceKeys.KEY_UI_THEME_CUSTOM;
25
import static com.keenwrite.preferences.WorkspaceKeys.KEY_UI_THEME_SELECTION;
23
import static com.keenwrite.preferences.SkinProperty.toFilename;
24
import static com.keenwrite.preferences.WorkspaceKeys.KEY_UI_SKIN_CUSTOM;
25
import static com.keenwrite.preferences.WorkspaceKeys.KEY_UI_SKIN_SELECTION;
2626
import static com.keenwrite.ui.actions.ApplicationBars.*;
2727
import static javafx.application.Platform.runLater;
...
9696
9797
  private void initStylesheets( final Scene scene, final Workspace workspace ) {
98
    final var internal = workspace.themeProperty( KEY_UI_THEME_SELECTION );
99
    final var external = workspace.fileProperty( KEY_UI_THEME_CUSTOM );
100
    final var inTheme = internal.get();
101
    final var exTheme = external.get();
102
    applyStylesheets( scene, inTheme, exTheme );
98
    final var internal = workspace.skinProperty( KEY_UI_SKIN_SELECTION );
99
    final var external = workspace.fileProperty( KEY_UI_SKIN_CUSTOM );
100
    final var inSkin = internal.get();
101
    final var exSkin = external.get();
102
    applyStylesheets( scene, inSkin, exSkin );
103103
104104
    internal.addListener(
105105
      ( c, o, n ) -> {
106106
        if( n != null ) {
107
          applyStylesheets( scene, n, exTheme );
107
          applyStylesheets( scene, n, exSkin );
108108
        }
109109
      }
...
118118
        if( n != null ) {
119119
          try {
120
            applyStylesheets( scene, inTheme, n );
120
            applyStylesheets( scene, inSkin, n );
121121
          } catch( final Exception ex ) {
122122
            // Changes to the CSS file won't autoload, which is okay.
...
129129
    mFileWatchService.removeListener( mStylesheetFileListener );
130130
    mStylesheetFileListener = event ->
131
      runLater( () -> applyStylesheets( scene, inTheme, event.getFile() ) );
131
      runLater( () -> applyStylesheets( scene, inSkin, event.getFile() ) );
132132
    mFileWatchService.addListener( mStylesheetFileListener );
133133
  }
134134
135135
  private String getStylesheet( final String filename ) {
136
    return get( STYLESHEET_APPLICATION_THEME, filename );
136
    return get( STYLESHEET_APPLICATION_SKIN, filename );
137137
  }
138138
M src/main/java/com/keenwrite/Messages.java
99
import java.util.Stack;
1010
11
import static com.keenwrite.Constants.APP_BUNDLE_NAME;
11
import static com.keenwrite.constants.Constants.APP_BUNDLE_NAME;
1212
import static java.util.ResourceBundle.getBundle;
1313
A src/main/java/com/keenwrite/constants/Constants.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.constants;
3
4
import com.keenwrite.Bootstrap;
5
import com.keenwrite.Services;
6
import com.keenwrite.service.Settings;
7
8
import java.io.File;
9
import java.nio.charset.Charset;
10
import java.nio.file.Path;
11
import java.util.Locale;
12
13
import static com.keenwrite.Bootstrap.APP_TITLE_LOWERCASE;
14
import static com.keenwrite.preferences.LocaleScripts.withScript;
15
import static java.io.File.separator;
16
import static java.lang.String.format;
17
import static java.lang.System.getProperty;
18
19
/**
20
 * Defines application-wide default values.
21
 */
22
public final class Constants {
23
24
  /**
25
   * Used by the default settings to load the {@link Settings} service. This
26
   * must come before any attempt is made to create a {@link Settings} object.
27
   * The reference to {@link Bootstrap#APP_TITLE_LOWERCASE} should cause the
28
   * JVM to load {@link Bootstrap} prior to proceeding. Loading that class
29
   * beforehand will read the bootstrap properties file to determine the
30
   * application name, which is then used to locate the settings properties.
31
   */
32
  public static final String PATH_PROPERTIES_SETTINGS =
33
    format( "/com/%s/settings.properties", APP_TITLE_LOWERCASE );
34
35
  /**
36
   * The {@link Settings} uses {@link #PATH_PROPERTIES_SETTINGS}.
37
   */
38
  public static final Settings sSettings = Services.load( Settings.class );
39
40
  public static final double WINDOW_X_DEFAULT = 0;
41
  public static final double WINDOW_Y_DEFAULT = 0;
42
  public static final double WINDOW_W_DEFAULT = 1200;
43
  public static final double WINDOW_H_DEFAULT = 800;
44
45
  public static final File DOCUMENT_DEFAULT = getFile( "document" );
46
  public static final File DEFINITION_DEFAULT = getFile( "definition" );
47
48
  public static final String APP_BUNDLE_NAME = get( "application.messages" );
49
50
  public static final String STYLESHEET_APPLICATION_BASE =
51
    get( "file.stylesheet.application.base" );
52
  public static final String STYLESHEET_APPLICATION_SKIN =
53
    get( "file.stylesheet.application.skin" );
54
  public static final String STYLESHEET_MARKDOWN =
55
    get( "file.stylesheet.markdown" );
56
  public static final String STYLESHEET_MARKDOWN_LOCALE =
57
    "file.stylesheet.markdown.locale";
58
  public static final String STYLESHEET_PREVIEW =
59
    get( "file.stylesheet.preview" );
60
  public static final String STYLESHEET_PREVIEW_LOCALE =
61
    "file.stylesheet.preview.locale";
62
63
  public static final String FILE_PREFERENCES = getPreferencesFilename();
64
65
  /**
66
   * Refer to file name extension settings in the configuration file. Do not
67
   * terminate with a period.
68
   */
69
  public static final String GLOB_PREFIX_FILE = "file.ext";
70
71
  /**
72
   * Three parameters: line number, column number, and offset.
73
   */
74
  public static final String STATUS_BAR_LINE = "Main.status.line";
75
76
  public static final String STATUS_BAR_OK = "Main.status.state.default";
77
78
  /**
79
   * Used to show an error while parsing, usually syntactical.
80
   */
81
  public static final String STATUS_PARSE_ERROR = "Main.status.error.parse";
82
  public static final String STATUS_DEFINITION_BLANK =
83
    "Main.status.error.def.blank";
84
  public static final String STATUS_DEFINITION_EMPTY =
85
    "Main.status.error.def.empty";
86
87
  /**
88
   * One parameter: the word under the cursor that could not be found.
89
   */
90
  public static final String STATUS_DEFINITION_MISSING =
91
    "Main.status.error.def.missing";
92
93
  /**
94
   * Used when creating flat maps relating to resolved variables.
95
   */
96
  public static final int MAP_SIZE_DEFAULT = 128;
97
98
  /**
99
   * Default image extension order to use when scanning.
100
   */
101
  public static final String PERSIST_IMAGES_DEFAULT =
102
    get( "file.ext.image.order" );
103
104
  /**
105
   * Default working directory to use for R startup script.
106
   */
107
  public static final File USER_DIRECTORY =
108
    new File( System.getProperty( "user.dir" ) );
109
110
  public static final String NEWLINE = System.lineSeparator();
111
112
  /**
113
   * Default path to use for an untitled (pathless) file.
114
   */
115
  public static final Path DEFAULT_DIRECTORY = USER_DIRECTORY.toPath();
116
117
  /**
118
   * Default character set to use when reading/writing files.
119
   */
120
  public static final Charset DEFAULT_CHARSET = Charset.defaultCharset();
121
122
  /**
123
   * Default starting delimiter for definition variables. This value must
124
   * not overlap math delimiters, so do not use $ tokens as the first
125
   * delimiter.
126
   */
127
  public static final String DEF_DELIM_BEGAN_DEFAULT = "{{";
128
129
  /**
130
   * Default ending delimiter for definition variables.
131
   */
132
  public static final String DEF_DELIM_ENDED_DEFAULT = "}}";
133
134
  /**
135
   * Default starting delimiter when inserting R variables.
136
   */
137
  public static final String R_DELIM_BEGAN_DEFAULT = "x( ";
138
139
  /**
140
   * Default ending delimiter when inserting R variables.
141
   */
142
  public static final String R_DELIM_ENDED_DEFAULT = " )";
143
144
  /**
145
   * Resource directory where different language lexicons are located.
146
   */
147
  public static final String LEXICONS_DIRECTORY = "lexicons";
148
149
  /**
150
   * Absolute location of true type font files within the Java archive file.
151
   */
152
  public static final String FONT_DIRECTORY = "/fonts";
153
154
  /**
155
   * Default text editor font name.
156
   */
157
  public static final String FONT_NAME_EDITOR_DEFAULT = "Noto Sans Regular";
158
159
  /**
160
   * Default text editor font size, in points.
161
   */
162
  public static final float FONT_SIZE_EDITOR_DEFAULT = 12f;
163
164
  /**
165
   * Default preview font name.
166
   */
167
  public static final String FONT_NAME_PREVIEW_DEFAULT = "Source Serif 4";
168
169
  /**
170
   * Default preview font size, in points.
171
   */
172
  public static final float FONT_SIZE_PREVIEW_DEFAULT = 13f;
173
174
  /**
175
   * Default monospace preview font name.
176
   */
177
  public static final String FONT_NAME_PREVIEW_MONO_NAME_DEFAULT =
178
    "Source Code Pro";
179
180
  /**
181
   * Default monospace preview font size, in points.
182
   */
183
  public static final float FONT_SIZE_PREVIEW_MONO_SIZE_DEFAULT = 13f;
184
185
  /**
186
   * Default locale for font loading, including ISO 15924 alpha-4 script code.
187
   */
188
  public static final Locale LOCALE_DEFAULT = withScript( Locale.getDefault() );
189
190
  /**
191
   * Default CSS to apply (resolves to a minimal implementation).
192
   */
193
  public static final String SKIN_DEFAULT = "Modena Light";
194
195
  /**
196
   * Custom CSS to apply.
197
   */
198
  public static final File SKIN_CUSTOM_DEFAULT = null;
199
200
  /**
201
   * Default identifier to use for synchronized scrolling.
202
   */
203
  public static final String CARET_ID = "caret";
204
205
  /**
206
   * Default spacing for UI items (e.g., toolbars).
207
   */
208
  public static final int UI_CONTROL_SPACING = 10;
209
210
  /**
211
   * Default server name for rendering diagrams.
212
   * <p>
213
   * TODO: Make this a preference so that local installs are possible.
214
   */
215
  public static final String DIAGRAM_SERVER_NAME = "kroki.io";
216
217
  /**
218
   * Application action messages properties prefix.
219
   */
220
  public static final String ACTION_PREFIX = "Action.";
221
222
  /**
223
   * Prevent instantiation.
224
   */
225
  private Constants() {
226
  }
227
228
  /**
229
   * Converts from points to pixels because FlyingSaucer cannot handle points
230
   * properly. This is used to convert font sizes.
231
   *
232
   * @param points The points to convert to pixels.
233
   * @return The given number of points in equivalent pixels.
234
   */
235
  public static int toPixels( final double points ) {
236
    return (int) (points * (1 + 1 / 3f));
237
  }
238
239
  static String get( final String key ) {
240
    return sSettings.getSetting( key, "" );
241
  }
242
243
  /**
244
   * Returns a default {@link File} instance based on the given key suffix.
245
   *
246
   * @param suffix Appended to {@code "file.default."}.
247
   * @return A new {@link File} instance that references the settings file name.
248
   */
249
  private static File getFile( final String suffix ) {
250
    return new File( get( "file.default." + suffix ) );
251
  }
252
253
  /**
254
   * Returns the equivalent of {@code $HOME/.filename.xml}.
255
   */
256
  private static String getPreferencesFilename() {
257
    return format(
258
      "%s%s.%s.xml",
259
      getProperty( "user.home" ),
260
      separator,
261
      APP_TITLE_LOWERCASE
262
    );
263
  }
264
}
1265
A src/main/java/com/keenwrite/constants/GraphicsConstants.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.constants;
3
4
import javafx.scene.image.Image;
5
import javafx.scene.image.ImageView;
6
7
import java.util.ArrayList;
8
import java.util.List;
9
10
import static com.keenwrite.constants.Constants.get;
11
12
/**
13
 * Defines application-wide default values for GUI-related items. This helps
14
 * ensure that unit tests that have no graphical dependencies will pass.
15
 */
16
public class GraphicsConstants {
17
  public static final List<Image> LOGOS = createImages(
18
    "file.logo.16",
19
    "file.logo.32",
20
    "file.logo.128",
21
    "file.logo.256",
22
    "file.logo.512"
23
  );
24
25
  public static final Image ICON_DIALOG = LOGOS.get( 1 );
26
27
  public static final ImageView ICON_DIALOG_NODE = new ImageView( ICON_DIALOG );
28
29
  /**
30
   * Converts the given file names to images, such as application icons.
31
   *
32
   * @param keys The file names to convert to images.
33
   * @return The images loaded from the file name references.
34
   */
35
  private static List<Image> createImages( final String... keys ) {
36
    final List<Image> images = new ArrayList<>( keys.length );
37
38
    for( final var key : keys ) {
39
      images.add( new Image( get( key ) ) );
40
    }
41
42
    return images;
43
  }
44
}
145
M src/main/java/com/keenwrite/editors/TextEditor.java
3131
   *
3232
   * @param indexes Document offset where style is to start and end.
33
   * @param style The style class to apply between the given offset indexes.
33
   * @param style   The style class to apply between the given offset indexes.
3434
   */
3535
  default void stylize( final IndexRange indexes, final String style ) {
...
149149
   * Requests making the selected text, or word at caret, bold.
150150
   */
151
  default void bold() {
152
  }
151
  default void bold() { }
153152
154153
  /**
155154
   * Requests making the selected text, or word at caret, italic.
156155
   */
157
  default void italic() {
158
  }
156
  default void italic() { }
159157
160158
  /**
161159
   * Requests making the selected text, or word at caret, a superscript.
162160
   */
163
  default void superscript() {
164
  }
161
  default void superscript() { }
165162
166163
  /**
167164
   * Requests making the selected text, or word at caret, a subscript.
168165
   */
169
  default void subscript() {
170
  }
166
  default void subscript() { }
171167
172168
  /**
173169
   * Requests making the selected text, or word at caret, struck.
174170
   */
175
  default void strikethrough() {
176
  }
171
  default void strikethrough() { }
177172
178173
  /**
179174
   * Requests making the selected text, or word at caret, a blockquote block.
180175
   */
181
  default void blockquote() {
182
  }
176
  default void blockquote() { }
183177
184178
  /**
185179
   * Requests making the selected text, or word at caret, inline code.
186180
   */
187
  default void code() {
188
  }
181
  default void code() { }
189182
190183
  /**
191184
   * Requests making the selected text, or word at caret, a fenced code block.
192185
   */
193
  default void fencedCodeBlock() {
194
  }
186
  default void fencedCodeBlock() { }
195187
196188
  /**
197189
   * Requests making the selected text, or word at caret, a heading.
198190
   *
199191
   * @param level The heading level to apply (typically 1 through 3).
200192
   */
201
  default void heading( final int level ) {
202
  }
193
  default void heading( final int level ) { }
203194
204195
  /**
205196
   * Requests making the selected text, or word at caret, an unordered list
206197
   * block.
207198
   */
208
  default void unorderedList() {
209
  }
199
  default void unorderedList() { }
210200
211201
  /**
212202
   * Requests making the selected text, or word at caret, an ordered list block.
213203
   */
214
  default void orderedList() {
215
  }
204
  default void orderedList() { }
216205
217206
  /**
218207
   * Requests making the selected text, or inserting at the caret, a
219208
   * horizontal rule.
220209
   */
221
  default void horizontalRule() {
222
  }
210
  default void horizontalRule() { }
223211
}
224212
M src/main/java/com/keenwrite/editors/TextResource.java
1111
import java.nio.file.Path;
1212
13
import static com.keenwrite.Constants.DEFAULT_CHARSET;
13
import static com.keenwrite.constants.Constants.DEFAULT_CHARSET;
1414
import static com.keenwrite.events.StatusEvent.clue;
1515
import static java.nio.charset.Charset.forName;
M src/main/java/com/keenwrite/editors/definition/DefinitionEditor.java
22
package com.keenwrite.editors.definition;
33
4
import com.keenwrite.Constants;
4
import com.keenwrite.constants.Constants;
55
import com.keenwrite.editors.TextDefinition;
66
import com.keenwrite.sigils.Tokens;
...
2626
import java.util.regex.Pattern;
2727
28
import static com.keenwrite.Constants.*;
28
import static com.keenwrite.constants.Constants.*;
2929
import static com.keenwrite.Messages.get;
3030
import static com.keenwrite.events.StatusEvent.clue;
M src/main/java/com/keenwrite/editors/definition/TreeItemMapper.java
1212
import java.util.Stack;
1313
14
import static com.keenwrite.Constants.MAP_SIZE_DEFAULT;
14
import static com.keenwrite.constants.Constants.MAP_SIZE_DEFAULT;
1515
1616
/**
M src/main/java/com/keenwrite/editors/markdown/MarkdownEditor.java
33
44
import com.keenwrite.Caret;
5
import com.keenwrite.Constants;
5
import com.keenwrite.constants.Constants;
66
import com.keenwrite.editors.TextEditor;
77
import com.keenwrite.preferences.LocaleProperty;
...
3131
import java.util.regex.Pattern;
3232
33
import static com.keenwrite.Constants.*;
33
import static com.keenwrite.constants.Constants.*;
3434
import static com.keenwrite.MainApp.keyDown;
3535
import static com.keenwrite.Messages.get;
A src/main/java/com/keenwrite/events/ExportFailedEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
/**
5
 * Responsible for kicking off an alert message when exporting (e.g., to PDF)
6
 * fails. This can happen when the executable to typeset the document cannot
7
 * be found.
8
 */
9
public class ExportFailedEvent implements AppEvent {
10
  public static void fireExportFailedEvent() {
11
    new ExportFailedEvent().fire();
12
  }
13
}
114
A src/main/java/com/keenwrite/events/HyperlinkOpenEvent.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.events;
3
4
import java.io.IOException;
5
import java.net.URI;
6
7
import static com.keenwrite.events.StatusEvent.clue;
8
9
/**
10
 * Collates information about a URL requested to be opened.
11
 */
12
public class HyperlinkOpenEvent implements AppEvent {
13
  private final URI mUri;
14
15
  private HyperlinkOpenEvent( final URI uri ) {
16
    mUri = uri;
17
  }
18
19
  /**
20
   * Requests to open the default browser at the given location.
21
   *
22
   * @param uri The location to open.
23
   */
24
  public static void fireHyperlinkOpenEvent( final URI uri )
25
    throws IOException {
26
    new HyperlinkOpenEvent( uri ).fire();
27
  }
28
29
  /**
30
   * Requests to open the default browser at the given location.
31
   *
32
   * @param uri The location to open.
33
   */
34
  public static void fireHyperlinkOpenEvent( final String uri ) {
35
    try {
36
      fireHyperlinkOpenEvent( new URI( uri ) );
37
    } catch( final Exception ex ) {
38
      clue( ex );
39
    }
40
  }
41
42
  /**
43
   * Returns the requested resource to be opened.
44
   *
45
   * @return A reference that can be opened in a web browser.
46
   */
47
  public URI getUri() {
48
    return mUri;
49
  }
50
}
151
M src/main/java/com/keenwrite/events/StatusEvent.java
66
import java.util.stream.Collectors;
77
8
import static com.keenwrite.Constants.NEWLINE;
9
import static com.keenwrite.Constants.STATUS_BAR_OK;
108
import static com.keenwrite.Messages.get;
9
import static com.keenwrite.constants.Constants.NEWLINE;
10
import static com.keenwrite.constants.Constants.STATUS_BAR_OK;
11
import static java.lang.String.format;
12
import static java.lang.String.join;
1113
import static java.util.Arrays.stream;
1214
1315
/**
1416
 * Collates information about an application issue. The issues can be
1517
 * exceptions, state problems, parsing errors, and so forth.
1618
 */
1719
public class StatusEvent implements AppEvent {
1820
  private static final String PACKAGE_NAME = MainApp.class.getPackageName();
1921
20
  /**
21
   * Indicates that there are no issues to bring to the user's attention.
22
   */
23
  private static final StatusEvent OK =
24
    new StatusEvent( get( STATUS_BAR_OK, "OK" ) );
22
  private static final String ENGLISHIFY =
23
    "(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])";
2524
2625
  /**
...
7776
7877
    return sb.toString();
78
  }
79
80
  public String getException() {
81
    return mProblem == null ? "" : toEnglish( mProblem );
7982
  }
8083
8184
  private static boolean filter( final StackTraceElement e ) {
8285
    final var clazz = e.getClassName();
8386
    return clazz.contains( PACKAGE_NAME ) ||
8487
      clazz.contains( "org.renjin." ) ||
8588
      clazz.contains( "sun." ) ||
8689
      clazz.contains( "flexmark." ) ||
8790
      clazz.contains( "java." );
91
  }
92
93
  /**
94
   * Separates the exception class name from TitleCase into lowercase,
95
   * space-separated words. This makes the exception look a little more like
96
   * English. Any {@link RuntimeException} instances passed into this method
97
   * will have the cause extracted, if possible.
98
   *
99
   * @param problem The exception that triggered the status event change.
100
   * @return A human-readable message with the exception name and the
101
   * exception's message.
102
   */
103
  private static String toEnglish( Throwable problem ) {
104
    assert problem != null;
105
106
    // Subclasses of RuntimeException must be subject to Englishification.
107
    if( problem.getClass().equals( RuntimeException.class ) &&
108
      (problem = problem.getCause()) == null ) {
109
      return "";
110
    }
111
112
    final var className = problem.getClass().getSimpleName();
113
    final var words = join( " ", className.split( ENGLISHIFY ) );
114
    return format( " (%s: %s)", words.toLowerCase(), problem.getMessage() );
88115
  }
89116
...
98125
99126
  /**
100
   * Resets the status bar to a default message.
127
   * Resets the status bar to a default message. Indicates that there are no
128
   * issues to bring to the user's attention.
101129
   */
102130
  public static void clue() {
103
    OK.fire();
131
    fireStatusEvent( get( STATUS_BAR_OK, "OK" ) );
104132
  }
105133
...
130158
   */
131159
  public static void clue( final Throwable problem ) {
132
    fireStatusEvent( problem.getMessage(), problem );
160
    fireStatusEvent( "", problem );
133161
  }
134162
A src/main/java/com/keenwrite/io/HttpFacade.java
1
package com.keenwrite.io;
2
3
import java.io.BufferedInputStream;
4
import java.io.Closeable;
5
import java.io.IOException;
6
import java.io.InputStream;
7
import java.net.HttpURLConnection;
8
import java.net.URI;
9
import java.net.URL;
10
import java.net.URLConnection;
11
import java.util.zip.GZIPInputStream;
12
13
import static com.keenwrite.events.StatusEvent.clue;
14
import static java.lang.System.getProperty;
15
import static java.lang.System.setProperty;
16
import static java.net.HttpURLConnection.HTTP_OK;
17
import static java.net.HttpURLConnection.setFollowRedirects;
18
19
/**
20
 * Responsible for making HTTP requests, a thin wrapper around the
21
 * {@link URLConnection} class. This will attempt to use compression.
22
 * <p>
23
 * This class must be used within a try-with-resources block to ensure all
24
 * resources are released, even if only calling {@link Response#getMediaType()}.
25
 * </p>
26
 */
27
public class HttpFacade {
28
  static {
29
    setProperty( "http.keepAlive", "false" );
30
    setFollowRedirects( true );
31
  }
32
33
  /**
34
   * Sends an HTTP GET request to a server.
35
   *
36
   * @param url The remote resource to fetch.
37
   * @return The server response.
38
   */
39
  public static Response httpGet( final URL url ) throws Exception {
40
    return new Response(url);
41
  }
42
43
  /**
44
   * Convenience method to send an HTTP GET request to a server.
45
   *
46
   * @param uri The remote resource to fetch.
47
   * @return The server response.
48
   * @see #httpGet(URL)
49
   */
50
  public static Response httpGet( final URI uri ) throws Exception {
51
    return httpGet( uri.toURL() );
52
  }
53
54
  /**
55
   * Convenience method to send an HTTP GET request to a server.
56
   *
57
   * @param url The remote resource to fetch.
58
   * @return The server response.
59
   * @see #httpGet(URL)
60
   */
61
  public static Response httpGet( final String url ) throws Exception {
62
    return httpGet( new URL( url ) );
63
  }
64
65
  /**
66
   * Callers are responsible for closing the response.
67
   */
68
  public static final class Response implements Closeable {
69
    private final HttpURLConnection mConn;
70
    private final BufferedInputStream mStream;
71
72
    private Response( final URL url ) throws IOException {
73
      assert url != null;
74
75
      clue( "Main.status.image.request.init" );
76
      final var connection = url.openConnection();
77
78
      if( connection instanceof HttpURLConnection ) {
79
        mConn = (HttpURLConnection) connection;
80
        mConn.setUseCaches( false );
81
        mConn.setInstanceFollowRedirects( true );
82
        mConn.setRequestProperty( "Accept-Encoding", "gzip" );
83
        mConn.setRequestProperty( "User-Agent", getProperty( "http.agent" ) );
84
        mConn.setRequestMethod( "GET" );
85
        mConn.setConnectTimeout( 15000 );
86
        mConn.setRequestProperty( "connection", "close" );
87
        mConn.connect();
88
        clue( "Main.status.image.request.fetch", url.getHost() );
89
90
        final var code = mConn.getResponseCode();
91
92
        // Even though there are other "okay" error codes, tell the user when
93
        // a resource has changed in any unexpected way.
94
        if( code != HTTP_OK ) {
95
          throw new IOException( url.toString() + " [HTTP " + code + "]" );
96
        }
97
98
        mStream = openBufferedInputStream();
99
      }
100
      else {
101
        throw new UnsupportedOperationException( url.toString() );
102
      }
103
    }
104
105
    /**
106
     * Returns the {@link MediaType} based on the resulting HTTP content type
107
     * provided by the server. If the content type from the server is not
108
     * found, this will probe the first several bytes to determine the type.
109
     *
110
     * @return The stream's IANA-defined {@link MediaType}.
111
     */
112
    public MediaType getMediaType() throws IOException {
113
      final var contentType = mConn.getContentType();
114
      var mediaType = MediaType.valueFrom( contentType );
115
116
      if( mediaType.isUndefined() ) {
117
        mediaType = MediaTypeSniffer.getMediaType( mStream );
118
      }
119
120
      clue( "Main.status.image.request.success", mediaType );
121
      return mediaType;
122
    }
123
124
    /**
125
     * Returns the stream opened using an HTTP connection, decompressing if
126
     * the server supports gzip compression. The caller must close the stream
127
     * by calling {@link #close()} on this object.
128
     *
129
     * @return The stream representing the content at the URL used to
130
     * construct the {@link HttpFacade}.
131
     */
132
    public InputStream getInputStream() throws IOException {
133
      return mStream;
134
    }
135
136
    /**
137
     * This will disconnect the HTTP request and close the associated stream.
138
     */
139
    @Override
140
    public void close() {
141
      mConn.disconnect();
142
    }
143
144
    /**
145
     * Opens the connection for reading. It is an error to call this more than
146
     * once. This may use gzip compression. A {@link BufferedInputStream} is
147
     * returned to allow peeking at the stream when checking the content
148
     * type.
149
     *
150
     * @return The {@link InputStream} containing content from an HTTP request.
151
     * @throws IOException Could not open the stream.
152
     */
153
    private BufferedInputStream openBufferedInputStream() throws IOException {
154
      final var encoding = mConn.getContentEncoding();
155
      final var is = mConn.getInputStream();
156
157
      return new BufferedInputStream(
158
        "gzip".equalsIgnoreCase( encoding ) ? new GZIPInputStream( is ) : is );
159
    }
160
  }
161
}
1162
D src/main/java/com/keenwrite/io/HttpMediaType.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.io;
3
4
import java.net.MalformedURLException;
5
import java.net.URI;
6
import java.net.URL;
7
import java.net.http.HttpClient;
8
import java.net.http.HttpRequest;
9
10
import static com.keenwrite.events.StatusEvent.clue;
11
import static com.keenwrite.io.MediaType.UNDEFINED;
12
import static java.net.http.HttpClient.Redirect.NORMAL;
13
import static java.net.http.HttpRequest.BodyPublishers.noBody;
14
import static java.net.http.HttpResponse.BodyHandlers.ofString;
15
import static java.time.Duration.ofSeconds;
16
17
/**
18
 * Responsible for determining {@link MediaType} based on the content-type from
19
 * an HTTP request.
20
 */
21
public final class HttpMediaType {
22
23
  private static final HttpClient HTTP_CLIENT = HttpClient
24
    .newBuilder()
25
    .connectTimeout( ofSeconds( 10 ) )
26
    .followRedirects( NORMAL )
27
    .build();
28
29
  /**
30
   * Performs an HTTP HEAD request to determine the media type based on the
31
   * Content-Type header returned from the server.
32
   *
33
   * @param uri Determine the media type for this resource.
34
   * @return The data type for the resource or {@link MediaType#UNDEFINED} if
35
   * unmapped.
36
   * @throws MalformedURLException The {@link URI} could not be converted to
37
   *                               an instance of {@link URL}.
38
   */
39
  public static MediaType valueFrom( final URI uri )
40
    throws MalformedURLException {
41
    final var mediaType = new MediaType[]{UNDEFINED};
42
43
    try {
44
      clue( "Main.status.image.request.init" );
45
      final var request = HttpRequest
46
        .newBuilder()
47
        .setHeader( "User-Agent", System.getProperty( "http.agent" ) )
48
        .method( "HEAD", noBody() )
49
        .uri( uri )
50
        .build();
51
      clue( "Main.status.image.request.fetch", uri.getHost() );
52
      final var response = HTTP_CLIENT.send( request, ofString() );
53
      final var headers = response.headers();
54
      final var map = headers.map();
55
56
      map.forEach( ( key, values ) -> {
57
        if( "content-type".equalsIgnoreCase( key ) ) {
58
          var header = values.get( 0 );
59
          // Trim off the character encoding.
60
          var i = header.indexOf( ';' );
61
          header = header.substring( 0, i == -1 ? header.length() : i );
62
63
          // Split the type and subtype.
64
          i = header.indexOf( '/' );
65
          i = i == -1 ? header.length() : i;
66
          final var type = header.substring( 0, i );
67
          final var subtype = header.substring( i + 1 );
68
69
          mediaType[ 0 ] = MediaType.valueFrom( type, subtype );
70
          clue( "Main.status.image.request.success", mediaType[ 0 ] );
71
        }
72
      } );
73
74
      clue();
75
    } catch( final Exception ex ) {
76
      clue( ex );
77
    }
78
79
    return mediaType[ 0 ];
80
  }
81
}
821
M src/main/java/com/keenwrite/io/MediaType.java
33
44
import java.io.File;
5
import java.io.IOException;
56
import java.nio.file.Path;
67
78
import static com.keenwrite.io.MediaType.TypeName.*;
89
import static com.keenwrite.io.MediaTypeExtension.getMediaType;
10
import static java.io.File.createTempFile;
911
import static org.apache.commons.io.FilenameUtils.getExtension;
1012
...
1719
 */
1820
public enum MediaType {
19
  /*
20
   * Internal values applied to non-editor tabs.
21
   */
22
  APP_DOCUMENT_OUTLINE(
23
    APPLICATION, "x-document-outline"
24
  ),
25
  APP_DOCUMENT_STATISTICS(
26
    APPLICATION, "x-document-statistics"
27
  ),
28
  APP_FILE_MANAGER(
29
    APPLICATION, "x-file-manager"
30
  ),
21
  APP_DOCUMENT_OUTLINE( APPLICATION, "x-document-outline" ),
22
  APP_DOCUMENT_STATISTICS( APPLICATION, "x-document-statistics" ),
23
  APP_FILE_MANAGER( APPLICATION, "x-file-manager" ),
3124
32
  /*
33
   * Internal values used to distinguish document outline tabs from editors.
34
   */
35
  APP_JAVA_OBJECT(
36
    APPLICATION, "x-java-serialized-object"
37
  ),
25
  APP_ACAD( APPLICATION, "acad" ),
26
  APP_JAVA_OBJECT( APPLICATION, "x-java-serialized-object" ),
27
  APP_JAVA( APPLICATION, "java" ),
28
  APP_PS( APPLICATION, "postscript" ),
29
  APP_EPS( APPLICATION, "eps" ),
30
  APP_PDF( APPLICATION, "pdf" ),
31
  APP_ZIP( APPLICATION, "zip" ),
3832
3933
  /*
...
8175
  IMAGE_NAPLPS( "naplps" ),
8276
  IMAGE_PNG( "png" ),
77
  IMAGE_PHOTOSHOP( "photoshop" ),
8378
  IMAGE_SVG_XML( "svg+xml" ),
8479
  IMAGE_T38( "t38" ),
8580
  IMAGE_TIFF( "tiff" ),
8681
  IMAGE_WEBP( "webp" ),
8782
  IMAGE_WMF( "wmf" ),
83
  IMAGE_X_BITMAP( "x-xbitmap" ),
84
  IMAGE_X_PIXMAP( "x-xpixmap" ),
85
86
  /*
87
   * Standard audio types.
88
   */
89
  AUDIO_BASIC( AUDIO, "basic" ),
90
  AUDIO_MP3( AUDIO, "mp3" ),
91
  AUDIO_WAV( AUDIO, "x-wav" ),
92
93
  /*
94
   * Standard video types.
95
   */
96
  VIDEO_MNG( VIDEO, "x-mng" ),
8897
8998
  /*
...
96105
  TEXT_R_MARKDOWN( TEXT, "R+markdown" ),
97106
  TEXT_R_XML( TEXT, "R+xml" ),
107
  TEXT_XHTML( TEXT, "xhtml+xml" ),
108
  TEXT_XML( TEXT, "xml" ),
98109
  TEXT_YAML( TEXT, "yaml" ),
99110
...
108119
  public enum TypeName {
109120
    APPLICATION,
121
    AUDIO,
110122
    IMAGE,
111123
    TEXT,
112
    UNDEFINED
124
    UNDEFINED,
125
    VIDEO
113126
  }
114127
...
159172
   */
160173
  public static MediaType valueFrom( final File file ) {
161
    return valueFrom( file.getName() );
174
    assert file != null;
175
    return fromFilename( file.getName() );
176
  }
177
178
  /**
179
   * Returns the {@link MediaType} associated with the given file name.
180
   *
181
   * @param filename The file name that may contain an extension associated
182
   *                 with a known {@link MediaType}.
183
   * @return {@link MediaType#UNDEFINED} if the extension has not been
184
   * assigned, otherwise the {@link MediaType} associated with this
185
   * URL's file name extension.
186
   */
187
  public static MediaType fromFilename( final String filename ) {
188
    assert filename != null;
189
    return getMediaType( getExtension( filename ) );
162190
  }
163191
...
172200
   */
173201
  public static MediaType valueFrom( final Path path ) {
202
    assert path != null;
174203
    return valueFrom( path.toFile() );
175204
  }
176205
177206
  /**
178
   * Returns the {@link MediaType} associated with the given file name.
207
   * Determines the media type an IANA-defined, semi-colon-separated string.
208
   * This is often used after making an HTTP request to extract the type
209
   * and subtype from the content-type.
179210
   *
180
   * @param filename The file name that may contain an extension associated
181
   *                 with a known {@link MediaType}.
182
   * @return {@link MediaType#UNDEFINED} if the extension has not been
183
   * assigned, otherwise the {@link MediaType} associated with this
184
   * URL's file name extension.
211
   * @param header The content-type header value, may be {@code null}.
212
   * @return The data type for the resource or {@link MediaType#UNDEFINED} if
213
   * unmapped.
185214
   */
186
  public static MediaType valueFrom( final String filename ) {
187
    return getMediaType( getExtension( filename ) );
215
  public static MediaType valueFrom( String header ) {
216
    if( header == null || header.isBlank() ) {
217
      return UNDEFINED;
218
    }
219
220
    // Trim off the character encoding.
221
    var i = header.indexOf( ';' );
222
    header = header.substring( 0, i == -1 ? header.length() : i );
223
224
    // Split the type and subtype.
225
    i = header.indexOf( '/' );
226
    i = i == -1 ? header.length() : i;
227
    final var type = header.substring( 0, i );
228
    final var subtype = header.substring( i + 1 );
229
230
    return valueFrom( type, subtype );
188231
  }
189232
...
198241
  public static MediaType valueFrom(
199242
    final String type, final String subtype ) {
200
    for( final var mediaType : MediaType.values() ) {
243
    assert type != null;
244
    assert subtype != null;
245
246
    for( final var mediaType : values() ) {
201247
      if( mediaType.equals( type, subtype ) ) {
202248
        return mediaType;
...
216262
   */
217263
  public boolean equals( final String type, final String subtype ) {
264
    assert type != null;
265
    assert subtype != null;
266
218267
    return mTypeName.name().equalsIgnoreCase( type ) &&
219268
      mSubtype.equalsIgnoreCase( subtype );
...
231280
232281
  /**
233
   * Used by {@link MediaTypeExtension} to initialize associations where the
234
   * subtype name and the file name extension have a 1:1 mapping.
282
   * Answers whether this instance is a scalable vector graphic.
283
   *
284
   * @return {@code true} if this instance represents an SVG object.
285
   */
286
  public boolean isSvg() {
287
    return this == IMAGE_SVG_XML;
288
  }
289
290
  public boolean isUndefined() {
291
    return this == UNDEFINED;
292
  }
293
294
  /**
295
   * Returns the IANA-defined subtype classification. Primarily used by
296
   * {@link MediaTypeExtension} to initialize associations where the subtype
297
   * name and the file name extension have a 1:1 mapping.
235298
   *
236299
   * @return The IANA subtype value.
237300
   */
238
  String getSubtype() {
301
  public String getSubtype() {
239302
    return mSubtype;
303
  }
304
305
  /**
306
   * Creates a temporary {@link File} that starts with the given prefix. The
307
   * file will be deleted when the application exits.
308
   *
309
   * @param prefix The file name begins with this string (may be empty).
310
   * @return The fully qualified path to the temporary file.
311
   * @throws IOException Could not create the temporary file.
312
   */
313
  public Path createTemporaryFile( final String prefix ) throws IOException {
314
    assert prefix != null;
315
316
    final var file = createTempFile(
317
      prefix, '.' + MediaTypeExtension.valueFrom( this ).getExtension() );
318
    file.deleteOnExit();
319
    return file.toPath();
240320
  }
241321
M src/main/java/com/keenwrite/io/MediaTypeExtension.java
1313
 */
1414
public enum MediaTypeExtension {
15
  MEDIA_APP_ACAD( APP_ACAD, of( "dwg" ) ),
16
  MEDIA_APP_PDF( APP_PDF ),
17
  MEDIA_APP_PS( APP_PS, of( "ps" ) ),
18
  MEDIA_APP_EPS( APP_EPS ),
19
  MEDIA_APP_ZIP( APP_ZIP ),
20
21
  MEDIA_AUDIO_MP3( AUDIO_MP3 ),
22
  MEDIA_AUDIO_BASIC( AUDIO_BASIC, of( "au" ) ),
23
  MEDIA_AUDIO_WAV( AUDIO_WAV, of( "wav" ) ),
24
1525
  MEDIA_FONT_OTF( FONT_OTF ),
1626
  MEDIA_FONT_TTF( FONT_TTF ),
1727
1828
  MEDIA_IMAGE_APNG( IMAGE_APNG ),
1929
  MEDIA_IMAGE_BMP( IMAGE_BMP ),
2030
  MEDIA_IMAGE_GIF( IMAGE_GIF ),
2131
  MEDIA_IMAGE_JPEG( IMAGE_JPEG,
2232
                    of( "jpg", "jpe", "jpeg", "jfif", "pjpeg", "pjp" ) ),
2333
  MEDIA_IMAGE_PNG( IMAGE_PNG ),
34
  MEDIA_IMAGE_PSD( IMAGE_PHOTOSHOP, of( "psd" ) ),
2435
  MEDIA_IMAGE_SVG( IMAGE_SVG_XML, of( "svg" ) ),
2536
  MEDIA_IMAGE_TIFF( IMAGE_TIFF, of( "tiff", "tif" ) ),
2637
  MEDIA_IMAGE_WEBP( IMAGE_WEBP ),
38
  MEDIA_IMAGE_X_BITMAP( IMAGE_X_BITMAP, of( "xbm" ) ),
39
  MEDIA_IMAGE_X_PIXMAP( IMAGE_X_PIXMAP, of( "xpm" ) ),
40
41
  MEDIA_VIDEO_MNG( VIDEO_MNG, of( "mng" ) ),
2742
2843
  MEDIA_TEXT_MARKDOWN( TEXT_MARKDOWN, of(
2944
    "md", "markdown", "mdown", "mdtxt", "mdtext", "mdwn", "mkd", "mkdown",
3045
    "mkdn" ) ),
3146
  MEDIA_TEXT_PLAIN( TEXT_PLAIN, of( "txt", "asc", "ascii", "text", "utxt" ) ),
3247
  MEDIA_TEXT_R_MARKDOWN( TEXT_R_MARKDOWN, of( "Rmd" ) ),
3348
  MEDIA_TEXT_R_XML( TEXT_R_XML, of( "Rxml" ) ),
49
  MEDIA_TEXT_XHTML( TEXT_XHTML, of( "xhtml" ) ),
50
  MEDIA_TEXT_XML( TEXT_XML ),
3451
  MEDIA_TEXT_YAML( TEXT_YAML, of( "yaml", "yml" ) ),
3552
A src/main/java/com/keenwrite/io/MediaTypeSniffer.java
1
package com.keenwrite.io;
2
3
import java.io.*;
4
import java.nio.file.Path;
5
import java.util.LinkedHashMap;
6
import java.util.Map;
7
8
import static com.keenwrite.io.MediaType.*;
9
import static java.lang.System.arraycopy;
10
11
/**
12
 * Responsible for associating file signatures with IANA-defined
13
 * {@link MediaType} instances. For details see:
14
 * <ul>
15
 *   <li>
16
 *     <a href="https://www.garykessler.net/library/file_sigs.html">Kessler's List</a>
17
 *   </li>
18
 *   <li>
19
 *     <a href="https://en.wikipedia.org/wiki/List_of_file_signatures">Wikipedia's List</a>
20
 *   </li>
21
 *   <li>
22
 *     <a href="https://github.com/veniware/Space-Maker/blob/master/FileSignatures.cs">Space Maker's List</a>
23
 *   </li>
24
 * </ul>
25
 */
26
public class MediaTypeSniffer {
27
  private static final int FORMAT_LENGTH = 11;
28
  private static final int END_OF_DATA = -2;
29
30
  private static final Map<int[], MediaType> FORMAT = new LinkedHashMap<>();
31
32
  static {
33
    //@formatter:off
34
    FORMAT.put( ints( 0x3C, 0x73, 0x76, 0x67, 0x20 ), IMAGE_SVG_XML );
35
    FORMAT.put( ints( 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A ), IMAGE_PNG );
36
    FORMAT.put( ints( 0xFF, 0xD8, 0xFF, 0xE0 ), IMAGE_JPEG );
37
    FORMAT.put( ints( 0xFF, 0xD8, 0xFF, 0xEE ), IMAGE_JPEG );
38
    FORMAT.put( ints( 0xFF, 0xD8, 0xFF, 0xE1, -1, -1, 0x45, 0x78, 0x69, 0x66, 0x00 ), IMAGE_JPEG );
39
    FORMAT.put( ints( 0x49, 0x49, 0x2A, 0x00 ), IMAGE_TIFF );
40
    FORMAT.put( ints( 0x4D, 0x4D, 0x00, 0x2A ), IMAGE_TIFF );
41
    FORMAT.put( ints( 0x47, 0x49, 0x46, 0x38 ), IMAGE_GIF );
42
    FORMAT.put( ints( 0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E ), APP_PDF );
43
    FORMAT.put( ints( 0x25, 0x21, 0x50, 0x53, 0x2D, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x2D ), APP_EPS );
44
    FORMAT.put( ints( 0x25, 0x21, 0x50, 0x53 ), APP_PS );
45
    FORMAT.put( ints( 0x38, 0x42, 0x50, 0x53, 0x00, 0x01 ), IMAGE_PHOTOSHOP );
46
    FORMAT.put( ints( 0x8A, 0x4D, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A ), VIDEO_MNG );
47
    FORMAT.put( ints( 0x42, 0x4D ), IMAGE_BMP );
48
    FORMAT.put( ints( 0xFF, 0xFB, 0x30 ), AUDIO_MP3 );
49
    FORMAT.put( ints( 0x49, 0x44, 0x33 ), AUDIO_MP3 );
50
    FORMAT.put( ints( 0x3C, 0x21 ), TEXT_HTML );
51
    FORMAT.put( ints( 0x3C, 0x68, 0x74, 0x6D, 0x6C ), TEXT_HTML );
52
    FORMAT.put( ints( 0x3C, 0x68, 0x65, 0x61, 0x64 ), TEXT_HTML );
53
    FORMAT.put( ints( 0x3C, 0x62, 0x6F, 0x64, 0x79 ), TEXT_HTML );
54
    FORMAT.put( ints( 0x3C, 0x48, 0x54, 0x4D, 0x4C ), TEXT_HTML );
55
    FORMAT.put( ints( 0x3C, 0x48, 0x45, 0x41, 0x44 ), TEXT_HTML );
56
    FORMAT.put( ints( 0x3C, 0x42, 0x4F, 0x44, 0x59 ), TEXT_HTML );
57
    FORMAT.put( ints( 0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20 ), TEXT_XML );
58
    FORMAT.put( ints( 0xFE, 0xFF, 0x00, 0x3C, 0x00, 0x3f, 0x00, 0x78 ), TEXT_XML );
59
    FORMAT.put( ints( 0xFF, 0xFE, 0x3C, 0x00, 0x3F, 0x00, 0x78, 0x00 ), TEXT_XML );
60
    FORMAT.put( ints( 0x23, 0x64, 0x65, 0x66 ), IMAGE_X_BITMAP );
61
    FORMAT.put( ints( 0x21, 0x20, 0x58, 0x50, 0x4D, 0x32 ), IMAGE_X_PIXMAP );
62
    FORMAT.put( ints( 0x2E, 0x73, 0x6E, 0x64 ), AUDIO_BASIC );
63
    FORMAT.put( ints( 0x64, 0x6E, 0x73, 0x2E ), AUDIO_BASIC );
64
    FORMAT.put( ints( 0x52, 0x49, 0x46, 0x46 ), AUDIO_WAV );
65
    FORMAT.put( ints( 0x50, 0x4B ), APP_ZIP );
66
    FORMAT.put( ints( 0x41, 0x43, -1, -1, -1, -1, 0x00, 0x00, 0x00, 0x00, 0x00 ), APP_ACAD );
67
    FORMAT.put( ints( 0xCA, 0xFE, 0xBA, 0xBE ), APP_JAVA );
68
    FORMAT.put( ints( 0xAC, 0xED ), APP_JAVA_OBJECT );
69
    //@formatter:on
70
  }
71
72
  private MediaTypeSniffer() {
73
  }
74
75
  /**
76
   * Returns the {@link MediaType} for a given set of bytes.
77
   *
78
   * @param data Binary data to compare against the list of known formats.
79
   * @return The IANA-defined {@link MediaType}, or
80
   * {@link MediaType#UNDEFINED} if indeterminate.
81
   */
82
  public static MediaType getMediaType( final byte[] data ) {
83
    assert data != null;
84
85
    final var source = new int[]{
86
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
87
88
    for( int i = 0; i < data.length; i++ ) {
89
      source[ i ] = data[ i ] & 0xFF;
90
    }
91
92
    for( final var key : FORMAT.keySet() ) {
93
      int i = -1;
94
      boolean matches = true;
95
96
      while( ++i < FORMAT_LENGTH && key[ i ] != END_OF_DATA && matches ) {
97
        matches = key[ i ] == source[ i ] || key[ i ] == -1;
98
      }
99
100
      if( matches ) {
101
        return FORMAT.get( key );
102
      }
103
    }
104
105
    return UNDEFINED;
106
  }
107
108
  /**
109
   * Convenience method to return the probed media type for the given
110
   * {@link Path} instance by delegating to {@link #getMediaType(InputStream)}.
111
   *
112
   * @param path Path to ascertain the {@link MediaType}.
113
   * @return The IANA-defined {@link MediaType}, or
114
   * {@link MediaType#UNDEFINED} if indeterminate.
115
   * @throws IOException Could not read from the {@link SysFile}.
116
   */
117
  public static MediaType getMediaType( final Path path ) throws IOException {
118
    return getMediaType( path.toFile() );
119
  }
120
121
  /**
122
   * Convenience method to return the probed media type for the given
123
   * {@link SysFile} instance by delegating to
124
   * {@link #getMediaType(InputStream)}.
125
   *
126
   * @param file File to ascertain the {@link MediaType}.
127
   * @return The IANA-defined {@link MediaType}, or
128
   * {@link MediaType#UNDEFINED} if indeterminate.
129
   * @throws IOException Could not read from the {@link SysFile}.
130
   */
131
  public static MediaType getMediaType( final File file )
132
    throws IOException {
133
    try( final var fis = new FileInputStream( file ) ) {
134
      return getMediaType( fis );
135
    }
136
  }
137
138
  /**
139
   * Convenience method to return the probed media type for the given
140
   * {@link BufferedInputStream} instance. <strong>This resets the stream
141
   * pointer</strong> making the call idempotent. Users of this class should
142
   * prefer to call this method when operating on streams to avoid advancing
143
   * the stream.
144
   *
145
   * @param bis Data source to ascertain the {@link MediaType}.
146
   * @return The IANA-defined {@link MediaType}, or
147
   * {@link MediaType#UNDEFINED} if indeterminate.
148
   * @throws IOException Could not read from the {@link SysFile}.
149
   */
150
  public static MediaType getMediaType( final BufferedInputStream bis )
151
    throws IOException {
152
    bis.mark( FORMAT_LENGTH );
153
    final var result = getMediaType( (InputStream) bis );
154
    bis.reset();
155
156
    return result;
157
  }
158
159
  /**
160
   * Helper method to return the probed media type for the given
161
   * {@link InputStream} instance. The caller is responsible for closing
162
   * the stream. <strong>This advances the stream pointer.</strong>
163
   *
164
   * @param is Data source to ascertain the {@link MediaType}.
165
   * @return The IANA-defined {@link MediaType}, or
166
   * {@link MediaType#UNDEFINED} if indeterminate.
167
   * @throws IOException Could not read from the {@link InputStream}.
168
   * @see #getMediaType(BufferedInputStream) to perform a non-destructive
169
   * read.
170
   */
171
  private static MediaType getMediaType( final InputStream is )
172
    throws IOException {
173
    final var input = new byte[ FORMAT_LENGTH ];
174
    final var count = is.read( input, 0, FORMAT_LENGTH );
175
176
    if( count > 1 ) {
177
      final var available = new byte[ count ];
178
      arraycopy( input, 0, available, 0, count );
179
      return getMediaType( available );
180
    }
181
182
    return UNDEFINED;
183
  }
184
185
  /**
186
   * Creates an array of integers from the given data, padded with {@link
187
   * #END_OF_DATA} values up to {@link #FORMAT_LENGTH}.
188
   *
189
   * @param data The input byte values to pad.
190
   * @return The data with padding.
191
   */
192
  private static int[] ints( final int... data ) {
193
    final var magic = new int[ FORMAT_LENGTH ];
194
    int i = -1;
195
    while( ++i < data.length ) {
196
      magic[ i ] = data[ i ];
197
    }
198
199
    while( i < FORMAT_LENGTH ) {
200
      magic[ i++ ] = END_OF_DATA;
201
    }
202
203
    return magic;
204
  }
205
}
1206
A src/main/java/com/keenwrite/io/SysFile.java
1
package com.keenwrite.io;
2
3
import java.nio.file.Path;
4
import java.nio.file.Paths;
5
import java.util.stream.Stream;
6
7
import static java.lang.System.getenv;
8
import static java.nio.file.Files.isExecutable;
9
import static java.util.regex.Pattern.quote;
10
11
/**
12
 * Responsible for file-related functionality.
13
 */
14
public class SysFile extends java.io.File {
15
  /**
16
   * For finding executable programs.
17
   */
18
  private static final String[] EXTENSIONS = new String[]
19
    {"", ".com", ".exe", ".bat", ".cmd"};
20
21
  /**
22
   * Creates a new instance for a given file name.
23
   *
24
   * @param pathname File name to represent for subsequent operations.
25
   */
26
  public SysFile( final String pathname ) {
27
    super( pathname );
28
  }
29
30
  /**
31
   * For a file name that represents an executable (without an extension)
32
   * file, this determines whether the executable is found in the PATH
33
   * environment variable. This will search the PATH each time the method
34
   * is invoked, triggering a full directory scan for all paths listed in
35
   * the environment variable. The result is not cached, so avoid calling
36
   * this in a critical loop.
37
   *
38
   * @return {@code true} when the given file name references an executable
39
   * file located in the PATH environment variable.
40
   */
41
  public boolean canRun() {
42
    final var exe = getName();
43
    final var paths = getenv( "PATH" ).split( quote( pathSeparator ) );
44
    return Stream.of( paths ).map( Paths::get ).anyMatch(
45
      path -> {
46
        final var p = path.resolve( exe );
47
48
        for( final var extension : EXTENSIONS ) {
49
          if( isExecutable( Path.of( p.toString() + extension ) ) ) {
50
            return true;
51
          }
52
        }
53
54
        return false;
55
      }
56
    );
57
  }
58
}
159
M src/main/java/com/keenwrite/preferences/LocaleProperty.java
1010
import java.util.Objects;
1111
12
import static com.keenwrite.Constants.LOCALE_DEFAULT;
12
import static com.keenwrite.constants.Constants.LOCALE_DEFAULT;
1313
import static com.keenwrite.preferences.Workspace.listProperty;
1414
import static java.util.Locale.forLanguageTag;
M src/main/java/com/keenwrite/preferences/PreferencesController.java
88
import com.dlsc.preferencesfx.model.Group;
99
import com.dlsc.preferencesfx.model.Setting;
10
import com.dlsc.preferencesfx.util.StorageHandler;
1011
import com.dlsc.preferencesfx.view.NavigationView;
1112
import javafx.beans.property.DoubleProperty;
...
2324
import static com.dlsc.formsfx.model.structure.Field.ofStringType;
2425
import static com.dlsc.preferencesfx.PreferencesFxEvent.EVENT_PREFERENCES_SAVED;
25
import static com.keenwrite.Constants.ICON_DIALOG;
2626
import static com.keenwrite.Messages.get;
27
import static com.keenwrite.constants.GraphicsConstants.ICON_DIALOG;
2728
import static com.keenwrite.preferences.LocaleProperty.localeListProperty;
28
import static com.keenwrite.preferences.ThemeProperty.themeListProperty;
29
import static com.keenwrite.preferences.SkinProperty.skinListProperty;
2930
import static com.keenwrite.preferences.WorkspaceKeys.*;
3031
import static javafx.scene.control.ButtonType.CANCEL;
...
8889
8990
  /**
90
   * Creates the preferences dialog.
91
   * <p>
92
   * TODO: Make this dynamic by iterating over all "Preferences.*" values
93
   * that follow a particular naming pattern.
94
   * </p>
91
   * Creates the preferences dialog based using {@link XmlStorageHandler} and
92
   * numerous {@link Category} objects.
9593
   *
96
   * @return A new instance of preferences for users to edit.
94
   * @return A component for editing preferences.
95
   * @throws RuntimeException Could not construct the {@link PreferencesFx}
96
   *                          object (e.g., illegal access permissions,
97
   *                          unmapped XML resource).
9798
   */
9899
  private PreferencesFx createPreferencesFx() {
99
    return PreferencesFx.of(
100
      new XmlStorageHandler(),
100
    return PreferencesFx.of( createStorageHandler(), createCategories() )
101
                        .instantPersistent( false )
102
                        .dialogIcon( ICON_DIALOG );
103
  }
104
105
  private StorageHandler createStorageHandler() {
106
    return new XmlStorageHandler();
107
  }
108
109
  private Category[] createCategories() {
110
    return new Category[]{
111
      Category.of(
112
        get( KEY_DOC ),
113
        Group.of(
114
          get( KEY_DOC_TITLE ),
115
          Setting.of( label( KEY_DOC_TITLE ) ),
116
          Setting.of( title( KEY_DOC_TITLE ),
117
                      stringProperty( KEY_DOC_TITLE ) )
118
        ),
119
        Group.of(
120
          get( KEY_DOC_AUTHOR ),
121
          Setting.of( label( KEY_DOC_AUTHOR ) ),
122
          Setting.of( title( KEY_DOC_AUTHOR ),
123
                      stringProperty( KEY_DOC_AUTHOR ) )
124
        ),
125
        Group.of(
126
          get( KEY_DOC_BYLINE ),
127
          Setting.of( label( KEY_DOC_BYLINE ) ),
128
          Setting.of( title( KEY_DOC_BYLINE ),
129
                      stringProperty( KEY_DOC_BYLINE ) )
130
        ),
131
        Group.of(
132
          get( KEY_DOC_ADDRESS ),
133
          Setting.of( label( KEY_DOC_ADDRESS ) ),
134
          createMultilineSetting( "Address", KEY_DOC_ADDRESS )
135
        ),
136
        Group.of(
137
          get( KEY_DOC_PHONE ),
138
          Setting.of( label( KEY_DOC_PHONE ) ),
139
          Setting.of( title( KEY_DOC_PHONE ),
140
                      stringProperty( KEY_DOC_PHONE ) )
141
        ),
142
        Group.of(
143
          get( KEY_DOC_EMAIL ),
144
          Setting.of( label( KEY_DOC_EMAIL ) ),
145
          Setting.of( title( KEY_DOC_EMAIL ),
146
                      stringProperty( KEY_DOC_EMAIL ) )
147
        ),
148
        Group.of(
149
          get( KEY_DOC_KEYWORDS ),
150
          Setting.of( label( KEY_DOC_KEYWORDS ) ),
151
          Setting.of( title( KEY_DOC_KEYWORDS ),
152
                      stringProperty( KEY_DOC_KEYWORDS ) )
153
        ),
154
        Group.of(
155
          get( KEY_DOC_COPYRIGHT ),
156
          Setting.of( label( KEY_DOC_COPYRIGHT ) ),
157
          Setting.of( title( KEY_DOC_COPYRIGHT ),
158
                      stringProperty( KEY_DOC_COPYRIGHT ) )
159
        ),
160
        Group.of(
161
          get( KEY_DOC_DATE ),
162
          Setting.of( label( KEY_DOC_DATE ) ),
163
          Setting.of( title( KEY_DOC_DATE ),
164
                      stringProperty( KEY_DOC_DATE ) )
165
        )
166
      ),
167
      Category.of(
168
        get( KEY_TYPESET ),
169
        Group.of(
170
          get( KEY_TYPESET_CONTEXT ),
171
          Setting.of( label( KEY_TYPESET_CONTEXT_THEMES_PATH ) ),
172
          Setting.of( title( KEY_TYPESET_CONTEXT_THEMES_PATH ),
173
                      fileProperty( KEY_TYPESET_CONTEXT_THEMES_PATH ), true )
174
        )
175
      ),
101176
      Category.of(
102177
        get( KEY_R ),
...
112187
          get( KEY_R_SCRIPT ),
113188
          Setting.of( label( KEY_R_SCRIPT ) ),
114
          createScriptSetting()
189
          createMultilineSetting( "Script", KEY_R_SCRIPT )
115190
        ),
116191
        Group.of(
...
200275
      ),
201276
      Category.of(
202
        get( KEY_UI_THEME ),
277
        get( KEY_UI_SKIN ),
203278
        Group.of(
204
          get( KEY_UI_THEME_SELECTION ),
205
          Setting.of( label( KEY_UI_THEME_SELECTION ) ),
206
          Setting.of( title( KEY_UI_THEME_SELECTION ),
207
                      themeListProperty(),
208
                      themeProperty( KEY_UI_THEME_SELECTION ) )
279
          get( KEY_UI_SKIN_SELECTION ),
280
          Setting.of( label( KEY_UI_SKIN_SELECTION ) ),
281
          Setting.of( title( KEY_UI_SKIN_SELECTION ),
282
                      skinListProperty(),
283
                      skinProperty( KEY_UI_SKIN_SELECTION ) )
209284
        ),
210285
        Group.of(
211
          get( KEY_UI_THEME_CUSTOM ),
212
          Setting.of( label( KEY_UI_THEME_CUSTOM ) ),
213
          Setting.of( title( KEY_UI_THEME_CUSTOM ),
214
                      fileProperty( KEY_UI_THEME_CUSTOM ), false )
286
          get( KEY_UI_SKIN_CUSTOM ),
287
          Setting.of( label( KEY_UI_SKIN_CUSTOM ) ),
288
          Setting.of( title( KEY_UI_SKIN_CUSTOM ),
289
                      fileProperty( KEY_UI_SKIN_CUSTOM ), false )
215290
        )
216291
      ),
...
224299
                      localeProperty( KEY_LANGUAGE_LOCALE ) )
225300
        )
226
      )
227
    ).instantPersistent( false ).dialogIcon( ICON_DIALOG );
301
      )};
228302
  }
229303
230304
  @SuppressWarnings( "unchecked" )
231
  private Setting<StringField, StringProperty> createScriptSetting() {
232
    final Setting<StringField, StringProperty> scriptSetting =
233
      Setting.of( "Script", stringProperty( KEY_R_SCRIPT ) );
234
    final var field = scriptSetting.getElement();
305
  private Setting<StringField, StringProperty> createMultilineSetting(
306
    final String description, final Key property ) {
307
    final Setting<StringField, StringProperty> setting =
308
      Setting.of( description, stringProperty( property ) );
309
    final var field = setting.getElement();
235310
    field.multiline( true );
236311
237
    return scriptSetting;
312
    return setting;
238313
  }
239314
...
284359
  }
285360
286
  private ObjectProperty<String> themeProperty( final Key key ) {
287
    return mWorkspace.themeProperty( key );
361
  private ObjectProperty<String> skinProperty( final Key key ) {
362
    return mWorkspace.skinProperty( key );
288363
  }
289364
M src/main/java/com/keenwrite/preferences/SimpleFontControl.java
1717
import org.controlsfx.dialog.FontSelectorDialog;
1818
19
import static com.keenwrite.Constants.ICON_DIALOG;
19
import static com.keenwrite.constants.GraphicsConstants.ICON_DIALOG;
2020
import static com.keenwrite.events.StatusEvent.clue;
2121
import static java.lang.System.currentTimeMillis;
A src/main/java/com/keenwrite/preferences/SkinProperty.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preferences;
3
4
import com.keenwrite.constants.Constants;
5
import javafx.beans.property.SimpleObjectProperty;
6
import javafx.collections.ObservableList;
7
8
import java.util.LinkedHashSet;
9
import java.util.Set;
10
11
import static com.keenwrite.constants.Constants.SKIN_DEFAULT;
12
import static com.keenwrite.preferences.Workspace.listProperty;
13
14
/**
15
 * Maintains a list of look and feels that the user may choose.
16
 */
17
public final class SkinProperty extends SimpleObjectProperty<String> {
18
  /**
19
   * Ordered set of available skins.
20
   */
21
  private static final Set<String> sSkins = new LinkedHashSet<>();
22
23
  static {
24
    sSkins.add( "Count Darcula" );
25
    sSkins.add( "Haunted Grey" );
26
    sSkins.add( "Modena Dark" );
27
    sSkins.add( SKIN_DEFAULT );
28
    sSkins.add( "Silver Cavern" );
29
    sSkins.add( "Solarized Dark" );
30
    sSkins.add( "Vampire Byte" );
31
  }
32
33
  public SkinProperty( final String skin ) {
34
    super( skin );
35
  }
36
37
  public static ObservableList<String> skinListProperty() {
38
    return listProperty( sSkins );
39
  }
40
41
  /**
42
   * Returns the given skin name as a sanitized file name, which must map
43
   * to a stylesheet file bundled with the application. This does not include
44
   * the path to the stylesheet. If the given name is not known, the file
45
   * name for {@link Constants#SKIN_DEFAULT} is returned. The extension must
46
   * be added separately.
47
   *
48
   * @param skin The name to convert to a file name.
49
   * @return The given name converted lower case, spaces replaced with
50
   * underscores, without the ".css" extension appended.
51
   */
52
  public static String toFilename( final String skin ) {
53
    return sanitize( skin ).toLowerCase().replace( ' ', '_' );
54
  }
55
56
  /**
57
   * Ensures that the given name is in the list of known skins.
58
   *
59
   * @param skin Validate this name's existence.
60
   * @return The given name, if valid, otherwise the default skin.
61
   */
62
  private static String sanitize( final String skin ) {
63
    return sSkins.contains( skin ) ? skin : SKIN_DEFAULT;
64
  }
65
}
166
D src/main/java/com/keenwrite/preferences/ThemeProperty.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preferences;
3
4
import com.keenwrite.Constants;
5
import javafx.beans.property.SimpleObjectProperty;
6
import javafx.collections.ObservableList;
7
8
import java.util.LinkedHashSet;
9
import java.util.Set;
10
11
import static com.keenwrite.Constants.THEME_DEFAULT;
12
import static com.keenwrite.preferences.Workspace.listProperty;
13
14
/**
15
 * Responsible for providing a list of themes from which the user may pick.
16
 */
17
public final class ThemeProperty extends SimpleObjectProperty<String> {
18
  /**
19
   * Ordered set of available themes.
20
   */
21
  private static final Set<String> sThemes = new LinkedHashSet<>();
22
23
  static {
24
    sThemes.add( "Count Darcula" );
25
    sThemes.add( "Haunted Grey" );
26
    sThemes.add( "Modena Dark" );
27
    sThemes.add( THEME_DEFAULT );
28
    sThemes.add( "Silver Cavern" );
29
    sThemes.add( "Solarized Dark" );
30
    sThemes.add( "Vampire Byte" );
31
  }
32
33
  public ThemeProperty( final String themeName ) {
34
    super( themeName );
35
  }
36
37
  public static ObservableList<String> themeListProperty() {
38
    return listProperty( sThemes );
39
  }
40
41
  /**
42
   * Returns the given theme name as a sanitized file name, which must map
43
   * to a stylesheet file bundled with the application. This does not include
44
   * the path to the stylesheet. If the given theme name cannot be found in
45
   * the known theme list, the file name for {@link Constants#THEME_DEFAULT}
46
   * is returned. The extension must be added separately.
47
   *
48
   * @param theme The name to convert to a file name.
49
   * @return The given theme name converted lower case, spaces replaced with
50
   * underscores, without the ".css" extension appended.
51
   */
52
  public static String toFilename( final String theme ) {
53
    return sanitize( theme ).toLowerCase().replace( ' ', '_' );
54
  }
55
56
  /**
57
   * Ensures that the given theme name is in the list of known themes.
58
   *
59
   * @param theme Validate this theme name's existence.
60
   * @return The given theme name, if valid, otherwise the default theme name.
61
   */
62
  private static String sanitize( final String theme ) {
63
    return sThemes.contains( theme ) ? theme : THEME_DEFAULT;
64
  }
65
}
661
M src/main/java/com/keenwrite/preferences/Workspace.java
22
package com.keenwrite.preferences;
33
4
import com.keenwrite.Constants;
5
import com.keenwrite.sigils.Tokens;
6
import javafx.application.Platform;
7
import javafx.beans.property.*;
8
import javafx.collections.ObservableList;
9
import org.apache.commons.configuration2.XMLConfiguration;
10
import org.apache.commons.configuration2.builder.fluent.Configurations;
11
import org.apache.commons.configuration2.io.FileHandler;
12
13
import java.io.File;
14
import java.util.*;
15
import java.util.function.BiConsumer;
16
import java.util.function.BooleanSupplier;
17
import java.util.function.Consumer;
18
import java.util.function.Function;
19
20
import static com.keenwrite.Bootstrap.APP_TITLE_LOWERCASE;
21
import static com.keenwrite.Constants.*;
22
import static com.keenwrite.Launcher.getVersion;
23
import static com.keenwrite.events.StatusEvent.clue;
24
import static com.keenwrite.preferences.WorkspaceKeys.*;
25
import static java.util.Map.entry;
26
import static javafx.application.Platform.runLater;
27
import static javafx.collections.FXCollections.observableArrayList;
28
import static javafx.collections.FXCollections.observableSet;
29
30
/**
31
 * Responsible for defining behaviours for separate projects. A workspace has
32
 * the ability to save and restore a session, including the window dimensions,
33
 * tab setup, files, and user preferences.
34
 * <p>
35
 * The configuration must support hierarchical (nested) configuration nodes
36
 * to persist the user interface state. Although possible with a flat
37
 * configuration file, it's not nearly as simple or elegant.
38
 * </p>
39
 * <p>
40
 * Neither JSON nor HOCON support schema validation and versioning, which makes
41
 * XML the more suitable configuration file format. Schema validation and
42
 * versioning provide future-proofing and ease of reading and upgrading previous
43
 * versions of the configuration file.
44
 * </p>
45
 * <p>
46
 * Persistent preferences may be set directly by the user or indirectly by
47
 * the act of using the application.
48
 * </p>
49
 * <p>
50
 * Note the following definitions:
51
 * </p>
52
 * <dl>
53
 *   <dt>File</dt>
54
 *   <dd>References a file name (no path), path, or directory.</dd>
55
 *   <dt>Path</dt>
56
 *   <dd>Fully qualified file name, which includes all parent directories.</dd>
57
 *   <dt>Dir</dt>
58
 *   <dd>Directory without a file name ({@link File#isDirectory()} is true)
59
 *   .</dd>
60
 * </dl>
61
 */
62
public final class Workspace {
63
  //@formatter:off
64
  private final Map<Key, Property<?>> VALUES = Map.ofEntries(
65
    entry( KEY_META_VERSION, asStringProperty( getVersion() ) ),
66
    entry( KEY_META_NAME, asStringProperty( "default" ) ),
67
    
68
    entry( KEY_R_SCRIPT, asStringProperty( "" ) ),
69
    entry( KEY_R_DIR, asFileProperty( USER_DIRECTORY ) ),
70
    entry( KEY_R_DELIM_BEGAN, asStringProperty( R_DELIM_BEGAN_DEFAULT ) ),
71
    entry( KEY_R_DELIM_ENDED, asStringProperty( R_DELIM_ENDED_DEFAULT ) ),
72
    
73
    entry( KEY_IMAGES_DIR, asFileProperty( USER_DIRECTORY ) ),
74
    entry( KEY_IMAGES_ORDER, asStringProperty( PERSIST_IMAGES_DEFAULT ) ),
75
    
76
    entry( KEY_DEF_PATH, asFileProperty( DEFINITION_DEFAULT ) ),
77
    entry( KEY_DEF_DELIM_BEGAN, asStringProperty( DEF_DELIM_BEGAN_DEFAULT ) ),
78
    entry( KEY_DEF_DELIM_ENDED, asStringProperty( DEF_DELIM_ENDED_DEFAULT ) ),
79
80
    entry( KEY_UI_RECENT_DIR, asFileProperty( USER_DIRECTORY ) ),
81
    entry( KEY_UI_RECENT_DOCUMENT, asFileProperty( DOCUMENT_DEFAULT ) ),
82
    entry( KEY_UI_RECENT_DEFINITION, asFileProperty( DEFINITION_DEFAULT ) ),
83
    
84
    entry( KEY_UI_FONT_EDITOR_NAME, asStringProperty( FONT_NAME_EDITOR_DEFAULT ) ),
85
    entry( KEY_UI_FONT_EDITOR_SIZE, asDoubleProperty( FONT_SIZE_EDITOR_DEFAULT ) ),
86
    entry( KEY_UI_FONT_PREVIEW_NAME, asStringProperty( FONT_NAME_PREVIEW_DEFAULT ) ),
87
    entry( KEY_UI_FONT_PREVIEW_SIZE, asDoubleProperty( FONT_SIZE_PREVIEW_DEFAULT ) ),
88
    entry( KEY_UI_FONT_PREVIEW_MONO_NAME, asStringProperty( FONT_NAME_PREVIEW_MONO_NAME_DEFAULT ) ),
89
    entry( KEY_UI_FONT_PREVIEW_MONO_SIZE, asDoubleProperty( FONT_SIZE_PREVIEW_MONO_SIZE_DEFAULT ) ),
90
91
    entry( KEY_UI_WINDOW_X, asDoubleProperty( WINDOW_X_DEFAULT ) ),
92
    entry( KEY_UI_WINDOW_Y, asDoubleProperty( WINDOW_Y_DEFAULT ) ),
93
    entry( KEY_UI_WINDOW_W, asDoubleProperty( WINDOW_W_DEFAULT ) ),
94
    entry( KEY_UI_WINDOW_H, asDoubleProperty( WINDOW_H_DEFAULT ) ),
95
    entry( KEY_UI_WINDOW_MAX, asBooleanProperty() ),
96
    entry( KEY_UI_WINDOW_FULL, asBooleanProperty() ),
97
98
    entry( KEY_UI_THEME_SELECTION, asThemeProperty( THEME_DEFAULT ) ),
99
    entry( KEY_UI_THEME_CUSTOM, asFileProperty( THEME_CUSTOM_DEFAULT ) ),
100
101
    entry( KEY_LANGUAGE_LOCALE, asLocaleProperty( LOCALE_DEFAULT ) )
102
    );
103
  //@formatter:on
104
105
  private StringProperty asStringProperty( final String defaultValue ) {
106
    return new SimpleStringProperty( defaultValue );
107
  }
108
109
  private DoubleProperty asDoubleProperty( final double defaultValue ) {
110
    return new SimpleDoubleProperty( defaultValue );
111
  }
112
113
  private BooleanProperty asBooleanProperty() {
114
    return new SimpleBooleanProperty();
115
  }
116
117
  private FileProperty asFileProperty( final File defaultValue ) {
118
    return new FileProperty( defaultValue );
119
  }
120
121
  @SuppressWarnings( "SameParameterValue" )
122
  private ThemeProperty asThemeProperty( final String defaultValue ) {
123
    return new ThemeProperty( defaultValue );
124
  }
125
126
  @SuppressWarnings( "SameParameterValue" )
127
  private LocaleProperty asLocaleProperty( final Locale defaultValue ) {
128
    return new LocaleProperty( defaultValue );
129
  }
130
131
  /**
132
   * Helps instantiate {@link Property} instances for XML configuration items.
133
   */
134
  private static final Map<Class<?>, Function<String, Object>> UNMARSHALL =
135
    Map.of(
136
      LocaleProperty.class, LocaleProperty::parseLocale,
137
      SimpleBooleanProperty.class, Boolean::parseBoolean,
138
      SimpleDoubleProperty.class, Double::parseDouble,
139
      SimpleFloatProperty.class, Float::parseFloat,
140
      FileProperty.class, File::new
141
    );
142
143
  private static final Map<Class<?>, Function<String, Object>> MARSHALL =
144
    Map.of(
145
      LocaleProperty.class, LocaleProperty::toLanguageTag
146
    );
147
148
  private final Map<Key, SetProperty<?>> SETS = Map.ofEntries(
149
    entry(
150
      KEY_UI_FILES_PATH,
151
      new SimpleSetProperty<>( observableSet( new HashSet<>() ) )
152
    )
153
  );
154
155
  /**
156
   * Creates a new {@link Workspace} that will attempt to load a configuration
157
   * file. If the configuration file cannot be loaded, the workspace settings
158
   * will return default values. This allows unit tests to provide an instance
159
   * of {@link Workspace} when necessary without encountering failures.
160
   */
161
  public Workspace() {
162
    load( FILE_PREFERENCES );
163
  }
164
165
  /**
166
   * Creates a new {@link Workspace} that will attempt to load the given
167
   * configuration file.
168
   *
169
   * @param filename The file to load.
170
   */
171
  public Workspace( final String filename ) {
172
    load( filename );
173
  }
174
175
  /**
176
   * Creates an instance of {@link ObservableList} that is based on a
177
   * modifiable observable array list for the given items.
178
   *
179
   * @param items The items to wrap in an observable list.
180
   * @param <E>   The type of items to add to the list.
181
   * @return An observable property that can have its contents modified.
182
   */
183
  public static <E> ObservableList<E> listProperty( final Set<E> items ) {
184
    return new SimpleListProperty<>( observableArrayList( items ) );
185
  }
186
187
  /**
188
   * Returns a value that represents a setting in the application that the user
189
   * may configure, either directly or indirectly.
190
   *
191
   * @param key The reference to the users' preference stored in deference
192
   *            of app reëntrance.
193
   * @return An observable property to be persisted.
194
   */
195
  @SuppressWarnings( "unchecked" )
196
  public <T, U extends Property<T>> U valuesProperty( final Key key ) {
197
    // The type that goes into the map must come out.
198
    return (U) VALUES.get( key );
199
  }
200
201
  /**
202
   * Returns a list of values that represent a setting in the application that
203
   * the user may configure, either directly or indirectly. The property
204
   * returned is backed by a mutable {@link Set}.
205
   *
206
   * @param key The {@link Key} associated with a preference value.
207
   * @return An observable property to be persisted.
208
   */
209
  @SuppressWarnings( "unchecked" )
210
  public <T> SetProperty<T> setsProperty( final Key key ) {
211
    // The type that goes into the map must come out.
212
    return (SetProperty<T>) SETS.get( key );
213
  }
214
215
  /**
216
   * Returns the {@link Boolean} preference value associated with the given
217
   * {@link Key}. The caller must be sure that the given {@link Key} is
218
   * associated with a value that matches the return type.
219
   *
220
   * @param key The {@link Key} associated with a preference value.
221
   * @return The value associated with the given {@link Key}.
222
   */
223
  public boolean toBoolean( final Key key ) {
224
    return (Boolean) valuesProperty( key ).getValue();
225
  }
226
227
  /**
228
   * Returns the {@link Double} preference value associated with the given
229
   * {@link Key}. The caller must be sure that the given {@link Key} is
230
   * associated with a value that matches the return type.
231
   *
232
   * @param key The {@link Key} associated with a preference value.
233
   * @return The value associated with the given {@link Key}.
234
   */
235
  public double toDouble( final Key key ) {
236
    return (Double) valuesProperty( key ).getValue();
237
  }
238
239
  public File toFile( final Key key ) {
240
    return fileProperty( key ).get();
241
  }
242
243
  public String toString( final Key key ) {
244
    return stringProperty( key ).get();
245
  }
246
247
  public Tokens toTokens( final Key began, final Key ended ) {
248
    return new Tokens( stringProperty( began ), stringProperty( ended ) );
249
  }
250
251
  @SuppressWarnings( "SameParameterValue" )
252
  public DoubleProperty doubleProperty( final Key key ) {
253
    return valuesProperty( key );
254
  }
255
256
  /**
257
   * Returns the {@link File} {@link Property} associated with the given
258
   * {@link Key} from the internal list of preference values. The caller
259
   * must be sure that the given {@link Key} is associated with a {@link File}
260
   * {@link Property}.
261
   *
262
   * @param key The {@link Key} associated with a preference value.
263
   * @return The value associated with the given {@link Key}.
264
   */
265
  public ObjectProperty<File> fileProperty( final Key key ) {
266
    return valuesProperty( key );
267
  }
268
269
  public ObjectProperty<String> themeProperty( final Key key ) {
270
    return valuesProperty( key );
271
  }
272
273
  public LocaleProperty localeProperty( final Key key ) {
274
    return valuesProperty( key );
275
  }
276
277
  /**
278
   * Returns the language locale setting for the
279
   * {@link WorkspaceKeys#KEY_LANGUAGE_LOCALE} key.
280
   *
281
   * @return The user's current locale setting.
282
   */
283
  public Locale getLocale() {
284
    return localeProperty( KEY_LANGUAGE_LOCALE ).toLocale();
285
  }
286
287
  public StringProperty stringProperty( final Key key ) {
288
    return valuesProperty( key );
289
  }
290
291
  public void loadValueKeys( final Consumer<Key> consumer ) {
292
    VALUES.keySet().forEach( consumer );
293
  }
294
295
  public void loadSetKeys( final Consumer<Key> consumer ) {
296
    SETS.keySet().forEach( consumer );
297
  }
298
299
  /**
300
   * Calls the given consumer for all single-value keys. For lists, see
301
   * {@link #saveSets(BiConsumer)}.
302
   *
303
   * @param consumer Called to accept each preference key value.
304
   */
305
  public void saveValues( final BiConsumer<Key, Property<?>> consumer ) {
306
    VALUES.forEach( consumer );
307
  }
308
309
  /**
310
   * Calls the given consumer for all multi-value keys. For single items, see
311
   * {@link #saveValues(BiConsumer)}. Callers are responsible for iterating
312
   * over the list of items retrieved through this method.
313
   *
314
   * @param consumer Called to accept each preference key list.
315
   */
316
  public void saveSets( final BiConsumer<Key, SetProperty<?>> consumer ) {
317
    SETS.forEach( consumer );
318
  }
319
320
  /**
321
   * Delegates to {@link #listen(Key, ReadOnlyProperty, BooleanSupplier)},
322
   * providing a value of {@code true} for the {@link BooleanSupplier} to
323
   * indicate the property changes always take effect.
324
   *
325
   * @param key      The value to bind to the internal key property.
326
   * @param property The external property value that sets the internal value.
327
   */
328
  public <T> void listen( final Key key, final ReadOnlyProperty<T> property ) {
329
    listen( key, property, () -> true );
330
  }
331
332
  /**
333
   * Binds a read-only property to a value in the preferences. This allows
334
   * user interface properties to change and the preferences will be
335
   * synchronized automatically.
336
   * <p>
337
   * This calls {@link Platform#runLater(Runnable)} to ensure that all pending
338
   * application window states are finished before assessing whether property
339
   * changes should be applied. Without this, exiting the application while the
340
   * window is maximized would persist the window's maximum dimensions,
341
   * preventing restoration to its prior, non-maximum size.
342
   * </p>
343
   *
344
   * @param key      The value to bind to the internal key property.
345
   * @param property The external property value that sets the internal value.
346
   * @param enabled  Indicates whether property changes should be applied.
347
   */
348
  public <T> void listen(
349
    final Key key,
350
    final ReadOnlyProperty<T> property,
351
    final BooleanSupplier enabled ) {
352
    property.addListener(
353
      ( c, o, n ) -> runLater( () -> {
354
        if( enabled.getAsBoolean() ) {
355
          valuesProperty( key ).setValue( n );
356
        }
357
      } )
358
    );
359
  }
360
361
  /**
362
   * Saves the current workspace.
363
   */
364
  public void save() {
365
    try {
366
      final var config = new XMLConfiguration();
367
368
      // The root config key can only be set for an empty configuration file.
369
      config.setRootElementName( APP_TITLE_LOWERCASE );
370
      valuesProperty( KEY_META_VERSION ).setValue( getVersion() );
371
372
      saveValues( ( key, property ) ->
373
                    config.setProperty( key.toString(), marshall( property ) )
374
      );
375
376
      saveSets( ( key, set ) -> {
377
        final var keyName = key.toString();
378
        set.forEach( ( value ) -> config.addProperty( keyName, value ) );
379
      } );
380
      new FileHandler( config ).save( FILE_PREFERENCES );
381
    } catch( final Exception ex ) {
382
      clue( ex );
383
    }
384
  }
385
386
  /**
387
   * Attempts to load the {@link Constants#FILE_PREFERENCES} configuration file.
388
   * If not found, this will fall back to an empty configuration file, leaving
389
   * the application to fill in default values.
390
   *
391
   * @param filename The file containing user preferences to load.
392
   */
393
  private void load( final String filename ) {
394
    try {
395
      final var config = new Configurations().xml( filename );
396
397
      loadValueKeys( ( key ) -> {
398
        final var configValue = config.getProperty( key.toString() );
399
400
        // Allow other properties to load, even if any are missing.
401
        if( configValue != null ) {
402
          final var propertyValue = valuesProperty( key );
403
          propertyValue.setValue( unmarshall( propertyValue, configValue ) );
404
        }
405
      } );
406
407
      loadSetKeys( ( key ) -> {
408
        final var configSet =
409
          new LinkedHashSet<>( config.getList( key.toString() ) );
410
        final var propertySet = setsProperty( key );
411
        propertySet.setValue( observableSet( configSet ) );
412
      } );
413
    } catch( final Exception ex ) {
414
      clue( ex );
415
    }
416
  }
417
418
  private Object unmarshall(
419
    final Property<?> property, final Object configValue ) {
420
    String setting = configValue.toString();
421
422
    // TODO: #118 - Font upgrade, which can be removed in a few releases.
423
    if( setting.equalsIgnoreCase( "Source Serif Pro" ) ) {
424
      setting = "Source Serif 4";
425
    }
426
427
    return UNMARSHALL
428
      .getOrDefault( property.getClass(), ( value ) -> value )
429
      .apply( setting );
430
  }
431
432
  private Object marshall( final Property<?> property ) {
433
    return property.getValue() == null
434
      ? null
435
      : MARSHALL
436
      .getOrDefault( property.getClass(), ( __ ) -> property.getValue() )
437
      .apply( property.getValue().toString() );
4
import com.keenwrite.constants.Constants;
5
import com.keenwrite.sigils.Tokens;
6
import javafx.application.Platform;
7
import javafx.beans.property.*;
8
import javafx.collections.ObservableList;
9
import org.apache.commons.configuration2.XMLConfiguration;
10
import org.apache.commons.configuration2.builder.fluent.Configurations;
11
import org.apache.commons.configuration2.io.FileHandler;
12
13
import java.io.File;
14
import java.time.Year;
15
import java.time.ZonedDateTime;
16
import java.util.*;
17
import java.util.function.BiConsumer;
18
import java.util.function.BooleanSupplier;
19
import java.util.function.Consumer;
20
import java.util.function.Function;
21
22
import static com.keenwrite.Bootstrap.APP_TITLE_LOWERCASE;
23
import static com.keenwrite.Launcher.getVersion;
24
import static com.keenwrite.constants.Constants.*;
25
import static com.keenwrite.events.StatusEvent.clue;
26
import static com.keenwrite.preferences.WorkspaceKeys.*;
27
import static java.lang.String.valueOf;
28
import static java.lang.System.getProperty;
29
import static java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME;
30
import static java.util.Map.entry;
31
import static javafx.application.Platform.runLater;
32
import static javafx.collections.FXCollections.observableArrayList;
33
import static javafx.collections.FXCollections.observableSet;
34
35
/**
36
 * Responsible for defining behaviours for separate projects. A workspace has
37
 * the ability to save and restore a session, including the window dimensions,
38
 * tab setup, files, and user preferences.
39
 * <p>
40
 * The configuration must support hierarchical (nested) configuration nodes
41
 * to persist the user interface state. Although possible with a flat
42
 * configuration file, it's not nearly as simple or elegant.
43
 * </p>
44
 * <p>
45
 * Neither JSON nor HOCON support schema validation and versioning, which makes
46
 * XML the more suitable configuration file format. Schema validation and
47
 * versioning provide future-proofing and ease of reading and upgrading previous
48
 * versions of the configuration file.
49
 * </p>
50
 * <p>
51
 * Persistent preferences may be set directly by the user or indirectly by
52
 * the act of using the application.
53
 * </p>
54
 * <p>
55
 * Note the following definitions:
56
 * </p>
57
 * <dl>
58
 *   <dt>File</dt>
59
 *   <dd>References a file name (no path), path, or directory.</dd>
60
 *   <dt>Path</dt>
61
 *   <dd>Fully qualified file name, which includes all parent directories.</dd>
62
 *   <dt>Dir</dt>
63
 *   <dd>Directory without a file name ({@link File#isDirectory()} is true)
64
 *   .</dd>
65
 * </dl>
66
 */
67
public final class Workspace {
68
  private final Map<Key, Property<?>> VALUES = Map.ofEntries(
69
    entry( KEY_META_VERSION, asStringProperty( getVersion() ) ),
70
    entry( KEY_META_NAME, asStringProperty( "default" ) ),
71
72
    entry( KEY_DOC_TITLE, asStringProperty( "title" ) ),
73
    entry( KEY_DOC_AUTHOR, asStringProperty( getProperty( "user.name" ) ) ),
74
    entry( KEY_DOC_BYLINE, asStringProperty( getProperty( "user.name" ) ) ),
75
    entry( KEY_DOC_ADDRESS, asStringProperty( "" ) ),
76
    entry( KEY_DOC_PHONE, asStringProperty( "" ) ),
77
    entry( KEY_DOC_EMAIL, asStringProperty( "" ) ),
78
    entry( KEY_DOC_KEYWORDS, asStringProperty( "science, nature" ) ),
79
    entry( KEY_DOC_COPYRIGHT, asStringProperty( getYear() ) ),
80
    entry( KEY_DOC_DATE, asStringProperty( getDate() ) ),
81
82
    entry( KEY_R_SCRIPT, asStringProperty( "" ) ),
83
    entry( KEY_R_DIR, asFileProperty( USER_DIRECTORY ) ),
84
    entry( KEY_R_DELIM_BEGAN, asStringProperty( R_DELIM_BEGAN_DEFAULT ) ),
85
    entry( KEY_R_DELIM_ENDED, asStringProperty( R_DELIM_ENDED_DEFAULT ) ),
86
87
    entry( KEY_IMAGES_DIR, asFileProperty( USER_DIRECTORY ) ),
88
    entry( KEY_IMAGES_ORDER, asStringProperty( PERSIST_IMAGES_DEFAULT ) ),
89
90
    entry( KEY_DEF_PATH, asFileProperty( DEFINITION_DEFAULT ) ),
91
    entry( KEY_DEF_DELIM_BEGAN, asStringProperty( DEF_DELIM_BEGAN_DEFAULT ) ),
92
    entry( KEY_DEF_DELIM_ENDED, asStringProperty( DEF_DELIM_ENDED_DEFAULT ) ),
93
94
    entry( KEY_UI_RECENT_DIR, asFileProperty( USER_DIRECTORY ) ),
95
    entry( KEY_UI_RECENT_DOCUMENT, asFileProperty( DOCUMENT_DEFAULT ) ),
96
    entry( KEY_UI_RECENT_DEFINITION, asFileProperty( DEFINITION_DEFAULT ) ),
97
98
    //@formatter:off
99
    entry( KEY_UI_FONT_EDITOR_NAME, asStringProperty( FONT_NAME_EDITOR_DEFAULT ) ),
100
    entry( KEY_UI_FONT_EDITOR_SIZE, asDoubleProperty( FONT_SIZE_EDITOR_DEFAULT ) ),
101
    entry( KEY_UI_FONT_PREVIEW_NAME, asStringProperty( FONT_NAME_PREVIEW_DEFAULT ) ),
102
    entry( KEY_UI_FONT_PREVIEW_SIZE, asDoubleProperty( FONT_SIZE_PREVIEW_DEFAULT ) ),
103
    entry( KEY_UI_FONT_PREVIEW_MONO_NAME, asStringProperty( FONT_NAME_PREVIEW_MONO_NAME_DEFAULT ) ),
104
    entry( KEY_UI_FONT_PREVIEW_MONO_SIZE, asDoubleProperty( FONT_SIZE_PREVIEW_MONO_SIZE_DEFAULT ) ),
105
106
    entry( KEY_UI_WINDOW_X, asDoubleProperty( WINDOW_X_DEFAULT ) ),
107
    entry( KEY_UI_WINDOW_Y, asDoubleProperty( WINDOW_Y_DEFAULT ) ),
108
    entry( KEY_UI_WINDOW_W, asDoubleProperty( WINDOW_W_DEFAULT ) ),
109
    entry( KEY_UI_WINDOW_H, asDoubleProperty( WINDOW_H_DEFAULT ) ),
110
    entry( KEY_UI_WINDOW_MAX, asBooleanProperty() ),
111
    entry( KEY_UI_WINDOW_FULL, asBooleanProperty() ),
112
113
    entry( KEY_UI_SKIN_SELECTION, asSkinProperty( SKIN_DEFAULT ) ),
114
    entry( KEY_UI_SKIN_CUSTOM, asFileProperty( SKIN_CUSTOM_DEFAULT ) ),
115
116
    entry( KEY_LANGUAGE_LOCALE, asLocaleProperty( LOCALE_DEFAULT ) ),
117
118
    entry( KEY_TYPESET_CONTEXT_THEMES_PATH, asFileProperty( USER_DIRECTORY ) ),
119
    entry( KEY_TYPESET_CONTEXT_THEME_SELECTION, asStringProperty( "boschet" ) )
120
    //@formatter:on
121
  );
122
123
  private StringProperty asStringProperty( final String defaultValue ) {
124
    return new SimpleStringProperty( defaultValue );
125
  }
126
127
  private DoubleProperty asDoubleProperty( final double defaultValue ) {
128
    return new SimpleDoubleProperty( defaultValue );
129
  }
130
131
  private BooleanProperty asBooleanProperty() {
132
    return new SimpleBooleanProperty();
133
  }
134
135
  private FileProperty asFileProperty( final File defaultValue ) {
136
    return new FileProperty( defaultValue );
137
  }
138
139
  @SuppressWarnings( "SameParameterValue" )
140
  private SkinProperty asSkinProperty( final String defaultValue ) {
141
    return new SkinProperty( defaultValue );
142
  }
143
144
  @SuppressWarnings( "SameParameterValue" )
145
  private LocaleProperty asLocaleProperty( final Locale defaultValue ) {
146
    return new LocaleProperty( defaultValue );
147
  }
148
149
  /**
150
   * Helps instantiate {@link Property} instances for XML configuration items.
151
   */
152
  private static final Map<Class<?>, Function<String, Object>> UNMARSHALL =
153
    Map.of(
154
      LocaleProperty.class, LocaleProperty::parseLocale,
155
      SimpleBooleanProperty.class, Boolean::parseBoolean,
156
      SimpleDoubleProperty.class, Double::parseDouble,
157
      SimpleFloatProperty.class, Float::parseFloat,
158
      FileProperty.class, File::new
159
    );
160
161
  private static final Map<Class<?>, Function<String, Object>> MARSHALL =
162
    Map.of(
163
      LocaleProperty.class, LocaleProperty::toLanguageTag
164
    );
165
166
  private final Map<Key, SetProperty<?>> SETS = Map.ofEntries(
167
    entry(
168
      KEY_UI_FILES_PATH,
169
      new SimpleSetProperty<>( observableSet( new HashSet<>() ) )
170
    )
171
  );
172
173
  /**
174
   * Creates a new {@link Workspace} that will attempt to load a configuration
175
   * file. If the configuration file cannot be loaded, the workspace settings
176
   * will return default values. This allows unit tests to provide an instance
177
   * of {@link Workspace} when necessary without encountering failures.
178
   */
179
  public Workspace() {
180
    load( FILE_PREFERENCES );
181
  }
182
183
  /**
184
   * Creates a new {@link Workspace} that will attempt to load the given
185
   * configuration file.
186
   *
187
   * @param filename The file to load.
188
   */
189
  public Workspace( final String filename ) {
190
    load( filename );
191
  }
192
193
  /**
194
   * Creates an instance of {@link ObservableList} that is based on a
195
   * modifiable observable array list for the given items.
196
   *
197
   * @param items The items to wrap in an observable list.
198
   * @param <E>   The type of items to add to the list.
199
   * @return An observable property that can have its contents modified.
200
   */
201
  public static <E> ObservableList<E> listProperty( final Set<E> items ) {
202
    return new SimpleListProperty<>( observableArrayList( items ) );
203
  }
204
205
  /**
206
   * Returns a value that represents a setting in the application that the user
207
   * may configure, either directly or indirectly.
208
   *
209
   * @param key The reference to the users' preference stored in deference
210
   *            of app reëntrance.
211
   * @return An observable property to be persisted.
212
   */
213
  @SuppressWarnings( "unchecked" )
214
  public <T, U extends Property<T>> U valuesProperty( final Key key ) {
215
    assert key != null;
216
    // The type that goes into the map must come out.
217
    return (U) VALUES.get( key );
218
  }
219
220
  /**
221
   * Returns a list of values that represent a setting in the application that
222
   * the user may configure, either directly or indirectly. The property
223
   * returned is backed by a mutable {@link Set}.
224
   *
225
   * @param key The {@link Key} associated with a preference value.
226
   * @return An observable property to be persisted.
227
   */
228
  @SuppressWarnings( "unchecked" )
229
  public <T> SetProperty<T> setsProperty( final Key key ) {
230
    assert key != null;
231
    // The type that goes into the map must come out.
232
    return (SetProperty<T>) SETS.get( key );
233
  }
234
235
  /**
236
   * Returns the {@link Boolean} preference value associated with the given
237
   * {@link Key}. The caller must be sure that the given {@link Key} is
238
   * associated with a value that matches the return type.
239
   *
240
   * @param key The {@link Key} associated with a preference value.
241
   * @return The value associated with the given {@link Key}.
242
   */
243
  public boolean toBoolean( final Key key ) {
244
    assert key != null;
245
    return (Boolean) valuesProperty( key ).getValue();
246
  }
247
248
  /**
249
   * Returns the {@link Double} preference value associated with the given
250
   * {@link Key}. The caller must be sure that the given {@link Key} is
251
   * associated with a value that matches the return type.
252
   *
253
   * @param key The {@link Key} associated with a preference value.
254
   * @return The value associated with the given {@link Key}.
255
   */
256
  public double toDouble( final Key key ) {
257
    assert key != null;
258
    return (Double) valuesProperty( key ).getValue();
259
  }
260
261
  public File toFile( final Key key ) {
262
    assert key != null;
263
    return fileProperty( key ).get();
264
  }
265
266
  public String toString( final Key key ) {
267
    assert key != null;
268
    return stringProperty( key ).get();
269
  }
270
271
  public Tokens toTokens( final Key began, final Key ended ) {
272
    assert began != null;
273
    assert ended != null;
274
    return new Tokens( stringProperty( began ), stringProperty( ended ) );
275
  }
276
277
  @SuppressWarnings( "SameParameterValue" )
278
  public DoubleProperty doubleProperty( final Key key ) {
279
    assert key != null;
280
    return valuesProperty( key );
281
  }
282
283
  /**
284
   * Returns the {@link File} {@link Property} associated with the given
285
   * {@link Key} from the internal list of preference values. The caller
286
   * must be sure that the given {@link Key} is associated with a {@link File}
287
   * {@link Property}.
288
   *
289
   * @param key The {@link Key} associated with a preference value.
290
   * @return The value associated with the given {@link Key}.
291
   */
292
  public ObjectProperty<File> fileProperty( final Key key ) {
293
    assert key != null;
294
    return valuesProperty( key );
295
  }
296
297
  public ObjectProperty<String> skinProperty( final Key key ) {
298
    assert key != null;
299
    return valuesProperty( key );
300
  }
301
302
  public LocaleProperty localeProperty( final Key key ) {
303
    assert key != null;
304
    return valuesProperty( key );
305
  }
306
307
  /**
308
   * Returns the language locale setting for the
309
   * {@link WorkspaceKeys#KEY_LANGUAGE_LOCALE} key.
310
   *
311
   * @return The user's current locale setting.
312
   */
313
  public Locale getLocale() {
314
    return localeProperty( KEY_LANGUAGE_LOCALE ).toLocale();
315
  }
316
317
  public StringProperty stringProperty( final Key key ) {
318
    assert key != null;
319
    return valuesProperty( key );
320
  }
321
322
  public void loadValueKeys( final Consumer<Key> consumer ) {
323
    VALUES.keySet().forEach( consumer );
324
  }
325
326
  public void loadSetKeys( final Consumer<Key> consumer ) {
327
    SETS.keySet().forEach( consumer );
328
  }
329
330
  /**
331
   * Calls the given consumer for all single-value keys. For lists, see
332
   * {@link #saveSets(BiConsumer)}.
333
   *
334
   * @param consumer Called to accept each preference key value.
335
   */
336
  public void saveValues( final BiConsumer<Key, Property<?>> consumer ) {
337
    VALUES.forEach( consumer );
338
  }
339
340
  /**
341
   * Calls the given consumer for all multi-value keys. For single items, see
342
   * {@link #saveValues(BiConsumer)}. Callers are responsible for iterating
343
   * over the list of items retrieved through this method.
344
   *
345
   * @param consumer Called to accept each preference key list.
346
   */
347
  public void saveSets( final BiConsumer<Key, SetProperty<?>> consumer ) {
348
    SETS.forEach( consumer );
349
  }
350
351
  /**
352
   * Delegates to {@link #listen(Key, ReadOnlyProperty, BooleanSupplier)},
353
   * providing a value of {@code true} for the {@link BooleanSupplier} to
354
   * indicate the property changes always take effect.
355
   *
356
   * @param key      The value to bind to the internal key property.
357
   * @param property The external property value that sets the internal value.
358
   */
359
  public <T> void listen( final Key key, final ReadOnlyProperty<T> property ) {
360
    listen( key, property, () -> true );
361
  }
362
363
  /**
364
   * Binds a read-only property to a value in the preferences. This allows
365
   * user interface properties to change and the preferences will be
366
   * synchronized automatically.
367
   * <p>
368
   * This calls {@link Platform#runLater(Runnable)} to ensure that all pending
369
   * application window states are finished before assessing whether property
370
   * changes should be applied. Without this, exiting the application while the
371
   * window is maximized would persist the window's maximum dimensions,
372
   * preventing restoration to its prior, non-maximum size.
373
   * </p>
374
   *
375
   * @param key      The value to bind to the internal key property.
376
   * @param property The external property value that sets the internal value.
377
   * @param enabled  Indicates whether property changes should be applied.
378
   */
379
  public <T> void listen(
380
    final Key key,
381
    final ReadOnlyProperty<T> property,
382
    final BooleanSupplier enabled ) {
383
    property.addListener(
384
      ( c, o, n ) -> runLater( () -> {
385
        if( enabled.getAsBoolean() ) {
386
          valuesProperty( key ).setValue( n );
387
        }
388
      } )
389
    );
390
  }
391
392
  /**
393
   * Saves the current workspace.
394
   */
395
  public void save() {
396
    try {
397
      final var config = new XMLConfiguration();
398
399
      // The root config key can only be set for an empty configuration file.
400
      config.setRootElementName( APP_TITLE_LOWERCASE );
401
      valuesProperty( KEY_META_VERSION ).setValue( getVersion() );
402
403
      saveValues( ( key, property ) ->
404
                    config.setProperty( key.toString(), marshall( property ) )
405
      );
406
407
      saveSets( ( key, set ) -> {
408
        final var keyName = key.toString();
409
        set.forEach( ( value ) -> config.addProperty( keyName, value ) );
410
      } );
411
      new FileHandler( config ).save( FILE_PREFERENCES );
412
    } catch( final Exception ex ) {
413
      clue( ex );
414
    }
415
  }
416
417
  /**
418
   * Attempts to load the {@link Constants#FILE_PREFERENCES} configuration file.
419
   * If not found, this will fall back to an empty configuration file, leaving
420
   * the application to fill in default values.
421
   *
422
   * @param filename The file containing user preferences to load.
423
   */
424
  private void load( final String filename ) {
425
    try {
426
      final var config = new Configurations().xml( filename );
427
428
      loadValueKeys( ( key ) -> {
429
        final var configValue = config.getProperty( key.toString() );
430
431
        // Allow other properties to load, even if any are missing.
432
        if( configValue != null ) {
433
          final var propertyValue = valuesProperty( key );
434
          propertyValue.setValue( unmarshall( propertyValue, configValue ) );
435
        }
436
      } );
437
438
      loadSetKeys( ( key ) -> {
439
        final var configSet =
440
          new LinkedHashSet<>( config.getList( key.toString() ) );
441
        final var propertySet = setsProperty( key );
442
        propertySet.setValue( observableSet( configSet ) );
443
      } );
444
    } catch( final Exception ex ) {
445
      clue( ex );
446
    }
447
  }
448
449
  private Object unmarshall(
450
    final Property<?> property, final Object configValue ) {
451
    final var setting = configValue.toString();
452
453
    return UNMARSHALL
454
      .getOrDefault( property.getClass(), ( value ) -> value )
455
      .apply( setting );
456
  }
457
458
  private Object marshall( final Property<?> property ) {
459
    return property.getValue() == null
460
      ? null
461
      : MARSHALL
462
      .getOrDefault( property.getClass(), ( __ ) -> property.getValue() )
463
      .apply( property.getValue().toString() );
464
  }
465
466
  private String getYear() {
467
    return valueOf( Year.now().getValue() );
468
  }
469
470
  private String getDate() {
471
    return ZonedDateTime.now().format( RFC_1123_DATE_TIME );
438472
  }
439473
}
M src/main/java/com/keenwrite/preferences/WorkspaceKeys.java
1616
  public static final Key KEY_META_VERSION = key( KEY_META, "version" );
1717
18
  public static final Key KEY_DOC = key( KEY_ROOT, "document" );
19
  public static final Key KEY_DOC_TITLE = key( KEY_DOC, "title" );
20
  public static final Key KEY_DOC_AUTHOR = key( KEY_DOC, "author" );
21
  public static final Key KEY_DOC_BYLINE = key( KEY_DOC, "byline" );
22
  public static final Key KEY_DOC_ADDRESS = key( KEY_DOC, "address" );
23
  public static final Key KEY_DOC_PHONE = key( KEY_DOC, "phone" );
24
  public static final Key KEY_DOC_EMAIL = key( KEY_DOC, "email" );
25
  public static final Key KEY_DOC_KEYWORDS = key( KEY_DOC, "keywords" );
26
  public static final Key KEY_DOC_DATE = key( KEY_DOC, "date" );
27
  public static final Key KEY_DOC_COPYRIGHT = key( KEY_DOC, "copyright" );
28
1829
  public static final Key KEY_R = key( KEY_ROOT, "r" );
1930
  public static final Key KEY_R_SCRIPT = key( KEY_R, "script" );
...
6172
  public static final Key KEY_UI_WINDOW_MAX = key( KEY_UI_WINDOW, "maximized" );
6273
  public static final Key KEY_UI_WINDOW_FULL = key( KEY_UI_WINDOW, "full" );
63
64
  public static final Key KEY_UI_THEME = key( KEY_UI, "theme" );
65
  public static final Key KEY_UI_THEME_SELECTION = key( KEY_UI_THEME, "selection" );
66
67
  public static final Key KEY_UI_THEME_CUSTOM = key( KEY_UI_THEME, "custom" );
6874
69
//  public static final Key KEY_UI_THEME_CUSTOM = key( KEY_UI_THEME, "custom" );
70
//  public static final Key KEY_UI_THEME_CUSTOM_FONT = key( KEY_UI_THEME_CUSTOM, "font" );
71
//  public static final Key KEY_UI_THEME_CUSTOM_FONT_SIZE = key( KEY_UI_THEME_CUSTOM_FONT, "size" );
72
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS = key( KEY_UI_THEME_CUSTOM, "colours" );
73
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_BASE = key( KEY_UI_THEME_CUSTOM_COLOURS, "base" );
74
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_BG = key( KEY_UI_THEME_CUSTOM_COLOURS, "background" );
75
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_CONTROLS = key( KEY_UI_THEME_CUSTOM_COLOURS, "controls" );
76
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_ROW1 = key( KEY_UI_THEME_CUSTOM_COLOURS, "row" );
77
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_ROW2 = key( KEY_UI_THEME_CUSTOM_COLOURS, "row" );
78
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_FG = key( KEY_UI_THEME_CUSTOM_COLOURS, "foreground" );
79
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_FG_LIGHT = key( KEY_UI_THEME_CUSTOM_COLOURS_FG, "light" );
80
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_FG_MEDIUM = key( KEY_UI_THEME_CUSTOM_COLOURS_FG, "medium" );
81
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_FG_DARK = key( KEY_UI_THEME_CUSTOM_COLOURS_FG, "dark" );
82
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_ACCENT = key( KEY_UI_THEME_CUSTOM_COLOURS, "accent" );
83
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_UNFOCUSED = key( KEY_UI_THEME_CUSTOM_COLOURS, "unfocused" );
84
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_SCROLLBAR = key( KEY_UI_THEME_CUSTOM_COLOURS, "scrollbar" );
85
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_SCROLLBAR_BUTTON = key( KEY_UI_THEME_CUSTOM_COLOURS_SCROLLBAR, "button" );
86
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_SCROLLBAR_BUTTON_RELEASED = key( KEY_UI_THEME_CUSTOM_COLOURS_SCROLLBAR_BUTTON, "released" );
87
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_SCROLLBAR_BUTTON_PRESSED = key( KEY_UI_THEME_CUSTOM_COLOURS_SCROLLBAR_BUTTON, "pressed" );
88
//  public static final Key KEY_UI_THEME_CUSTOM_COLOURS_SCROLLBAR_BUTTON_HOVER = key( KEY_UI_THEME_CUSTOM_COLOURS_SCROLLBAR_BUTTON, "hover" );
75
  public static final Key KEY_UI_SKIN = key( KEY_UI, "skin" );
76
  public static final Key KEY_UI_SKIN_SELECTION = key( KEY_UI_SKIN, "selection" );
77
  public static final Key KEY_UI_SKIN_CUSTOM = key( KEY_UI_SKIN, "custom" );
8978
9079
  public static final Key KEY_LANGUAGE = key( KEY_ROOT, "language" );
9180
  public static final Key KEY_LANGUAGE_LOCALE = key( KEY_LANGUAGE, "locale" );
81
82
  public static final Key KEY_TYPESET = key( KEY_ROOT, "typeset" );
83
  public static final Key KEY_TYPESET_CONTEXT = key( KEY_TYPESET, "context" );
84
  public static final Key KEY_TYPESET_CONTEXT_THEMES = key( KEY_TYPESET_CONTEXT, "themes" );
85
  public static final Key KEY_TYPESET_CONTEXT_THEMES_PATH = key( KEY_TYPESET_CONTEXT_THEMES, "path" );
86
  public static final Key KEY_TYPESET_CONTEXT_THEME_SELECTION = key( KEY_TYPESET_CONTEXT_THEMES, "selection" );
9287
  //@formatter:on
9388
9489
  /**
95
   *
90
   * Only for constants, do not instantiate.
9691
   */
9792
  private WorkspaceKeys() { }
M src/main/java/com/keenwrite/preview/HtmlPanel.java
1818
import java.net.URI;
1919
20
import static com.keenwrite.events.FileOpenEvent.fireFileOpenEvent;
2120
import static com.keenwrite.events.DocumentChangedEvent.fireDocumentChangedEvent;
21
import static com.keenwrite.events.FileOpenEvent.fireFileOpenEvent;
22
import static com.keenwrite.events.HyperlinkOpenEvent.fireHyperlinkOpenEvent;
2223
import static com.keenwrite.events.StatusEvent.clue;
2324
import static com.keenwrite.util.ProtocolScheme.getProtocol;
24
import static java.awt.Desktop.Action.BROWSE;
25
import static java.awt.Desktop.getDesktop;
2625
import static java.lang.Boolean.FALSE;
2726
import static java.lang.Boolean.TRUE;
...
7170
  private static final class HyperlinkListener extends LinkListener {
7271
    @Override
73
    public void linkClicked( final BasicPanel panel, final String uri ) {
72
    public void linkClicked( final BasicPanel panel, final String link ) {
7473
      try {
75
        switch( getProtocol( uri ) ) {
76
          case HTTP -> {
77
            final var desktop = getDesktop();
74
        final var uri = new URI( link );
7875
79
            if( desktop.isSupported( BROWSE ) ) {
80
              desktop.browse( new URI( uri ) );
81
            }
82
          }
83
          case FILE -> fireFileOpenEvent( new URI( uri ) );
76
        switch( getProtocol( uri ) ) {
77
          case HTTP -> fireHyperlinkOpenEvent( uri );
78
          case FILE -> fireFileOpenEvent( uri );
8479
        }
8580
      } catch( final Exception ex ) {
...
110105
    final var doc = CONVERTER.fromJsoup( soup );
111106
    final Runnable renderDocument = () -> setDocument( doc, baseUri, XNH );
107
    doc.setDocumentURI( baseUri );
112108
113109
    // Access to a Swing component must occur from the Event Dispatch
M src/main/java/com/keenwrite/preview/HtmlPreview.java
55
import com.keenwrite.preferences.LocaleProperty;
66
import com.keenwrite.preferences.Workspace;
7
import javafx.application.Platform;
8
import javafx.beans.property.DoubleProperty;
9
import javafx.beans.property.StringProperty;
10
import javafx.embed.swing.SwingNode;
11
import org.greenrobot.eventbus.Subscribe;
12
import org.xhtmlrenderer.render.Box;
13
import org.xhtmlrenderer.swing.SwingReplacedElementFactory;
14
15
import javax.swing.*;
16
import java.awt.*;
17
import java.net.URL;
18
import java.nio.file.Path;
19
import java.util.Locale;
20
21
import static com.keenwrite.Constants.*;
22
import static com.keenwrite.Messages.get;
23
import static com.keenwrite.events.Bus.register;
24
import static com.keenwrite.events.ScrollLockEvent.fireScrollLockEvent;
25
import static com.keenwrite.events.StatusEvent.clue;
26
import static com.keenwrite.preferences.WorkspaceKeys.*;
27
import static com.keenwrite.ui.fonts.IconFactory.getIconFont;
28
import static java.awt.BorderLayout.*;
29
import static java.lang.Math.max;
30
import static java.lang.String.format;
31
import static java.lang.Thread.sleep;
32
import static javafx.application.Platform.runLater;
33
import static javafx.scene.CacheHint.SPEED;
34
import static javax.swing.SwingUtilities.invokeLater;
35
import static org.controlsfx.glyphfont.FontAwesome.Glyph.LOCK;
36
import static org.controlsfx.glyphfont.FontAwesome.Glyph.UNLOCK_ALT;
37
38
/**
39
 * Responsible for parsing an HTML document.
40
 */
41
public final class HtmlPreview extends SwingNode {
42
43
  /**
44
   * The order is important: Swing factory will replace SVG images with
45
   * a blank image, which will cause the chained factory to cache the image
46
   * and exit. Instead, the SVG must execute first to rasterize the content.
47
   * Consequently, the chained factory must maintain insertion order.
48
   */
49
  private static final ChainedReplacedElementFactory FACTORY
50
    = new ChainedReplacedElementFactory(
51
    new SvgReplacedElementFactory(),
52
    new SwingReplacedElementFactory()
53
  );
54
55
  /**
56
   * Used to populate the {@link #HTML_HEAD} with stylesheet file references.
57
   */
58
  private static final String HTML_STYLESHEET =
59
    "<link rel='stylesheet' href='%s'>";
60
61
  private static final String HTML_BASE =
62
    "<base href='%s'>";
63
64
  /**
65
   * Render CSS using points (pt) not pixels (px) to reduce the chance of
66
   * poor rendering. The {@link #generateHead()} method fills placeholders.
67
   * When the user has not set a locale, only one stylesheet is added to
68
   * the document. In order, the placeholders are as follows:
69
   * <ol>
70
   * <li>%s --- language</li>
71
   * <li>%s --- default stylesheet</li>
72
   * <li>%s --- language-specific stylesheet</li>
73
   * <li>%s --- font family</li>
74
   * <li>%d --- font size (must be pixels, not points due to bug)</li>
75
   * <li>%s --- base href</li>
76
   * </p>
77
   */
78
  private static final String HTML_HEAD =
79
    """
80
      <!doctype html>
81
      <html lang='%s'><head><title> </title><meta charset='utf-8'>
82
      %s%s<style>body{font-family:'%s';font-size: %dpx;}</style>%s</head><body>
83
      """;
84
85
  private static final String HTML_TAIL = "</body></html>";
86
87
  private static final URL HTML_STYLE_PREVIEW = toUrl( STYLESHEET_PREVIEW );
88
89
  /**
90
   * Reusing this buffer prevents repetitious memory re-allocations.
91
   */
92
  private final StringBuilder mDocument = new StringBuilder( 65536 );
93
94
95
  private HtmlPanel mView;
96
  private JScrollPane mScrollPane;
97
  private String mBaseUriPath = "";
98
  private String mHead = "";
99
100
  private boolean mLocked;
101
  private final JButton mScrollLockButton = new JButton();
102
103
  private final Workspace mWorkspace;
104
105
  /**
106
   * Creates a new preview pane that can scroll to the caret position within the
107
   * document.
108
   *
109
   * @param workspace Contains locale and font size information.
110
   */
111
  public HtmlPreview( final Workspace workspace ) {
112
    mWorkspace = workspace;
113
114
    // Attempts to prevent a flash of black un-styled content upon load.
115
    setStyle( "-fx-background-color: white;" );
116
117
    invokeLater( () -> {
118
      mHead = generateHead();
119
      mView = new HtmlPanel();
120
      mScrollPane = new JScrollPane( mView );
121
      final var verticalBar = mScrollPane.getVerticalScrollBar();
122
      final var verticalPanel = new JPanel( new BorderLayout() );
123
124
      mScrollLockButton.setFont( getIconFont( 14 ) );
125
      mScrollLockButton.setText( getLockText( mLocked ) );
126
      mScrollLockButton.setMargin( new Insets( 1, 0, 0, 0 ) );
127
      mScrollLockButton.addActionListener( e -> fireScrollLockEvent( !mLocked ) );
128
129
      verticalPanel.add( verticalBar, CENTER );
130
      verticalPanel.add( mScrollLockButton, PAGE_END );
131
132
      final var wrapper = new JPanel( new BorderLayout() );
133
      wrapper.add( mScrollPane, CENTER );
134
      wrapper.add( verticalPanel, LINE_END );
135
136
      // Enabling the cache attempts to prevent black flashes when resizing.
137
      setCache( true );
138
      setCacheHint( SPEED );
139
      setContent( wrapper );
140
141
      final var context = mView.getSharedContext();
142
      final var textRenderer = context.getTextRenderer();
143
      context.setReplacedElementFactory( FACTORY );
144
      textRenderer.setSmoothingThreshold( 0 );
145
146
      localeProperty().addListener( ( c, o, n ) -> rerender() );
147
      fontFamilyProperty().addListener( ( c, o, n ) -> rerender() );
148
      fontSizeProperty().addListener( ( c, o, n ) -> rerender() );
149
    } );
150
151
    register( this );
152
  }
153
154
  @Subscribe
155
  public void handle( final ScrollLockEvent event ) {
156
    mLocked = event.isLocked();
157
    invokeLater( () -> mScrollLockButton.setText( getLockText( mLocked ) ) );
158
  }
159
160
  /**
161
   * Updates the internal HTML source shown in the preview pane.
162
   *
163
   * @param html The new HTML document to display.
164
   */
165
  public void render( final String html ) {
166
    mView.render( decorate( html ), getBaseUri() );
167
  }
168
169
  /**
170
   * Clears the caches then re-renders the content.
171
   */
172
  public void refresh() {
173
    FACTORY.clearCache();
174
    rerender();
175
  }
176
177
  /**
178
   * Recomputes the HTML head then renders the document.
179
   */
180
  private void rerender() {
181
    mHead = generateHead();
182
    render( mDocument.toString() );
183
  }
184
185
  /**
186
   * Attaches the HTML head prefix and HTML tail suffix to the given HTML
187
   * string.
188
   *
189
   * @param html The HTML to adorn with opening and closing tags.
190
   * @return A complete HTML document, ready for rendering.
191
   */
192
  private String decorate( final String html ) {
193
    mDocument.setLength( 0 );
194
    mDocument.append( html );
195
196
    // Head and tail must be separate from document due to re-rendering.
197
    return mHead + mDocument.toString() + HTML_TAIL;
198
  }
199
200
  /**
201
   * Called when settings are changed that affect the HTML document preamble.
202
   * This is a minor performance optimization to avoid generating the head
203
   * each time that the document itself changes.
204
   *
205
   * @return A new doctype and HTML {@code head} element.
206
   */
207
  private String generateHead() {
208
    final var locale = getLocale();
209
    final var url = toUrl( locale );
210
    final var base = getBaseUri();
211
212
    // Point sizes are converted to pixels because of a rendering bug.
213
    return format(
214
      HTML_HEAD,
215
      locale.getLanguage(),
216
      format( HTML_STYLESHEET, HTML_STYLE_PREVIEW ),
217
      url == null ? "" : format( HTML_STYLESHEET, url ),
218
      getFontFamily(),
219
      toPixels( getFontSize() ),
220
      base.isBlank() ? "" : format( HTML_BASE, base )
221
    );
222
  }
223
224
  /**
225
   * Clears the preview pane by rendering an empty string.
226
   */
227
  public void clear() {
228
    render( "" );
229
  }
230
231
  /**
232
   * Sets the base URI to the containing directory the file being edited.
233
   *
234
   * @param path The path to the file being edited.
235
   */
236
  public void setBaseUri( final Path path ) {
237
    final var parent = path.getParent();
238
    mBaseUriPath = parent == null ? "" : parent.toUri().toString();
239
  }
240
241
  /**
242
   * Scrolls to the closest element matching the given identifier without
243
   * waiting for the document to be ready.
244
   *
245
   * @param id Scroll the preview pane to this unique paragraph identifier.
246
   */
247
  public void scrollTo( final String id ) {
248
    if( mLocked ) {
249
      return;
250
    }
251
252
    final Runnable scrollToBox = () -> {
253
      int iter = 0;
254
      Box box = null;
255
256
      while( iter++ < 3 && ((box = mView.getBoxById( id )) == null) ) {
257
        try {
258
          sleep( 10 );
259
        } catch( final Exception ex ) {
260
          clue( ex );
261
        }
262
      }
263
264
      scrollTo( box );
265
    };
266
267
    if( Platform.isFxApplicationThread() ) {
268
      scrollToBox.run();
269
    }
270
    else {
271
      runLater( scrollToBox );
272
    }
273
  }
274
275
  /**
276
   * Scrolls to the location specified by the {@link Box} that corresponds
277
   * to a point somewhere in the preview pane. If there is no caret, then
278
   * this will not change the scroll position. Changing the scroll position
279
   * to the top if the {@link Box} instance is {@code null} will result in
280
   * jumping around a lot and inconsistent synchronization issues.
281
   *
282
   * @param box The rectangular region containing the caret, or {@code null}
283
   *            if the HTML does not have a caret.
284
   */
285
  private void scrollTo( final Box box ) {
286
    if( box != null ) {
287
      scrollTo( createPoint( box ) );
288
    }
289
  }
290
291
  private void scrollTo( final Point point ) {
292
    invokeLater( () -> {
293
      mView.scrollTo( point );
294
      getScrollPane().repaint();
295
    } );
296
  }
297
298
  /**
299
   * Creates a {@link Point} to use as a reference for scrolling to the area
300
   * described by the given {@link Box}. The {@link Box} coordinates are used
301
   * to populate the {@link Point}'s location, with minor adjustments for
302
   * vertical centering.
303
   *
304
   * @param box The {@link Box} that represents a scrolling anchor reference.
305
   * @return A coordinate suitable for scrolling to.
306
   */
307
  private Point createPoint( final Box box ) {
308
    assert box != null;
309
310
    // Scroll back up by half the height of the scroll bar to keep the typing
311
    // area within the view port. Otherwise the view port will have jumped too
312
    // high up and the most recently typed letters won't be visible.
313
    int y = max( box.getAbsY() - getVerticalScrollBarHeight() / 2, 0 );
314
    int x = box.getAbsX();
315
316
    if( !box.getStyle().isInline() ) {
317
      final var margin = box.getMargin( mView.getLayoutContext() );
318
      y += margin.top();
319
      x += margin.left();
320
    }
321
322
    return new Point( x, y );
323
  }
324
325
  private String getBaseUri() {
326
    return mBaseUriPath;
327
  }
328
329
  private JScrollPane getScrollPane() {
330
    return mScrollPane;
331
  }
332
333
  public JScrollBar getVerticalScrollBar() {
334
    return getScrollPane().getVerticalScrollBar();
335
  }
336
337
  private int getVerticalScrollBarHeight() {
338
    return getVerticalScrollBar().getHeight();
339
  }
340
341
  /**
342
   * Returns the ISO 639 alpha-2 or alpha-3 language code followed by a hyphen
343
   * followed by the ISO 15924 alpha-4 script code, followed by an ISO 3166
344
   * alpha-2 country code or UN M.49 numeric-3 area code. For example, this
345
   * could return "en-Latn-CA" for Canadian English written in the Latin
346
   * character set.
347
   *
348
   * @return Unique identifier for language and country.
349
   */
350
  private static URL toUrl( final Locale locale ) {
351
    return toUrl(
352
      get(
353
        sSettings.getSetting( STYLESHEET_PREVIEW_LOCALE, "" ),
354
        locale.getLanguage(),
355
        locale.getScript(),
356
        locale.getCountry()
357
      )
358
    );
359
  }
360
361
  private static URL toUrl( final String path ) {
362
    return HtmlPreview.class.getResource( path );
363
  }
364
365
  private Locale getLocale() {
366
    return localeProperty().toLocale();
367
  }
368
369
  private LocaleProperty localeProperty() {
370
    return mWorkspace.localeProperty( KEY_LANGUAGE_LOCALE );
371
  }
372
373
  private String getFontFamily() {
374
    return fontFamilyProperty().get();
375
  }
376
377
  private StringProperty fontFamilyProperty() {
378
    return mWorkspace.stringProperty( KEY_UI_FONT_PREVIEW_NAME );
379
  }
380
381
  private double getFontSize() {
382
    return fontSizeProperty().get();
383
  }
384
385
  /**
386
   * Returns the font size in points.
387
   *
388
   * @return The user-defined font size (in pt).
389
   */
390
  private DoubleProperty fontSizeProperty() {
391
    return mWorkspace.doubleProperty( KEY_UI_FONT_PREVIEW_SIZE );
392
  }
393
394
  private String getLockText( final boolean locked ) {
395
    return Character.toString( (locked ? LOCK : UNLOCK_ALT).getChar() );
7
import javafx.beans.property.DoubleProperty;
8
import javafx.beans.property.StringProperty;
9
import javafx.embed.swing.SwingNode;
10
import org.greenrobot.eventbus.Subscribe;
11
import org.xhtmlrenderer.render.Box;
12
import org.xhtmlrenderer.swing.SwingReplacedElementFactory;
13
14
import javax.swing.*;
15
import java.awt.*;
16
import java.net.URL;
17
import java.nio.file.Path;
18
import java.util.Locale;
19
20
import static com.keenwrite.Messages.get;
21
import static com.keenwrite.constants.Constants.*;
22
import static com.keenwrite.events.Bus.register;
23
import static com.keenwrite.events.ScrollLockEvent.fireScrollLockEvent;
24
import static com.keenwrite.events.StatusEvent.clue;
25
import static com.keenwrite.preferences.WorkspaceKeys.*;
26
import static com.keenwrite.ui.fonts.IconFactory.getIconFont;
27
import static java.awt.BorderLayout.*;
28
import static java.awt.event.KeyEvent.*;
29
import static java.lang.Math.max;
30
import static java.lang.String.format;
31
import static java.lang.Thread.sleep;
32
import static javafx.scene.CacheHint.SPEED;
33
import static javax.swing.JComponent.WHEN_IN_FOCUSED_WINDOW;
34
import static javax.swing.KeyStroke.getKeyStroke;
35
import static javax.swing.SwingUtilities.invokeLater;
36
import static org.controlsfx.glyphfont.FontAwesome.Glyph.LOCK;
37
import static org.controlsfx.glyphfont.FontAwesome.Glyph.UNLOCK_ALT;
38
39
/**
40
 * Responsible for parsing an HTML document.
41
 */
42
public final class HtmlPreview extends SwingNode {
43
44
  /**
45
   * The order is important: Swing factory will replace SVG images with
46
   * a blank image, which will cause the chained factory to cache the image
47
   * and exit. Instead, the SVG must execute first to rasterize the content.
48
   * Consequently, the chained factory must maintain insertion order.
49
   */
50
  private static final ChainedReplacedElementFactory FACTORY
51
    = new ChainedReplacedElementFactory(
52
    new SvgReplacedElementFactory(),
53
    new SwingReplacedElementFactory()
54
  );
55
56
  /**
57
   * Used to populate the {@link #HTML_HEAD} with stylesheet file references.
58
   */
59
  private static final String HTML_STYLESHEET =
60
    "<link rel='stylesheet' href='%s'>";
61
62
  private static final String HTML_BASE =
63
    "<base href='%s'>";
64
65
  /**
66
   * Render CSS using points (pt) not pixels (px) to reduce the chance of
67
   * poor rendering. The {@link #generateHead()} method fills placeholders.
68
   * When the user has not set a locale, only one stylesheet is added to
69
   * the document. In order, the placeholders are as follows:
70
   * <ol>
71
   * <li>%s --- language</li>
72
   * <li>%s --- default stylesheet</li>
73
   * <li>%s --- language-specific stylesheet</li>
74
   * <li>%s --- font family</li>
75
   * <li>%d --- font size (must be pixels, not points due to bug)</li>
76
   * <li>%s --- base href</li>
77
   * </p>
78
   */
79
  private static final String HTML_HEAD =
80
    """
81
      <!doctype html>
82
      <html lang='%s'><head><title> </title><meta charset='utf-8'>
83
      %s%s<style>body{font-family:'%s';font-size: %dpx;}</style>%s</head><body>
84
      """;
85
86
  private static final String HTML_TAIL = "</body></html>";
87
88
  private static final URL HTML_STYLE_PREVIEW = toUrl( STYLESHEET_PREVIEW );
89
90
  /**
91
   * Reusing this buffer prevents repetitious memory re-allocations.
92
   */
93
  private final StringBuilder mDocument = new StringBuilder( 65536 );
94
95
  private HtmlPanel mView;
96
  private JScrollPane mScrollPane;
97
  private String mBaseUriPath = "";
98
  private String mHead = "";
99
100
  private volatile boolean mLocked;
101
  private final JButton mScrollLockButton = new JButton();
102
103
  private final Workspace mWorkspace;
104
105
  /**
106
   * Creates a new preview pane that can scroll to the caret position within the
107
   * document.
108
   *
109
   * @param workspace Contains locale and font size information.
110
   */
111
  public HtmlPreview( final Workspace workspace ) {
112
    mWorkspace = workspace;
113
114
    // Attempts to prevent a flash of black un-styled content upon load.
115
    setStyle( "-fx-background-color: white;" );
116
117
    invokeLater( () -> {
118
      mHead = generateHead();
119
      mView = new HtmlPanel();
120
      mScrollPane = new JScrollPane( mView );
121
      final var verticalBar = mScrollPane.getVerticalScrollBar();
122
      final var verticalPanel = new JPanel( new BorderLayout() );
123
124
      final var map = verticalBar.getInputMap( WHEN_IN_FOCUSED_WINDOW );
125
      addKeyboardEvents( map );
126
127
      mScrollLockButton.setFont( getIconFont( 14 ) );
128
      mScrollLockButton.setText( getLockText( mLocked ) );
129
      mScrollLockButton.setMargin( new Insets( 1, 0, 0, 0 ) );
130
      mScrollLockButton.addActionListener( e -> fireScrollLockEvent( !mLocked ) );
131
132
      verticalPanel.add( verticalBar, CENTER );
133
      verticalPanel.add( mScrollLockButton, PAGE_END );
134
135
      final var wrapper = new JPanel( new BorderLayout() );
136
      wrapper.add( mScrollPane, CENTER );
137
      wrapper.add( verticalPanel, LINE_END );
138
139
      // Enabling the cache attempts to prevent black flashes when resizing.
140
      setCache( true );
141
      setCacheHint( SPEED );
142
      setContent( wrapper );
143
144
      final var context = mView.getSharedContext();
145
      final var textRenderer = context.getTextRenderer();
146
      context.setReplacedElementFactory( FACTORY );
147
      textRenderer.setSmoothingThreshold( 0 );
148
149
      localeProperty().addListener( ( c, o, n ) -> rerender() );
150
      fontFamilyProperty().addListener( ( c, o, n ) -> rerender() );
151
      fontSizeProperty().addListener( ( c, o, n ) -> rerender() );
152
    } );
153
154
    register( this );
155
  }
156
157
  @Subscribe
158
  public void handle( final ScrollLockEvent event ) {
159
    mLocked = event.isLocked();
160
    invokeLater( () -> mScrollLockButton.setText( getLockText( mLocked ) ) );
161
  }
162
163
  /**
164
   * Updates the internal HTML source shown in the preview pane.
165
   *
166
   * @param html The new HTML document to display.
167
   */
168
  public void render( final String html ) {
169
    mView.render( decorate( html ), getBaseUri() );
170
  }
171
172
  /**
173
   * Clears the caches then re-renders the content.
174
   */
175
  public void refresh() {
176
    FACTORY.clearCache();
177
    rerender();
178
  }
179
180
  /**
181
   * Recomputes the HTML head then renders the document.
182
   */
183
  private void rerender() {
184
    mHead = generateHead();
185
    render( mDocument.toString() );
186
  }
187
188
  /**
189
   * Attaches the HTML head prefix and HTML tail suffix to the given HTML
190
   * string.
191
   *
192
   * @param html The HTML to adorn with opening and closing tags.
193
   * @return A complete HTML document, ready for rendering.
194
   */
195
  private String decorate( final String html ) {
196
    mDocument.setLength( 0 );
197
    mDocument.append( html );
198
199
    // Head and tail must be separate from document due to re-rendering.
200
    return mHead + mDocument + HTML_TAIL;
201
  }
202
203
  /**
204
   * Called when settings are changed that affect the HTML document preamble.
205
   * This is a minor performance optimization to avoid generating the head
206
   * each time that the document itself changes.
207
   *
208
   * @return A new doctype and HTML {@code head} element.
209
   */
210
  private String generateHead() {
211
    final var locale = getLocale();
212
    final var url = toUrl( locale );
213
    final var base = getBaseUri();
214
215
    // Point sizes are converted to pixels because of a rendering bug.
216
    return format(
217
      HTML_HEAD,
218
      locale.getLanguage(),
219
      format( HTML_STYLESHEET, HTML_STYLE_PREVIEW ),
220
      url == null ? "" : format( HTML_STYLESHEET, url ),
221
      getFontFamily(),
222
      toPixels( getFontSize() ),
223
      base.isBlank() ? "" : format( HTML_BASE, base )
224
    );
225
  }
226
227
  /**
228
   * Clears the preview pane by rendering an empty string.
229
   */
230
  public void clear() {
231
    render( "" );
232
  }
233
234
  /**
235
   * Sets the base URI to the containing directory the file being edited.
236
   *
237
   * @param path The path to the file being edited.
238
   */
239
  public void setBaseUri( final Path path ) {
240
    final var parent = path.getParent();
241
    mBaseUriPath = parent == null ? "" : parent.toUri().toString();
242
  }
243
244
  /**
245
   * Scrolls to the closest element matching the given identifier without
246
   * waiting for the document to be ready.
247
   *
248
   * @param id Scroll the preview pane to this unique paragraph identifier.
249
   */
250
  public void scrollTo( final String id ) {
251
    if( mLocked ) {
252
      return;
253
    }
254
255
    invokeLater( () -> {
256
      int iter = 0;
257
      Box box = null;
258
259
      while( iter++ < 3 && ((box = mView.getBoxById( id )) == null) ) {
260
        try {
261
          sleep( 10 );
262
        } catch( final Exception ex ) {
263
          clue( ex );
264
        }
265
      }
266
267
      scrollTo( box );
268
    } );
269
  }
270
271
  /**
272
   * Scrolls to the location specified by the {@link Box} that corresponds
273
   * to a point somewhere in the preview pane. If there is no caret, then
274
   * this will not change the scroll position. Changing the scroll position
275
   * to the top if the {@link Box} instance is {@code null} will result in
276
   * jumping around a lot and inconsistent synchronization issues.
277
   *
278
   * @param box The rectangular region containing the caret, or {@code null}
279
   *            if the HTML does not have a caret.
280
   */
281
  private void scrollTo( final Box box ) {
282
    if( box != null ) {
283
      invokeLater( () -> {
284
        mView.scrollTo( createPoint( box ) );
285
        getScrollPane().repaint();
286
      } );
287
    }
288
  }
289
290
  /**
291
   * Creates a {@link Point} to use as a reference for scrolling to the area
292
   * described by the given {@link Box}. The {@link Box} coordinates are used
293
   * to populate the {@link Point}'s location, with minor adjustments for
294
   * vertical centering.
295
   *
296
   * @param box The {@link Box} that represents a scrolling anchor reference.
297
   * @return A coordinate suitable for scrolling to.
298
   */
299
  private Point createPoint( final Box box ) {
300
    assert box != null;
301
302
    // Scroll back up by half the height of the scroll bar to keep the typing
303
    // area within the view port. Otherwise the view port will have jumped too
304
    // high up and the most recently typed letters won't be visible.
305
    int y = max( box.getAbsY() - getVerticalScrollBarHeight() / 2, 0 );
306
    int x = box.getAbsX();
307
308
    if( !box.getStyle().isInline() ) {
309
      final var margin = box.getMargin( mView.getLayoutContext() );
310
      y += margin.top();
311
      x += margin.left();
312
    }
313
314
    return new Point( x, y );
315
  }
316
317
  private String getBaseUri() {
318
    return mBaseUriPath;
319
  }
320
321
  private JScrollPane getScrollPane() {
322
    return mScrollPane;
323
  }
324
325
  public JScrollBar getVerticalScrollBar() {
326
    return getScrollPane().getVerticalScrollBar();
327
  }
328
329
  private int getVerticalScrollBarHeight() {
330
    return getVerticalScrollBar().getHeight();
331
  }
332
333
  /**
334
   * Returns the ISO 639 alpha-2 or alpha-3 language code followed by a hyphen
335
   * followed by the ISO 15924 alpha-4 script code, followed by an ISO 3166
336
   * alpha-2 country code or UN M.49 numeric-3 area code. For example, this
337
   * could return "en-Latn-CA" for Canadian English written in the Latin
338
   * character set.
339
   *
340
   * @return Unique identifier for language and country.
341
   */
342
  private static URL toUrl( final Locale locale ) {
343
    return toUrl(
344
      get(
345
        sSettings.getSetting( STYLESHEET_PREVIEW_LOCALE, "" ),
346
        locale.getLanguage(),
347
        locale.getScript(),
348
        locale.getCountry()
349
      )
350
    );
351
  }
352
353
  private static URL toUrl( final String path ) {
354
    return HtmlPreview.class.getResource( path );
355
  }
356
357
  private Locale getLocale() {
358
    return localeProperty().toLocale();
359
  }
360
361
  private LocaleProperty localeProperty() {
362
    return mWorkspace.localeProperty( KEY_LANGUAGE_LOCALE );
363
  }
364
365
  private String getFontFamily() {
366
    return fontFamilyProperty().get();
367
  }
368
369
  private StringProperty fontFamilyProperty() {
370
    return mWorkspace.stringProperty( KEY_UI_FONT_PREVIEW_NAME );
371
  }
372
373
  private double getFontSize() {
374
    return fontSizeProperty().get();
375
  }
376
377
  /**
378
   * Returns the font size in points.
379
   *
380
   * @return The user-defined font size (in pt).
381
   */
382
  private DoubleProperty fontSizeProperty() {
383
    return mWorkspace.doubleProperty( KEY_UI_FONT_PREVIEW_SIZE );
384
  }
385
386
  private String getLockText( final boolean locked ) {
387
    return Character.toString( (locked ? LOCK : UNLOCK_ALT).getChar() );
388
  }
389
390
  /**
391
   * Maps keyboard events to scrollbar commands so that users may control
392
   * the {@link HtmlPreview} panel using the keyboard.
393
   *
394
   * @param map The map to update with keyboard events.
395
   */
396
  private void addKeyboardEvents( final InputMap map ) {
397
    map.put( getKeyStroke( VK_DOWN, 0 ), "positiveUnitIncrement" );
398
    map.put( getKeyStroke( VK_UP, 0 ), "negativeUnitIncrement" );
399
    map.put( getKeyStroke( VK_PAGE_DOWN, 0 ), "positiveBlockIncrement" );
400
    map.put( getKeyStroke( VK_PAGE_UP, 0 ), "negativeBlockIncrement" );
401
    map.put( getKeyStroke( VK_HOME, 0 ), "minScroll" );
402
    map.put( getKeyStroke( VK_END, 0 ), "maxScroll" );
396403
  }
397404
}
D src/main/java/com/keenwrite/preview/RenderingSettings.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.preview;
3
4
import java.util.HashMap;
5
import java.util.Map;
6
7
import static java.awt.RenderingHints.*;
8
import static java.awt.Toolkit.getDefaultToolkit;
9
10
/**
11
 * Responsible for supplying consistent rendering hints throughout the
12
 * application, such as image rendering for {@link SvgRasterizer}.
13
 */
14
@SuppressWarnings("rawtypes")
15
public final class RenderingSettings {
16
17
  /**
18
   * Default hints for high-quality rendering that may be changed by
19
   * the system's rendering hints.
20
   */
21
  private static final Map<Object, Object> DEFAULT_HINTS = Map.of(
22
      KEY_ANTIALIASING,
23
      VALUE_ANTIALIAS_ON,
24
      KEY_ALPHA_INTERPOLATION,
25
      VALUE_ALPHA_INTERPOLATION_QUALITY,
26
      KEY_COLOR_RENDERING,
27
      VALUE_COLOR_RENDER_QUALITY,
28
      KEY_DITHERING,
29
      VALUE_DITHER_DISABLE,
30
      KEY_FRACTIONALMETRICS,
31
      VALUE_FRACTIONALMETRICS_ON,
32
      KEY_INTERPOLATION,
33
      VALUE_INTERPOLATION_BICUBIC,
34
      KEY_RENDERING,
35
      VALUE_RENDER_QUALITY,
36
      KEY_STROKE_CONTROL,
37
      VALUE_STROKE_PURE,
38
      KEY_TEXT_ANTIALIASING,
39
      VALUE_TEXT_ANTIALIAS_ON
40
  );
41
42
  /**
43
   * Shared hints for high-quality rendering.
44
   */
45
  public static final Map<Object, Object> RENDERING_HINTS = new HashMap<>(
46
      DEFAULT_HINTS
47
  );
48
49
  static {
50
    final var toolkit = getDefaultToolkit();
51
    final var hints = toolkit.getDesktopProperty( "awt.font.desktophints" );
52
53
    if( hints instanceof Map ) {
54
      final var map = (Map) hints;
55
      for( final var key : map.keySet() ) {
56
        final var hint = map.get( key );
57
        RENDERING_HINTS.put( key, hint );
58
      }
59
    }
60
  }
61
62
  /**
63
   * Prevent instantiation as per Joshua Bloch's recommendation.
64
   */
65
  private RenderingSettings() {
66
  }
67
}
681
M src/main/java/com/keenwrite/preview/SvgRasterizer.java
22
package com.keenwrite.preview;
33
4
import javafx.scene.image.ImageView;
54
import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
5
import org.apache.batik.css.parser.Parser;
66
import org.apache.batik.gvt.renderer.ImageRenderer;
77
import org.apache.batik.transcoder.TranscoderException;
88
import org.apache.batik.transcoder.TranscoderInput;
99
import org.apache.batik.transcoder.TranscoderOutput;
1010
import org.apache.batik.transcoder.image.ImageTranscoder;
11
import org.apache.batik.util.XMLResourceDescriptor;
12
import org.w3c.css.sac.CSSException;
1113
import org.w3c.dom.Document;
1214
import org.w3c.dom.Element;
1315
1416
import javax.xml.transform.Transformer;
1517
import javax.xml.transform.TransformerFactory;
1618
import javax.xml.transform.dom.DOMSource;
1719
import javax.xml.transform.stream.StreamResult;
1820
import java.awt.*;
1921
import java.awt.image.BufferedImage;
20
import java.io.File;
21
import java.io.InputStream;
22
import java.io.StringReader;
23
import java.io.StringWriter;
22
import java.io.*;
2423
import java.net.URI;
2524
import java.nio.file.Path;
2625
import java.text.NumberFormat;
26
import java.text.ParseException;
27
import java.util.HashMap;
28
import java.util.Map;
2729
2830
import static com.keenwrite.events.StatusEvent.clue;
29
import static com.keenwrite.preview.RenderingSettings.RENDERING_HINTS;
31
import static java.awt.RenderingHints.*;
32
import static java.awt.Toolkit.getDefaultToolkit;
3033
import static java.awt.image.BufferedImage.TYPE_INT_RGB;
3134
import static java.nio.charset.StandardCharsets.UTF_8;
3235
import static java.text.NumberFormat.getIntegerInstance;
3336
import static javax.xml.transform.OutputKeys.*;
3437
import static org.apache.batik.transcoder.SVGAbstractTranscoder.KEY_WIDTH;
38
import static org.apache.batik.transcoder.image.ImageTranscoder.KEY_PIXEL_UNIT_TO_MILLIMETER;
3539
import static org.apache.batik.util.XMLResourceDescriptor.getXMLParserClassName;
3640
3741
/**
3842
 * Responsible for converting SVG images into rasterized PNG images.
3943
 */
44
@SuppressWarnings( "rawtypes" )
4045
public final class SvgRasterizer {
46
  /**
47
   * Default hints for high-quality rendering that may be changed by
48
   * the system's rendering hints.
49
   */
50
  private static final Map<Object, Object> DEFAULT_HINTS = Map.of(
51
    KEY_ANTIALIASING, VALUE_ANTIALIAS_ON,
52
    KEY_ALPHA_INTERPOLATION, VALUE_ALPHA_INTERPOLATION_QUALITY,
53
    KEY_COLOR_RENDERING, VALUE_COLOR_RENDER_QUALITY,
54
    KEY_DITHERING, VALUE_DITHER_DISABLE,
55
    KEY_FRACTIONALMETRICS, VALUE_FRACTIONALMETRICS_ON,
56
    KEY_INTERPOLATION, VALUE_INTERPOLATION_BICUBIC,
57
    KEY_RENDERING, VALUE_RENDER_QUALITY,
58
    KEY_STROKE_CONTROL, VALUE_STROKE_PURE,
59
    KEY_TEXT_ANTIALIASING, VALUE_TEXT_ANTIALIAS_ON
60
  );
61
62
  /**
63
   * Shared hints for high-quality rendering.
64
   */
65
  private static final Map<Object, Object> RENDERING_HINTS = new HashMap<>(
66
    DEFAULT_HINTS
67
  );
68
69
  static {
70
    final var toolkit = getDefaultToolkit();
71
    final var hints = toolkit.getDesktopProperty( "awt.font.desktophints" );
72
73
    if( hints instanceof Map ) {
74
      final var map = (Map) hints;
75
76
      for( final var key : map.keySet() ) {
77
        final var hint = map.get( key );
78
        RENDERING_HINTS.put( key, hint );
79
      }
80
    }
81
  }
82
83
  /**
84
   * <a href="https://issues.apache.org/jira/browse/BATIK-1112">Bug fix</a>
85
   */
86
  public static final class InkscapeCssParser extends Parser {
87
    public void parseStyleDeclaration( final String source )
88
      throws CSSException, IOException {
89
      super.parseStyleDeclaration(
90
        source.replaceAll( "-inkscape-font-specification:[^;\"]*;", "" )
91
      );
92
    }
93
  }
94
95
  static {
96
    XMLResourceDescriptor.setCSSParserClassName(
97
      InkscapeCssParser.class.getName()
98
    );
99
  }
100
41101
  private static final SAXSVGDocumentFactory FACTORY_DOM =
42102
    new SAXSVGDocumentFactory( getXMLParserClassName() );
...
160220
161221
  /**
162
   * Rasterizes the resource specified by the path into an image.
222
   * Rasterizes the given SVG input stream into an image at 96 DPI.
163223
   *
164
   * @param svg The SVG data to rasterize.
165
   * @return The resource at the given path as an {@link ImageView}.
224
   * @param svg The SVG data to rasterize, must be closed by caller.
225
   * @return The given input stream converted to a rasterized image.
166226
   */
167227
  public static BufferedImage rasterize( final InputStream svg )
168228
    throws TranscoderException {
169
    final var in = new TranscoderInput( svg );
229
    return rasterize( svg, 96 );
230
  }
231
232
  /**
233
   * Rasterizes the given SVG input stream into an image.
234
   *
235
   * @param svg The SVG data to rasterize, must be closed by caller.
236
   * @param dpi Resolution to use when rasterizing (default is 96 DPI).
237
   * @return The given input stream converted to a rasterized image at the
238
   * given resolution.
239
   */
240
  public static BufferedImage rasterize(
241
    final InputStream svg, final float dpi ) throws TranscoderException {
170242
    final var transcoder = new BufferedImageTranscoder();
171
    transcoder.transcode( in, null );
243
    transcoder.addTranscodingHint(
244
      KEY_PIXEL_UNIT_TO_MILLIMETER, 1f / dpi * 25.4f );
245
    transcoder.transcode( new TranscoderInput( svg ), null );
172246
    return transcoder.getImage();
173247
  }
...
180254
   * @return The rasterized image.
181255
   */
182
  public static BufferedImage rasterize( final Document svg, final int width ) {
183
    try {
184
      final var transcoder = new BufferedImageTranscoder();
185
      final var input = new TranscoderInput( svg );
186
187
      transcoder.addTranscodingHint( KEY_WIDTH, (float) width );
188
      transcoder.transcode( input, null );
189
      return transcoder.getImage();
190
    } catch( final Exception ex ) {
191
      clue( ex );
192
    }
193
194
    return BROKEN_IMAGE_PLACEHOLDER;
256
  public static BufferedImage rasterize( final Document svg, final int width )
257
    throws TranscoderException {
258
    final var transcoder = new BufferedImageTranscoder();
259
    transcoder.addTranscodingHint( KEY_WIDTH, (float) width );
260
    transcoder.transcode( new TranscoderInput( svg ), null );
261
    return transcoder.getImage();
195262
  }
196
197
  public static BufferedImage rasterize( final Document document ) {
198
    try {
199
      final var root = document.getDocumentElement();
200
      final var width = root.getAttribute( "width" );
201
      return rasterize( document, INT_FORMAT.parse( width ).intValue() );
202
    } catch( final Exception ex ) {
203
      clue( ex );
204
    }
205263
206
    return BROKEN_IMAGE_PLACEHOLDER;
264
  /**
265
   * Rasterizes the given vector graphic file using the width dimension
266
   * specified by the document's width attribute.
267
   *
268
   * @param document The {@link Document} containing a vector graphic.
269
   * @return A rasterized image as an instance of {@link BufferedImage}, or
270
   * {@link #BROKEN_IMAGE_PLACEHOLDER} if the graphic could not be rasterized.
271
   */
272
  public static BufferedImage rasterize( final Document document )
273
    throws ParseException, TranscoderException {
274
    final var root = document.getDocumentElement();
275
    final var width = root.getAttribute( "width" );
276
    return rasterize( document, INT_FORMAT.parse( width ).intValue() );
207277
  }
208278
...
260330
   * @return The vector graphic transcoded into a raster image format.
261331
   */
262
  public static BufferedImage rasterizeString( final String xml ) {
263
    try {
264
      final var document = toDocument( xml );
265
      final var root = document.getDocumentElement();
266
      final var width = root.getAttribute( "width" );
267
      return rasterizeString( xml, INT_FORMAT.parse( width ).intValue() );
268
    } catch( final Exception ex ) {
269
      clue( ex );
270
    }
271
272
    return BROKEN_IMAGE_PLACEHOLDER;
332
  public static BufferedImage rasterizeString( final String xml )
333
    throws ParseException, TranscoderException {
334
    final var document = toDocument( xml );
335
    final var root = document.getDocumentElement();
336
    final var width = root.getAttribute( "width" );
337
    return rasterizeString( xml, INT_FORMAT.parse( width ).intValue() );
273338
  }
274339
...
282347
   * @return The vector graphic transcoded into a raster image format.
283348
   */
284
  public static BufferedImage rasterizeString( final String svg, final int w ) {
349
  public static BufferedImage rasterizeString( final String svg, final int w )
350
    throws TranscoderException {
285351
    return rasterize( toDocument( svg ), w );
286352
  }
M src/main/java/com/keenwrite/preview/SvgReplacedElementFactory.java
22
package com.keenwrite.preview;
33
4
import com.keenwrite.io.HttpMediaType;
54
import com.keenwrite.io.MediaType;
65
import com.keenwrite.ui.adapters.ReplacedElementAdapter;
7
import org.w3c.dom.Element;
86
import org.xhtmlrenderer.extend.ReplacedElement;
97
import org.xhtmlrenderer.extend.UserAgentCallback;
...
1715
1816
import static com.keenwrite.events.StatusEvent.clue;
19
import static com.keenwrite.io.MediaType.*;
17
import static com.keenwrite.io.HttpFacade.httpGet;
2018
import static com.keenwrite.preview.MathRenderer.MATH_RENDERER;
2119
import static com.keenwrite.preview.SvgRasterizer.BROKEN_IMAGE_PLACEHOLDER;
...
5351
        case HTML_IMAGE -> {
5452
          final var source = e.getAttribute( HTML_IMAGE_SRC );
53
          var mediaType = MediaType.fromFilename( source );
5554
          URI uri = null;
5655
5756
          if( getProtocol( source ).isHttp() ) {
58
            var mediaType = MediaType.valueFrom( source );
59
60
            if( isSvg( mediaType ) || mediaType == UNDEFINED ) {
57
            if( mediaType.isSvg() || mediaType.isUndefined() ) {
6158
              uri = new URI( source );
59
60
              try( final var response = httpGet( uri ) ) {
61
                mediaType = response.getMediaType();
62
              }
6263
6364
              // Attempt to rasterize SVG depending on URL resource content.
64
              if( !isSvg( HttpMediaType.valueFrom( uri ) ) ) {
65
              if( !mediaType.isSvg() ) {
6566
                uri = null;
6667
              }
6768
            }
6869
          }
69
          else if( isSvg( MediaType.valueFrom( source ) ) ) {
70
          else if( mediaType.isSvg() ) {
7071
            // Attempt to rasterize based on file name.
7172
            final var path = Path.of( new URI( source ).getPath() );
7273
7374
            if( path.isAbsolute() ) {
7475
              uri = path.toUri();
7576
            }
7677
            else {
77
              final var base = new URI( getBaseUri( e ) ).getPath();
78
              final var base = new URI( e.getBaseURI() ).getPath();
7879
              uri = Path.of( base, source ).toUri();
7980
            }
...
9899
99100
    return image;
100
  }
101
102
  private String getBaseUri( final Element e ) {
103
    try {
104
      final var doc = e.getOwnerDocument();
105
      final var html = doc.getDocumentElement();
106
      final var head = html.getFirstChild();
107
      final var children = head.getChildNodes();
108
109
      for( int i = children.getLength() - 1; i >= 0; i-- ) {
110
        final var child = children.item( i );
111
        final var name = child.getLocalName();
112
113
        if( "base".equalsIgnoreCase( name ) ) {
114
          final var attrs = child.getAttributes();
115
          final var item = attrs.getNamedItem( "href" );
116
117
          return item.getNodeValue();
118
        }
119
      }
120
    } catch( final Exception ex ) {
121
      clue( ex );
122
    }
123
124
    return "";
125101
  }
126102
127103
  private static ImageReplacedElement createImageReplacedElement(
128104
    final BufferedImage bi ) {
129105
    return new ImageReplacedElement( bi, bi.getWidth(), bi.getHeight() );
130
  }
131
132
  private static boolean isSvg( final MediaType mediaType ) {
133
    return mediaType == TEXT_PLAIN || mediaType == IMAGE_SVG_XML;
134106
  }
135107
}
M src/main/java/com/keenwrite/processors/ExecutorProcessor.java
55
import java.util.concurrent.atomic.AtomicReference;
66
7
import static com.keenwrite.events.StatusEvent.clue;
8
97
/**
108
 * Responsible for transforming data through a variety of chained handlers.
...
4644
    while( handler.isPresent() ) {
4745
      handler = handler.flatMap( p -> {
48
        try {
49
          result.set( p.apply( result.get() ) );
50
        } catch( final Exception ex ) {
51
          clue( ex );
52
        }
53
46
        result.set( p.apply( result.get() ) );
5447
        return p.next();
5548
      } );
M src/main/java/com/keenwrite/processors/HtmlPreviewProcessor.java
55
66
/**
7
 * Responsible for notifying the HTMLPreviewPane when the succession chain has
8
 * updated. This decouples knowledge of changes to the editor panel from the
9
 * HTML preview panel as well as any processing that takes place before the
10
 * final HTML preview is rendered. This is the last link in the processor
11
 * chain.
7
 * Responsible for notifying the {@link HtmlPreview} when the succession
8
 * chain has updated. This decouples knowledge of changes to the editor panel
9
 * from the HTML preview panel as well as any processing that takes place
10
 * before the final HTML preview is rendered. This is the last link in the
11
 * processor chain.
1212
 */
1313
public final class HtmlPreviewProcessor extends ExecutorProcessor<String> {
A src/main/java/com/keenwrite/processors/PdfProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors;
3
4
import com.keenwrite.typesetting.Typesetter;
5
6
import java.io.IOException;
7
8
import static com.keenwrite.Bootstrap.APP_TITLE_LOWERCASE;
9
import static com.keenwrite.Messages.get;
10
import static com.keenwrite.events.StatusEvent.clue;
11
import static com.keenwrite.io.MediaType.TEXT_XML;
12
import static java.nio.file.Files.deleteIfExists;
13
import static java.nio.file.Files.writeString;
14
15
/**
16
 * Responsible for using a typesetting engine to convert an XHTML document
17
 * into a PDF file. This must not be run from the JavaFX thread.
18
 */
19
public final class PdfProcessor extends ExecutorProcessor<String> {
20
  private final ProcessorContext mContext;
21
22
  public PdfProcessor( final ProcessorContext context ) {
23
    assert context != null;
24
    mContext = context;
25
  }
26
27
  /**
28
   * Converts a document by calling a third-party library to typeset the given
29
   * XHTML document.
30
   *
31
   * @param xhtml The document to convert to a PDF file.
32
   * @return {@code null} because there is no valid return value from generating
33
   * a PDF file.
34
   */
35
  public String apply( final String xhtml ) {
36
    try {
37
      clue( get( "Main.status.typeset.create" ) );
38
      final var document = TEXT_XML.createTemporaryFile( APP_TITLE_LOWERCASE );
39
      final var pathInput = writeString( document, xhtml );
40
      final var pathOutput = mContext.getExportPath();
41
      final var typesetter = new Typesetter( mContext.getWorkspace() );
42
43
      typesetter.typeset( pathInput, pathOutput );
44
45
      // Smote the temporary file after typesetting the document.
46
      deleteIfExists( document );
47
    } catch( final IOException | InterruptedException ex ) {
48
      // Typesetter runtime exceptions will pass up the call stack.
49
      clue( get( "Main.status.typeset.failed" ), ex );
50
    }
51
52
    // Do not continue processing (the document was typeset into a binary).
53
    return null;
54
  }
55
}
156
M src/main/java/com/keenwrite/processors/ProcessorContext.java
22
package com.keenwrite.processors;
33
4
import com.keenwrite.Constants;
4
import com.keenwrite.Caret;
5
import com.keenwrite.constants.Constants;
56
import com.keenwrite.ExportFormat;
67
import com.keenwrite.io.FileType;
78
import com.keenwrite.preferences.Workspace;
89
import com.keenwrite.preview.HtmlPreview;
9
import com.keenwrite.Caret;
1010
1111
import java.nio.file.Path;
1212
import java.util.Map;
1313
1414
import static com.keenwrite.AbstractFileFactory.lookup;
15
import static com.keenwrite.Constants.DEFAULT_DIRECTORY;
15
import static com.keenwrite.constants.Constants.DEFAULT_DIRECTORY;
1616
1717
/**
1818
 * Provides a context for configuring a chain of {@link Processor} instances.
1919
 */
2020
public final class ProcessorContext {
2121
  private final HtmlPreview mHtmlPreview;
2222
  private final Map<String, String> mResolvedMap;
2323
  private final Path mDocumentPath;
24
  private final Path mExportPath;
2425
  private final Caret mCaret;
2526
  private final ExportFormat mExportFormat;
...
3435
   * @param htmlPreview  Where to display the final (HTML) output.
3536
   * @param resolvedMap  Fully expanded interpolated strings.
36
   * @param documentPath         Path to the document to process.
37
   * @param documentPath Path to the document to process.
38
   * @param exportPath   Fully qualified filename to use when exporting.
39
   * @param exportFormat Indicate configuration options for export format.
40
   * @param workspace    Persistent user preferences settings.
3741
   * @param caret        Location of the caret in the edited document, which is
3842
   *                     used to synchronize the scrollbars.
39
   * @param exportFormat Indicate configuration options for export format.
4043
   */
4144
  public ProcessorContext(
4245
    final HtmlPreview htmlPreview,
4346
    final Map<String, String> resolvedMap,
4447
    final Path documentPath,
45
    final Caret caret,
48
    final Path exportPath,
4649
    final ExportFormat exportFormat,
47
    final Workspace workspace ) {
50
    final Workspace workspace,
51
    final Caret caret ) {
4852
    assert htmlPreview != null;
4953
    assert resolvedMap != null;
5054
    assert documentPath != null;
51
    assert caret != null;
5255
    assert exportFormat != null;
5356
    assert workspace != null;
57
    assert caret != null;
5458
5559
    mHtmlPreview = htmlPreview;
5660
    mResolvedMap = resolvedMap;
5761
    mDocumentPath = documentPath;
5862
    mCaret = caret;
63
    mExportPath = exportPath;
5964
    mExportFormat = exportFormat;
6065
    mWorkspace = workspace;
6166
  }
6267
63
  @SuppressWarnings( "SameParameterValue" )
64
  boolean isExportFormat( final ExportFormat format ) {
68
  public boolean isExportFormat( final ExportFormat format ) {
6569
    return mExportFormat == format;
6670
  }
...
7781
  Map<String, String> getResolvedMap() {
7882
    return mResolvedMap;
83
  }
84
85
  /**
86
   * Fully qualified file name to use when exporting (e.g., document.pdf).
87
   *
88
   * @return Full path to a file name.
89
   */
90
  public Path getExportPath() {
91
    return mExportPath;
7992
  }
8093
M src/main/java/com/keenwrite/processors/ProcessorFactory.java
66
import com.keenwrite.processors.markdown.MarkdownProcessor;
77
8
import static com.keenwrite.ExportFormat.NONE;
8
import static com.keenwrite.ExportFormat.*;
9
import static com.keenwrite.processors.IdentityProcessor.IDENTITY;
910
1011
/**
...
4142
    final var successor = context.isExportFormat( NONE )
4243
      ? createHtmlPreviewProcessor()
44
      : context.isExportFormat( XHTML_TEX )
45
      ? createXhtmlProcessor( context )
46
      : context.isExportFormat( APPLICATION_PDF )
47
      ? createPdfProcessor( context )
4348
      : createIdentityProcessor();
4449
...
5459
5560
  /**
56
   * Creates a processor chain suitable for parsing and rendering the file
57
   * opened at the given tab.
61
   * Creates a new {@link Processor} chain suitable for parsing and rendering
62
   * the file opened at the given tab.
5863
   *
5964
   * @param context The tab containing a text editor, path, and caret position.
...
7277
   */
7378
  private Processor<String> createIdentityProcessor() {
74
    return IdentityProcessor.IDENTITY;
79
    return IDENTITY;
7580
  }
7681
...
114119
    final var xmlp = new XmlProcessor( successor, getProcessorContext() );
115120
    return createDefinitionProcessor( xmlp );
121
  }
122
123
  /**
124
   * Instantiates a new {@link Processor} that wraps an HTML document into
125
   * its final, well-formed state (including head and body tags). This is
126
   * useful for generating XHTML documents suitable for typesetting (using
127
   * an engine such as LuaTeX).
128
   *
129
   * @return An instance of {@link Processor} that completes an HTML document.
130
   */
131
  private Processor<String> createXhtmlProcessor(
132
    final ProcessorContext context ) {
133
    return createXhtmlProcessor( IDENTITY, context );
134
  }
135
136
  private Processor<String> createXhtmlProcessor(
137
    final Processor<String> successor, final ProcessorContext context ) {
138
    return new XhtmlProcessor( successor, context );
139
  }
140
141
  private Processor<String> createPdfProcessor(
142
    final ProcessorContext context ) {
143
    final var pdfp = new PdfProcessor( context );
144
    return createXhtmlProcessor( pdfp, context );
116145
  }
117146
A src/main/java/com/keenwrite/processors/XhtmlProcessor.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors;
3
4
import com.keenwrite.preferences.Key;
5
import com.keenwrite.preferences.Workspace;
6
import com.keenwrite.ui.heuristics.WordCounter;
7
import javafx.beans.property.StringProperty;
8
import org.jsoup.nodes.Document;
9
10
import javax.xml.parsers.DocumentBuilderFactory;
11
import javax.xml.transform.TransformerFactory;
12
import javax.xml.transform.dom.DOMSource;
13
import javax.xml.transform.stream.StreamResult;
14
import java.io.FileNotFoundException;
15
import java.nio.file.Path;
16
import java.util.Locale;
17
import java.util.Map;
18
import java.util.Map.Entry;
19
import java.util.regex.Pattern;
20
21
import static com.keenwrite.Bootstrap.APP_TITLE_LOWERCASE;
22
import static com.keenwrite.Messages.get;
23
import static com.keenwrite.events.StatusEvent.clue;
24
import static com.keenwrite.io.HttpFacade.httpGet;
25
import static com.keenwrite.preferences.WorkspaceKeys.*;
26
import static com.keenwrite.processors.text.TextReplacementFactory.replace;
27
import static com.keenwrite.util.ProtocolScheme.getProtocol;
28
import static java.lang.String.format;
29
import static java.lang.String.valueOf;
30
import static java.nio.file.Files.copy;
31
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
32
import static java.util.regex.Pattern.UNICODE_CHARACTER_CLASS;
33
import static java.util.regex.Pattern.compile;
34
import static javax.xml.transform.OutputKeys.INDENT;
35
import static javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION;
36
import static org.jsoup.Jsoup.parse;
37
import static org.jsoup.nodes.Document.OutputSettings.Syntax;
38
39
/**
40
 * Responsible for making an HTML document complete by wrapping it with html
41
 * and body elements. This doesn't have to be super-efficient because it's
42
 * not run in real-time.
43
 */
44
public final class XhtmlProcessor extends ExecutorProcessor<String> {
45
  private final static Pattern BLANK =
46
    compile( "\\p{Blank}", UNICODE_CHARACTER_CLASS );
47
48
  private final ProcessorContext mContext;
49
50
  public XhtmlProcessor(
51
    final Processor<String> successor, final ProcessorContext context ) {
52
    super( successor );
53
54
    assert context != null;
55
    mContext = context;
56
  }
57
58
  /**
59
   * Responsible for producing a well-formed XML document complete with
60
   * metadata (title, author, keywords, copyright, and date).
61
   *
62
   * @param html The HTML document to transform into an XHTML document.
63
   * @return The transformed HTML document.
64
   */
65
  @Override
66
  public String apply( final String html ) {
67
    clue( get( "Main.status.typeset.xhtml" ) );
68
69
    final var doc = parse( html );
70
    setMetaData( doc );
71
    doc.outputSettings().syntax( Syntax.xml );
72
73
    for( final var img : doc.getElementsByTag( "img" ) ) {
74
      try {
75
        final var imageFile = exportImage( img.attr( "src" ) );
76
77
        img.attr( "src", imageFile.toString() );
78
      } catch( final Exception ex ) {
79
        clue( ex );
80
      }
81
    }
82
83
    return doc.html();
84
  }
85
86
  /**
87
   * Applies the metadata fields to the document.
88
   *
89
   * @param doc The document to adorn with metadata.
90
   */
91
  private void setMetaData( final Document doc ) {
92
    doc.title( getTitle() );
93
94
    final var metadata = createMetaData( doc );
95
    final var head = doc.head();
96
    metadata.entrySet().forEach( entry -> head.append( createMeta( entry ) ) );
97
  }
98
99
  private String createMeta( final Entry<String, String> entry ) {
100
    return format(
101
      "<meta name='%s' content='%s'>", entry.getKey(), entry.getValue()
102
    );
103
  }
104
105
  /**
106
   * Generates document metadata, including word count.
107
   *
108
   * @param doc The document containing the text to tally.
109
   * @return A map of metadata key/value pairs.
110
   */
111
  private Map<String, String> createMetaData( final Document doc ) {
112
    return Map.of(
113
      "author", getAuthor(),
114
      "byline", getByline(),
115
      "address", getAddress(),
116
      "phone", getPhone(),
117
      "email", getEmail(),
118
      "count", getWordCount( doc ),
119
      "keywords", getKeywords(),
120
      "copyright", getCopyright(),
121
      "date", getDate()
122
    );
123
  }
124
125
  /**
126
   * For a given src URI, this method will attempt to normalize it such that a
127
   * third-party application can find the file. Normalization could entail
128
   * downloading from the Internet or finding a suitable file name extension.
129
   *
130
   * @param src A path, local or remote, to a partial or complete file name.
131
   * @return A local file system path to the source path.
132
   * @throws Exception Could not read from, write to, or find a file.
133
   */
134
  private Path exportImage( final String src ) throws Exception {
135
    Path imageFile = null;
136
137
    final var protocol = getProtocol( src );
138
139
    // Download remote resources into temporary files.
140
    if( protocol.isRemote() ) {
141
      final var response = httpGet( src );
142
      final var mediaType = response.getMediaType();
143
144
      imageFile = mediaType.createTemporaryFile( APP_TITLE_LOWERCASE );
145
146
      try( final var image = response.getInputStream() ) {
147
        copy( image, imageFile, REPLACE_EXISTING );
148
      }
149
150
      // Strip comments, superfluous whitespace, DOCTYPE, and XML declarations.
151
      if( mediaType.isSvg() ) {
152
        sanitize( imageFile );
153
      }
154
    }
155
    else {
156
      final var extensions = " " + getImageOrder().trim();
157
      var imagePath = getImagePath();
158
      var found = false;
159
160
      // By including " " in the extensions, the first element returned
161
      // will be the empty string. Thus the first extension to try is the
162
      // file's default extension. Subsequent iterations will try to find
163
      // a file that has a name matching one of the preferred extensions.
164
      for( final var extension : BLANK.split( extensions ) ) {
165
        final var filename = format(
166
          "%s%s%s", src, extension.isBlank() ? "" : ".", extension );
167
        imageFile = Path.of( imagePath, filename );
168
169
        if( imageFile.toFile().exists() ) {
170
          found = true;
171
          break;
172
        }
173
      }
174
175
      if( !found ) {
176
        imagePath = getDocumentDir().toString();
177
        imageFile = Path.of( imagePath, src );
178
179
        if( !imageFile.toFile().exists() ) {
180
          throw new FileNotFoundException( imageFile.toString() );
181
        }
182
      }
183
    }
184
185
    return imageFile;
186
  }
187
188
  /**
189
   * Remove whitespace, comments, and XML/DOCTYPE declarations to make
190
   * processing work with ConTeXt.
191
   *
192
   * @param path The SVG file to process.
193
   * @throws Exception The file could not be processed.
194
   */
195
  private void sanitize( final Path path )
196
    throws Exception {
197
    final var file = path.toFile();
198
199
    final var dbf = DocumentBuilderFactory.newInstance();
200
    dbf.setIgnoringComments( true );
201
    dbf.setIgnoringElementContentWhitespace( true );
202
203
    final var db = dbf.newDocumentBuilder();
204
    final var document = db.parse( file );
205
206
    final var tf = TransformerFactory.newInstance();
207
    final var transformer = tf.newTransformer();
208
209
    final var source = new DOMSource( document );
210
    final var result = new StreamResult( file );
211
    transformer.setOutputProperty( OMIT_XML_DECLARATION, "yes" );
212
    transformer.setOutputProperty( INDENT, "no" );
213
    transformer.transform( source, result );
214
  }
215
216
  private String getImagePath() {
217
    return getWorkspace().toFile( KEY_IMAGES_DIR ).toString();
218
  }
219
220
  private String getImageOrder() {
221
    return getWorkspace().toString( KEY_IMAGES_ORDER );
222
  }
223
224
  /**
225
   * Returns the absolute path to the document being edited, which can be used
226
   * to find files included using relative paths.
227
   *
228
   * @return The directory containing the edited file.
229
   */
230
  private Path getDocumentDir() {
231
    return mContext.getBaseDir();
232
  }
233
234
  private Workspace getWorkspace() {
235
    return mContext.getWorkspace();
236
  }
237
238
  private Locale getLocale() { return getWorkspace().getLocale(); }
239
240
  private String getTitle() {
241
    return resolve( KEY_DOC_TITLE );
242
  }
243
244
  private String getAuthor() {
245
    return resolve( KEY_DOC_AUTHOR );
246
  }
247
248
  private String getByline() {
249
    return resolve( KEY_DOC_BYLINE );
250
  }
251
252
  private String getAddress() {
253
    return resolve( KEY_DOC_ADDRESS ).replaceAll( "\n", "\\\\\\break{}" );
254
  }
255
256
  private String getPhone() {
257
    return resolve( KEY_DOC_PHONE );
258
  }
259
260
  private String getEmail() {
261
    return resolve( KEY_DOC_EMAIL );
262
  }
263
264
  private String getWordCount( final Document doc ) {
265
    final var text = doc.wholeText();
266
    final var wordCounter = WordCounter.create( getLocale() );
267
    return valueOf( wordCounter.countWords( text ) );
268
  }
269
270
  private String getKeywords() {
271
    return resolve( KEY_DOC_KEYWORDS );
272
  }
273
274
  private String getCopyright() {
275
    return resolve( KEY_DOC_COPYRIGHT );
276
  }
277
278
  private String getDate() {
279
    return resolve( KEY_DOC_DATE );
280
  }
281
282
  private String resolve( final Key key ) {
283
    return replace( asString( key ), mContext.getResolvedMap() );
284
  }
285
286
  private String asString( final Key key ) {
287
    return stringProperty( key ).get();
288
  }
289
290
  private StringProperty stringProperty( final Key key ) {
291
    return getWorkspace().stringProperty( key );
292
  }
293
}
1294
M src/main/java/com/keenwrite/processors/markdown/BaseMarkdownProcessor.java
55
import com.keenwrite.processors.Processor;
66
import com.keenwrite.processors.ProcessorContext;
7
import com.keenwrite.processors.markdown.extensions.fences.FencedDivExtension;
78
import com.keenwrite.processors.markdown.extensions.r.RExtension;
89
import com.vladsch.flexmark.ext.definition.DefinitionExtension;
...
2021
import java.util.ArrayList;
2122
import java.util.List;
23
24
import static com.keenwrite.ExportFormat.APPLICATION_PDF;
25
import static com.vladsch.flexmark.ext.typographic.TypographicExtension.ENABLE_SMARTS;
2226
2327
/**
...
3539
    super( successor );
3640
37
    final var extensions = createExtensions( context );
41
    // Disable emdash, endash, and ellipses conversion for PDF exports. The
42
    // typesetting software will perform the appropriate styling. This allows
43
    // manuscripts to include verbatim hyphens, for example.
44
    final var builder = Parser.builder();
45
    builder.set( ENABLE_SMARTS, !context.isExportFormat( APPLICATION_PDF ) );
3846
39
    mParser = Parser.builder().extensions( extensions ).build();
47
    final var extensions = createExtensions( context );
48
    mParser = builder.extensions( extensions ).build();
4049
    mRenderer = HtmlRenderer.builder().extensions( extensions ).build();
4150
  }
...
5867
    extensions.add( SuperscriptExtension.create() );
5968
    extensions.add( TablesExtension.create() );
60
    extensions.add( TypographicExtension.create() );
69
    extensions.add( FencedDivExtension.create() );
70
71
    if( !context.isExportFormat( APPLICATION_PDF ) ) {
72
      extensions.add( TypographicExtension.create() );
73
    }
6174
6275
    return extensions;
M src/main/java/com/keenwrite/processors/markdown/MarkdownProcessor.java
77
import com.keenwrite.processors.ProcessorContext;
88
import com.keenwrite.processors.markdown.extensions.*;
9
import com.keenwrite.processors.markdown.extensions.fences.FencedBlockExtension;
910
import com.keenwrite.processors.markdown.extensions.r.RExtension;
1011
import com.keenwrite.processors.markdown.extensions.tex.TeXExtension;
M src/main/java/com/keenwrite/processors/markdown/extensions/CaretExtension.java
33
44
import com.keenwrite.Caret;
5
import com.keenwrite.Constants;
5
import com.keenwrite.constants.Constants;
66
import com.keenwrite.processors.ProcessorContext;
77
import com.vladsch.flexmark.ext.tables.TableBlock;
...
1616
import org.jetbrains.annotations.NotNull;
1717
18
import static com.keenwrite.Constants.CARET_ID;
18
import static com.keenwrite.constants.Constants.CARET_ID;
1919
import static com.keenwrite.processors.markdown.extensions.EmptyNode.EMPTY_NODE;
2020
import static com.vladsch.flexmark.html.HtmlRenderer.Builder;
D src/main/java/com/keenwrite/processors/markdown/extensions/FencedBlockExtension.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions;
3
4
import com.keenwrite.processors.DefinitionProcessor;
5
import com.keenwrite.processors.Processor;
6
import com.keenwrite.processors.markdown.MarkdownProcessor;
7
import com.vladsch.flexmark.ast.FencedCodeBlock;
8
import com.vladsch.flexmark.html.renderer.DelegatingNodeRendererFactory;
9
import com.vladsch.flexmark.html.renderer.NodeRenderer;
10
import com.vladsch.flexmark.html.renderer.NodeRenderingHandler;
11
import com.vladsch.flexmark.util.data.DataHolder;
12
import com.vladsch.flexmark.util.sequence.BasedSequence;
13
import org.jetbrains.annotations.NotNull;
14
15
import java.io.ByteArrayOutputStream;
16
import java.util.HashSet;
17
import java.util.Set;
18
import java.util.zip.Deflater;
19
20
import static com.keenwrite.Constants.DIAGRAM_SERVER_NAME;
21
import static com.keenwrite.events.StatusEvent.clue;
22
import static com.vladsch.flexmark.html.HtmlRenderer.Builder;
23
import static com.vladsch.flexmark.html.renderer.LinkType.LINK;
24
import static java.lang.String.format;
25
import static java.util.Base64.getUrlEncoder;
26
import static java.util.zip.Deflater.BEST_COMPRESSION;
27
import static java.util.zip.Deflater.FULL_FLUSH;
28
29
/**
30
 * Responsible for converting textual diagram descriptions into HTML image
31
 * elements.
32
 */
33
public class FencedBlockExtension extends HtmlRendererAdapter {
34
  private final static String DIAGRAM_STYLE = "diagram-";
35
  private final static int DIAGRAM_STYLE_LEN = DIAGRAM_STYLE.length();
36
37
  private final Processor<String> mProcessor;
38
39
  public FencedBlockExtension( final Processor<String> processor ) {
40
    assert processor != null;
41
    mProcessor = processor;
42
  }
43
44
  /**
45
   * Creates a new parser for fenced blocks. This calls out to a web service
46
   * to generate SVG files of text diagrams.
47
   * <p>
48
   * Internally, this creates a {@link DefinitionProcessor} to substitute
49
   * variable definitions. This is necessary because the order of processors
50
   * matters. If the {@link DefinitionProcessor} comes before an instance of
51
   * {@link MarkdownProcessor}, for example, then the caret position in the
52
   * preview pane will not align with the caret position in the editor
53
   * pane. The {@link MarkdownProcessor} must come before all else. However,
54
   * when parsing fenced blocks, the variables within the block must be
55
   * interpolated before being sent to the diagram web service.
56
   * </p>
57
   *
58
   * @param processor Used to pre-process the text.
59
   * @return A new {@link FencedBlockExtension} capable of shunting ASCII
60
   * diagrams to a service for conversion to SVG.
61
   */
62
  public static FencedBlockExtension create(
63
    final Processor<String> processor ) {
64
    return new FencedBlockExtension( processor );
65
  }
66
67
  @Override
68
  public void extend(
69
    @NotNull final Builder builder, @NotNull final String rendererType ) {
70
    builder.nodeRendererFactory( new Factory() );
71
  }
72
73
  /**
74
   * Converts the given {@link BasedSequence} to a lowercase value.
75
   *
76
   * @param text The character string to convert to lowercase.
77
   * @return The lowercase text value, or the empty string for no text.
78
   */
79
  private static String sanitize( final BasedSequence text ) {
80
    assert text != null;
81
    return text.toString().toLowerCase();
82
  }
83
84
  private class CustomRenderer implements NodeRenderer {
85
86
    @Override
87
    public Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() {
88
      final var set = new HashSet<NodeRenderingHandler<?>>();
89
90
      set.add( new NodeRenderingHandler<>(
91
        FencedCodeBlock.class, ( node, context, html ) -> {
92
        final var style = sanitize( node.getInfo() );
93
94
        if( style.startsWith( DIAGRAM_STYLE ) ) {
95
          final var type = style.substring( DIAGRAM_STYLE_LEN );
96
          final var content = node.getContentChars().normalizeEOL();
97
          final var text = mProcessor.apply( content );
98
          final var encoded = encode( text );
99
          final var source = format(
100
            "https://%s/%s/svg/%s", DIAGRAM_SERVER_NAME, type, encoded );
101
102
          final var link = context.resolveLink( LINK, source, false );
103
104
          html.attr( "src", source );
105
          html.withAttr( link );
106
          html.tagVoid( "img" );
107
        }
108
        else {
109
          context.delegateRender();
110
        }
111
      } ) );
112
113
      return set;
114
    }
115
116
    private byte[] compress( byte[] source ) {
117
      final var inLen = source.length;
118
      final var result = new byte[ inLen ];
119
      final var compressor = new Deflater( BEST_COMPRESSION );
120
121
      compressor.setInput( source, 0, inLen );
122
      compressor.finish();
123
      final var outLen = compressor.deflate( result, 0, inLen, FULL_FLUSH );
124
      compressor.end();
125
126
      try( final var out = new ByteArrayOutputStream() ) {
127
        out.write( result, 0, outLen );
128
        return out.toByteArray();
129
      } catch( final Exception ex ) {
130
        clue( ex );
131
        throw new RuntimeException( ex );
132
      }
133
    }
134
135
    private String encode( final String decoded ) {
136
      return getUrlEncoder().encodeToString( compress( decoded.getBytes() ) );
137
    }
138
  }
139
140
  private class Factory implements DelegatingNodeRendererFactory {
141
    public Factory() {}
142
143
    @NotNull
144
    @Override
145
    public NodeRenderer apply( @NotNull final DataHolder options ) {
146
      return new CustomRenderer();
147
    }
148
149
    /**
150
     * Return {@code null} to indicate this may delegate to the core renderer.
151
     */
152
    @Override
153
    public Set<Class<?>> getDelegates() {
154
      return null;
155
    }
156
  }
157
}
1581
A src/main/java/com/keenwrite/processors/markdown/extensions/fences/ClosingDivBlock.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions.fences;
3
4
import com.vladsch.flexmark.html.HtmlWriter;
5
6
/**
7
 * Responsible for helping to generate a closing div element.
8
 */
9
class ClosingDivBlock extends DivBlock {
10
  @Override
11
  void export( final HtmlWriter html ) {
12
    html.closeTag( HTML_DIV );
13
  }
14
}
115
A src/main/java/com/keenwrite/processors/markdown/extensions/fences/DivBlock.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions.fences;
3
4
import com.vladsch.flexmark.html.HtmlWriter;
5
import com.vladsch.flexmark.util.ast.Block;
6
import com.vladsch.flexmark.util.sequence.BasedSequence;
7
import org.jetbrains.annotations.NotNull;
8
9
abstract class DivBlock extends Block {
10
  static final CharSequence HTML_DIV = "div";
11
12
  @Override
13
  @NotNull
14
  public BasedSequence[] getSegments() {
15
    return EMPTY_SEGMENTS;
16
  }
17
18
  /**
19
   * Append an opening or closing HTML div element to the given writer.
20
   *
21
   * @param html Builds the HTML document to be written.
22
   */
23
  abstract void export( HtmlWriter html );
24
}
125
A src/main/java/com/keenwrite/processors/markdown/extensions/fences/FencedBlockExtension.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions.fences;
3
4
import com.keenwrite.processors.DefinitionProcessor;
5
import com.keenwrite.processors.Processor;
6
import com.keenwrite.processors.markdown.MarkdownProcessor;
7
import com.keenwrite.processors.markdown.extensions.HtmlRendererAdapter;
8
import com.vladsch.flexmark.ast.FencedCodeBlock;
9
import com.vladsch.flexmark.html.renderer.DelegatingNodeRendererFactory;
10
import com.vladsch.flexmark.html.renderer.NodeRenderer;
11
import com.vladsch.flexmark.html.renderer.NodeRenderingHandler;
12
import com.vladsch.flexmark.util.data.DataHolder;
13
import com.vladsch.flexmark.util.sequence.BasedSequence;
14
import org.jetbrains.annotations.NotNull;
15
16
import java.io.ByteArrayOutputStream;
17
import java.util.HashSet;
18
import java.util.Set;
19
import java.util.zip.Deflater;
20
21
import static com.keenwrite.constants.Constants.DIAGRAM_SERVER_NAME;
22
import static com.keenwrite.events.StatusEvent.clue;
23
import static com.vladsch.flexmark.html.HtmlRenderer.Builder;
24
import static com.vladsch.flexmark.html.renderer.LinkType.LINK;
25
import static java.lang.String.format;
26
import static java.util.Base64.getUrlEncoder;
27
import static java.util.zip.Deflater.BEST_COMPRESSION;
28
import static java.util.zip.Deflater.FULL_FLUSH;
29
30
/**
31
 * Responsible for converting textual diagram descriptions into HTML image
32
 * elements.
33
 */
34
public class FencedBlockExtension extends HtmlRendererAdapter {
35
  private final static String DIAGRAM_STYLE = "diagram-";
36
  private final static int DIAGRAM_STYLE_LEN = DIAGRAM_STYLE.length();
37
38
  private final Processor<String> mProcessor;
39
40
  public FencedBlockExtension( final Processor<String> processor ) {
41
    assert processor != null;
42
    mProcessor = processor;
43
  }
44
45
  /**
46
   * Creates a new parser for fenced blocks. This calls out to a web service
47
   * to generate SVG files of text diagrams.
48
   * <p>
49
   * Internally, this creates a {@link DefinitionProcessor} to substitute
50
   * variable definitions. This is necessary because the order of processors
51
   * matters. If the {@link DefinitionProcessor} comes before an instance of
52
   * {@link MarkdownProcessor}, for example, then the caret position in the
53
   * preview pane will not align with the caret position in the editor
54
   * pane. The {@link MarkdownProcessor} must come before all else. However,
55
   * when parsing fenced blocks, the variables within the block must be
56
   * interpolated before being sent to the diagram web service.
57
   * </p>
58
   *
59
   * @param processor Used to pre-process the text.
60
   * @return A new {@link FencedBlockExtension} capable of shunting ASCII
61
   * diagrams to a service for conversion to SVG.
62
   */
63
  public static FencedBlockExtension create(
64
    final Processor<String> processor ) {
65
    return new FencedBlockExtension( processor );
66
  }
67
68
  @Override
69
  public void extend(
70
    @NotNull final Builder builder, @NotNull final String rendererType ) {
71
    builder.nodeRendererFactory( new Factory() );
72
  }
73
74
  /**
75
   * Converts the given {@link BasedSequence} to a lowercase value.
76
   *
77
   * @param text The character string to convert to lowercase.
78
   * @return The lowercase text value, or the empty string for no text.
79
   */
80
  private static String sanitize( final BasedSequence text ) {
81
    assert text != null;
82
    return text.toString().toLowerCase();
83
  }
84
85
  private class CustomRenderer implements NodeRenderer {
86
87
    @Override
88
    public Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() {
89
      final var set = new HashSet<NodeRenderingHandler<?>>();
90
91
      set.add( new NodeRenderingHandler<>(
92
        FencedCodeBlock.class, ( node, context, html ) -> {
93
        final var style = sanitize( node.getInfo() );
94
95
        if( style.startsWith( DIAGRAM_STYLE ) ) {
96
          final var type = style.substring( DIAGRAM_STYLE_LEN );
97
          final var content = node.getContentChars().normalizeEOL();
98
          final var text = mProcessor.apply( content );
99
          final var encoded = encode( text );
100
          final var source = format(
101
            "https://%s/%s/svg/%s", DIAGRAM_SERVER_NAME, type, encoded );
102
103
          final var link = context.resolveLink( LINK, source, false );
104
105
          html.attr( "src", source );
106
          html.withAttr( link );
107
          html.tagVoid( "img" );
108
        }
109
        else {
110
          context.delegateRender();
111
        }
112
      } ) );
113
114
      return set;
115
    }
116
117
    private byte[] compress( byte[] source ) {
118
      final var inLen = source.length;
119
      final var result = new byte[ inLen ];
120
      final var compressor = new Deflater( BEST_COMPRESSION );
121
122
      compressor.setInput( source, 0, inLen );
123
      compressor.finish();
124
      final var outLen = compressor.deflate( result, 0, inLen, FULL_FLUSH );
125
      compressor.end();
126
127
      try( final var out = new ByteArrayOutputStream() ) {
128
        out.write( result, 0, outLen );
129
        return out.toByteArray();
130
      } catch( final Exception ex ) {
131
        clue( ex );
132
        throw new RuntimeException( ex );
133
      }
134
    }
135
136
    private String encode( final String decoded ) {
137
      return getUrlEncoder().encodeToString( compress( decoded.getBytes() ) );
138
    }
139
  }
140
141
  private class Factory implements DelegatingNodeRendererFactory {
142
    public Factory() {}
143
144
    @NotNull
145
    @Override
146
    public NodeRenderer apply( @NotNull final DataHolder options ) {
147
      return new CustomRenderer();
148
    }
149
150
    /**
151
     * Return {@code null} to indicate this may delegate to the core renderer.
152
     */
153
    @Override
154
    public Set<Class<?>> getDelegates() {
155
      return null;
156
    }
157
  }
158
}
1159
A src/main/java/com/keenwrite/processors/markdown/extensions/fences/FencedDivExtension.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions.fences;
3
4
import com.keenwrite.processors.markdown.extensions.HtmlRendererAdapter;
5
import com.vladsch.flexmark.html.HtmlRenderer;
6
import com.vladsch.flexmark.parser.Parser;
7
import com.vladsch.flexmark.parser.block.*;
8
import com.vladsch.flexmark.util.ast.Block;
9
import com.vladsch.flexmark.util.data.DataHolder;
10
import com.vladsch.flexmark.util.data.MutableDataHolder;
11
import com.vladsch.flexmark.util.html.Attribute;
12
import com.vladsch.flexmark.util.html.AttributeImpl;
13
import org.jetbrains.annotations.NotNull;
14
import org.jetbrains.annotations.Nullable;
15
16
import java.util.ArrayList;
17
import java.util.Set;
18
import java.util.regex.Pattern;
19
20
import static com.vladsch.flexmark.parser.Parser.ParserExtension;
21
22
/**
23
 * Responsible for parsing div block syntax into HTML div tags. Fenced div
24
 * blocks start with three or more consecutive colons, followed by a space,
25
 * followed by attributes. The attributes can be either a single word, or
26
 * multiple words nested in braces. For example:
27
 *
28
 * <p>
29
 * ::: poem
30
 * Tyger Tyger, burning bright,
31
 * In the forests of the night;
32
 * What immortal hand or eye,
33
 * Could frame thy fearful symmetry?
34
 * :::
35
 * </p>
36
 * <p>
37
 * As well as:
38
 * </p>
39
 * <p>
40
 * ::: {#verse .p .d k=v author="Emily Dickinson"}
41
 * Because I could not stop for Death --
42
 * He kindly stopped for me --
43
 * The Carriage held but just Ourselves --
44
 * And Immortality.
45
 * :::
46
 * </p>
47
 *
48
 * <p>
49
 * The second example produces the following starting {@code div} element:
50
 * </p>
51
 * <p>
52
 * &lt;div id="verse" class="p d" data-k="v" data-author="Emily Dickson"&gt;
53
 * </p>
54
 */
55
public class FencedDivExtension extends HtmlRendererAdapter
56
  implements ParserExtension {
57
  /**
58
   * Matches any number of colons at start of line. This will match both the
59
   * opening and closing fences, with any number of colons.
60
   */
61
  private static final Pattern FENCE = Pattern.compile( "^:::.*" );
62
63
  /**
64
   * After a fenced div is detected, this will match the opening fence.
65
   */
66
  private static final Pattern FENCE_OPENING = Pattern.compile(
67
    "^:::+\\s+([\\p{IsAlphabetic}\\p{IsDigit}-_]+|\\{.+})\\s*$" );
68
69
  /**
70
   * Matches whether extended syntax is being used.
71
   */
72
  private static final Pattern ATTR_CSS = Pattern.compile( "\\{(.+)}" );
73
74
  /**
75
   * Matches either individual CSS definitions (id/class, {@code <d>}) or
76
   * key/value pairs ({@code <k>} and {@link <v>}). The key/value pair
77
   * will match optional quotes.
78
   */
79
  private static final Pattern ATTR_PAIRS = Pattern.compile(
80
    "\\s*" +
81
      "(?<d>[#.][\\p{IsAlphabetic}\\p{IsDigit}-_]+[^\\s=])|" +
82
      "((?<k>[\\p{IsAlphabetic}\\p{IsDigit}-_]+)=" +
83
      "\"*(?<v>(?<=\")[^\"]+(?=\")|([^\\s]+))\"*)" );
84
85
  public static FencedDivExtension create() {
86
    return new FencedDivExtension();
87
  }
88
89
  @Override
90
  public void parserOptions( final MutableDataHolder options ) {
91
  }
92
93
  @Override
94
  public void extend( final Parser.Builder builder ) {
95
    builder.customBlockParserFactory( new Factory() );
96
  }
97
98
  /**
99
   * Creates a renderer that can generate HTML div elements.
100
   *
101
   * @param builder      The document builder.
102
   * @param rendererType Indicates the document type to be built.
103
   */
104
  @Override
105
  public void extend( @NotNull final HtmlRenderer.Builder builder,
106
                      @NotNull final String rendererType ) {
107
    if( "HTML".equalsIgnoreCase( rendererType ) ) {
108
      builder.nodeRendererFactory( new FencedDivRenderer.Factory() );
109
    }
110
  }
111
112
  /**
113
   * Responsible for creating an instance of {@link ParserFactory}.
114
   */
115
  private static class Factory implements CustomBlockParserFactory {
116
    @Override
117
    public @NotNull BlockParserFactory apply(
118
      @NotNull final DataHolder options ) {
119
      return new ParserFactory( options );
120
    }
121
122
    @Override
123
    public @Nullable Set<Class<?>> getAfterDependents() { return null; }
124
125
    @Override
126
    public @Nullable Set<Class<?>> getBeforeDependents() { return null; }
127
128
    @Override
129
    public boolean affectsGlobalScope() { return false; }
130
  }
131
132
  /**
133
   * Responsible for creating a fenced div parser that is appropriate for the
134
   * type of fenced div encountered: opening or closing.
135
   */
136
  private static class ParserFactory extends AbstractBlockParserFactory {
137
    public ParserFactory( final DataHolder options ) {
138
      super( options );
139
    }
140
141
    /**
142
     * Try to match an opening or closing fenced div.
143
     *
144
     * @param state              Block parser state.
145
     * @param matchedBlockParser Last matched open block parser.
146
     * @return Wrapper for the opening or closing parser, upon finding :::.
147
     */
148
    @Override
149
    public BlockStart tryStart(
150
      final ParserState state, final MatchedBlockParser matchedBlockParser ) {
151
      return
152
        state.getIndent() == 0 && FENCE.matcher( state.getLine() ).matches()
153
          ? parseFence( state )
154
          : BlockStart.none();
155
    }
156
157
    /**
158
     * After finding a fenced div, this will further disambiguate an opening
159
     * from a closing fence.
160
     *
161
     * @param state Block parser state, contains line to parse.
162
     * @return Wrapper for the opening or closing parser, upon finding :::.
163
     */
164
    private BlockStart parseFence( final ParserState state ) {
165
      final var fence = FENCE_OPENING.matcher( state.getLine() );
166
167
      return BlockStart.of(
168
        fence.matches()
169
          ? new OpeningParser( fence.group( 1 ) )
170
          : new ClosingParser()
171
      ).atIndex( state.getIndex() );
172
    }
173
  }
174
175
  /**
176
   * Abstracts common {@link OpeningParser} and {@link ClosingParser} methods.
177
   */
178
  private static abstract class DivBlockParser extends AbstractBlockParser {
179
    @Override
180
    public BlockContinue tryContinue( final ParserState state ) {
181
      return BlockContinue.none();
182
    }
183
184
    @Override
185
    public void closeBlock( final ParserState state ) {}
186
  }
187
188
  /**
189
   * Responsible for creating an instance of {@link OpeningDivBlock}.
190
   */
191
  private static class OpeningParser extends DivBlockParser {
192
    private final OpeningDivBlock mBlock;
193
194
    /**
195
     * Parses the arguments upon construction.
196
     *
197
     * @param args Text after :::, excluding leading/trailing whitespace.
198
     */
199
    public OpeningParser( final String args ) {
200
      final var attrs = new ArrayList<Attribute>();
201
      final var cssMatcher = ATTR_CSS.matcher( args );
202
203
      if( cssMatcher.matches() ) {
204
        // Split the text between braces into tokens and/or key-value pairs.
205
        final var pairMatcher = ATTR_PAIRS.matcher( cssMatcher.group( 1 ) );
206
207
        while( pairMatcher.find() ) {
208
          final var cssDef = pairMatcher.group( "d" );
209
          String cssAttrKey = "class";
210
          String cssAttrVal;
211
212
          // When no regular CSS definition (id or class), use key/value pairs.
213
          if( cssDef == null ) {
214
            cssAttrKey = "data-" + pairMatcher.group( "k" );
215
            cssAttrVal = pairMatcher.group( "v" );
216
          }
217
          else {
218
            // This will strip the "#" and "." off the start of CSS definition.
219
            var index = 1;
220
221
            // Default CSS attribute name is "class", switch to "id" for #.
222
            if( cssDef.startsWith( "#" ) ) {
223
              cssAttrKey = "id";
224
            }
225
            else if( !cssDef.startsWith( "." ) ) {
226
              index = 0;
227
            }
228
229
            cssAttrVal = cssDef.substring( index );
230
          }
231
232
          attrs.add( AttributeImpl.of( cssAttrKey, cssAttrVal ) );
233
        }
234
      }
235
      else {
236
        attrs.add( AttributeImpl.of( "class", args ) );
237
      }
238
239
      mBlock = new OpeningDivBlock( attrs );
240
    }
241
242
    @Override
243
    public Block getBlock() {
244
      return mBlock;
245
    }
246
  }
247
248
  /**
249
   * Responsible for creating an instance of {@link ClosingDivBlock}.
250
   */
251
  private static class ClosingParser extends DivBlockParser {
252
    private final ClosingDivBlock mBlock = new ClosingDivBlock();
253
254
    @Override
255
    public Block getBlock() {
256
      return mBlock;
257
    }
258
  }
259
}
1260
A src/main/java/com/keenwrite/processors/markdown/extensions/fences/FencedDivRenderer.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions.fences;
3
4
import com.vladsch.flexmark.html.HtmlWriter;
5
import com.vladsch.flexmark.html.renderer.NodeRenderer;
6
import com.vladsch.flexmark.html.renderer.NodeRendererContext;
7
import com.vladsch.flexmark.html.renderer.NodeRendererFactory;
8
import com.vladsch.flexmark.html.renderer.NodeRenderingHandler;
9
import com.vladsch.flexmark.util.data.DataHolder;
10
import org.jetbrains.annotations.NotNull;
11
import org.jetbrains.annotations.Nullable;
12
13
import java.util.Set;
14
15
/**
16
 * Responsible for rendering opening and closing fenced div blocks as HTMl
17
 * div elements.
18
 */
19
class FencedDivRenderer implements NodeRenderer {
20
  @Override
21
  public @Nullable Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() {
22
    return Set.of(
23
      new NodeRenderingHandler<>( OpeningDivBlock.class, this::render ),
24
      new NodeRenderingHandler<>( ClosingDivBlock.class, this::render )
25
    );
26
  }
27
28
  /**
29
   * Renders the opening fenced div block as an HTML {@code <div>} element.
30
   */
31
  void render( final OpeningDivBlock node,
32
               final NodeRendererContext context,
33
               final HtmlWriter html ) {
34
    node.export( html );
35
  }
36
37
  /**
38
   * Renders the closing fenced div block as an HTML {@code </div>} element.
39
   */
40
  void render( final ClosingDivBlock node,
41
               final NodeRendererContext context,
42
               final HtmlWriter html ) {
43
    node.export( html );
44
  }
45
46
  static class Factory implements @NotNull NodeRendererFactory {
47
    @Override
48
    public @NotNull NodeRenderer apply( @NotNull final DataHolder options ) {
49
      return new FencedDivRenderer();
50
    }
51
  }
52
}
153
A src/main/java/com/keenwrite/processors/markdown/extensions/fences/OpeningDivBlock.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.processors.markdown.extensions.fences;
3
4
import com.vladsch.flexmark.html.HtmlWriter;
5
import com.vladsch.flexmark.util.html.Attribute;
6
7
import java.util.ArrayList;
8
import java.util.List;
9
10
/**
11
 * Responsible for helping to generate an opening div element.
12
 */
13
class OpeningDivBlock extends DivBlock {
14
  private final List<Attribute> mAttributes = new ArrayList<>();
15
16
  OpeningDivBlock( final List<Attribute> attributes ) {
17
    assert attributes != null;
18
    mAttributes.addAll( attributes );
19
  }
20
21
  void export( final HtmlWriter html ) {
22
    mAttributes.forEach( html::attr );
23
    html.withAttr().tag( HTML_DIV );
24
  }
25
}
126
M src/main/java/com/keenwrite/processors/markdown/extensions/r/RExtension.java
132132
            }
133133
134
            blockNode.appendChild( node );
134
            if( node != null ) {
135
              blockNode.appendChild( node );
136
            }
135137
          }
136138
        }
M src/main/java/com/keenwrite/processors/markdown/extensions/tex/TeXInlineDelimiterProcessor.java
1414
                       final Delimiter closer,
1515
                       final int delimitersUsed ) {
16
    final var node = new TexNode();
16
    final var node = new TexNode( opener, closer );
1717
    opener.moveNodesBetweenDelimitersTo( node, closer );
1818
  }
...
4343
  @Override
4444
  public int getDelimiterUse(
45
      final DelimiterRun opener, final DelimiterRun closer ) {
45
    final DelimiterRun opener, final DelimiterRun closer ) {
4646
    return 1;
4747
  }
...
7373
  @Override
7474
  public Node unmatchedDelimiterNode(
75
      final InlineParser inlineParser, final DelimiterRun delimiter ) {
75
    final InlineParser inlineParser, final DelimiterRun delimiter ) {
7676
    return null;
7777
  }
M src/main/java/com/keenwrite/processors/markdown/extensions/tex/TexNode.java
33
44
import com.vladsch.flexmark.ast.DelimitedNodeImpl;
5
import com.vladsch.flexmark.parser.core.delimiter.Delimiter;
56
67
public class TexNode extends DelimitedNodeImpl {
...
1314
  public static final String TOKEN_CLOSE = "$";
1415
15
  public TexNode() {
16
  private final String mOpener;
17
  private final String mCloser;
18
19
  /**
20
   * Creates a new TeX node representation that can distinguish between '$'
21
   * and '$$' as opening/closing delimiters. The '$' is used for inline
22
   * TeX statements and '$$' is used for multi-line statements.
23
   *
24
   * @param opener The opening delimiter.
25
   * @param closer The closing delimiter.
26
   */
27
  public TexNode( final Delimiter opener, final Delimiter closer ) {
28
    mOpener = getDelimiter( opener );
29
    mCloser = getDelimiter( closer );
30
  }
31
32
  /**
33
   * @return Either '$' or '$$.
34
   */
35
  public String getOpeningDelimiter() { return mOpener; }
36
37
  /**
38
   * @return Either '$' or '$$.
39
   */
40
  public String getClosingDelimiter() { return mCloser; }
41
42
  private String getDelimiter( final Delimiter delimiter ) {
43
    return delimiter.getInput().subSequence(
44
      delimiter.getStartIndex(), delimiter.getEndIndex()
45
    ).toString();
1646
  }
1747
}
M src/main/java/com/keenwrite/processors/markdown/extensions/tex/TexNodeRenderer.java
2323
2424
public class TexNodeRenderer {
25
  private static final RendererFacade RENDERER =
26
    new TexElementNodeRenderer( false );
27
2528
  private static final Map<ExportFormat, RendererFacade> EXPORT_RENDERERS =
2629
    Map.of(
30
      APPLICATION_PDF, new TexElementNodeRenderer( true ),
2731
      HTML_TEX_SVG, new TexSvgNodeRenderer(),
2832
      HTML_TEX_DELIMITED, new TexDelimNodeRenderer(),
33
      XHTML_TEX, new TexElementNodeRenderer( true ),
2934
      MARKDOWN_PLAIN, new TexDelimNodeRenderer(),
30
      NONE, new TexElementNodeRenderer()
35
      NONE, RENDERER
3136
    );
3237
3338
  public static class Factory implements NodeRendererFactory {
3439
    private final RendererFacade mNodeRenderer;
3540
3641
    public Factory(
3742
      final ExportFormat exportFormat, final Processor<String> processor ) {
38
      mNodeRenderer = EXPORT_RENDERERS.get( exportFormat );
43
      mNodeRenderer = EXPORT_RENDERERS.getOrDefault( exportFormat, RENDERER );
3944
      mNodeRenderer.setProcessor( processor );
4045
    }
4146
4247
    @NotNull
4348
    @Override
44
    public NodeRenderer apply( @NotNull DataHolder options ) {
49
    public NodeRenderer apply( @NotNull final DataHolder options ) {
4550
      return mNodeRenderer;
4651
    }
...
5358
    @Override
5459
    public @Nullable Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() {
55
      final var h = new NodeRenderingHandler<>( TexNode.class, this::render );
56
      return Set.of( h );
60
      return Set.of(
61
        new NodeRenderingHandler<>( TexNode.class, this::render )
62
      );
5763
    }
5864
...
8389
   */
8490
  private static class TexElementNodeRenderer extends RendererFacade {
91
    private final boolean mIncludeDelimiter;
92
93
    private TexElementNodeRenderer( final boolean includeDelimiter ) {
94
      mIncludeDelimiter = includeDelimiter;
95
    }
96
8597
    void render( final TexNode node,
8698
                 final NodeRendererContext context,
8799
                 final HtmlWriter html ) {
100
      final var text = getProcessor().apply( node.getText().toString() );
101
      final var content =
102
        mIncludeDelimiter
103
          ? node.getOpeningDelimiter() + text + node.getClosingDelimiter()
104
          : text;
88105
      html.tag( HTML_TEX );
89
      html.raw( getProcessor().apply( node.getText().toString() ) );
106
      html.raw( content );
90107
      html.closeTag( HTML_TEX );
91108
    }
M src/main/java/com/keenwrite/processors/r/InlineRProcessor.java
1717
import java.util.concurrent.atomic.AtomicBoolean;
1818
19
import static com.keenwrite.Constants.STATUS_PARSE_ERROR;
19
import static com.keenwrite.constants.Constants.STATUS_PARSE_ERROR;
2020
import static com.keenwrite.Messages.get;
2121
import static com.keenwrite.events.StatusEvent.clue;
A src/main/java/com/keenwrite/quotes/SmartQuotes.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.quotes;
3
4
import java.io.BufferedReader;
5
import java.io.InputStreamReader;
6
import java.util.AbstractMap.SimpleEntry;
7
import java.util.ArrayList;
8
import java.util.Map;
9
import java.util.function.Function;
10
import java.util.regex.Pattern;
11
12
import static java.util.Arrays.binarySearch;
13
import static java.util.Collections.sort;
14
15
/**
16
 * Responsible for converting straight quotes into smart quotes. This must be
17
 * used on plain text. The class will not parse HTML, TeX, or non-English text.
18
 */
19
public class SmartQuotes {
20
21
  /**
22
   * The main regex captures all words that contain an apostrophe. The terms
23
   * inner, outer, began, and ended define where the apostrophes can be found
24
   * in a particular word. The following text contains 3 word matches against
25
   * the "inner" pattern:
26
   *
27
   * <p>
28
   * 'Janes' said, ''E'll be spooky, Sam's son with the jack-o'-lantern!',"
29
   * said the O'Mally twins'---y'know---ghosts in unison.'
30
   * </p>
31
   */
32
  private static final Map<String, Pattern> PATTERNS = Map.ofEntries(
33
    // @formatter:off
34
    createEntry( "inner", "(?<![\\p{L}'])(?:\\p{L}+')+\\p{L}+(?![\\p{L}'])" ),
35
    createEntry( "began", "(?<!\\p{L})(?:'\\p{L}+)+(?![\\p{L}'])" ),
36
    createEntry( "ended", "(?<![\\p{L}'])(?:\\p{L}+')+(?!\\p{L})" ),
37
    createEntry( "outer", "(?<!\\p{L})'\\p{L}+'(?!\\p{L})" ),
38
    createEntry( "years", "'(?=\\d{2}s?)" ),
39
    createEntry( "+ings", "[\\p{L}]{2,}in'\\s?" ),
40
    createEntry( "prime", "((-?[0-9]\\d*(\\.\\d+)?)\\\\?'\\s?(-?[0-9]\\d*(\\.\\d+)?)\\\\?\")|((-?[0-9]\\d*(\\.\\d+)?)(''|\")\\s?(x|×)\\s?(-?[0-9]\\d*(\\.\\d+)?)(''|\"))|((-?[0-9]\\d*(\\.\\d+)?)'')" ),
41
    createEntry( "texop", "``" ),
42
    createEntry( "texcl", "''" ),
43
    createEntry( "white", "(?!\\s+)\"|\"(?!\\s+)" ),
44
    createEntry( "slash", "\\\\\"" )
45
    // @formatter:on
46
  );
47
48
  private static SimpleEntry<String, Pattern> createEntry(
49
    final String key, final String regex ) {
50
    return new SimpleEntry<>( key, Pattern.compile( regex ) );
51
  }
52
53
  /**
54
   * Left single quote replacement text.
55
   */
56
  private static final String QUOTE_SINGLE_LEFT = "&lsquo;";
57
58
  /**
59
   * Right single quote replacement text.
60
   */
61
  private static final String QUOTE_SINGLE_RIGHT = "&rsquo;";
62
63
  /**
64
   * Left double quote replacement text.
65
   */
66
  private static final String QUOTE_DOUBLE_LEFT = "&ldquo;";
67
68
  /**
69
   * Right double quote replacement text.
70
   */
71
  private static final String QUOTE_DOUBLE_RIGHT = "&rdquo;";
72
73
  /**
74
   * Apostrophe replacement text.
75
   */
76
  private static final String APOSTROPHE = "&apos;";
77
78
  /**
79
   * Prime replacement text.
80
   */
81
  private static final String SINGLE_PRIME = "&prime;";
82
83
  /**
84
   * Double prime replacement text.
85
   */
86
  private static final String DOUBLE_PRIME = "&Prime;";
87
88
  /**
89
   * Temporary single quote marker near end of Unicode private use area.
90
   */
91
  private static final String SQ = "\uF8FE";
92
93
  /**
94
   * Temporary double quote marker near end of Unicode private use area.
95
   */
96
  private static final String DQ = "\uF8FD";
97
98
  private final Map<String, String[]> CONTRACTIONS = Map.ofEntries(
99
    load( "inner" ),
100
    load( "began" ),
101
    load( "ended" ),
102
    load( "outer" ),
103
    load( "verbs" )
104
  );
105
106
  public SmartQuotes() {
107
  }
108
109
  /**
110
   * Replaces straight single and double quotes with curly quotes or primes,
111
   * depending on the context.
112
   *
113
   * @param text The text that may contain straight single or double quotes.
114
   * @return All single and double quotes replaced with typographically
115
   * correct quotation marks.
116
   */
117
  public String replace( String text ) {
118
    // Replace known contractions.
119
    text = contractions( text );
120
121
    // Replace miscellaneous verb contractions.
122
    text = verbs( text );
123
124
    // Replace primes and double-primes (e.g., 5'4").
125
    text = primes( text );
126
127
    // Replace decade contractions.
128
    text = decades( text );
129
130
    // Replace contractions of words ending in "ing" (e.g., washin').
131
    text = suffixes( text );
132
133
    // Replace double backticks.
134
    text = backticks( text );
135
136
    // Unescape straight double quotes.
137
    text = escapes( text );
138
139
    return text;
140
  }
141
142
  /**
143
   * Replaces all strings in the given text that match the given pattern,
144
   * provided the functor answers {@code true} to the matched regex.
145
   *
146
   * @param text    The text to perform a replacement.
147
   * @param pattern The regular expression pattern to match.
148
   * @param filter  Controls whether a text replacement is made.
149
   * @return The given text with matching patterns replaced, conditionally.
150
   */
151
  private String replace( final String text,
152
                          final Pattern pattern,
153
                          final Function<String, Boolean> filter,
154
                          final Function<String, String> subst ) {
155
    final var sb = new StringBuilder( text.length() * 2 );
156
    final var matcher = pattern.matcher( text );
157
158
    while( matcher.find() ) {
159
      final var match = matcher.group( 0 );
160
      if( filter.apply( match ) ) {
161
        matcher.appendReplacement( sb, subst.apply( match ) );
162
      }
163
    }
164
165
    matcher.appendTail( sb );
166
    return sb.toString();
167
  }
168
169
  /**
170
   * Convenience method that always performs string replacement upon a match,
171
   * unconditionally.
172
   */
173
  private String apostrophize( final String text, final Pattern pattern ) {
174
    return apostrophize( text, pattern, ( match ) -> true );
175
  }
176
177
  private String apostrophize( final String text, final String pattern ) {
178
    return apostrophize( text, PATTERNS.get( pattern ) );
179
  }
180
181
  private String decades( final String text ) {
182
    return apostrophize( text, "years" );
183
  }
184
185
  private String suffixes( final String text ) {
186
    return apostrophize( text, "+ings" );
187
  }
188
189
  /**
190
   * Convenience method that replaces each straight quote in the given {@code
191
   * text} that passes through the given filter with an {@link #APOSTROPHE}.
192
   */
193
  private String apostrophize(
194
    final String text,
195
    final Pattern pattern,
196
    final Function<String, Boolean> filter ) {
197
    return replace(
198
      text,
199
      pattern,
200
      filter,
201
      ( match ) -> match.replaceAll( "'", APOSTROPHE ) );
202
  }
203
204
  private String contractions( String text ) {
205
    final var elements = new String[]{"inner", "began", "ended", "outer"};
206
207
    for( final var item : elements ) {
208
      final var pattern = PATTERNS.get( item );
209
      final var contractions = CONTRACTIONS.get( item );
210
211
      text = apostrophize(
212
        text,
213
        pattern,
214
        ( match ) -> binarySearch( contractions, match.toLowerCase() ) >= 0
215
      );
216
    }
217
218
    return text;
219
  }
220
221
  /**
222
   * Replaces verb endings, such as 'll and 've, with words not explicitly
223
   * listed as contractions in the dictionary sources.
224
   *
225
   * @param text The text to replace.
226
   * @return The given text with matching patterns replaced.
227
   */
228
  private String verbs( String text ) {
229
    for( final var contraction : CONTRACTIONS.get( "verbs" ) ) {
230
      final var pattern = Pattern.compile( "[\\p{L}]+" + contraction );
231
      text = apostrophize( text, pattern );
232
    }
233
234
    return text;
235
  }
236
237
  private String primes( final String text ) {
238
    System.out.println( "REPLACE: " + text);
239
    return replace(
240
      text,
241
      PATTERNS.get( "prime" ),
242
      ( match ) -> true,
243
      ( match ) -> match.replaceAll( "''", DOUBLE_PRIME )
244
                        .replaceAll( "\"", DOUBLE_PRIME )
245
                        .replaceAll( "'", SINGLE_PRIME )
246
                        .replaceAll( "\\\\", "" )
247
    );
248
  }
249
250
  /**
251
   * Replace all double backticks with opening double quote.
252
   */
253
  private String backticks( String text ) {
254
    final var sb = new StringBuilder( text.length() * 2 );
255
    final var opening = PATTERNS.get( "texop" );
256
    final var opener = opening.matcher( text );
257
    var count = 0;
258
259
    while( opener.find() ) {
260
      count++;
261
      opener.appendReplacement( sb, QUOTE_DOUBLE_LEFT );
262
    }
263
264
    opener.appendTail( sb );
265
266
    if( count > 0 ) {
267
      text = sb.toString();
268
      sb.setLength( 0 );
269
270
      final var closing = PATTERNS.get( "texcl" );
271
      final var closer = closing.matcher( text );
272
      while( count > 0 && closer.find() ) {
273
        count--;
274
        closer.appendReplacement( sb, QUOTE_DOUBLE_RIGHT );
275
      }
276
277
      closer.appendTail( sb );
278
    }
279
280
    return sb.toString();
281
  }
282
283
  private String escapes( final String text ) {
284
    return replace(
285
      text,
286
      PATTERNS.get( "slash" ),
287
      ( match ) -> true,
288
      ( match ) -> match.replaceAll( "\\\\", "" )
289
    );
290
  }
291
292
  /**
293
   * Reads the list of words containing contractions.
294
   */
295
  @SuppressWarnings( "SameParameterValue" )
296
  private SimpleEntry<String, String[]> load( final String prefix ) {
297
    // Allocate enough elements to hold all the contractions.
298
    final var result = new ArrayList<String>( 1024 );
299
300
    try( final var in = openResource( prefix + ".txt" ) ) {
301
      for( String line; ((line = in.readLine()) != null); ) {
302
        result.add( line );
303
      }
304
305
      sort( result );
306
    } catch( final Exception ex ) {
307
      throw new RuntimeException( ex );
308
    }
309
310
    return new SimpleEntry<>( prefix, result.toArray( new String[ 0 ] ) );
311
  }
312
313
  private BufferedReader openResource( final String filename ) {
314
    final var in = getClass().getResourceAsStream( filename );
315
    assert in != null;
316
317
    return new BufferedReader( new InputStreamReader( in ) );
318
  }
319
}
1320
M src/main/java/com/keenwrite/service/events/impl/ButtonOrderPane.java
66
import javafx.scene.control.DialogPane;
77
8
import static com.keenwrite.Constants.sSettings;
8
import static com.keenwrite.constants.Constants.sSettings;
99
import static javafx.scene.control.ButtonBar.BUTTON_ORDER_WINDOWS;
1010
M src/main/java/com/keenwrite/service/events/impl/DefaultNotifier.java
1010
import java.nio.file.Path;
1111
12
import static com.keenwrite.Constants.ICON_DIALOG_NODE;
12
import static com.keenwrite.constants.GraphicsConstants.ICON_DIALOG_NODE;
1313
import static com.keenwrite.Messages.get;
1414
import static javafx.scene.control.Alert.AlertType.CONFIRMATION;
M src/main/java/com/keenwrite/service/impl/DefaultSettings.java
1313
import java.util.List;
1414
15
import static com.keenwrite.Constants.PATH_PROPERTIES_SETTINGS;
15
import static com.keenwrite.constants.Constants.PATH_PROPERTIES_SETTINGS;
1616
1717
/**
M src/main/java/com/keenwrite/spelling/impl/SymSpellSpeller.java
1717
import java.util.stream.Collectors;
1818
19
import static com.keenwrite.Constants.LEXICONS_DIRECTORY;
19
import static com.keenwrite.constants.Constants.LEXICONS_DIRECTORY;
2020
import static com.keenwrite.events.StatusEvent.clue;
2121
import static io.gitlab.rxp90.jsymspell.SymSpell.Verbosity;
A src/main/java/com/keenwrite/typesetting/Typesetter.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.typesetting;
3
4
import com.keenwrite.io.SysFile;
5
import com.keenwrite.preferences.Workspace;
6
7
import java.io.*;
8
import java.nio.file.NoSuchFileException;
9
import java.nio.file.Path;
10
import java.util.ArrayList;
11
import java.util.List;
12
import java.util.Scanner;
13
import java.util.concurrent.Callable;
14
import java.util.regex.Pattern;
15
16
import static com.keenwrite.Messages.get;
17
import static com.keenwrite.constants.Constants.DEFAULT_DIRECTORY;
18
import static com.keenwrite.events.StatusEvent.clue;
19
import static com.keenwrite.preferences.WorkspaceKeys.KEY_TYPESET_CONTEXT_THEMES_PATH;
20
import static com.keenwrite.preferences.WorkspaceKeys.KEY_TYPESET_CONTEXT_THEME_SELECTION;
21
import static java.lang.ProcessBuilder.Redirect.DISCARD;
22
import static java.lang.String.format;
23
import static java.lang.System.currentTimeMillis;
24
import static java.nio.file.Files.deleteIfExists;
25
import static java.nio.file.Files.newDirectoryStream;
26
import static java.util.concurrent.TimeUnit.*;
27
import static org.apache.commons.io.FilenameUtils.removeExtension;
28
29
/**
30
 * Responsible for invoking an executable to typeset text. This will
31
 * construct suitable command-line arguments to invoke the typesetting engine.
32
 */
33
public class Typesetter {
34
  private static final SysFile TYPESETTER = new SysFile( "mtxrun" );
35
36
  private final Workspace mWorkspace;
37
38
  /**
39
   * Creates a new {@link Typesetter} instance capable of configuring the
40
   * typesetter used to generate a typeset document.
41
   */
42
  public Typesetter( final Workspace workspace ) {
43
    mWorkspace = workspace;
44
  }
45
46
  public static boolean canRun() {
47
    return TYPESETTER.canRun();
48
  }
49
50
  /**
51
   * This will typeset the document using a new process. The return value only
52
   * indicates whether the typesetter exists, not whether the typesetting was
53
   * successful.
54
   *
55
   * @param in  The input document to typeset.
56
   * @param out Path to the finished typeset document.
57
   * @throws IOException                 If the process could not be started.
58
   * @throws InterruptedException        If the process was killed.
59
   * @throws TypesetterNotFoundException When no typesetter is along the PATH.
60
   */
61
  public void typeset( final Path in, final Path out )
62
    throws IOException, InterruptedException, TypesetterNotFoundException {
63
    if( TYPESETTER.canRun() ) {
64
      clue( get( "Main.status.typeset.began", out ) );
65
      final var task = new TypesetTask( in, out );
66
      final var time = currentTimeMillis();
67
      final var success = task.typeset();
68
69
      clue( get(
70
        "Main.status.typeset.ended." + (success ? "success" : "failure"),
71
        out, since( time ) )
72
      );
73
    }
74
    else {
75
      throw new TypesetterNotFoundException( TYPESETTER.toString() );
76
    }
77
  }
78
79
  /**
80
   * Calculates the time that has elapsed from the current time to the
81
   * given moment in time.
82
   *
83
   * @param start The starting time, which should be before the current time.
84
   * @return A human-readable formatted time.
85
   * @see #asElapsed(long)
86
   */
87
  private static String since( final long start ) {
88
    return asElapsed( currentTimeMillis() - start );
89
  }
90
91
  /**
92
   * Converts an elapsed time to a human-readable format (hours, minutes,
93
   * seconds, and milliseconds).
94
   *
95
   * @param elapsed An elapsed time, in milliseconds.
96
   * @return Human-readable elapsed time.
97
   */
98
  private static String asElapsed( final long elapsed ) {
99
    final var hours = MILLISECONDS.toHours( elapsed );
100
    final var eHours = elapsed - HOURS.toMillis( hours );
101
    final var minutes = MILLISECONDS.toMinutes( eHours );
102
    final var eMinutes = eHours - MINUTES.toMillis( minutes );
103
    final var seconds = MILLISECONDS.toSeconds( eMinutes );
104
    final var eSeconds = eMinutes - SECONDS.toMillis( seconds );
105
    final var milliseconds = MILLISECONDS.toMillis( eSeconds );
106
107
    return format( "%02d:%02d:%02d.%03d",
108
                   hours, minutes, seconds, milliseconds );
109
  }
110
111
  /**
112
   * Launches a task to typeset a document.
113
   */
114
  private class TypesetTask implements Callable<Boolean> {
115
    private final List<String> mArgs = new ArrayList<>();
116
    private final Path mInput;
117
    private final Path mOutput;
118
119
    /**
120
     * Working directory must be set because ConTeXt cannot write the
121
     * result to an arbitrary location.
122
     */
123
    private final Path mDirectory;
124
125
    private TypesetTask( final Path input, final Path output ) {
126
      assert input != null;
127
      assert output != null;
128
129
      final var parentDir = output.getParent();
130
      mInput = input;
131
      mOutput = output;
132
      mDirectory = parentDir == null ? DEFAULT_DIRECTORY : parentDir;
133
    }
134
135
    /**
136
     * Initializes ConTeXt, which means creating the cache directory if it
137
     * doesn't already exist. The theme entry point must be named 'main.tex'.
138
     *
139
     * @return {@code true} if the cache directory exists.
140
     */
141
    private boolean reinitialize() {
142
      final var filename = mOutput.getFileName();
143
      final var themes = getThemesPath();
144
      final var theme = getThemesSelection();
145
      final var cacheExists = !isEmpty( getCacheDir().toPath() );
146
147
      // Ensure invoking multiple times will load the correct arguments.
148
      mArgs.clear();
149
      mArgs.add( TYPESETTER.getName() );
150
151
      if( cacheExists ) {
152
        mArgs.add( "--autogenerate" );
153
        mArgs.add( "--script" );
154
        mArgs.add( "mtx-context" );
155
        mArgs.add( "--batchmode" );
156
        mArgs.add( "--nonstopmode" );
157
        mArgs.add( "--purgeall" );
158
        mArgs.add( "--path='" + Path.of( themes.toString(), theme ) + "'" );
159
        mArgs.add( "--environment='main'" );
160
        mArgs.add( "--result='" + filename + "'" );
161
        mArgs.add( mInput.toString() );
162
163
        final var sb = new StringBuilder( 128 );
164
        mArgs.forEach( arg -> sb.append( arg ).append( " " ) );
165
        clue( sb.toString() );
166
      }
167
      else {
168
        mArgs.add( "--generate" );
169
      }
170
171
      return cacheExists;
172
    }
173
174
    /**
175
     * Setting {@code TEXMFCACHE} when run on a fresh system fails on first
176
     * run. If the cache directory doesn't exist, attempt to create it, then
177
     * call ConTeXt to generate the PDF. This is brittle because if the
178
     * directory is empty, or not populated with cached data, a false positive
179
     * will be returned, resulting in no PDF being created.
180
     *
181
     * @return {@code true} if the document was typeset successfully.
182
     * @throws IOException          If the process could not be started.
183
     * @throws InterruptedException If the process was killed.
184
     */
185
    private boolean typeset() throws IOException, InterruptedException {
186
      return reinitialize() ? call() : call() && reinitialize() && call();
187
    }
188
189
    @Override
190
    public Boolean call() throws IOException, InterruptedException {
191
      final var builder = new ProcessBuilder( mArgs );
192
      builder.directory( mDirectory.toFile() );
193
      builder.environment().put( "TEXMFCACHE", getCacheDir().toString() );
194
195
      // Without redirecting (or draining) stderr, the command may not
196
      // terminate successfully.
197
      builder.redirectError( DISCARD );
198
199
      final var process = builder.start();
200
201
      // Reading from stdout allows slurping page numbers while generating.
202
      final var listener = new PaginationListener( process.getInputStream() );
203
      listener.start();
204
205
      process.waitFor();
206
      final var exit = process.exitValue();
207
      process.destroy();
208
209
      // If there was an error, the typesetter will leave behind log, pdf, and
210
      // error files.
211
      if( exit != 0 ) {
212
        final var xmlName = mInput.getFileName().toString();
213
        final var srcName = mOutput.getFileName().toString();
214
        final var logName = newExtension( xmlName, ".log" );
215
        final var errName = newExtension( xmlName, "-error.log" );
216
        final var pdfName = newExtension( xmlName, ".pdf" );
217
        final var badName = newExtension( srcName, ".log" );
218
219
        deleteIfExists( badName );
220
        deleteIfExists( logName );
221
        deleteIfExists( errName );
222
        deleteIfExists( pdfName );
223
      }
224
225
      // Exit value for a successful invocation of the typesetter. This value
226
      // value is returned when creating the cache on the first run as well as
227
      // creating PDFs on subsequent runs (after the cache has been created).
228
      // Users don't care about exit codes, only whether the PDF was generated.
229
      return exit == 0;
230
    }
231
232
    private Path newExtension( final String baseName, final String ext ) {
233
      return mOutput.resolveSibling( removeExtension( baseName ) + ext );
234
    }
235
236
    /**
237
     * Returns the location of the cache directory.
238
     *
239
     * @return A fully qualified path to the location to store temporary
240
     * files between typesetting runs.
241
     */
242
    private java.io.File getCacheDir() {
243
      final var temp = System.getProperty( "java.io.tmpdir" );
244
      final var cache = Path.of( temp, "luatex-cache" );
245
      return cache.toFile();
246
    }
247
248
    /**
249
     * Answers whether the given directory is empty. The typesetting software
250
     * creates a non-empty directory by default. The return value from this
251
     * method is a proxy to answering whether the typesetter has been run for
252
     * the first time or not.
253
     *
254
     * @param path The directory to check for emptiness.
255
     * @return {@code true} if the directory is empty.
256
     */
257
    private boolean isEmpty( final Path path ) {
258
      try( final var stream = newDirectoryStream( path ) ) {
259
        return !stream.iterator().hasNext();
260
      } catch( final NoSuchFileException | FileNotFoundException ex ) {
261
        // A missing directory means it doesn't exist, ergo is empty.
262
        return true;
263
      } catch( final IOException ex ) {
264
        throw new RuntimeException( ex );
265
      }
266
    }
267
  }
268
269
  /**
270
   * Responsible for parsing the output from the typesetting engine and
271
   * updating the status bar to provide assurance that typesetting is
272
   * executing.
273
   *
274
   * <p>
275
   * Example lines written to standard output:
276
   * </p>
277
   * <pre>{@code
278
   * pages           > flushing realpage 15, userpage 15, subpage 15
279
   * pages           > flushing realpage 16, userpage 16, subpage 16
280
   * pages           > flushing realpage 1, userpage 1, subpage 1
281
   * pages           > flushing realpage 2, userpage 2, subpage 2
282
   * }</pre>
283
   * <p>
284
   * The lines are parsed; the first number is displayed in a status bar
285
   * message.
286
   * </p>
287
   */
288
  private static class PaginationListener extends Thread {
289
    private static final Pattern DIGITS = Pattern.compile( "[^\\d]+" );
290
291
    private final InputStream mInputStream;
292
293
    public PaginationListener( final InputStream in ) {
294
      mInputStream = in;
295
    }
296
297
    @Override
298
    public void run() {
299
      try( final var reader = createReader() ) {
300
        int pageCount = 1;
301
        int passCount = 1;
302
        int pageTotal = 0;
303
        String line;
304
305
        while( (line = reader.readLine()) != null ) {
306
          if( line.startsWith( "pages" ) ) {
307
            // The bottleneck will be the typesetting engine writing to stdout,
308
            // not the parsing of stdout.
309
            final var scanner = new Scanner( line ).useDelimiter( DIGITS );
310
            final var digits = scanner.next();
311
            final var page = Integer.parseInt( digits );
312
313
            // If the page number is less than the previous page count, it
314
            // means that the typesetting engine has started another pass.
315
            if( page < pageCount ) {
316
              passCount++;
317
              pageTotal = pageCount;
318
            }
319
320
            pageCount = page;
321
322
            // Let the user know that something is happening in the background.
323
            clue( get(
324
              "Main.status.typeset.page",
325
              pageCount, pageTotal < 1 ? "?" : pageTotal, passCount
326
            ) );
327
          }
328
        }
329
      } catch( final IOException ex ) {
330
        throw new RuntimeException( ex );
331
      }
332
    }
333
334
    private BufferedReader createReader() {
335
      return new BufferedReader( new InputStreamReader( mInputStream ) );
336
    }
337
  }
338
339
  private File getThemesPath() {
340
    return mWorkspace.toFile( KEY_TYPESET_CONTEXT_THEMES_PATH );
341
  }
342
343
  private String getThemesSelection() {
344
    return mWorkspace.toString( KEY_TYPESET_CONTEXT_THEME_SELECTION );
345
  }
346
}
1347
A src/main/java/com/keenwrite/typesetting/TypesetterNotFoundException.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.typesetting;
3
4
/**
5
 * Responsible for creating an alternate execution path when a typesetter
6
 * cannot be found.
7
 */
8
public class TypesetterNotFoundException extends RuntimeException {
9
  /**
10
   * Constructs a new exception that indicates the typesetting engine cannot
11
   * be found anywhere along the PATH.
12
   *
13
   * @param name Typesetter executable file name.
14
   */
15
  public TypesetterNotFoundException( final String name ) {
16
    super( name );
17
  }
18
}
119
M src/main/java/com/keenwrite/ui/actions/Action.java
1515
import java.util.List;
1616
17
import static com.keenwrite.Constants.ACTION_PREFIX;
17
import static com.keenwrite.constants.Constants.ACTION_PREFIX;
1818
import static com.keenwrite.ui.fonts.IconFactory.createGraphic;
1919
import static javafx.scene.input.KeyCombination.valueOf;
...
4141
    mIcon = icon;
4242
    mHandler = handler;
43
  }
44
45
  /**
46
   * Runs this action. Most actions are mapped to menu items, but some actions
47
   * (such as the Insert key to toggle overwrite mode) are not.
48
   */
49
  public void execute() {
50
    mHandler.handle( new ActionEvent() );
5143
  }
5244
...
9486
      tooltip = tooltip.substring( 0, tooltip.length() - 3 );
9587
    }
88
89
    // Do not display mnemonic accelerator character in tooltip text.
90
    // The accelerator key will still be available, this is display-only.
91
    tooltip = tooltip.replace( "_", "" );
9692
9793
    if( mAccelerator != null ) {
M src/main/java/com/keenwrite/ui/actions/ApplicationActions.java
99
import com.keenwrite.editors.markdown.HyperlinkModel;
1010
import com.keenwrite.editors.markdown.LinkVisitor;
11
import com.keenwrite.preferences.PreferencesController;
12
import com.keenwrite.preferences.Workspace;
13
import com.keenwrite.processors.markdown.MarkdownProcessor;
14
import com.keenwrite.search.SearchModel;
15
import com.keenwrite.ui.controls.SearchBar;
16
import com.keenwrite.ui.dialogs.ImageDialog;
17
import com.keenwrite.ui.dialogs.LinkDialog;
18
import com.keenwrite.ui.logging.LogView;
19
import com.vladsch.flexmark.ast.Link;
20
import javafx.scene.control.Alert;
21
import javafx.scene.control.Dialog;
22
import javafx.stage.Window;
23
import javafx.stage.WindowEvent;
24
25
import static com.keenwrite.Bootstrap.*;
26
import static com.keenwrite.Constants.ICON_DIALOG_NODE;
27
import static com.keenwrite.ExportFormat.*;
28
import static com.keenwrite.Messages.get;
29
import static com.keenwrite.events.StatusEvent.clue;
30
import static com.keenwrite.preferences.WorkspaceKeys.KEY_UI_RECENT_DIR;
31
import static com.keenwrite.processors.ProcessorFactory.createProcessors;
32
import static java.nio.file.Files.writeString;
33
import static javafx.event.Event.fireEvent;
34
import static javafx.scene.control.Alert.AlertType.INFORMATION;
35
import static javafx.stage.WindowEvent.WINDOW_CLOSE_REQUEST;
36
37
/**
38
 * Responsible for abstracting how functionality is mapped to the application.
39
 * This allows users to customize accelerator keys and will provide pluggable
40
 * functionality so that different text markup languages can change documents
41
 * using their respective syntax.
42
 */
43
@SuppressWarnings( "NonAsciiCharacters" )
44
public final class ApplicationActions {
45
  private static final String STYLE_SEARCH = "search";
46
47
  /**
48
   * When an action is executed, this is one of the recipients.
49
   */
50
  private final MainPane mMainPane;
51
52
  private final MainScene mMainScene;
53
54
  private final LogView mLogView;
55
56
  /**
57
   * Tracks finding text in the active document.
58
   */
59
  private final SearchModel mSearchModel;
60
61
  public ApplicationActions( final MainScene scene, final MainPane pane ) {
62
    mMainScene = scene;
63
    mMainPane = pane;
64
    mLogView = new LogView();
65
    mSearchModel = new SearchModel();
66
    mSearchModel.matchOffsetProperty().addListener( ( c, o, n ) -> {
67
      final var editor = getActiveTextEditor();
68
69
      // Clear highlighted areas before highlighting a new region.
70
      if( o != null ) {
71
        editor.unstylize( STYLE_SEARCH );
72
      }
73
74
      if( n != null ) {
75
        editor.moveTo( n.getStart() );
76
        editor.stylize( n, STYLE_SEARCH );
77
      }
78
    } );
79
80
    // When the active text editor changes, update the haystack.
81
    mMainPane.activeTextEditorProperty().addListener(
82
      ( c, o, n ) -> mSearchModel.search( getActiveTextEditor().getText() )
83
    );
84
  }
85
86
  public void file‿new() {
87
    getMainPane().newTextEditor();
88
  }
89
90
  public void file‿open() {
91
    getMainPane().open( createFileChooser().openFiles() );
92
  }
93
94
  public void file‿close() {
95
    getMainPane().close();
96
  }
97
98
  public void file‿close_all() {
99
    getMainPane().closeAll();
100
  }
101
102
  public void file‿save() {
103
    getMainPane().save();
104
  }
105
106
  public void file‿save_as() {
107
    final var file = createFileChooser().saveAs();
108
    file.ifPresent( ( f ) -> getMainPane().saveAs( f ) );
109
  }
110
111
  public void file‿save_all() {
112
    getMainPane().saveAll();
113
  }
114
115
  public void file‿export‿html_svg() {
116
    file‿export( HTML_TEX_SVG );
117
  }
118
119
  public void file‿export‿html_tex() {
120
    file‿export( HTML_TEX_DELIMITED );
121
  }
122
123
  public void file‿export‿markdown() {
124
    file‿export( MARKDOWN_PLAIN );
125
  }
126
127
  private void file‿export( final ExportFormat format ) {
128
    final var main = getMainPane();
129
    final var context = main.createProcessorContext( format );
130
    final var chain = createProcessors( context );
131
    final var editor = main.getActiveTextEditor();
132
    final var doc = editor.getText();
133
    final var export = chain.apply( doc );
134
    final var filename = format.toExportFilename( editor.getPath() );
135
    final var chooser = createFileChooser();
136
    final var file = chooser.exportAs( filename );
137
138
    file.ifPresent( ( f ) -> {
139
      try {
140
        writeString( f.toPath(), export );
141
        clue( get( "Main.status.export.success", f.toString() ) );
142
      } catch( final Exception ex ) {
143
        clue( ex );
144
      }
145
    } );
146
  }
147
148
  public void file‿exit() {
149
    final var window = getWindow();
150
    fireEvent( window, new WindowEvent( window, WINDOW_CLOSE_REQUEST ) );
151
  }
152
153
  public void edit‿undo() {
154
    getActiveTextEditor().undo();
155
  }
156
157
  public void edit‿redo() {
158
    getActiveTextEditor().redo();
159
  }
160
161
  public void edit‿cut() {
162
    getActiveTextEditor().cut();
163
  }
164
165
  public void edit‿copy() {
166
    getActiveTextEditor().copy();
167
  }
168
169
  public void edit‿paste() {
170
    getActiveTextEditor().paste();
171
  }
172
173
  public void edit‿select_all() {
174
    getActiveTextEditor().selectAll();
175
  }
176
177
  public void edit‿find() {
178
    final var nodes = getMainScene().getStatusBar().getLeftItems();
179
180
    if( nodes.isEmpty() ) {
181
      final var searchBar = new SearchBar();
182
183
      searchBar.matchIndexProperty().bind( mSearchModel.matchIndexProperty() );
184
      searchBar.matchCountProperty().bind( mSearchModel.matchCountProperty() );
185
186
      searchBar.setOnCancelAction( ( event ) -> {
187
        final var editor = getActiveTextEditor();
188
        nodes.remove( searchBar );
189
        editor.unstylize( STYLE_SEARCH );
190
        editor.getNode().requestFocus();
191
      } );
192
193
      searchBar.addInputListener( ( c, o, n ) -> {
194
        if( n != null && !n.isEmpty() ) {
195
          mSearchModel.search( n, getActiveTextEditor().getText() );
196
        }
197
      } );
198
199
      searchBar.setOnNextAction( ( event ) -> edit‿find_next() );
200
      searchBar.setOnPrevAction( ( event ) -> edit‿find_prev() );
201
202
      nodes.add( searchBar );
203
      searchBar.requestFocus();
204
    }
205
    else {
206
      nodes.clear();
207
    }
208
  }
209
210
  public void edit‿find_next() {
211
    mSearchModel.advance();
212
  }
213
214
  public void edit‿find_prev() {
215
    mSearchModel.retreat();
216
  }
217
218
  public void edit‿preferences() {
219
    new PreferencesController( getWorkspace() ).show();
220
  }
221
222
  public void format‿bold() {
223
    getActiveTextEditor().bold();
224
  }
225
226
  public void format‿italic() {
227
    getActiveTextEditor().italic();
228
  }
229
230
  public void format‿superscript() {
231
    getActiveTextEditor().superscript();
232
  }
233
234
  public void format‿subscript() {
235
    getActiveTextEditor().subscript();
236
  }
237
238
  public void format‿strikethrough() {
239
    getActiveTextEditor().strikethrough();
240
  }
241
242
  public void insert‿blockquote() {
243
    getActiveTextEditor().blockquote();
244
  }
245
246
  public void insert‿code() {
247
    getActiveTextEditor().code();
248
  }
249
250
  public void insert‿fenced_code_block() {
251
    getActiveTextEditor().fencedCodeBlock();
252
  }
253
254
  public void insert‿link() {
255
    insertObject( createLinkDialog() );
256
  }
257
258
  public void insert‿image() {
259
    insertObject( createImageDialog() );
260
  }
261
262
  private void insertObject( final Dialog<String> dialog ) {
263
    final var textArea = getActiveTextEditor().getTextArea();
264
    dialog.showAndWait().ifPresent( textArea::replaceSelection );
265
  }
266
267
  private Dialog<String> createLinkDialog() {
268
    return new LinkDialog( getWindow(), createHyperlinkModel() );
269
  }
270
271
  private Dialog<String> createImageDialog() {
272
    final var path = getActiveTextEditor().getPath();
273
    final var parentDir = path.getParent();
274
    return new ImageDialog( getWindow(), parentDir );
275
  }
276
277
  /**
278
   * Returns one of: selected text, word under cursor, or parsed hyperlink from
279
   * the Markdown AST.
280
   *
281
   * @return An instance containing the link URL and display text.
282
   */
283
  private HyperlinkModel createHyperlinkModel() {
284
    final var context = getMainPane().createProcessorContext();
285
    final var editor = getActiveTextEditor();
286
    final var textArea = editor.getTextArea();
287
    final var selectedText = textArea.getSelectedText();
288
289
    // Convert current paragraph to Markdown nodes.
290
    final var mp = MarkdownProcessor.create( context );
291
    final var p = textArea.getCurrentParagraph();
292
    final var paragraph = textArea.getText( p );
293
    final var node = mp.toNode( paragraph );
294
    final var visitor = new LinkVisitor( textArea.getCaretColumn() );
295
    final var link = visitor.process( node );
296
297
    if( link != null ) {
298
      textArea.selectRange( p, link.getStartOffset(), p, link.getEndOffset() );
299
    }
300
301
    return createHyperlinkModel( link, selectedText );
302
  }
303
304
  private HyperlinkModel createHyperlinkModel(
305
    final Link link, final String selection ) {
306
307
    return link == null
308
      ? new HyperlinkModel( selection, "https://localhost" )
309
      : new HyperlinkModel( link );
310
  }
311
312
  public void insert‿heading_1() {
313
    insert‿heading( 1 );
314
  }
315
316
  public void insert‿heading_2() {
317
    insert‿heading( 2 );
318
  }
319
320
  public void insert‿heading_3() {
321
    insert‿heading( 3 );
322
  }
323
324
  private void insert‿heading( final int level ) {
325
    getActiveTextEditor().heading( level );
326
  }
327
328
  public void insert‿unordered_list() {
329
    getActiveTextEditor().unorderedList();
330
  }
331
332
  public void insert‿ordered_list() {
333
    getActiveTextEditor().orderedList();
334
  }
335
336
  public void insert‿horizontal_rule() {
337
    getActiveTextEditor().horizontalRule();
338
  }
339
340
  public void definition‿create() {
341
    getActiveTextDefinition().createDefinition();
342
  }
343
344
  public void definition‿rename() {
345
    getActiveTextDefinition().renameDefinition();
346
  }
347
348
  public void definition‿delete() {
349
    getActiveTextDefinition().deleteDefinitions();
350
  }
351
352
  public void definition‿autoinsert() {
353
    getMainPane().autoinsert();
354
  }
355
356
  public void view‿refresh() {
357
    getMainPane().viewRefresh();
358
  }
359
360
  public void view‿preview() {
361
    getMainPane().viewPreview();
362
  }
363
364
  public void view‿outline() {
365
    getMainPane().viewOutline();
366
  }
367
368
  public void view‿files() { getMainPane().viewFiles(); }
369
370
  public void view‿statistics() {
371
    getMainPane().viewStatistics();
372
  }
373
374
  public void view‿menubar() {
375
    getMainScene().toggleMenuBar();
376
  }
377
378
  public void view‿toolbar() {
379
    getMainScene().toggleToolBar();
380
  }
381
382
  public void view‿statusbar() {
383
    getMainScene().toggleStatusBar();
384
  }
385
386
  public void view‿issues() {
387
    mLogView.view();
388
  }
389
390
  public void help‿about() {
391
    final var alert = new Alert( INFORMATION );
392
    final var prefix = "Dialog.about.";
393
    alert.setTitle( get( prefix + "title", APP_TITLE ) );
394
    alert.setHeaderText( get( prefix + "header", APP_TITLE ) );
395
    alert.setContentText( get( prefix + "content", APP_YEAR, APP_VERSION ) );
396
    alert.setGraphic( ICON_DIALOG_NODE );
397
    alert.initOwner( getWindow() );
398
    alert.showAndWait();
399
  }
400
401
  private FileChooserCommand createFileChooser() {
402
    final var dir = getWorkspace().fileProperty( KEY_UI_RECENT_DIR );
403
    return new FileChooserCommand( getWindow(), dir );
11
import com.keenwrite.events.ExportFailedEvent;
12
import com.keenwrite.preferences.PreferencesController;
13
import com.keenwrite.preferences.Workspace;
14
import com.keenwrite.processors.markdown.MarkdownProcessor;
15
import com.keenwrite.search.SearchModel;
16
import com.keenwrite.typesetting.Typesetter;
17
import com.keenwrite.ui.controls.SearchBar;
18
import com.keenwrite.ui.dialogs.ImageDialog;
19
import com.keenwrite.ui.dialogs.LinkDialog;
20
import com.keenwrite.ui.dialogs.ThemePicker;
21
import com.keenwrite.ui.explorer.FilePicker;
22
import com.keenwrite.ui.explorer.FilePickerFactory;
23
import com.keenwrite.ui.logging.LogView;
24
import com.vladsch.flexmark.ast.Link;
25
import javafx.concurrent.Task;
26
import javafx.scene.control.Alert;
27
import javafx.scene.control.Dialog;
28
import javafx.stage.Window;
29
import javafx.stage.WindowEvent;
30
31
import java.io.File;
32
import java.nio.file.Path;
33
import java.util.List;
34
import java.util.Optional;
35
import java.util.concurrent.ExecutorService;
36
37
import static com.keenwrite.Bootstrap.*;
38
import static com.keenwrite.ExportFormat.*;
39
import static com.keenwrite.Messages.get;
40
import static com.keenwrite.constants.GraphicsConstants.ICON_DIALOG_NODE;
41
import static com.keenwrite.events.StatusEvent.clue;
42
import static com.keenwrite.preferences.WorkspaceKeys.KEY_TYPESET_CONTEXT_THEMES_PATH;
43
import static com.keenwrite.preferences.WorkspaceKeys.KEY_TYPESET_CONTEXT_THEME_SELECTION;
44
import static com.keenwrite.processors.ProcessorFactory.createProcessors;
45
import static com.keenwrite.ui.explorer.FilePickerFactory.Options;
46
import static com.keenwrite.ui.explorer.FilePickerFactory.Options.*;
47
import static java.nio.file.Files.writeString;
48
import static java.util.concurrent.Executors.newFixedThreadPool;
49
import static javafx.application.Platform.runLater;
50
import static javafx.event.Event.fireEvent;
51
import static javafx.scene.control.Alert.AlertType.INFORMATION;
52
import static javafx.stage.WindowEvent.WINDOW_CLOSE_REQUEST;
53
54
/**
55
 * Responsible for abstracting how functionality is mapped to the application.
56
 * This allows users to customize accelerator keys and will provide pluggable
57
 * functionality so that different text markup languages can change documents
58
 * using their respective syntax.
59
 */
60
@SuppressWarnings( "NonAsciiCharacters" )
61
public final class ApplicationActions {
62
  private static final ExecutorService sExecutor = newFixedThreadPool( 1 );
63
64
  private static final String STYLE_SEARCH = "search";
65
66
  /**
67
   * When an action is executed, this is one of the recipients.
68
   */
69
  private final MainPane mMainPane;
70
71
  private final MainScene mMainScene;
72
73
  private final LogView mLogView;
74
75
  /**
76
   * Tracks finding text in the active document.
77
   */
78
  private final SearchModel mSearchModel;
79
80
  public ApplicationActions( final MainScene scene, final MainPane pane ) {
81
    mMainScene = scene;
82
    mMainPane = pane;
83
    mLogView = new LogView();
84
    mSearchModel = new SearchModel();
85
    mSearchModel.matchOffsetProperty().addListener( ( c, o, n ) -> {
86
      final var editor = getActiveTextEditor();
87
88
      // Clear highlighted areas before highlighting a new region.
89
      if( o != null ) {
90
        editor.unstylize( STYLE_SEARCH );
91
      }
92
93
      if( n != null ) {
94
        editor.moveTo( n.getStart() );
95
        editor.stylize( n, STYLE_SEARCH );
96
      }
97
    } );
98
99
    // When the active text editor changes, update the haystack.
100
    mMainPane.activeTextEditorProperty().addListener(
101
      ( c, o, n ) -> mSearchModel.search( getActiveTextEditor().getText() )
102
    );
103
  }
104
105
  public void file‿new() {
106
    getMainPane().newTextEditor();
107
  }
108
109
  public void file‿open() {
110
    pickFiles( FILE_OPEN_MULTIPLE ).ifPresent( l -> getMainPane().open( l ) );
111
  }
112
113
  public void file‿close() {
114
    getMainPane().close();
115
  }
116
117
  public void file‿close_all() {
118
    getMainPane().closeAll();
119
  }
120
121
  public void file‿save() {
122
    getMainPane().save();
123
  }
124
125
  public void file‿save_as() {
126
    pickFiles( FILE_SAVE_AS ).ifPresent( l -> getMainPane().saveAs( l ) );
127
  }
128
129
  public void file‿save_all() {
130
    getMainPane().saveAll();
131
  }
132
133
  private void file‿export( final ExportFormat format ) {
134
    final var main = getMainPane();
135
    final var editor = main.getActiveTextEditor();
136
    final var filename = format.toExportFilename( editor.getPath() );
137
    final var selection = pickFiles( filename, FILE_EXPORT );
138
139
    selection.ifPresent( ( files ) -> {
140
      final var file = files.get( 0 );
141
      final var path = file.toPath();
142
      final var document = editor.getText();
143
      final var context = main.createProcessorContext( path, format );
144
145
      final var task = new Task<Path>() {
146
        @Override
147
        protected Path call() throws Exception {
148
          final var chain = createProcessors( context );
149
          final var export = chain.apply( document );
150
151
          // Processors can export binary files. In such cases, processors
152
          // return null to prevent further processing.
153
          return export == null ? null : writeString( path, export );
154
        }
155
      };
156
157
      task.setOnSucceeded(
158
        e -> {
159
          final var result = task.getValue();
160
161
          // Binary formats must notify users of success independently.
162
          if( result != null ) {
163
            clue( get( "Main.status.export.success", result ) );
164
          }
165
        }
166
      );
167
168
      task.setOnFailed( e -> {
169
        final var ex = task.getException();
170
        clue( ex );
171
172
        if( ex instanceof TypeNotPresentException ) {
173
          fireExportFailedEvent();
174
        }
175
      } );
176
177
      sExecutor.execute( task );
178
    } );
179
  }
180
181
  public void file‿export‿pdf() {
182
    final var workspace = getWorkspace();
183
    final var themes = workspace.toFile( KEY_TYPESET_CONTEXT_THEMES_PATH );
184
    final var theme = workspace.stringProperty(
185
      KEY_TYPESET_CONTEXT_THEME_SELECTION );
186
187
    if( Typesetter.canRun() ) {
188
      // If the typesetter is installed, allow the user to select a theme. If
189
      // the themes aren't installed, a status message will appear.
190
      if( ThemePicker.choose( themes, theme ) ) {
191
        file‿export( APPLICATION_PDF );
192
      }
193
    }
194
    else {
195
      fireExportFailedEvent();
196
    }
197
  }
198
199
  public void file‿export‿html_svg() {
200
    file‿export( HTML_TEX_SVG );
201
  }
202
203
  public void file‿export‿html_tex() {
204
    file‿export( HTML_TEX_DELIMITED );
205
  }
206
207
  public void file‿export‿xhtml_tex() {
208
    file‿export( XHTML_TEX );
209
  }
210
211
  public void file‿export‿markdown() {
212
    file‿export( MARKDOWN_PLAIN );
213
  }
214
215
  private void fireExportFailedEvent() {
216
    runLater( ExportFailedEvent::fireExportFailedEvent );
217
  }
218
219
  public void file‿exit() {
220
    final var window = getWindow();
221
    fireEvent( window, new WindowEvent( window, WINDOW_CLOSE_REQUEST ) );
222
  }
223
224
  public void edit‿undo() {
225
    getActiveTextEditor().undo();
226
  }
227
228
  public void edit‿redo() {
229
    getActiveTextEditor().redo();
230
  }
231
232
  public void edit‿cut() {
233
    getActiveTextEditor().cut();
234
  }
235
236
  public void edit‿copy() {
237
    getActiveTextEditor().copy();
238
  }
239
240
  public void edit‿paste() {
241
    getActiveTextEditor().paste();
242
  }
243
244
  public void edit‿select_all() {
245
    getActiveTextEditor().selectAll();
246
  }
247
248
  public void edit‿find() {
249
    final var nodes = getMainScene().getStatusBar().getLeftItems();
250
251
    if( nodes.isEmpty() ) {
252
      final var searchBar = new SearchBar();
253
254
      searchBar.matchIndexProperty().bind( mSearchModel.matchIndexProperty() );
255
      searchBar.matchCountProperty().bind( mSearchModel.matchCountProperty() );
256
257
      searchBar.setOnCancelAction( ( event ) -> {
258
        final var editor = getActiveTextEditor();
259
        nodes.remove( searchBar );
260
        editor.unstylize( STYLE_SEARCH );
261
        editor.getNode().requestFocus();
262
      } );
263
264
      searchBar.addInputListener( ( c, o, n ) -> {
265
        if( n != null && !n.isEmpty() ) {
266
          mSearchModel.search( n, getActiveTextEditor().getText() );
267
        }
268
      } );
269
270
      searchBar.setOnNextAction( ( event ) -> edit‿find_next() );
271
      searchBar.setOnPrevAction( ( event ) -> edit‿find_prev() );
272
273
      nodes.add( searchBar );
274
      searchBar.requestFocus();
275
    }
276
    else {
277
      nodes.clear();
278
    }
279
  }
280
281
  public void edit‿find_next() {
282
    mSearchModel.advance();
283
  }
284
285
  public void edit‿find_prev() {
286
    mSearchModel.retreat();
287
  }
288
289
  public void edit‿preferences() {
290
    try {
291
      new PreferencesController( getWorkspace() ).show();
292
    } catch( final Exception ex ) {
293
      clue( ex );
294
    }
295
  }
296
297
  public void format‿bold() {
298
    getActiveTextEditor().bold();
299
  }
300
301
  public void format‿italic() {
302
    getActiveTextEditor().italic();
303
  }
304
305
  public void format‿superscript() {
306
    getActiveTextEditor().superscript();
307
  }
308
309
  public void format‿subscript() {
310
    getActiveTextEditor().subscript();
311
  }
312
313
  public void format‿strikethrough() {
314
    getActiveTextEditor().strikethrough();
315
  }
316
317
  public void insert‿blockquote() {
318
    getActiveTextEditor().blockquote();
319
  }
320
321
  public void insert‿code() {
322
    getActiveTextEditor().code();
323
  }
324
325
  public void insert‿fenced_code_block() {
326
    getActiveTextEditor().fencedCodeBlock();
327
  }
328
329
  public void insert‿link() {
330
    insertObject( createLinkDialog() );
331
  }
332
333
  public void insert‿image() {
334
    insertObject( createImageDialog() );
335
  }
336
337
  private void insertObject( final Dialog<String> dialog ) {
338
    final var textArea = getActiveTextEditor().getTextArea();
339
    dialog.showAndWait().ifPresent( textArea::replaceSelection );
340
  }
341
342
  private Dialog<String> createLinkDialog() {
343
    return new LinkDialog( getWindow(), createHyperlinkModel() );
344
  }
345
346
  private Dialog<String> createImageDialog() {
347
    final var path = getActiveTextEditor().getPath();
348
    final var parentDir = path.getParent();
349
    return new ImageDialog( getWindow(), parentDir );
350
  }
351
352
  /**
353
   * Returns one of: selected text, word under cursor, or parsed hyperlink from
354
   * the Markdown AST.
355
   *
356
   * @return An instance containing the link URL and display text.
357
   */
358
  private HyperlinkModel createHyperlinkModel() {
359
    final var context = getMainPane().createProcessorContext();
360
    final var editor = getActiveTextEditor();
361
    final var textArea = editor.getTextArea();
362
    final var selectedText = textArea.getSelectedText();
363
364
    // Convert current paragraph to Markdown nodes.
365
    final var mp = MarkdownProcessor.create( context );
366
    final var p = textArea.getCurrentParagraph();
367
    final var paragraph = textArea.getText( p );
368
    final var node = mp.toNode( paragraph );
369
    final var visitor = new LinkVisitor( textArea.getCaretColumn() );
370
    final var link = visitor.process( node );
371
372
    if( link != null ) {
373
      textArea.selectRange( p, link.getStartOffset(), p, link.getEndOffset() );
374
    }
375
376
    return createHyperlinkModel( link, selectedText );
377
  }
378
379
  private HyperlinkModel createHyperlinkModel(
380
    final Link link, final String selection ) {
381
382
    return link == null
383
      ? new HyperlinkModel( selection, "https://localhost" )
384
      : new HyperlinkModel( link );
385
  }
386
387
  public void insert‿heading_1() {
388
    insert‿heading( 1 );
389
  }
390
391
  public void insert‿heading_2() {
392
    insert‿heading( 2 );
393
  }
394
395
  public void insert‿heading_3() {
396
    insert‿heading( 3 );
397
  }
398
399
  private void insert‿heading( final int level ) {
400
    getActiveTextEditor().heading( level );
401
  }
402
403
  public void insert‿unordered_list() {
404
    getActiveTextEditor().unorderedList();
405
  }
406
407
  public void insert‿ordered_list() {
408
    getActiveTextEditor().orderedList();
409
  }
410
411
  public void insert‿horizontal_rule() {
412
    getActiveTextEditor().horizontalRule();
413
  }
414
415
  public void definition‿create() {
416
    getActiveTextDefinition().createDefinition();
417
  }
418
419
  public void definition‿rename() {
420
    getActiveTextDefinition().renameDefinition();
421
  }
422
423
  public void definition‿delete() {
424
    getActiveTextDefinition().deleteDefinitions();
425
  }
426
427
  public void definition‿autoinsert() {
428
    getMainPane().autoinsert();
429
  }
430
431
  public void view‿refresh() {
432
    getMainPane().viewRefresh();
433
  }
434
435
  public void view‿preview() {
436
    getMainPane().viewPreview();
437
  }
438
439
  public void view‿outline() {
440
    getMainPane().viewOutline();
441
  }
442
443
  public void view‿files() { getMainPane().viewFiles(); }
444
445
  public void view‿statistics() {
446
    getMainPane().viewStatistics();
447
  }
448
449
  public void view‿menubar() {
450
    getMainScene().toggleMenuBar();
451
  }
452
453
  public void view‿toolbar() {
454
    getMainScene().toggleToolBar();
455
  }
456
457
  public void view‿statusbar() {
458
    getMainScene().toggleStatusBar();
459
  }
460
461
  public void view‿issues() {
462
    mLogView.view();
463
  }
464
465
  public void help‿about() {
466
    final var alert = new Alert( INFORMATION );
467
    final var prefix = "Dialog.about.";
468
    alert.setTitle( get( prefix + "title", APP_TITLE ) );
469
    alert.setHeaderText( get( prefix + "header", APP_TITLE ) );
470
    alert.setContentText( get( prefix + "content", APP_YEAR, APP_VERSION ) );
471
    alert.setGraphic( ICON_DIALOG_NODE );
472
    alert.initOwner( getWindow() );
473
    alert.showAndWait();
474
  }
475
476
  private Optional<List<File>> pickFiles( final Options... options ) {
477
    return createPicker( options ).choose();
478
  }
479
480
  private Optional<List<File>> pickFiles(
481
    final File filename, final Options... options ) {
482
    final var picker = createPicker( options );
483
    picker.setInitialFilename( filename );
484
    return picker.choose();
485
  }
486
487
  private FilePicker createPicker( final Options... options ) {
488
    final var factory = new FilePickerFactory( getWorkspace() );
489
    return factory.createModal( getWindow(), options );
404490
  }
405491
M src/main/java/com/keenwrite/ui/actions/ApplicationBars.java
5757
      addAction( "file.export", e -> {} )
5858
        .addSubActions(
59
          addAction( "file.export.pdf", e -> actions.file‿export‿pdf() ),
5960
          addAction( "file.export.html_svg", e -> actions.file‿export‿html_svg() ),
6061
          addAction( "file.export.html_tex", e -> actions.file‿export‿html_tex() ),
62
          addAction( "file.export.xhtml_tex", e -> actions.file‿export‿xhtml_tex() ),
6163
          addAction( "file.export.markdown", e -> actions.file‿export‿markdown() )
6264
        ),
...
143145
      getAction( "file.open" ),
144146
      getAction( "file.save" ),
147
      SEPARATOR_ACTION,
148
      getAction( "file.export.pdf" ),
145149
      SEPARATOR_ACTION,
146150
      getAction( "edit.undo" ),
M src/main/java/com/keenwrite/ui/actions/FileChooserCommand.java
1515
import java.util.Optional;
1616
17
import static com.keenwrite.Constants.*;
17
import static com.keenwrite.constants.Constants.*;
1818
import static com.keenwrite.Messages.get;
1919
import static com.keenwrite.io.FileType.*;
M src/main/java/com/keenwrite/ui/controls/EventedStatusBar.java
77
88
import static com.keenwrite.events.Bus.register;
9
import static javafx.application.Platform.isFxApplicationThread;
910
import static javafx.application.Platform.runLater;
1011
...
2728
  @Subscribe
2829
  public void handle( final StatusEvent event ) {
29
    final var message = event.getMessage();
30
    final var m = event.getMessage() + event.getException();
3031
3132
    // Don't burden the repaint thread if there's no status bar change.
32
    if( !getText().equals( message ) ) {
33
      runLater(
34
        () -> {
35
          final var s = message == null ? "" : message;
36
          final var i = s.indexOf( '\n' );
37
          setText( s.substring( 0, i > 0 ? i : s.length() ) );
38
        }
39
      );
33
    if( !getText().equals( m ) ) {
34
      final var i = m.indexOf( '\n' );
35
36
      final Runnable update =
37
        () -> setText( m.substring( 0, i > 0 ? i : m.length() ) );
38
39
      if( isFxApplicationThread() ) {
40
        update.run();
41
      }
42
      else {
43
        runLater( update );
44
      }
4045
    }
4146
  }
M src/main/java/com/keenwrite/ui/dialogs/AbstractDialog.java
77
import javafx.stage.Window;
88
9
import static com.keenwrite.Constants.ICON_DIALOG;
9
import static com.keenwrite.constants.GraphicsConstants.ICON_DIALOG;
1010
import static com.keenwrite.Messages.get;
1111
import static javafx.scene.control.ButtonType.CANCEL;
A src/main/java/com/keenwrite/ui/dialogs/ThemePicker.java
1
/* Copyright 2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.dialogs;
3
4
import com.keenwrite.util.FileWalker;
5
import com.keenwrite.util.ResourceWalker;
6
import javafx.beans.property.StringProperty;
7
import javafx.scene.control.ChoiceDialog;
8
import javafx.scene.control.ComboBox;
9
import javafx.scene.input.KeyCode;
10
11
import java.io.File;
12
import java.io.FileInputStream;
13
import java.io.IOException;
14
import java.nio.file.Path;
15
import java.util.Properties;
16
import java.util.TreeMap;
17
18
import static com.keenwrite.Messages.get;
19
import static com.keenwrite.constants.GraphicsConstants.ICON_DIALOG_NODE;
20
import static com.keenwrite.events.StatusEvent.clue;
21
import static com.keenwrite.util.FileWalker.walk;
22
import static java.lang.Math.max;
23
24
/**
25
 * Responsible for allowing the user to pick from the available themes found
26
 * in the system.
27
 */
28
public class ThemePicker extends ChoiceDialog<String> {
29
  private final File mThemes;
30
  private final StringProperty mTheme;
31
32
  /**
33
   * Construction must use static method to allow caching themes in the
34
   * future, if needed.
35
   *
36
   * @see #choose(File, StringProperty)
37
   */
38
  @SuppressWarnings( "rawtypes" )
39
  private ThemePicker( final File themes, final StringProperty theme ) {
40
    assert themes != null;
41
    assert theme != null;
42
43
    mThemes = themes;
44
    mTheme = theme;
45
    setGraphic( ICON_DIALOG_NODE );
46
    setTitle( get( "Dialog.theme.title" ) );
47
    setHeaderText( get( "Dialog.theme.header" ) );
48
49
    final var options = (ComboBox) getDialogPane().lookup( ".combo-box" );
50
    options.setOnKeyPressed( ( event ) -> {
51
      // When the user presses the down arrow, open the drop-down. This prevents
52
      // navigating to the cancel button.
53
      if( event.getCode() == KeyCode.DOWN && !options.isShowing() ) {
54
        options.show();
55
        event.consume();
56
      }
57
    } );
58
  }
59
60
  /**
61
   * Prompts a user to select a theme, answering {@code false} if no theme
62
   * was selected. The themes must be on the native file system; using the
63
   * {@link FileWalker} is a little more optimal than {@link ResourceWalker}.
64
   *
65
   * @param themes Theme directory root.
66
   * @param theme  Selected theme property name.
67
   * @return {@code true} if the user accepted or selected a theme.
68
   */
69
  public static boolean choose(
70
    final File themes, final StringProperty theme ) {
71
    assert themes != null;
72
    assert theme != null;
73
74
    return new ThemePicker( themes, theme ).pick();
75
  }
76
77
  /**
78
   * @return {@code true} if the user accepted or selected a theme.
79
   * @see #choose(File, StringProperty)
80
   */
81
  private boolean pick() {
82
    try {
83
      // List themes in alphabetical order (human readable by directory name).
84
      final var choices = new TreeMap<String, String>();
85
      final String[] selection = new String[]{""};
86
87
      // Populate the choices with themes detected on the system.
88
      walk( mThemes.toPath(), "**/theme.properties", ( path ) -> {
89
        try {
90
          final var themeDisplay = readThemeName( path );
91
          final var themeName = path.getParent().toFile().getName();
92
          choices.put( themeDisplay, themeName );
93
94
          // Used to set the selected item to value from user's settings.
95
          if( themeName.equals( mTheme.get() ) ) {
96
            selection[ 0 ] = themeDisplay;
97
          }
98
        } catch( final Exception ex ) {
99
          clue( get( "Main.status.error.theme.name", path ) );
100
        }
101
      } );
102
103
      final var items = getItems();
104
      items.addAll( choices.keySet() );
105
      setSelectedItem( items.get( max( items.indexOf( selection[ 0 ] ), 0 ) ) );
106
107
      final var result = showAndWait();
108
109
      if( result.isPresent() ) {
110
        mTheme.set( choices.get( result.get() ) );
111
        return true;
112
      }
113
    } catch( final Exception ex ) {
114
      clue( get( "Main.status.error.theme.missing", mThemes ), ex );
115
    }
116
117
    return false;
118
  }
119
120
  /**
121
   * Returns the theme's human-friendly name from a file conforming to
122
   * {@link Properties}.
123
   *
124
   * @param file A fully qualified file name readable using {@link Properties}.
125
   * @return The human-friendly theme name.
126
   * @throws IOException          The {@link Properties} file cannot be read.
127
   * @throws NullPointerException The name field is not defined.
128
   */
129
  private String readThemeName( final Path file ) throws Exception {
130
    return read( file ).get( "name" ).toString();
131
  }
132
133
  private Properties read( final Path file ) throws IOException {
134
    final var properties = new Properties();
135
136
    try( final var in = new FileInputStream( file.toFile() ) ) {
137
      properties.load( in );
138
    }
139
140
    return properties;
141
  }
142
}
1143
A src/main/java/com/keenwrite/ui/explorer/FilePicker.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.explorer;
3
4
import java.io.File;
5
import java.nio.file.Path;
6
import java.util.List;
7
import java.util.Optional;
8
9
/**
10
 * Responsible for providing the user with a way to select a file.
11
 */
12
public interface FilePicker {
13
14
  /**
15
   * Establishes the default file name to use when the UI is displayed. The
16
   * path portion of the file, if any, is ignored.
17
   *
18
   * @param file The initial {@link File} to choose when prompting the user
19
   *             to select a file.
20
   */
21
  default void setInitialFilename( File file ) {}
22
23
  /**
24
   * Establishes the directory to browse when the UI is displayed.
25
   *
26
   * @param path The initial {@link Path} to use when navigating the system.
27
   */
28
  default void setInitialDirectory( Path path ) {}
29
30
  /**
31
   * Sets the list of file names to display. For example, a single call to
32
   * this method with values of ("**.pdf", "Portable Document Format (PDF)")
33
   * would display only a file listing of PDF files.
34
   *
35
   * @param glob Pattern that allows matching file names to be listed.
36
   * @param text Human-readable description of the pattern.
37
   */
38
  default void addIncludeFileFilter( String glob, String text ) {}
39
40
  /**
41
   * Sets the list of file names to suppress. For example, a single call to
42
   * this method with values of (".*") would prevent listing files that begin
43
   * with a period.
44
   *
45
   * @param glob Pattern that allows matching file names to be suppressed.
46
   */
47
  default void addExcludeFileFilter( String glob ) {}
48
49
  /**
50
   * Returns the list of {@link File} objects selected by the user.
51
   *
52
   * @return A list of {@link File} objects, empty when nothing was selected.
53
   */
54
  Optional<List<File>> choose();
55
}
156
A src/main/java/com/keenwrite/ui/explorer/FilePickerFactory.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.explorer;
3
4
import com.io7m.jwheatsheaf.ui.JWFileChoosers;
5
import com.keenwrite.preferences.Workspace;
6
import javafx.beans.property.ObjectProperty;
7
import javafx.scene.Node;
8
import javafx.stage.FileChooser;
9
import javafx.stage.Window;
10
11
import java.io.File;
12
import java.nio.file.Path;
13
import java.util.ArrayList;
14
import java.util.List;
15
import java.util.Locale;
16
import java.util.Optional;
17
18
import static com.io7m.jwheatsheaf.api.JWFileChooserAction.*;
19
import static com.io7m.jwheatsheaf.api.JWFileChooserConfiguration.Builder;
20
import static com.io7m.jwheatsheaf.api.JWFileChooserConfiguration.builder;
21
import static com.keenwrite.constants.Constants.USER_DIRECTORY;
22
import static com.keenwrite.events.StatusEvent.clue;
23
import static com.keenwrite.preferences.WorkspaceKeys.KEY_UI_RECENT_DIR;
24
import static java.nio.file.FileSystems.getDefault;
25
import static java.util.Optional.ofNullable;
26
27
/**
28
 * Shim for a {@link FilePicker} instance that is implemented in pure Java.
29
 * This particular picker is added to avoid using the bug-ridden JavaFX
30
 * {@link FileChooser} that invokes the native file chooser.
31
 */
32
public class FilePickerFactory {
33
  public enum Options {
34
    DIRECTORY_OPEN,
35
    FILE_IMPORT,
36
    FILE_EXPORT,
37
    FILE_OPEN_SINGLE,
38
    FILE_OPEN_MULTIPLE,
39
    FILE_OPEN_NEW,
40
    FILE_SAVE_AS,
41
    PERMIT_CREATE_DIRS,
42
  }
43
44
  private final ObjectProperty<File> mDirectory;
45
  private final Locale mLocale;
46
47
  public FilePickerFactory( final Workspace workspace ) {
48
    mDirectory = workspace.fileProperty( KEY_UI_RECENT_DIR );
49
    mLocale = workspace.getLocale();
50
  }
51
52
  public FilePicker createModal(
53
    final Window owner, final Options... options ) {
54
    final var picker = new PureFilePicker( owner, options );
55
    picker.setInitialDirectory( mDirectory.get().toPath() );
56
57
    return picker;
58
  }
59
60
  public Node createModeless() {
61
    return new FilesView( mDirectory, mLocale );
62
  }
63
64
  /**
65
   * Pure Java implementation of a file selection widget.
66
   */
67
  private class PureFilePicker implements FilePicker {
68
    private final Window mParent;
69
    private final Builder mBuilder;
70
71
    private PureFilePicker( final Window window, final Options... options ) {
72
      mParent = window;
73
      mBuilder = builder().setFileSystem( getDefault() );
74
75
      final var args = ofNullable( options ).orElse( options );
76
77
      var title = "Dialog.file.choose.open.title";
78
      var action = OPEN_EXISTING_SINGLE;
79
80
      // It is a programming error to provide options that save or export to
81
      // multiple files.
82
      for( final var arg : args ) {
83
        switch( arg ) {
84
          case FILE_EXPORT -> {
85
            title = "Dialog.file.choose.export.title";
86
            action = CREATE;
87
          }
88
          case FILE_SAVE_AS -> {
89
            title = "Dialog.file.choose.save.title";
90
            action = CREATE;
91
          }
92
          case FILE_OPEN_SINGLE -> action = OPEN_EXISTING_SINGLE;
93
          case FILE_OPEN_MULTIPLE -> action = OPEN_EXISTING_MULTIPLE;
94
          case PERMIT_CREATE_DIRS -> mBuilder.setAllowDirectoryCreation( true );
95
        }
96
      }
97
98
      //mBuilder.setTitle( get(title) );
99
      mBuilder.setAction( action );
100
    }
101
102
    @Override
103
    public void setInitialDirectory( final Path path ) {
104
      mBuilder.setInitialDirectory( path );
105
    }
106
107
    @Override
108
    public Optional<List<File>> choose() {
109
      final var config = mBuilder.build();
110
      try( final var chooserType = JWFileChoosers.create() ) {
111
        final var chooser = chooserType.create( mParent, config );
112
        final var paths = chooser.showAndWait();
113
        final var files = new ArrayList<File>( paths.size() );
114
        paths.forEach( path -> {
115
          final var file = path.toFile();
116
          files.add( file );
117
118
          // Set to the directory of the last file opened successfully.
119
          setRecentDirectory( file );
120
        } );
121
122
        return files.isEmpty() ? Optional.empty() : Optional.of( files );
123
      } catch( final Exception ex ) {
124
        clue( ex );
125
      }
126
127
      return Optional.empty();
128
    }
129
  }
130
131
  /**
132
   * Sets the value for the most recent directly selected. This will get the
133
   * parent location from the given file. If the parent is a readable directory
134
   * then this will update the most recent directory property.
135
   *
136
   * @param file A file contained in a directory.
137
   */
138
  private void setRecentDirectory( final File file ) {
139
    assert file != null;
140
141
    final var parent = file.getParentFile();
142
    final var dir = parent == null ? USER_DIRECTORY : parent;
143
144
    if( dir.isDirectory() && dir.canRead() ) {
145
      mDirectory.setValue( dir );
146
    }
147
  }
148
}
1149
M src/main/java/com/keenwrite/ui/explorer/FilesView.java
22
package com.keenwrite.ui.explorer;
33
4
import com.keenwrite.preferences.Workspace;
54
import com.keenwrite.ui.controls.BrowseButton;
65
import javafx.beans.property.*;
76
import javafx.collections.ObservableList;
87
import javafx.collections.transformation.SortedList;
98
import javafx.scene.control.*;
109
import javafx.scene.layout.BorderPane;
1110
import javafx.scene.layout.HBox;
11
import javafx.stage.FileChooser;
1212
import javafx.util.Callback;
1313
1414
import java.io.File;
1515
import java.io.IOException;
1616
import java.nio.file.Path;
1717
import java.nio.file.Paths;
1818
import java.time.Instant;
1919
import java.time.format.DateTimeFormatter;
20
import java.util.Comparator;
20
import java.util.List;
2121
import java.util.Locale;
22
import java.util.Optional;
2223
23
import static com.keenwrite.Constants.UI_CONTROL_SPACING;
24
import static com.keenwrite.constants.Constants.UI_CONTROL_SPACING;
2425
import static com.keenwrite.events.FileOpenEvent.fireFileOpenEvent;
2526
import static com.keenwrite.events.StatusEvent.clue;
26
import static com.keenwrite.preferences.WorkspaceKeys.KEY_UI_RECENT_DIR;
2727
import static com.keenwrite.ui.fonts.IconFactory.createFileIcon;
2828
import static java.nio.file.Files.size;
2929
import static java.time.Instant.ofEpochMilli;
3030
import static java.time.ZoneId.systemDefault;
3131
import static java.time.format.DateTimeFormatter.ofPattern;
32
import static java.util.Comparator.*;
32
import static java.util.Comparator.comparing;
3333
import static javafx.collections.FXCollections.observableArrayList;
3434
import static javafx.scene.control.TableView.CONSTRAINED_RESIZE_POLICY;
35
import static javafx.scene.input.KeyCode.ENTER;
3536
import static javafx.scene.layout.Priority.ALWAYS;
3637
import static org.apache.commons.io.FilenameUtils.getExtension;
3738
3839
/**
3940
 * Responsible for browsing files.
4041
 */
41
public class FilesView extends BorderPane {
42
public class FilesView extends BorderPane implements FilePicker {
4243
  /**
4344
   * When this directory changes, the input field will update accordingly.
...
6566
   * restored upon restart.
6667
   *
67
   * @param workspace Contains the initial (recent) directory and locale.
68
   * @param recent Contains the initial (recent) directory.
69
   * @param locale Contains the language settings.
6870
   */
69
  public FilesView( final Workspace workspace ) {
70
    assert workspace != null;
71
72
    mDirectory = workspace.fileProperty( KEY_UI_RECENT_DIR );
73
74
    final var locale = workspace.getLocale();
71
  public FilesView(
72
    final ObjectProperty<File> recent, final Locale locale ) {
73
    mDirectory = recent;
7574
    mDateFormatter = createFormatter( "yyyy-MMM-dd", locale );
7675
    mTimeFormatter = createFormatter( "HH:mm:ss", locale );
...
8887
    mDirectory.addListener( ( c, o, n ) -> updateListing( n ) );
8988
    updateListing( mDirectory.get() );
89
  }
90
91
  @Override
92
  public Optional<List<File>> choose() {
93
    return Optional.empty();
9094
  }
9195
...
111115
  }
112116
117
  /**
118
   * Allows the user to use an instance of {@link FileChooser} to change the
119
   * directory.
120
   *
121
   * @return The browse button and input field.
122
   */
113123
  private HBox createDirectoryChooser() {
114124
    final var dirProperty = directoryProperty();
115125
    final var directory = dirProperty.get();
116126
    final var hbox = new HBox();
117127
    final var field = new TextField();
118128
119129
    mDirectory.addListener( ( c, o, n ) -> {
120130
      if( n != null ) { field.setText( n.getAbsolutePath() ); }
131
    } );
132
133
    field.setOnKeyPressed( event -> {
134
      if( event.getCode() == ENTER ) {
135
        mDirectory.set( new File( field.getText() ) );
136
      }
121137
    } );
122138
M src/main/java/com/keenwrite/ui/fonts/IconFactory.java
3333
 */
3434
public class IconFactory {
35
  /**
36
   * File icon height, in pixels.
37
   */
38
  private static final int ICON_HEIGHT = 16;
3539
3640
  /**
...
121125
    final var imageView = new ImageView();
122126
    imageView.setPreserveRatio( true );
123
    imageView.setFitHeight( 52 );
127
    imageView.setFitHeight( ICON_HEIGHT );
124128
    imageView.setImage( image );
125129
M src/main/java/com/keenwrite/ui/heuristics/DocumentStatistics.java
66
import com.keenwrite.preview.HtmlPanel;
77
import com.keenwrite.util.MurmurHash;
8
import com.whitemagicsoftware.wordcount.Tokenizer;
98
import com.whitemagicsoftware.wordcount.TokenizerException;
10
import com.whitemagicsoftware.wordcount.TokenizerFactory;
119
import javafx.beans.property.IntegerProperty;
1210
import javafx.beans.property.SimpleIntegerProperty;
...
1917
import org.greenrobot.eventbus.Subscribe;
2018
import org.jsoup.Jsoup;
21
22
import java.util.Locale;
2319
2420
import static com.keenwrite.events.Bus.register;
2521
import static com.keenwrite.events.StatusEvent.clue;
2622
import static com.keenwrite.events.WordCountEvent.fireWordCountEvent;
2723
import static com.keenwrite.preferences.WorkspaceKeys.KEY_LANGUAGE_LOCALE;
2824
import static com.keenwrite.preferences.WorkspaceKeys.KEY_UI_FONT_EDITOR_NAME;
25
import static com.keenwrite.ui.heuristics.DocumentStatistics.StatEntry;
2926
import static java.lang.String.format;
30
import static java.util.Locale.ENGLISH;
3127
import static javafx.application.Platform.runLater;
3228
import static javafx.collections.FXCollections.observableArrayList;
3329
3430
/**
3531
 * Responsible for displaying document statistics, such as word count and
3632
 * word frequency.
3733
 */
38
public final class DocumentStatistics
39
  extends TableView<DocumentStatistics.StatEntry> {
40
  /**
41
   * Parses documents into word counts.
42
   */
43
  private static Tokenizer sTokenizer = createTokenizer( ENGLISH );
34
public final class DocumentStatistics extends TableView<StatEntry> {
4435
36
  private WordCounter mWordCounter;
4537
  private final ObservableList<StatEntry> mItems = observableArrayList();
4638
4739
  /**
4840
   * Creates a new observer of document change events that will gather and
4941
   * display document statistics (e.g., word counts).
5042
   *
5143
   * @param workspace Settings used to configure the statistics engine.
5244
   */
5345
  public DocumentStatistics( final Workspace workspace ) {
46
    mWordCounter = WordCounter.create( workspace.getLocale() );
47
5448
    final var sortedItems = new SortedList<>( mItems );
5549
    sortedItems.comparatorProperty().bind( comparatorProperty() );
...
8882
  public void handle( final DocumentChangedEvent event ) {
8983
    try {
90
      final var tokens = sTokenizer.tokenize( event.getDocument() );
91
      final var sum = new int[]{0};
92
9384
      runLater( () -> {
9485
        mItems.clear();
95
        tokens.forEach( ( k, v ) -> {
96
          final var count = v[ 0 ];
97
          if( count > 2 ) {
98
            mItems.add( new StatEntry( k, count ) );
86
        final var document = event.getDocument();
87
        final var wordCount = mWordCounter.countWords(
88
          document, ( k, count ) -> {
89
            // Generate statistics for words that occur thrice or more.
90
            if( count > 2 ) {
91
              mItems.add( new StatEntry( k, count ) );
92
            }
9993
          }
100
          sum[ 0 ] += count;
101
        } );
94
        );
10295
103
        fireWordCountEvent( sum[ 0 ] );
96
        fireWordCountEvent( wordCount );
10497
      } );
105
10698
    } catch( final TokenizerException ex ) {
10799
      clue( ex );
...
133125
    final var property = workspace.localeProperty( KEY_LANGUAGE_LOCALE );
134126
    property.addListener(
135
      ( c, o, n ) -> sTokenizer = createTokenizer( property.toLocale() )
127
      ( c, o, n ) -> mWordCounter = WordCounter.create( property.toLocale() )
136128
    );
137
  }
138
139
  /**
140
   * Creates a tokenizer for English text (can handle most Latin languages).
141
   *
142
   * @return An English-based tokenizer for counting words.
143
   */
144
  private static Tokenizer createTokenizer( final Locale language ) {
145
    return TokenizerFactory.create( language );
146129
  }
147130
A src/main/java/com/keenwrite/ui/heuristics/WordCounter.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.ui.heuristics;
3
4
import com.whitemagicsoftware.wordcount.Tokenizer;
5
import com.whitemagicsoftware.wordcount.TokenizerFactory;
6
7
import java.util.Locale;
8
import java.util.function.BiConsumer;
9
10
/**
11
 * Responsible for counting unique words as well as total words in a document.
12
 */
13
public class WordCounter {
14
  /**
15
   * Parses documents into word counts.
16
   */
17
  private final Tokenizer mTokenizer;
18
19
  /**
20
   * Constructs a new {@link WordCounter} instance using the given tokenizer.
21
   *
22
   * @param tokenizer The class responsible for parsing a document into unique
23
   *                  and total word counts.
24
   */
25
  private WordCounter( final Tokenizer tokenizer ) {
26
    mTokenizer = tokenizer;
27
  }
28
29
  /**
30
   * Counts the number of unique words in the document.
31
   *
32
   * @param document The document to tally.
33
   * @return The total number of words in the document.
34
   */
35
  public int countWords( final String document ) {
36
    return countWords( document, ( k, count ) -> {} );
37
  }
38
39
  /**
40
   * Counts the number of unique words in the document.
41
   *
42
   * @param document The document to tally.
43
   * @param consumer The action to take for each unique word/count pair.
44
   * @return The total number of words in the document.
45
   */
46
  public int countWords(
47
    final String document, final BiConsumer<String, Integer> consumer ) {
48
    final var tokens = mTokenizer.tokenize( document );
49
    final var sum = new int[]{0};
50
51
    tokens.forEach( ( k, v ) -> {
52
      final var count = v[ 0 ];
53
      consumer.accept( k, count );
54
      sum[ 0 ] += count;
55
    } );
56
57
    return sum[ 0 ];
58
  }
59
60
  /**
61
   * Constructs a new {@link WordCounter} capable of tokenizing a document
62
   * into words using the given {@link Locale}.
63
   *
64
   * @param locale The {@link Tokenizer}'s language settings.
65
   */
66
  public static WordCounter create( final Locale locale ) {
67
    return new WordCounter( createTokenizer( locale ) );
68
  }
69
70
  /**
71
   * Creates a tokenizer for English text (can handle most Latin languages).
72
   *
73
   * @return An English-based tokenizer for counting words.
74
   */
75
  private static Tokenizer createTokenizer( final Locale language ) {
76
    return TokenizerFactory.create( language );
77
  }
78
}
179
M src/main/java/com/keenwrite/ui/logging/LogView.java
1717
1818
import static com.keenwrite.Bootstrap.APP_TITLE_LOWERCASE;
19
import static com.keenwrite.Constants.ACTION_PREFIX;
20
import static com.keenwrite.Constants.ICON_DIALOG;
19
import static com.keenwrite.constants.Constants.ACTION_PREFIX;
20
import static com.keenwrite.constants.GraphicsConstants.ICON_DIALOG;
2121
import static com.keenwrite.Messages.get;
2222
import static com.keenwrite.events.Bus.register;
M src/main/java/com/keenwrite/util/BoundedCache.java
2525
2626
  @Override
27
  protected boolean removeEldestEntry(
28
      final Map.Entry<K, V> eldest ) {
27
  protected boolean removeEldestEntry( final Map.Entry<K, V> eldest ) {
2928
    return size() > mCacheSize;
3029
  }
A src/main/java/com/keenwrite/util/FileWalker.java
1
/* Copyright 2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.util;
3
4
import java.io.IOException;
5
import java.nio.file.Files;
6
import java.nio.file.Path;
7
import java.util.function.Consumer;
8
9
import static java.nio.file.FileSystems.getDefault;
10
11
/**
12
 * Responsible for finding files in a file system that match a particular
13
 * globbing file name pattern.
14
 *
15
 * @see ResourceWalker#walk(String, String, Consumer)
16
 */
17
public class FileWalker {
18
  /**
19
   * Walks the given directory hierarchy for files that match the given
20
   * globbing file name pattern. This will search to a depth of 10 directories
21
   * deep (to avoid infinite recursion).
22
   *
23
   * @param path Root directory to scan for files matching the glob.
24
   * @param glob Only files matching the pattern will be consumed.
25
   * @param c    Function to call for each matching path found.
26
   * @throws IOException Could not walk the tree.
27
   */
28
  public static void walk(
29
    final Path path, final String glob, final Consumer<Path> c )
30
    throws IOException {
31
    final var matcher = getDefault().getPathMatcher( "glob:" + glob );
32
33
    try( final var walk = Files.walk( path, 10 ) ) {
34
      for( final var it = walk.iterator(); it.hasNext(); ) {
35
        final var p = it.next();
36
        if( matcher.matches( p ) ) {
37
          c.accept( p );
38
        }
39
      }
40
    }
41
  }
42
}
143
M src/main/java/com/keenwrite/util/FontLoader.java
1212
import java.util.Map;
1313
14
import static com.keenwrite.Constants.FONT_DIRECTORY;
14
import static com.keenwrite.constants.Constants.FONT_DIRECTORY;
1515
import static com.keenwrite.events.StatusEvent.clue;
1616
import static com.keenwrite.util.ProtocolScheme.valueFrom;
17
import static com.keenwrite.util.ResourceWalker.GLOB_FONTS;
1817
import static com.keenwrite.util.ResourceWalker.walk;
1918
import static java.awt.Font.TRUETYPE_FONT;
...
2827
 */
2928
public final class FontLoader {
29
  /**
30
   * Globbing pattern to match font names.
31
   */
32
  public static final String GLOB_FONTS = "**.{ttf,otf}";
3033
3134
  /**
M src/main/java/com/keenwrite/util/ProtocolScheme.java
33
44
import java.io.File;
5
import java.net.MalformedURLException;
56
import java.net.URI;
67
import java.net.URL;
...
4041
   * Returns the protocol for a given URI or file name.
4142
   *
42
   * @param resource Determine the protocol for this URI or file name.
43
   * @param uri Determine the protocol for this URI or file name.
4344
   * @return The protocol for the given resource.
4445
   */
45
  public static ProtocolScheme getProtocol( final String resource ) {
46
  public static ProtocolScheme getProtocol( final String uri ) {
4647
    try {
47
      final var uri = new URI( resource );
48
      return uri.isAbsolute()
49
        ? valueFrom( uri )
50
        : valueFrom( new URL( resource ) );
48
      return getProtocol( new URI( uri ) );
5149
    } catch( final Exception ex ) {
5250
      // Using double-slashes is a short-hand to instruct the browser to
5351
      // reference a resource using the parent URL's security model. This
5452
      // is known as a protocol-relative URL.
55
      return resource.startsWith( "//" )
56
        ? HTTP
57
        : valueFrom( new File( resource ) );
53
      return uri.startsWith( "//" ) ? HTTP : valueFrom( new File( uri ) );
5854
    }
55
  }
56
57
  /**
58
   * Returns the protocol for a given URI or file name.
59
   *
60
   * @param uri Determine the protocol for this URI or file name.
61
   * @return The protocol for the given resource.
62
   */
63
  public static ProtocolScheme getProtocol( final URI uri )
64
    throws MalformedURLException {
65
    return uri.isAbsolute()
66
      ? valueFrom( uri )
67
      : valueFrom( uri.toURL() );
5968
  }
6069
...
109118
   * Determines the protocol scheme for a given {@link URL}.
110119
   *
111
   * @param url A {@link URL} that contains a protocol scheme.
120
   * @param url The {@link URL} containing a protocol scheme.
112121
   * @return {@link #UNKNOWN} if the protocol is unrecognized, otherwise a
113122
   * valid value from this enumeration.
114123
   */
115124
  public static ProtocolScheme valueFrom( final URL url ) {
116125
    return valueFrom( url.getProtocol() );
126
  }
127
128
  /**
129
   * Answers whether the given {@link URL} points to a remote resource.
130
   *
131
   * @param url The {@link URL} containing a protocol scheme.
132
   * @return {@link true} if the protocol must be fetched via HTTP or FTP.
133
   */
134
  public static boolean isRemote( final URL url ) {
135
    return valueFrom( url ).isRemote();
117136
  }
118137
...
148167
   * Answers whether the given protocol represents a remote resource.
149168
   *
150
   * @return {@code true} the protocol is HTTP(S) or FTP.
169
   * @return {@code true} the protocol is HTTP or FTP.
151170
   */
152171
  public boolean isRemote() {
M src/main/java/com/keenwrite/util/ResourceWalker.java
55
import java.net.URISyntaxException;
66
import java.nio.file.FileSystem;
7
import java.nio.file.Files;
87
import java.nio.file.Path;
98
import java.nio.file.Paths;
109
import java.util.function.Consumer;
1110
1211
import static com.keenwrite.util.ProtocolScheme.JAR;
1312
import static com.keenwrite.util.ProtocolScheme.valueFrom;
14
import static java.nio.file.FileSystems.getDefault;
1513
import static java.nio.file.FileSystems.newFileSystem;
1614
import static java.util.Collections.emptyMap;
1715
1816
/**
19
 * Responsible for finding file resources.
17
 * Responsible for finding file resources, regardless if they exist within
18
 * a Java Archive (.jar) file or on the native file system.
19
 *
20
 * @see FileWalker#walk(Path, String, Consumer)
2021
 */
2122
public final class ResourceWalker {
22
  /**
23
   * Globbing pattern to match font names.
24
   */
25
  public static final String GLOB_FONTS = "**.{ttf,otf}";
2623
2724
  /**
28
   * @param directory The root directory to scan for files matching the glob.
29
   * @param c         The consumer function to call for each matching path
30
   *                  found.
31
   * @throws URISyntaxException Could not convert the resource to a URI.
25
   * Walks the given directory hierarchy for files that match the given
26
   * globbing file name pattern.
27
   *
28
   * @param directory Root directory to scan for files matching the glob.
29
   * @param glob      Only files matching the pattern will be consumed.
30
   * @param c         Function to call for each matching path found.
3231
   * @throws IOException        Could not walk the tree.
32
   * @throws URISyntaxException Could not convert the resource to a URI.
3333
   */
3434
  public static void walk(
3535
    final String directory, final String glob, final Consumer<Path> c )
3636
    throws URISyntaxException, IOException {
3737
    final var resource = ResourceWalker.class.getResource( directory );
38
    final var matcher = getDefault().getPathMatcher( "glob:" + glob );
3938
4039
    if( resource != null ) {
...
5150
      }
5251
53
      try( final var walk = Files.walk( path, 10 ) ) {
54
        for( final var it = walk.iterator(); it.hasNext(); ) {
55
          final Path p = it.next();
56
          if( matcher.matches( p ) ) {
57
            c.accept( p );
58
          }
59
        }
52
      try {
53
        FileWalker.walk( path, glob, c );
6054
      } finally {
6155
        if( fs != null ) { fs.close(); }
M src/main/resources/com/keenwrite/messages.properties
66
77
# ########################################################################
8
# Menu Bar
9
# ########################################################################
10
11
Main.menu.file=_File
12
Main.menu.edit=_Edit
13
Main.menu.insert=_Insert
14
Main.menu.format=Forma_t
15
Main.menu.definition=_Variable
16
Main.menu.view=Vie_w
17
Main.menu.help=_Help
18
19
# ########################################################################
20
# Detachable Tabs
21
# ########################################################################
22
23
# {0} is the application title; {1} is a unique window ID.
24
Detach.tab.title={0} - {1}
25
26
# ########################################################################
27
# Status Bar
28
# ########################################################################
29
30
Main.status.text.offset=offset
31
Main.status.line=Line {0} of {1}, ${Main.status.text.offset} {2}
32
Main.status.state.default=OK
33
Main.status.export.success=Saved as {0}
34
35
Main.status.error.bootstrap.eval=Note: Bootstrap variable of ''{0}'' not found
36
37
Main.status.error.parse={0} (near ${Main.status.text.offset} {1})
38
Main.status.error.def.blank=Move the caret to a word before inserting a variable
39
Main.status.error.def.empty=Create a variable before inserting one
40
Main.status.error.def.missing=No variable value found for ''{0}''
41
Main.status.error.r=Error with [{0}...]: {1}
42
Main.status.error.file.missing=Not found: {0}
43
44
Main.status.error.messages.recursion=Lookup depth exceeded, check for loops in ''{0}''
45
Main.status.error.messages.syntax=Missing ''}'' in ''{0}''
46
47
Main.status.error.undo=Cannot undo; beginning of undo history reached
48
Main.status.error.redo=Cannot redo; end of redo history reached
49
50
Main.status.image.request.init=Initializing HTTP request
51
Main.status.image.request.fetch=Requesting content type from {0}
52
Main.status.image.request.success=Determined content type ''{0}''
53
Main.status.image.request.error.media=No media type for ''{0}''
54
Main.status.image.request.error.cert=Could not accept certificate for ''{0}''
55
56
Main.status.font.search.missing=No font name starting with ''{0}'' was found
57
58
# ########################################################################
59
# Search Bar
60
# ########################################################################
61
62
Main.search.stop.tooltip=Close search bar
63
Main.search.stop.icon=CLOSE
64
Main.search.next.tooltip=Find next match
65
Main.search.next.icon=CHEVRON_DOWN
66
Main.search.prev.tooltip=Find previous match
67
Main.search.prev.icon=CHEVRON_UP
68
Main.search.find.tooltip=Search document for text
69
Main.search.find.icon=SEARCH
70
Main.search.match.none=No matches
71
Main.search.match.some={0} of {1} matches
72
73
# ########################################################################
74
# Workspace preferences
75
# ########################################################################
76
77
workspace.r=R
78
workspace.r.script=Startup Script
79
workspace.r.script.desc=Script runs prior to executing R statements within the document.
80
workspace.r.dir=Working Directory
81
workspace.r.dir.desc=Value assigned to {0}application.r.working.directory{1} and usable in the startup script.
82
workspace.r.dir.title=Directory
83
workspace.r.delimiter.began=Delimiter Prefix
84
workspace.r.delimiter.began.desc=Prefix of expression that wraps inserted variables.
85
workspace.r.delimiter.began.title=Opening
86
workspace.r.delimiter.ended=Delimiter Suffix
87
workspace.r.delimiter.ended.desc=Suffix of expression that wraps inserted variables.
88
workspace.r.delimiter.ended.title=Closing
89
90
workspace.images=Images
91
workspace.images.dir=Absolute Directory
92
workspace.images.dir.desc=Path to search for local file system images.
93
workspace.images.dir.title=Directory
94
workspace.images.order=Extensions
95
workspace.images.order.desc=Preferred order of image file types to embed, separated by spaces.
96
workspace.images.order.title=Extensions
97
98
workspace.definition=Variable
99
workspace.definition.path=File name
100
workspace.definition.path.desc=Absolute path to interpolated string variables.
101
workspace.definition.path.title=Path
102
workspace.definition.delimiter.began=Delimiter Prefix
103
workspace.definition.delimiter.began.desc=Indicates when a variable name is starting.
104
workspace.definition.delimiter.began.title=Opening
105
workspace.definition.delimiter.ended=Delimiter Suffix
106
workspace.definition.delimiter.ended.desc=Indicates when a variable name is ending.
107
workspace.definition.delimiter.ended.title=Closing
108
109
workspace.ui.theme=Themes
110
workspace.ui.theme.selection=Bundled
111
workspace.ui.theme.selection.desc=Pre-packaged application style (default: Modena Light)
112
workspace.ui.theme.selection.title=Name
113
workspace.ui.theme.custom=Custom
114
workspace.ui.theme.custom.desc=User-defined JavaFX cascading stylesheet file
115
workspace.ui.theme.custom.title=Path
116
117
workspace.ui.font=Fonts
118
workspace.ui.font.editor=Editor Font
119
workspace.ui.font.editor.name=Name
120
workspace.ui.font.editor.name.desc=Text editor font name (sans-serif font recommended).
121
workspace.ui.font.editor.name.title=Family
122
workspace.ui.font.editor.size=Size
123
workspace.ui.font.editor.size.desc=Font size.
124
workspace.ui.font.editor.size.title=Points
125
workspace.ui.font.preview=Preview Font
126
workspace.ui.font.preview.name=Name
127
workspace.ui.font.preview.name.desc=Preview pane font name (must support ligatures, serif font recommended).
128
workspace.ui.font.preview.name.title=Family
129
workspace.ui.font.preview.size=Size
130
workspace.ui.font.preview.size.desc=Font size.
131
workspace.ui.font.preview.size.title=Points
132
workspace.ui.font.preview.mono.name=Name
133
workspace.ui.font.preview.mono.name.desc=Monospace font name.
134
workspace.ui.font.preview.mono.name.title=Family
135
workspace.ui.font.preview.mono.size=Size
136
workspace.ui.font.preview.mono.size.desc=Monospace font size.
137
workspace.ui.font.preview.mono.size.title=Points
138
139
workspace.language=Language
140
workspace.language.locale=Internationalization
141
workspace.language.locale.desc=Language for application and HTML export.
142
workspace.language.locale.title=Locale
143
144
# ########################################################################
145
# Definition Pane and its Tree View
146
# ########################################################################
147
148
Definition.menu.add.default=Undefined
149
150
# ########################################################################
151
# Variable Definitions Pane
152
# ########################################################################
153
154
Pane.definition.node.root.title=Variables
155
156
# ########################################################################
157
# HTML Preview Pane
158
# ########################################################################
159
160
Pane.preview.title=Preview
161
162
# ########################################################################
163
# Document Outline Pane
164
# ########################################################################
165
166
Pane.outline.title=Outline
167
168
# ########################################################################
169
# File Manager Pane
170
# ########################################################################
171
172
Pane.files.title=Files
173
174
# ########################################################################
175
# Document Outline Pane
176
# ########################################################################
177
178
Pane.statistics.title=Statistics
179
180
# ########################################################################
181
# Failure messages with respect to YAML files.
182
# ########################################################################
183
184
yaml.error.open=Could not open YAML file (ensure non-empty file).
185
yaml.error.unresolvable=Too much indirection for: ''{0}'' = ''{1}''.
186
yaml.error.missing=Empty variable value for key ''{0}''.
187
yaml.error.tree.form=Unassigned variable near ''{0}''.
188
189
# ########################################################################
190
# Text Resource
191
# ########################################################################
192
193
TextResource.load.error.unsaved=The file ''{0}'' is unsaved or does not exist.
194
TextResource.load.error.permissions=The file ''{0}'' must be readable and writable.
195
196
# ########################################################################
197
# Text Resources
198
# ########################################################################
199
200
TextResource.saveFailed.message=Failed to save ''{0}''.\n\nReason: {1}
201
TextResource.saveFailed.title=Save
202
203
# ########################################################################
204
# File Open
205
# ########################################################################
206
207
Dialog.file.choose.open.title=Open File
208
Dialog.file.choose.save.title=Save File
209
Dialog.file.choose.export.title=Export File
210
211
Dialog.file.choose.filter.title.source=Source Files
212
Dialog.file.choose.filter.title.definition=Variable Files
213
Dialog.file.choose.filter.title.xml=XML Files
214
Dialog.file.choose.filter.title.all=All Files
215
216
# ########################################################################
217
# Browse File
218
# ########################################################################
219
220
BrowseFileButton.chooser.title=Open local file
221
BrowseFileButton.chooser.allFilesFilter=All Files
222
BrowseFileButton.tooltip=${BrowseFileButton.chooser.title}
223
224
# ########################################################################
225
# Browse Directory
226
# ########################################################################
227
228
BrowseDirectoryButton.chooser.title=Open local directory
229
BrowseDirectoryButton.tooltip=${BrowseDirectoryButton.chooser.title}
230
231
# ########################################################################
232
# Alert Dialog
233
# ########################################################################
234
235
Alert.file.close.title=Close
236
Alert.file.close.text=Save changes to {0}?
237
238
# ########################################################################
239
# Image Dialog
240
# ########################################################################
241
242
Dialog.image.title=Image
243
Dialog.image.chooser.imagesFilter=Images
244
Dialog.image.previewLabel.text=Markdown Preview\:
245
Dialog.image.textLabel.text=Alternate Text\:
246
Dialog.image.titleLabel.text=Title (tooltip)\:
247
Dialog.image.urlLabel.text=Image URL\:
248
249
# ########################################################################
250
# Hyperlink Dialog
251
# ########################################################################
252
253
Dialog.link.title=Link
254
Dialog.link.previewLabel.text=Markdown Preview\:
255
Dialog.link.textLabel.text=Link Text\:
256
Dialog.link.titleLabel.text=Title (tooltip)\:
257
Dialog.link.urlLabel.text=Link URL\:
258
259
# ########################################################################
260
# About Dialog
261
# ########################################################################
262
263
Dialog.about.title=About {0}
264
Dialog.about.header={0}
265
Dialog.about.content=Copyright 2016-{0} White Magic Software, Ltd.\n\nVersion: {1}
266
267
# ########################################################################
268
# Application Actions
269
# ########################################################################
270
271
Action.file.new.description=Create a new file
272
Action.file.new.accelerator=Shortcut+N
273
Action.file.new.icon=FILE_ALT
274
Action.file.new.text=_New
275
276
Action.file.open.description=Open a new file
277
Action.file.open.accelerator=Shortcut+O
278
Action.file.open.text=_Open...
279
Action.file.open.icon=FOLDER_OPEN_ALT
280
281
Action.file.close.description=Close the current document
282
Action.file.close.accelerator=Shortcut+W
283
Action.file.close.text=_Close
284
285
Action.file.close_all.description=Close all open documents
286
Action.file.close_all.accelerator=Ctrl+F4
287
Action.file.close_all.text=Close All
288
289
Action.file.save.description=Save the document
290
Action.file.save.accelerator=Shortcut+S
291
Action.file.save.text=_Save
292
Action.file.save.icon=FLOPPY_ALT
293
294
Action.file.save_as.description=Rename the current document
295
Action.file.save_as.text=Save _As
296
297
Action.file.save_all.description=Save all open documents
298
Action.file.save_all.accelerator=Shortcut+Shift+S
299
Action.file.save_all.text=Save A_ll
300
301
Action.file.export.html_svg.description=Export the current document as HTML + SVG
302
Action.file.export.text=_Export As
303
Action.file.export.html_svg.text=HTML and S_VG
304
305
Action.file.export.html_tex.description=Export the current document as HTML + TeX
306
Action.file.export.html_tex.text=HTML and _TeX
8
# Workspace preferences
9
# ########################################################################
10
11
workspace.document=Document
12
workspace.document.title=Title Name
13
workspace.document.title.desc=Full document title, or variable reference (e.g., '{{'book.title'}}').
14
workspace.document.title.title=Title
15
workspace.document.author=Author Name
16
workspace.document.author.desc=Full name of primary author, or variable reference (e.g., '{{'book.author'}}').
17
workspace.document.author.title=Name
18
workspace.document.byline=Byline
19
workspace.document.byline.desc=Author name, pen name, byline, pseudonym, or variable reference.
20
workspace.document.byline.title=Name
21
workspace.document.address=Address
22
workspace.document.address.desc=Author mailing address, or variable reference.
23
workspace.document.address.title=Address
24
workspace.document.phone=Phone
25
workspace.document.phone.desc=Author phone number, or variable reference.
26
workspace.document.phone.title=Number
27
workspace.document.email=Email
28
workspace.document.email.desc=Author email address, or variable reference.
29
workspace.document.email.title=Email
30
workspace.document.keywords=Keywords
31
workspace.document.keywords.desc=Comma-separated words relating to subject matter, or variable reference.
32
workspace.document.keywords.title=Words
33
workspace.document.copyright=Copyright
34
workspace.document.copyright.desc=Continuous years of publication, or variable reference.
35
workspace.document.copyright.title=Year(s)
36
workspace.document.date=Publish Date
37
workspace.document.date.desc=Date and time document was published, or variable reference.
38
workspace.document.date.title=Timestamp
39
40
workspace.r=R
41
workspace.r.script=Startup Script
42
workspace.r.script.desc=Script runs prior to executing R statements within the document.
43
workspace.r.dir=Working Directory
44
workspace.r.dir.desc=Value assigned to {0}application.r.working.directory{1} and usable in the startup script.
45
workspace.r.dir.title=Directory
46
workspace.r.delimiter.began=Delimiter Prefix
47
workspace.r.delimiter.began.desc=Prefix of expression that wraps inserted variables.
48
workspace.r.delimiter.began.title=Opening
49
workspace.r.delimiter.ended=Delimiter Suffix
50
workspace.r.delimiter.ended.desc=Suffix of expression that wraps inserted variables.
51
workspace.r.delimiter.ended.title=Closing
52
53
workspace.images=Images
54
workspace.images.dir=Absolute Directory
55
workspace.images.dir.desc=Path to search for local file system images.
56
workspace.images.dir.title=Directory
57
workspace.images.order=Extensions
58
workspace.images.order.desc=Preferred order of image file types to embed, separated by spaces.
59
workspace.images.order.title=Extensions
60
61
workspace.definition=Variable
62
workspace.definition.path=File name
63
workspace.definition.path.desc=Absolute path to interpolated string variables.
64
workspace.definition.path.title=Path
65
workspace.definition.delimiter.began=Delimiter Prefix
66
workspace.definition.delimiter.began.desc=Indicates when a variable name is starting.
67
workspace.definition.delimiter.began.title=Opening
68
workspace.definition.delimiter.ended=Delimiter Suffix
69
workspace.definition.delimiter.ended.desc=Indicates when a variable name is ending.
70
workspace.definition.delimiter.ended.title=Closing
71
72
workspace.ui.skin=Skins
73
workspace.ui.skin.selection=Bundled
74
workspace.ui.skin.selection.desc=Pre-packaged application style (default: Modena Light).
75
workspace.ui.skin.selection.title=Name
76
workspace.ui.skin.custom=Custom
77
workspace.ui.skin.custom.desc=User-defined JavaFX cascading stylesheet file.
78
workspace.ui.skin.custom.title=Path
79
80
workspace.ui.font=Fonts
81
workspace.ui.font.editor=Editor Font
82
workspace.ui.font.editor.name=Name
83
workspace.ui.font.editor.name.desc=Text editor font name (sans-serif font recommended).
84
workspace.ui.font.editor.name.title=Family
85
workspace.ui.font.editor.size=Size
86
workspace.ui.font.editor.size.desc=Font size.
87
workspace.ui.font.editor.size.title=Points
88
workspace.ui.font.preview=Preview Font
89
workspace.ui.font.preview.name=Name
90
workspace.ui.font.preview.name.desc=Preview pane font name (must support ligatures, serif font recommended).
91
workspace.ui.font.preview.name.title=Family
92
workspace.ui.font.preview.size=Size
93
workspace.ui.font.preview.size.desc=Font size.
94
workspace.ui.font.preview.size.title=Points
95
workspace.ui.font.preview.mono.name=Name
96
workspace.ui.font.preview.mono.name.desc=Monospace font name.
97
workspace.ui.font.preview.mono.name.title=Family
98
workspace.ui.font.preview.mono.size=Size
99
workspace.ui.font.preview.mono.size.desc=Monospace font size.
100
workspace.ui.font.preview.mono.size.title=Points
101
102
workspace.language=Language
103
workspace.language.locale=Internationalization
104
workspace.language.locale.desc=Language for application and HTML export.
105
workspace.language.locale.title=Locale
106
107
workspace.typeset=Typesetting
108
workspace.typeset.context=ConTeXt
109
workspace.typeset.context.themes.path=Paths
110
workspace.typeset.context.themes.path.desc=Directory containing theme subdirectories.
111
workspace.typeset.context.themes.path.title=Themes
112
113
# ########################################################################
114
# Menu Bar
115
# ########################################################################
116
117
Main.menu.file=_File
118
Main.menu.edit=_Edit
119
Main.menu.insert=_Insert
120
Main.menu.format=Forma_t
121
Main.menu.definition=_Variable
122
Main.menu.view=Vie_w
123
Main.menu.help=_Help
124
125
# ########################################################################
126
# Detachable Tabs
127
# ########################################################################
128
129
# {0} is the application title; {1} is a unique window ID.
130
Detach.tab.title={0} - {1}
131
132
# ########################################################################
133
# Status Bar
134
# ########################################################################
135
136
Main.status.text.offset=offset
137
Main.status.line=Line {0} of {1}, ${Main.status.text.offset} {2}
138
Main.status.state.default=OK
139
Main.status.export.success=Saved as ''{0}''
140
141
Main.status.error.bootstrap.eval=Note: Bootstrap variable of ''{0}'' not found
142
143
Main.status.error.parse={0} (near ${Main.status.text.offset} {1})
144
Main.status.error.def.blank=Move the caret to a word before inserting a variable
145
Main.status.error.def.empty=Create a variable before inserting one
146
Main.status.error.def.missing=No variable value found for ''{0}''
147
Main.status.error.r=Error with [{0}...]: {1}
148
Main.status.error.file.missing=Not found: ''{0}''
149
150
Main.status.error.messages.recursion=Lookup depth exceeded, check for loops in ''{0}''
151
Main.status.error.messages.syntax=Missing ''}'' in ''{0}''
152
153
Main.status.error.undo=Cannot undo; beginning of undo history reached
154
Main.status.error.redo=Cannot redo; end of redo history reached
155
156
Main.status.error.theme.missing=Install themes before exporting (no themes found at ''{0}'')
157
Main.status.error.theme.name=Cannot find theme name for ''{0}''
158
159
Main.status.image.request.init=Initializing HTTP request
160
Main.status.image.request.fetch=Requesting content type from ''{0}''
161
Main.status.image.request.success=Determined content type ''{0}''
162
Main.status.image.request.error.media=No media type for ''{0}''
163
Main.status.image.request.error.cert=Could not accept certificate for ''{0}''
164
165
Main.status.font.search.missing=No font name starting with ''{0}'' was found
166
167
Main.status.typeset.create=Creating typesetter
168
Main.status.typeset.xhtml=Export document as XHTML
169
Main.status.typeset.began=Started typesetting ''{0}''
170
Main.status.typeset.failed=Could not generate PDF file
171
Main.status.typeset.page=Typesetting page {0} of {1} (pass {2})
172
Main.status.typeset.ended.success=Finished typesetting ''{0}'' ({1} elapsed)
173
Main.status.typeset.ended.failure=Failed to typeset ''{0}'' ({1} elapsed)
174
175
# ########################################################################
176
# Search Bar
177
# ########################################################################
178
179
Main.search.stop.tooltip=Close search bar
180
Main.search.stop.icon=CLOSE
181
Main.search.next.tooltip=Find next match
182
Main.search.next.icon=CHEVRON_DOWN
183
Main.search.prev.tooltip=Find previous match
184
Main.search.prev.icon=CHEVRON_UP
185
Main.search.find.tooltip=Search document for text
186
Main.search.find.icon=SEARCH
187
Main.search.match.none=No matches
188
Main.search.match.some={0} of {1} matches
189
190
# ########################################################################
191
# Definition Pane and its Tree View
192
# ########################################################################
193
194
Definition.menu.add.default=Undefined
195
196
# ########################################################################
197
# Variable Definitions Pane
198
# ########################################################################
199
200
Pane.definition.node.root.title=Variables
201
202
# ########################################################################
203
# HTML Preview Pane
204
# ########################################################################
205
206
Pane.preview.title=Preview
207
208
# ########################################################################
209
# Document Outline Pane
210
# ########################################################################
211
212
Pane.outline.title=Outline
213
214
# ########################################################################
215
# File Manager Pane
216
# ########################################################################
217
218
Pane.files.title=Files
219
220
# ########################################################################
221
# Document Outline Pane
222
# ########################################################################
223
224
Pane.statistics.title=Statistics
225
226
# ########################################################################
227
# Failure messages with respect to YAML files.
228
# ########################################################################
229
230
yaml.error.open=Could not open YAML file (ensure non-empty file).
231
yaml.error.unresolvable=Too much indirection for: ''{0}'' = ''{1}''.
232
yaml.error.missing=Empty variable value for key ''{0}''.
233
yaml.error.tree.form=Unassigned variable near ''{0}''.
234
235
# ########################################################################
236
# Text Resource
237
# ########################################################################
238
239
TextResource.load.error.unsaved=The file ''{0}'' is unsaved or does not exist.
240
TextResource.load.error.permissions=The file ''{0}'' must be readable and writable.
241
242
# ########################################################################
243
# Text Resources
244
# ########################################################################
245
246
TextResource.saveFailed.message=Failed to save ''{0}''.\n\nReason: {1}
247
TextResource.saveFailed.title=Save
248
249
# ########################################################################
250
# File Open
251
# ########################################################################
252
253
Dialog.file.choose.open.title=Open File
254
Dialog.file.choose.save.title=Save File
255
Dialog.file.choose.export.title=Export File
256
257
Dialog.file.choose.filter.title.source=Source Files
258
Dialog.file.choose.filter.title.definition=Variable Files
259
Dialog.file.choose.filter.title.xml=XML Files
260
Dialog.file.choose.filter.title.all=All Files
261
262
# ########################################################################
263
# Browse File
264
# ########################################################################
265
266
BrowseFileButton.chooser.title=Open local file
267
BrowseFileButton.chooser.allFilesFilter=All Files
268
BrowseFileButton.tooltip=${BrowseFileButton.chooser.title}
269
270
# ########################################################################
271
# Browse Directory
272
# ########################################################################
273
274
BrowseDirectoryButton.chooser.title=Open local directory
275
BrowseDirectoryButton.tooltip=${BrowseDirectoryButton.chooser.title}
276
277
# ########################################################################
278
# Alert Dialog
279
# ########################################################################
280
281
Alert.file.close.title=Close
282
Alert.file.close.text=Save changes to {0}?
283
284
# ########################################################################
285
# Typesetting Alert Dialog
286
# ########################################################################
287
288
Alert.typesetter.missing.title=Missing Typesetter
289
Alert.typesetter.missing.header=Install typesetter
290
Alert.typesetter.missing.version=for {0} {1} {2}-bit
291
Alert.typesetter.missing.installer.text=Download and install ConTeXt
292
Alert.typesetter.missing.installer.url=https://wiki.contextgarden.net/Installation
293
294
# ########################################################################
295
# Image Dialog
296
# ########################################################################
297
298
Dialog.image.title=Image
299
Dialog.image.chooser.imagesFilter=Images
300
Dialog.image.previewLabel.text=Markdown Preview\:
301
Dialog.image.textLabel.text=Alternate Text\:
302
Dialog.image.titleLabel.text=Title (tooltip)\:
303
Dialog.image.urlLabel.text=Image URL\:
304
305
# ########################################################################
306
# Hyperlink Dialog
307
# ########################################################################
308
309
Dialog.link.title=Link
310
Dialog.link.previewLabel.text=Markdown Preview\:
311
Dialog.link.textLabel.text=Link Text\:
312
Dialog.link.titleLabel.text=Title (tooltip)\:
313
Dialog.link.urlLabel.text=Link URL\:
314
315
# ########################################################################
316
# Themes Dialog
317
# ########################################################################
318
319
Dialog.theme.title=Typesetting theme
320
Dialog.theme.header=Choose a typesetting theme
321
322
# ########################################################################
323
# About Dialog
324
# ########################################################################
325
326
Dialog.about.title=About {0}
327
Dialog.about.header={0}
328
Dialog.about.content=Copyright 2016-{0} White Magic Software, Ltd.\n\nVersion: {1}
329
330
# ########################################################################
331
# Application Actions
332
# ########################################################################
333
334
Action.file.new.description=Create a new file
335
Action.file.new.accelerator=Shortcut+N
336
Action.file.new.icon=FILE_ALT
337
Action.file.new.text=_New
338
339
Action.file.open.description=Open a new file
340
Action.file.open.accelerator=Shortcut+O
341
Action.file.open.text=_Open...
342
Action.file.open.icon=FOLDER_OPEN_ALT
343
344
Action.file.close.description=Close the current document
345
Action.file.close.accelerator=Shortcut+W
346
Action.file.close.text=_Close
347
348
Action.file.close_all.description=Close all open documents
349
Action.file.close_all.accelerator=Ctrl+F4
350
Action.file.close_all.text=Close All
351
352
Action.file.save.description=Save the document
353
Action.file.save.accelerator=Shortcut+S
354
Action.file.save.text=_Save
355
Action.file.save.icon=FLOPPY_ALT
356
357
Action.file.save_as.description=Rename the current document
358
Action.file.save_as.text=Save _As
359
360
Action.file.save_all.description=Save all open documents
361
Action.file.save_all.accelerator=Shortcut+Shift+S
362
Action.file.save_all.text=Save A_ll
363
364
Action.file.export.pdf.description=Typeset the document
365
Action.file.export.pdf.accelerator=Shortcut+P
366
Action.file.export.pdf.text=_PDF
367
Action.file.export.pdf.icon=FILE_PDF_ALT
368
369
Action.file.export.html_svg.description=Export the current document as HTML + SVG
370
Action.file.export.text=_Export As
371
Action.file.export.html_svg.text=HTML and S_VG
372
373
Action.file.export.html_tex.description=Export the current document as HTML + TeX
374
Action.file.export.html_tex.text=HTML and _TeX
375
376
Action.file.export.xhtml_tex.description=Export as XHTML + TeX
377
Action.file.export.xhtml_tex.text=_XHTML and TeX
307378
308379
Action.file.export.markdown.description=Export the current document as Markdown
M src/main/resources/com/keenwrite/preview/webview.css
2828
}
2929
30
/* HEADERS ***/
3031
h1, h2, h3, h4, h5, h6 {
3132
  font-weight: bold;
...
7576
a:hover {
7677
  text-decoration: underline;
77
}
78
79
/* BULLET LISTS ***/
80
ul, ol {
81
  display: block;
82
  list-style: disc outside none;
83
  margin: 1em 0;
84
  padding: 0 0 0 2em;
85
}
86
87
ol {
88
  list-style-type: decimal;
8978
}
9079
91
ul ul, ol ul,
92
ol ol, ul ol {
93
  list-style-position: inside;
94
  margin-left: 1em;
80
/* ITEMIZED LISTS ***/
81
ol, ul {
82
  margin: 0 0 0 2em;
9583
}
9684
97
ul ul, ol ul {
98
  list-style-type: circle;
99
}
85
ol { list-style-type: decimal; }
86
ol ol { list-style-type: lower-alpha; }
87
ol ol ol { list-style-type: lower-roman; }
88
ol ol ol ol { list-style-type: upper-alpha; }
89
ol ol ol ol ol { list-style-type: upper-roman; }
90
ol ol ol ol ol ol { list-style-type: lower-greek; }
10091
101
ol ol, ul ol {
102
  list-style-type: lower-latin;
103
}
92
ul { list-style-type: disc; }
93
ul ul { list-style-type: circle; }
94
ul ul ul { list-style-type: square; }
95
ul ul ul ul { list-style-type: disc; }
96
ul ul ul ul ul { list-style-type: circle; }
97
ul ul ul ul ul ul { list-style-type: square; }
10498
10599
/* DEFINITION LISTS ***/
...
126120
}
127121
122
/* PREFORMATTED CODE ***/
128123
pre, code, tt {
129124
  /* Must be bundled in JAR file. */
...
159154
}
160155
156
/* BLOCKQUOTES ***/
161157
blockquote {
162158
  border-left: .25em solid #ccc;
...
171167
blockquote>:last-child {
172168
  margin-bottom: 0;
173
}
174
175
hr {
176
  clear: both;
177
  margin: 1.5em 0 1.5em;
178
  height: 0;
179
  overflow: hidden;
180
  border: none;
181
  background: transparent;
182
  border-bottom: .125em solid #ccc;
183169
}
184170
171
/* TABLES ***/
185172
table {
186173
  width: 100%;
...
201188
}
202189
190
/* IMAGES ***/
203191
img {
204192
  max-width: 100%;
205193
206194
  /* Tell FlyingSaucer to treat images as block elements.
207195
   * See SvgReplacedElementFactory.
208196
   */
209197
  display: inline-block;
210198
}
199
200
/* TEX ***/
211201
212202
/* Tell FlyingSaucer to treat tex elements as nodes.
...
226216
p tex {
227217
  vertical-align: baseline;
218
}
219
220
/* RULES ***/
221
hr {
222
  clear: both;
223
  margin: 1.5em 0 1.5em;
224
  height: 0;
225
  overflow: hidden;
226
  border: none;
227
  background: transparent;
228
  border-bottom: .125em solid #ccc;
228229
}
229230
A src/main/resources/com/keenwrite/quotes/en/README.md
1
Listing English contractions helps converting straight apostrophes into curly apostrophes. The files include:
2
3
* began.txt -- Contractions that begin with an apostrophe.
4
* ended.txt -- Contractions that end with an apostrophe.
5
* inner.txt -- Contractions that have internal apostrophes.
6
* outer.txt -- Contractions that start and end with an apostrophe.
7
* verbs.txt -- Contractions that form suffixes for a variety of words.
8
9
The contractions for verbs must be detected dynamically, all other contractions can be hard-coded into either regular expressions or EBNF grammars.
10
111
A src/main/resources/com/keenwrite/quotes/en/began.txt
1
'aporth
2
'bout
3
'boutcha
4
'boutchu
5
'choo
6
'dillo
7
'e'll
8
'ere
9
'e
10
'e's
11
'fraid
12
'fro
13
'ho
14
'kay
15
'lo
16
'n
17
'neath
18
'nother
19
'onna
20
'pon
21
'sblood
22
'scuse
23
'sfar
24
'sfoot
25
'sup
26
't
27
'taint
28
'tain't
29
'tis
30
'tisn't
31
'tshall
32
'twas
33
'twasn't
34
'tween
35
'twere
36
'tweren't
37
'twill
38
'twixt
39
'twon't
40
'twou'd
41
'twou'dn't
42
'twould
43
'twouldn't
44
'um
45
've
46
'zat
47
148
A src/main/resources/com/keenwrite/quotes/en/ended.txt
1
ain'
2
an'
3
burlin'
4
cas'
5
didn'
6
doan'
7
doin'
8
fo'
9
gerrin'
10
gon'
11
i'
12
Ima'
13
mo'
14
namsayin'
15
o'
16
ol'
17
o'th'
18
po'
19
t'
20
th'
21
122
A src/main/resources/com/keenwrite/quotes/en/inner.txt
1
aboves'd
2
after't
3
a'ight
4
ain't
5
ain'tcha
6
all's
7
and's
8
a'n't
9
an't
10
anybody'll
11
anybody's
12
aren'chu
13
aren't
14
a'right
15
as't
16
at's
17
bain't
18
bean't
19
before't
20
ben't
21
better'n
22
bettern't
23
bisn't
24
b'long
25
bo's'n
26
br'er
27
but's
28
by'r
29
by't
30
cain't
31
call't
32
cam'st
33
cann't
34
ca'n't
35
can't
36
can'tcha
37
can't've
38
can've
39
cap'n
40
casn't
41
ch'ill
42
c'mere
43
c'min
44
c'mon
45
col's
46
couldn't
47
couldn't've
48
couldn've
49
could've
50
cudn't
51
damfidon't
52
damnfidon't
53
daredn't
54
daren't
55
dasn't
56
dassn't
57
dat's
58
dere's
59
der's
60
didn't
61
didn'tcha
62
didn'tchya
63
di'n't
64
din't
65
doesn't
66
does't
67
don't
68
don'tcha
69
do't
70
dothn't
71
dudn't
72
dun't
73
dursen't
74
dursn't
75
durstn't
76
d'ya
77
d'y'all
78
d'ye
79
d'yer
80
d'you
81
e'en
82
e'er
83
everybody's
84
everyone's
85
ev'ry
86
far's
87
fo'c's'le
88
fo'c'sle
89
fo'c'stle
90
for't
91
f'rever
92
f'rexample
93
g'bye
94
g'day
95
g'head
96
gi's
97
giv'n
98
g'night
99
g'wan
100
hadn't
101
hadn't've
102
had've
103
hain't
104
ha'n't
105
han't
106
ha'pence
107
ha'pennies
108
ha'penny
109
ha'p'orth
110
ha'porth
111
ha'p'orths
112
hasn't
113
has't
114
haven't
115
have't
116
havn't
117
heav'n
118
he'd
119
he'd've
120
he'l
121
he'll
122
he'll've
123
here'll
124
here're
125
here's
126
her's
127
he's
128
he'sn't
129
he've
130
how'd
131
how'll
132
how'm
133
how're
134
how's
135
how't
136
how've
137
I'd
138
I'd-a
139
I'da
140
idn't
141
I'dn't've
142
I'd've
143
i'faith
144
if'n
145
if't
146
I'l
147
I'll
148
I'll've
149
I'm
150
I'm'a
151
I'm-a
152
I'ma
153
i'm'a
154
i'ma
155
I'mma
156
i'n
157
in's
158
i'n't
159
in't
160
into't
161
I's
162
i's
163
I'se
164
isn't
165
is't
166
it'd
167
it'd've
168
it'll
169
it's
170
it'sn't
171
I've
172
I'ven't
173
let's
174
li'l
175
littl'un
176
ma'am
177
mayn't
178
may't
179
may've
180
m'dear
181
mightn't
182
mightn't've
183
might've
184
m'lad
185
m'ladies
186
m'lady
187
m'lord
188
m'lords
189
mng't
190
more'n
191
mus'n't
192
musn't
193
mustn't
194
mustn't've
195
must've
196
needn't
197
nee'n't
198
ne'er
199
ne'er-do-well
200
never've
201
nobody'd
202
nobody's
203
nobody've
204
nor'easter
205
not've
206
n't
207
o'clock
208
o'er
209
o'erhead
210
o'erload
211
o'erloads
212
o'erlook
213
o'erlooks
214
Oi'll
215
Oi've
216
o'lantern
217
o'lanterns
218
one's
219
on't
220
other'n
221
oughtn't
222
oughtn't've
223
p'aps
224
penn'orth
225
pen'orth
226
people'd
227
po'boy
228
pow'r
229
p'r'aps
230
p'raps
231
pray'r
232
p'rhaps
233
pudd'n'head
234
r'coon
235
run-o'-the-mill
236
same's
237
see't
238
se'nnight
239
sev'n
240
shalln't
241
shall's
242
shall've
243
sha'n't
244
shan't
245
sh'd
246
she'd
247
she'd've
248
she'l
249
she'll
250
she'll've
251
she's
252
she've
253
shouldn't
254
shouldn't've
255
should've
256
s'long
257
s'matter
258
s'more
259
s'mores
260
somebody'd
261
somebody's
262
someone's
263
something's
264
sort've
265
so's
266
th'are
267
th'art
268
that'd
269
that'd've
270
that'll
271
that'll've
272
that're
273
that's
274
that've
275
them's
276
there'd
277
there'll
278
there're
279
there's
280
there've
281
these're
282
these've
283
they'd
284
they'da
285
they'd've
286
they'l
287
they'll
288
they'll've
289
they're
290
they's
291
they've
292
th'immortall
293
this'd
294
this'll
295
this's
296
this've
297
those're
298
those've
299
tho't
300
thou'dst
301
thou'lt
302
thou'rt
303
thou'st
304
tops'l
305
to't
306
to've
307
twasn't
308
twopenn'orths
309
t'ye
310
unto't
311
upon't
312
usedn't
313
usen't
314
us's
315
view't
316
wadn't
317
wait'll
318
wa'n't
319
wan't
320
warn't
321
wasn't
322
was't
323
wazn't
324
we'd
325
we'd've
326
we'l
327
we'll
328
we'll've
329
we're
330
weren't
331
we's
332
we've
333
we'ven't
334
what'd
335
whate'er
336
whatever's
337
what'll
338
what'm
339
what're
340
what's
341
what've
342
when'd
343
whene'er
344
when'll
345
when's
346
where'd
347
where'er
348
where'm
349
where're
350
where's
351
where've
352
which'd
353
which'll
354
which're
355
which's
356
which've
357
who'd
358
who'da
359
who'd've
360
whoe'er
361
who'll
362
who'm
363
whom're
364
who're
365
who's
366
who've
367
why'd
368
why'm
369
whyn't
370
why're
371
why's
372
willn't
373
will've
374
with't
375
wolln't
376
wo'n't
377
won't
378
won't've
379
woo't
380
worn't
381
wou'd
382
wouldn't
383
wouldn'ta
384
wouldn't've
385
would've
386
wudn't
387
y'ad
388
y'ain't
389
y'all
390
ya'll
391
y'all'd
392
y'all'd've
393
y'all'll
394
y'all're
395
y'allself
396
y'allselves
397
y'all've
398
y'are
399
y'ave
400
ye'd
401
ye'll
402
y'ere
403
ye're
404
yestere'en
405
yet's
406
ye've
407
y'ever
408
y'knew
409
y'know
410
you'd
411
you'dn't've
412
you'd've
413
you'l
414
you'll
415
you'll've
416
you're
417
you'ren't
418
yours'd
419
yours'll
420
yours've
421
you's
422
you'se
423
you've
424
you'ven't
425
yo've
426
y'see
427
1428
A src/main/resources/com/keenwrite/quotes/en/outer.txt
1
'n'
2
13
A src/main/resources/com/keenwrite/quotes/en/verbs.txt
1
'd
2
'll
3
'm
4
're
5
's
6
've
7
18
M src/main/resources/com/keenwrite/settings.properties
2424
# ########################################################################
2525
26
file.stylesheet.application.dir=${application.package}/themes
26
file.stylesheet.application.dir=${application.package}/skins
2727
file.stylesheet.application.base=${file.stylesheet.application.dir}/scene.css
28
file.stylesheet.application.theme=${file.stylesheet.application.dir}/{0}.css
28
file.stylesheet.application.skin=${file.stylesheet.application.dir}/{0}.css
2929
file.stylesheet.markdown=${application.package}/editor/markdown.css
3030
# {0} language code, {1} script code, {2} country code
A src/main/resources/com/keenwrite/skins/count_darcula.css
1
.root {
2
  -fx-base: rgb( 43, 43, 43 );
3
  -fx-background: -fx-base;
4
  -fx-control-inner-background: -fx-base;
5
6
  -fx-light-text-color: rgb( 187, 187, 187 );
7
  -fx-mid-text-color: derive( -fx-base, 100% );
8
  -fx-dark-text-color: derive( -fx-base, 25% );
9
  -fx-text-foreground: -fx-light-text-color;
10
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
11
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
12
13
  /* Make controls ( buttons, thumb, etc. ) slightly lighter */
14
  -fx-color: derive( -fx-base, 20% );
15
}
16
17
.caret {
18
  -fx-stroke: -fx-accent;
19
}
20
21
.glyph-icon {
22
  -fx-text-fill: -fx-light-text-color;
23
  -fx-fill: -fx-light-text-color;
24
}
25
26
.glyph-icon:hover {
27
  -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 );
28
}
29
30
/* Fix derived prompt color for text fields */
31
.text-input {
32
  -fx-prompt-text-fill: derive( -fx-control-inner-background, +50% );
33
}
34
35
/* Keep prompt invisible when focused ( above color fix overrides it ) */
36
.text-input:focused {
37
  -fx-prompt-text-fill: transparent;
38
}
39
40
/* Fix scroll bar buttons arrows colors */
41
.scroll-bar > .increment-button > .increment-arrow,
42
.scroll-bar > .decrement-button > .decrement-arrow {
43
  -fx-background-color: -fx-mark-highlight-color,  -fx-light-text-color;
44
}
45
46
.scroll-bar > .increment-button:hover > .increment-arrow,
47
.scroll-bar > .decrement-button:hover > .decrement-arrow {
48
  -fx-background-color: -fx-mark-highlight-color, rgb( 240, 240, 240 );
49
}
50
51
.scroll-bar > .increment-button:pressed > .increment-arrow,
52
.scroll-bar > .decrement-button:pressed > .decrement-arrow {
53
  -fx-background-color: -fx-mark-highlight-color, rgb( 255, 255, 255 );
54
}
155
A src/main/resources/com/keenwrite/skins/haunted_grey.css
1
/* https://stackoverflow.com/a/58441758/59087
2
 */
3
.root { 
4
  -fx-accent: #1e74c6;
5
  -fx-focus-color: -fx-accent;
6
  -fx-base: #373e43;
7
  -fx-control-inner-background: derive( -fx-base, 35% );
8
  -fx-control-inner-background-alt: -fx-control-inner-background;
9
10
  -fx-light-text-color: derive( -fx-base, 150% );
11
  -fx-mid-text-color: derive( -fx-base, 100% );
12
  -fx-dark-text-color: derive( -fx-base, 25% );
13
  -fx-text-foreground: -fx-light-text-color;
14
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
15
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
16
}
17
18
.glyph-icon {
19
  -fx-text-fill: -fx-light-text-color;
20
  -fx-fill: -fx-light-text-color;
21
}
22
23
.glyph-icon:hover {
24
  -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 );
25
}
26
27
.label {
28
  -fx-text-fill: -fx-light-text-color;
29
}
30
31
.text-field {
32
  -fx-prompt-text-fill: gray;
33
}
34
35
.button {
36
  -fx-focus-traversable: false;
37
}
38
39
.button:hover {
40
  -fx-text-fill: white;
41
}
42
43
.separator *.line { 
44
  -fx-background-color: #3C3C3C;
45
  -fx-border-style: solid;
46
  -fx-border-width: 1px;
47
}
48
49
.scroll-bar {
50
  -fx-background-color: derive( -fx-base, 45% );
51
}
52
53
.button:default {
54
  -fx-base: -fx-accent;
55
} 
56
57
.table-view {
58
  -fx-selection-bar-non-focused: derive( -fx-base, 50% );
59
}
60
61
.table-view .column-header .label {
62
  -fx-alignment: CENTER_LEFT;
63
  -fx-font-weight: none;
64
}
65
66
.list-cell:even,
67
.list-cell:odd,
68
.table-row-cell:even,
69
.table-row-cell:odd {  
70
  -fx-control-inner-background: derive( -fx-base, 15% );
71
}
72
73
.list-cell:empty,
74
.table-row-cell:empty {
75
  -fx-background-color: transparent;
76
}
77
78
.list-cell,
79
.table-row-cell {
80
  -fx-border-color: transparent;
81
  -fx-table-cell-border-color: transparent;
82
}
83
84
/* Avoid clipping text descenders in statistics table row. */
85
.table-row-cell {
86
  -fx-cell-size: 30px;
87
}
188
A src/main/resources/com/keenwrite/skins/modena_dark.css
1
/* https://github.com/joffrey-bion/javafx-themes/blob/master/css/modena_dark.css
2
 */
3
.root {
4
  -fx-base: rgb( 50, 50, 50 );
5
  -fx-background: -fx-base;
6
7
  /* Make controls ( buttons, thumb, etc. ) slightly lighter */
8
  -fx-color: derive( -fx-base, 10% );
9
10
  /* Text fields and table rows background */
11
  -fx-control-inner-background: rgb( 20, 20, 20 );
12
  /* Version of -fx-control-inner-background for alternative rows */
13
  -fx-control-inner-background-alt: derive( -fx-control-inner-background, 2.5% );
14
15
  /* Text colors depending on background's brightness */
16
  -fx-light-text-color: rgb( 220, 220, 220 );
17
  -fx-mid-text-color: rgb( 100, 100, 100 );
18
  -fx-dark-text-color: rgb( 20, 20, 20 );
19
  -fx-text-foreground: -fx-light-text-color;
20
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
21
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
22
23
  /* A bright blue for highlighting/accenting objects.  For example: selected
24
   * text; selected items in menus, lists, trees, and tables; progress bars */
25
  -fx-accent: rgb( 0, 80, 100 );
26
27
  /* Color of non-focused yet selected elements */
28
  -fx-selection-bar-non-focused: rgb( 50, 50, 50 );
29
}
30
31
.glyph-icon {
32
  -fx-text-fill: -fx-light-text-color;
33
  -fx-fill: -fx-light-text-color;
34
}
35
36
.glyph-icon:hover {
37
  -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 );
38
}
39
40
/* Fix derived prompt color for text fields */
41
.text-input {
42
  -fx-prompt-text-fill: derive( -fx-control-inner-background, +50% );
43
}
44
45
/* Keep prompt invisible when focused ( above color fix overrides it ) */
46
.text-input:focused {
47
  -fx-prompt-text-fill: transparent;
48
}
49
50
/* Fix scroll bar buttons arrows colors */
51
.scroll-bar > .increment-button > .increment-arrow,
52
.scroll-bar > .decrement-button > .decrement-arrow {
53
  -fx-background-color: -fx-mark-highlight-color, rgb( 220, 220, 220 );
54
}
55
56
.scroll-bar > .increment-button:hover > .increment-arrow,
57
.scroll-bar > .decrement-button:hover > .decrement-arrow {
58
  -fx-background-color: -fx-mark-highlight-color, rgb( 240, 240, 240 );
59
}
60
61
.scroll-bar > .increment-button:pressed > .increment-arrow,
62
.scroll-bar > .decrement-button:pressed > .decrement-arrow {
63
  -fx-background-color: -fx-mark-highlight-color, rgb( 255, 255, 255 );
64
}
165
A src/main/resources/com/keenwrite/skins/modena_light.css
1
.root {
2
  -fx-text-foreground: -fx-dark-text-color;
3
  -fx-text-background: derive( -fx-accent, 124% );
4
  -fx-text-selection: #a6d2ff;
5
}
16
A src/main/resources/com/keenwrite/skins/scene.css
1
/*
2
 * Copyright (c) 2015 Karl Tauber <karl at jformdesigner dot com>
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 *  o Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 *
11
 *  o Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 */
27
28
.tool-bar {
29
  -fx-spacing: 0;
30
}
31
32
.tool-bar .button {
33
  -fx-background-color: transparent;
34
}
35
36
.tool-bar .button:hover {
37
  -fx-background-color: -fx-shadow-highlight-color, -fx-outer-border, -fx-inner-border, -fx-body-color;
38
  -fx-color: -fx-hover-base;
39
}
40
41
.tool-bar .button:armed {
42
  -fx-color: -fx-pressed-base;
43
}
44
45
/* Definition editor drag and drop target.
46
 */
47
.drop-target {
48
  -fx-border-color: #eea82f;
49
  -fx-border-width: 0 0 2 0;
50
  -fx-padding: 3 3 1 3
51
}
152
A src/main/resources/com/keenwrite/skins/silver_cavern.css
1
/* https://toedter.com/2011/10/26/java-fx-2-0-css-styling/
2
 */
3
.root {
4
  -fx-base: rgb( 50, 50, 50 );
5
  -fx-background: -fx-base;
6
  -fx-control-inner-background: -fx-base;
7
8
  -fx-light-text-color: derive( -fx-base, 150% );
9
  -fx-mid-text-color: derive( -fx-base, 100% );
10
  -fx-dark-text-color: derive( -fx-base, 25% );
11
  -fx-text-foreground: -fx-light-text-color;
12
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
13
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
14
}
15
16
.glyph-icon {
17
  -fx-text-fill: -fx-light-text-color;
18
  -fx-fill: -fx-light-text-color;
19
}
20
21
.glyph-icon:hover {
22
  -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 );
23
}
24
 
25
.tab {
26
  -fx-background-color: linear-gradient( to top, -fx-base, derive( -fx-base, 30% ) );
27
}
28
29
.menu-bar {
30
  -fx-background-color: linear-gradient( to bottom, -fx-base, derive( -fx-base, 30% ) );
31
}
32
 
33
.tool-bar:horizontal {
34
  -fx-background-color: linear-gradient( to bottom, derive( -fx-base, +50% ), derive( -fx-base, -40% ), derive( -fx-base, -20% ) );
35
}
36
 
37
.button {
38
  -fx-background-color: transparent;
39
}
40
 
41
.button:hover {
42
  -fx-background-color: -fx-shadow-highlight-color, -fx-outer-border, -fx-inner-border, -fx-body-color;
43
  -fx-color: -fx-hover-base;
44
}
45
 
46
.table-view {
47
  -fx-table-cell-border-color:derive( -fx-base, +10% );
48
  -fx-table-header-border-color:derive( -fx-base, +20% );
49
}
50
 
51
.split-pane:horizontal > * > .split-pane-divider {
52
  -fx-border-color: transparent -fx-base transparent -fx-base;
53
  -fx-background-color: transparent, derive( -fx-base, 20% );
54
  -fx-background-insets: 0, 0 1 0 1;
55
}
56
57
.separator-label {
58
  -fx-text-fill: orange;
59
}
160
A src/main/resources/com/keenwrite/skins/solarized_dark.css
1
/* https://ethanschoonover.com/solarized
2
 */
3
.root {
4
  /* Solarized: base03 */
5
  -fx-base: rgb( 0, 43, 54 );
6
  -fx-background: -fx-base;
7
8
  /* Brighten controls */
9
  -fx-color: derive( -fx-base, -40% );
10
11
  -fx-control-inner-background: -fx-base;
12
  -fx-control-inner-background-alt: derive( -fx-control-inner-background, 2.5% );
13
14
  /* Text colors */
15
  /* Solarized: base0 */
16
  -fx-light-text-color: rgb( 131, 148, 150 );
17
  -fx-mid-text-color: derive( -fx-light-text-color, 50% );
18
  -fx-dark-text-color: derive( -fx-light-text-color, 25% );
19
  -fx-text-foreground: -fx-light-text-color;
20
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
21
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
22
23
  -fx-mid-text-color: derive( -fx-base, 100% );
24
  -fx-dark-text-color: derive( -fx-base, 25% );
25
  -fx-text-foreground: -fx-light-text-color;
26
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
27
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
28
29
  /* Accent colors */
30
  -fx-accent: rgb( 38, 139, 210 );
31
  -fx-focus-color: rgb( 253, 246, 227 );
32
33
  /* Non-focused-selected elements */
34
  -fx-selection-bar-non-focused: rgb( 0, 43, 54 );
35
}
36
37
.glyph-icon {
38
  -fx-text-fill: -fx-light-text-color;
39
  -fx-fill: -fx-light-text-color;
40
}
41
42
.glyph-icon:hover {
43
  -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 );
44
}
45
46
.scroll-bar {
47
  -fx-background-color: derive( -fx-base, 45% );
48
}
49
50
.caret {
51
  -fx-stroke: -fx-accent;
52
}
53
154
A src/main/resources/com/keenwrite/skins/vampire_byte.css
1
/* https://github.com/Col-E/Recaf/blob/master/src/main/resources/style/ui-dark.css
2
 */
3
.root {
4
  -fx-base: rgb( 45, 45, 46 );
5
  -fx-background: -fx-base;
6
7
  /* Brighten controls */
8
  -fx-color: derive( -fx-base, -40% );
9
10
  /* Control background */
11
  -fx-control-inner-background: rgb( 46, 46, 47 );
12
13
  /* Alternative control background ( rows ) */
14
  -fx-control-inner-background-alt: derive( -fx-control-inner-background, 2.5% );
15
16
  /* Text colors */
17
  -fx-light-text-color: rgb( 220, 220, 220 );
18
  -fx-mid-text-color: rgb( 100, 100, 100 );
19
  -fx-dark-text-color: rgb( 20, 20, 20 );
20
  -fx-text-foreground: -fx-light-text-color;
21
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
22
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
23
24
  /* Accent colors */
25
  -fx-accent: rgb( 51, 51, 52 );
26
  -fx-focus-color: rgb( 51, 51, 52 );
27
28
  /* Non-focused-selected elements */
29
  -fx-selection-bar-non-focused: rgb( 45, 45, 46 );
30
}
31
32
.glyph-icon {
33
  -fx-text-fill: -fx-light-text-color;
34
  -fx-fill: -fx-light-text-color;
35
}
36
37
.glyph-icon:hover {
38
  -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 );
39
}
40
41
* {
42
  -fx-highlight-fill: rgba( 0, 180, 255, 0.4 );
43
}
44
45
/* Scroll */
46
.scroll-bar {
47
  -fx-background-color: rgb( 61,61,62 );
48
}
49
.scroll-bar .thumb {
50
  -fx-background-color: rgb( 91,91,92 );
51
  -fx-background-radius: 0;
52
}
53
.scroll-bar .thumb:hover,
54
.scroll-bar .thumb:pressed {
55
  -fx-background-color: rgb( 141,141,142 );
56
}
57
.scroll-bar .increment-button .increment-arrow,
58
.scroll-bar .decrement-button .decrement-arrow {
59
  -fx-background-color: rgb( 200,200,200 );
60
}
61
.corner {
62
  -fx-background-color: rgb( 61,61,62 );
63
}
64
65
/* Menu */
66
.menu-bar {
67
  -fx-background-color: rgb( 45, 45, 48 );
68
}
69
.menu {
70
  -fx-padding: 6 14 6 14;
71
  -fx-background-insets: -1;
72
}
73
.menu-item {
74
  -fx-padding: 5 11 5 11;
75
  -fx-background-insets: -1;
76
}
77
.menu:hover {
78
  -fx-background-color: rgb( 61, 61, 62 );
79
}
80
.context-menu,
81
.menu:showing {
82
  -fx-background-color: rgb( 27, 27, 28 );
83
  -fx-border-insets: -1;
84
  -fx-border-width: 1;
85
  -fx-border-color: black;
86
}
87
.context-menu {
88
  -fx-min-width: 80px;
89
  -fx-background-insets: -1;
90
  -fx-border-insets: -1;
91
  -fx-border-width: 1;
92
  -fx-border-color: black;
93
}
94
.context-menu .menu-item:focused {
95
  -fx-background-color: rgb( 61, 61, 62 );
96
}
97
.context-menu-header {
98
  /* TODO: Find a way to disable hover coloring on the menu header */
99
  -fx-opacity: 1.0;
100
  -fx-background-color: rgb( 24, 50, 95 );
101
}
102
.context-menu-header .label {
103
  -fx-opacity: 1.0;
104
}
105
106
/* Tabs */
107
.tab-pane {
108
  -fx-tab-min-width: 100px;
109
}
110
.tab-pane *.tab-header-background {
111
  -fx-background-color: rgb( 29, 29, 31 );
112
  -fx-border-width: 0 0 1 0;
113
  -fx-border-color: black;
114
}
115
.headers-region {
116
  -fx-background-color: rgb( 75, 75, 76 );
117
}
118
.tab {
119
  -fx-background-color: rgb( 36,36,37 );
120
  -fx-background-insets: 2 -1 -1 -1;
121
  -fx-background-radius: 0;
122
  -fx-padding: 2 2 1 2;
123
  -fx-border-insets: 0;
124
  -fx-border-width: 1 1 1 1;
125
  -fx-border-color: black;
126
}
127
.tab:selected {
128
  -fx-background-color: rgb( 45, 45, 46 );
129
  -fx-background-insets: 2 -1 -1 -1;
130
  -fx-padding: 2;
131
  -fx-border-insets: 0;
132
  -fx-border-width: 1 1 0 1;
133
  -fx-border-color: black;
134
}
135
.tab:selected .focus-indicator {
136
  -fx-border-color: transparent;
137
}
138
139
/* Table */
140
.table-view {
141
  -fx-selection-bar: rgb( 50, 71, 77 );
142
  -fx-selection-bar-non-focused: rgb( 46, 56, 59 );
143
  -fx-background-color: rgb( 36,36,37 );
144
  -fx-background-insets: 2 -1 -1 -1;
145
  -fx-background-radius: 0;
146
  -fx-padding: -1;
147
  -fx-border-width: 0 1 1 1;
148
  -fx-border-color: rgb( 22, 22, 23 );
149
}
150
.table-view .filler,
151
.table-view .show-hide-columns-button,
152
.column-overlay {
153
  -fx-background-color: transparent;
154
}
155
.column-header-background {
156
  -fx-background-color: rgb( 36,36,37 );
157
  -fx-background-insets: 2 -1 -1 -1;
158
  -fx-padding: -1;
159
  -fx-border-insets: 0;
160
  -fx-border-width: 0 1 0 1;
161
  -fx-border-color: rgb( 22, 22, 23 );
162
}
163
.column-header {
164
  -fx-background-color: rgb( 45, 45, 46 );
165
  -fx-background-insets: -1 -0 -1 0;
166
  -fx-padding: 2;
167
  -fx-border-insets: 1 -1 1 0;
168
  -fx-border-width: 1;
169
  -fx-border-color: rgb( 22, 22, 23 );
170
}
171
172
/* Splitpane */
173
.split-pane-divider {
174
  -fx-background-color: black;
175
  -fx-padding: 0;
176
  -fx-background-insets: -5;
177
}
178
179
/* Tree */
180
.tree-table-view,
181
.tree-view {
182
  -fx-background-color: rgb( 29, 29, 31 );
183
  -fx-background-insets: 0;
184
  -fx-border-width: 0 1 0 0;
185
  -fx-border-color: black;
186
}
187
.tree-table-cell,
188
.tree-cell {
189
  -fx-background-color: rgb( 29, 29, 31 );
190
}
191
.tree-cell:selected {
192
  -fx-background-color: rgb( 44, 48, 55 );
193
}
194
195
/* Buttons */
196
.box,
197
.button,
198
.combo-box,
199
.slider .thumb {
200
  -fx-background-radius: 0;
201
  -fx-background-color: rgb( 63, 63, 70 );
202
  -fx-background-insets: 0;
203
  -fx-border-width: 1;
204
  -fx-border-color: rgb( 85, 85, 85 );
205
}
206
.check-box:hover .box,
207
.button:hover,
208
.combo-box:hover,
209
.slider .thumb:hover {
210
  -fx-background-color: rgb( 80, 80, 85 );
211
  -fx-border-color: rgb( 0, 122, 205 );
212
}
213
.check-box:pressed .box,
214
.button:pressed,
215
.combo-box:pressed,
216
.slider .thumb:pressed {
217
  -fx-background-color: rgb( 0, 122, 205 );
218
  -fx-border-color: rgb( 0, 162, 245 );
219
}
220
.combo-box:showing {
221
  -fx-background-color: rgb( 27, 27, 28 );
222
  -fx-border-width: 1 1 0 1;
223
  -fx-border-color: black;
224
}
225
.combo-box .combo-box-popup .list-cell {
226
  -fx-background-color: rgb( 27, 27, 28 );
227
}
228
.combo-box .combo-box-popup .list-cell:hover {
229
  -fx-background-color: rgb( 61, 61, 62 );
230
}
231
.combo-box .combo-box-popup .list-view {
232
  -fx-background-color: rgb( 27, 27, 28 );
233
  -fx-border-width: 0 1 1 1;
234
  -fx-border-color: black;
235
}
236
.hyperlink {
237
  -fx-text-fill: rgb( 30, 132, 250 );
238
}
239
hyperlink:visited {
240
  -fx-text-fill: rgb( 98, 59, 217 );
241
}
242
243
/* slider */
244
.slider .track {
245
  -fx-background-radius: 0;
246
  -fx-background-color: rgb( 29, 29, 31 );
247
  -fx-background-insets: 0;
248
  -fx-border-width: 1;
249
  -fx-border-color: rgb( 65, 65, 65 );
250
}
251
.slider .thumb {
252
  -fx-padding: 5;
253
}
254
.axis-tick-mark {
255
  -fx-stroke: rgb( 100, 100, 100 );
256
}
257
258
/* Text */
259
.text-area .content,
260
.text-field {
261
  -fx-background-radius: 0;
262
  -fx-background-color: rgb( 63, 63, 70 );
263
  -fx-background-insets: 0;
264
  -fx-border-width: 1;
265
  -fx-border-color: rgb( 85, 85, 85 );
266
}
267
.text-area {
268
  -fx-background-radius: 0;
269
  -fx-background-color: rgb( 63, 63, 70 );
270
  -fx-background-insets: 0;
271
  -fx-border-width: 1;
272
  -fx-border-color: rgb( 85, 85, 85 );
273
}
274
.text-area .content {
275
  -fx-border-width: 0;
276
}
277
278
/* Popup */
279
.tooltip {
280
  -fx-background-radius: 0;
281
  -fx-background-color: rgb( 40, 40, 42 );
282
  -fx-background-insets: 0;
283
  -fx-border-width: 1;
284
  -fx-border-color: rgb( 70, 70, 72 );
285
}
1286
D src/main/resources/com/keenwrite/themes/count_darcula.css
1
.root {
2
  -fx-base: rgb( 43, 43, 43 );
3
  -fx-background: -fx-base;
4
  -fx-control-inner-background: -fx-base;
5
6
  -fx-light-text-color: rgb( 187, 187, 187 );
7
  -fx-mid-text-color: derive( -fx-base, 100% );
8
  -fx-dark-text-color: derive( -fx-base, 25% );
9
  -fx-text-foreground: -fx-light-text-color;
10
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
11
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
12
13
  /* Make controls ( buttons, thumb, etc. ) slightly lighter */
14
  -fx-color: derive( -fx-base, 20% );
15
}
16
17
.caret {
18
  -fx-stroke: -fx-accent;
19
}
20
21
.glyph-icon {
22
  -fx-text-fill: -fx-light-text-color;
23
  -fx-fill: -fx-light-text-color;
24
}
25
26
.glyph-icon:hover {
27
  -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 );
28
}
29
30
/* Fix derived prompt color for text fields */
31
.text-input {
32
  -fx-prompt-text-fill: derive( -fx-control-inner-background, +50% );
33
}
34
35
/* Keep prompt invisible when focused ( above color fix overrides it ) */
36
.text-input:focused {
37
  -fx-prompt-text-fill: transparent;
38
}
39
40
/* Fix scroll bar buttons arrows colors */
41
.scroll-bar > .increment-button > .increment-arrow,
42
.scroll-bar > .decrement-button > .decrement-arrow {
43
  -fx-background-color: -fx-mark-highlight-color,  -fx-light-text-color;
44
}
45
46
.scroll-bar > .increment-button:hover > .increment-arrow,
47
.scroll-bar > .decrement-button:hover > .decrement-arrow {
48
  -fx-background-color: -fx-mark-highlight-color, rgb( 240, 240, 240 );
49
}
50
51
.scroll-bar > .increment-button:pressed > .increment-arrow,
52
.scroll-bar > .decrement-button:pressed > .decrement-arrow {
53
  -fx-background-color: -fx-mark-highlight-color, rgb( 255, 255, 255 );
54
}
551
D src/main/resources/com/keenwrite/themes/haunted_grey.css
1
/* https://stackoverflow.com/a/58441758/59087
2
 */
3
.root { 
4
  -fx-accent: #1e74c6;
5
  -fx-focus-color: -fx-accent;
6
  -fx-base: #373e43;
7
  -fx-control-inner-background: derive( -fx-base, 35% );
8
  -fx-control-inner-background-alt: -fx-control-inner-background;
9
10
  -fx-light-text-color: derive( -fx-base, 150% );
11
  -fx-mid-text-color: derive( -fx-base, 100% );
12
  -fx-dark-text-color: derive( -fx-base, 25% );
13
  -fx-text-foreground: -fx-light-text-color;
14
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
15
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
16
}
17
18
.glyph-icon {
19
  -fx-text-fill: -fx-light-text-color;
20
  -fx-fill: -fx-light-text-color;
21
}
22
23
.glyph-icon:hover {
24
  -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 );
25
}
26
27
.label {
28
  -fx-text-fill: -fx-light-text-color;
29
}
30
31
.text-field {
32
  -fx-prompt-text-fill: gray;
33
}
34
35
.button {
36
  -fx-focus-traversable: false;
37
}
38
39
.button:hover {
40
  -fx-text-fill: white;
41
}
42
43
.separator *.line { 
44
  -fx-background-color: #3C3C3C;
45
  -fx-border-style: solid;
46
  -fx-border-width: 1px;
47
}
48
49
.scroll-bar {
50
  -fx-background-color: derive( -fx-base, 45% );
51
}
52
53
.button:default {
54
  -fx-base: -fx-accent;
55
} 
56
57
.table-view {
58
  -fx-selection-bar-non-focused: derive( -fx-base, 50% );
59
}
60
61
.table-view .column-header .label {
62
  -fx-alignment: CENTER_LEFT;
63
  -fx-font-weight: none;
64
}
65
66
.list-cell:even,
67
.list-cell:odd,
68
.table-row-cell:even,
69
.table-row-cell:odd {  
70
  -fx-control-inner-background: derive( -fx-base, 15% );
71
}
72
73
.list-cell:empty,
74
.table-row-cell:empty {
75
  -fx-background-color: transparent;
76
}
77
78
.list-cell,
79
.table-row-cell {
80
  -fx-border-color: transparent;
81
  -fx-table-cell-border-color: transparent;
82
}
83
84
/* Avoid clipping text descenders in statistics table row. */
85
.table-row-cell {
86
  -fx-cell-size: 30px;
87
}
881
D src/main/resources/com/keenwrite/themes/modena_dark.css
1
/* https://github.com/joffrey-bion/javafx-themes/blob/master/css/modena_dark.css
2
 */
3
.root {
4
  -fx-base: rgb( 50, 50, 50 );
5
  -fx-background: -fx-base;
6
7
  /* Make controls ( buttons, thumb, etc. ) slightly lighter */
8
  -fx-color: derive( -fx-base, 10% );
9
10
  /* Text fields and table rows background */
11
  -fx-control-inner-background: rgb( 20, 20, 20 );
12
  /* Version of -fx-control-inner-background for alternative rows */
13
  -fx-control-inner-background-alt: derive( -fx-control-inner-background, 2.5% );
14
15
  /* Text colors depending on background's brightness */
16
  -fx-light-text-color: rgb( 220, 220, 220 );
17
  -fx-mid-text-color: rgb( 100, 100, 100 );
18
  -fx-dark-text-color: rgb( 20, 20, 20 );
19
  -fx-text-foreground: -fx-light-text-color;
20
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
21
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
22
23
  /* A bright blue for highlighting/accenting objects.  For example: selected
24
   * text; selected items in menus, lists, trees, and tables; progress bars */
25
  -fx-accent: rgb( 0, 80, 100 );
26
27
  /* Color of non-focused yet selected elements */
28
  -fx-selection-bar-non-focused: rgb( 50, 50, 50 );
29
}
30
31
.glyph-icon {
32
  -fx-text-fill: -fx-light-text-color;
33
  -fx-fill: -fx-light-text-color;
34
}
35
36
.glyph-icon:hover {
37
  -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 );
38
}
39
40
/* Fix derived prompt color for text fields */
41
.text-input {
42
  -fx-prompt-text-fill: derive( -fx-control-inner-background, +50% );
43
}
44
45
/* Keep prompt invisible when focused ( above color fix overrides it ) */
46
.text-input:focused {
47
  -fx-prompt-text-fill: transparent;
48
}
49
50
/* Fix scroll bar buttons arrows colors */
51
.scroll-bar > .increment-button > .increment-arrow,
52
.scroll-bar > .decrement-button > .decrement-arrow {
53
  -fx-background-color: -fx-mark-highlight-color, rgb( 220, 220, 220 );
54
}
55
56
.scroll-bar > .increment-button:hover > .increment-arrow,
57
.scroll-bar > .decrement-button:hover > .decrement-arrow {
58
  -fx-background-color: -fx-mark-highlight-color, rgb( 240, 240, 240 );
59
}
60
61
.scroll-bar > .increment-button:pressed > .increment-arrow,
62
.scroll-bar > .decrement-button:pressed > .decrement-arrow {
63
  -fx-background-color: -fx-mark-highlight-color, rgb( 255, 255, 255 );
64
}
651
D src/main/resources/com/keenwrite/themes/modena_light.css
1
.root {
2
  -fx-text-foreground: -fx-dark-text-color;
3
  -fx-text-background: derive( -fx-accent, 124% );
4
  -fx-text-selection: #a6d2ff;
5
}
61
D src/main/resources/com/keenwrite/themes/scene.css
1
/*
2
 * Copyright (c) 2015 Karl Tauber <karl at jformdesigner dot com>
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 *  o Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 *
11
 *  o Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 */
27
28
.tool-bar {
29
  -fx-spacing: 0;
30
}
31
32
.tool-bar .button {
33
  -fx-background-color: transparent;
34
}
35
36
.tool-bar .button:hover {
37
  -fx-background-color: -fx-shadow-highlight-color, -fx-outer-border, -fx-inner-border, -fx-body-color;
38
  -fx-color: -fx-hover-base;
39
}
40
41
.tool-bar .button:armed {
42
  -fx-color: -fx-pressed-base;
43
}
44
45
/* Definition editor drag and drop target.
46
 */
47
.drop-target {
48
  -fx-border-color: #eea82f;
49
  -fx-border-width: 0 0 2 0;
50
  -fx-padding: 3 3 1 3
51
}
521
D src/main/resources/com/keenwrite/themes/silver_cavern.css
1
/* https://toedter.com/2011/10/26/java-fx-2-0-css-styling/
2
 */
3
.root {
4
  -fx-base: rgb( 50, 50, 50 );
5
  -fx-background: -fx-base;
6
  -fx-control-inner-background: -fx-base;
7
8
  -fx-light-text-color: derive( -fx-base, 150% );
9
  -fx-mid-text-color: derive( -fx-base, 100% );
10
  -fx-dark-text-color: derive( -fx-base, 25% );
11
  -fx-text-foreground: -fx-light-text-color;
12
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
13
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
14
}
15
16
.glyph-icon {
17
  -fx-text-fill: -fx-light-text-color;
18
  -fx-fill: -fx-light-text-color;
19
}
20
21
.glyph-icon:hover {
22
  -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 );
23
}
24
 
25
.tab {
26
  -fx-background-color: linear-gradient( to top, -fx-base, derive( -fx-base, 30% ) );
27
}
28
29
.menu-bar {
30
  -fx-background-color: linear-gradient( to bottom, -fx-base, derive( -fx-base, 30% ) );
31
}
32
 
33
.tool-bar:horizontal {
34
  -fx-background-color: linear-gradient( to bottom, derive( -fx-base, +50% ), derive( -fx-base, -40% ), derive( -fx-base, -20% ) );
35
}
36
 
37
.button {
38
  -fx-background-color: transparent;
39
}
40
 
41
.button:hover {
42
  -fx-background-color: -fx-shadow-highlight-color, -fx-outer-border, -fx-inner-border, -fx-body-color;
43
  -fx-color: -fx-hover-base;
44
}
45
 
46
.table-view {
47
  -fx-table-cell-border-color:derive( -fx-base, +10% );
48
  -fx-table-header-border-color:derive( -fx-base, +20% );
49
}
50
 
51
.split-pane:horizontal > * > .split-pane-divider {
52
  -fx-border-color: transparent -fx-base transparent -fx-base;
53
  -fx-background-color: transparent, derive( -fx-base, 20% );
54
  -fx-background-insets: 0, 0 1 0 1;
55
}
56
57
.separator-label {
58
  -fx-text-fill: orange;
59
}
601
D src/main/resources/com/keenwrite/themes/solarized_dark.css
1
/* https://ethanschoonover.com/solarized
2
 */
3
.root {
4
  /* Solarized: base03 */
5
  -fx-base: rgb( 0, 43, 54 );
6
  -fx-background: -fx-base;
7
8
  /* Brighten controls */
9
  -fx-color: derive( -fx-base, -40% );
10
11
  -fx-control-inner-background: -fx-base;
12
  -fx-control-inner-background-alt: derive( -fx-control-inner-background, 2.5% );
13
14
  /* Text colors */
15
  /* Solarized: base0 */
16
  -fx-light-text-color: rgb( 131, 148, 150 );
17
  -fx-mid-text-color: derive( -fx-light-text-color, 50% );
18
  -fx-dark-text-color: derive( -fx-light-text-color, 25% );
19
  -fx-text-foreground: -fx-light-text-color;
20
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
21
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
22
23
  -fx-mid-text-color: derive( -fx-base, 100% );
24
  -fx-dark-text-color: derive( -fx-base, 25% );
25
  -fx-text-foreground: -fx-light-text-color;
26
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
27
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
28
29
  /* Accent colors */
30
  -fx-accent: rgb( 38, 139, 210 );
31
  -fx-focus-color: rgb( 253, 246, 227 );
32
33
  /* Non-focused-selected elements */
34
  -fx-selection-bar-non-focused: rgb( 0, 43, 54 );
35
}
36
37
.glyph-icon {
38
  -fx-text-fill: -fx-light-text-color;
39
  -fx-fill: -fx-light-text-color;
40
}
41
42
.glyph-icon:hover {
43
  -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 );
44
}
45
46
.scroll-bar {
47
  -fx-background-color: derive( -fx-base, 45% );
48
}
49
50
.caret {
51
  -fx-stroke: -fx-accent;
52
}
53
541
D src/main/resources/com/keenwrite/themes/vampire_byte.css
1
/* https://github.com/Col-E/Recaf/blob/master/src/main/resources/style/ui-dark.css
2
 */
3
.root {
4
  -fx-base: rgb( 45, 45, 46 );
5
  -fx-background: -fx-base;
6
7
  /* Brighten controls */
8
  -fx-color: derive( -fx-base, -40% );
9
10
  /* Control background */
11
  -fx-control-inner-background: rgb( 46, 46, 47 );
12
13
  /* Alternative control background ( rows ) */
14
  -fx-control-inner-background-alt: derive( -fx-control-inner-background, 2.5% );
15
16
  /* Text colors */
17
  -fx-light-text-color: rgb( 220, 220, 220 );
18
  -fx-mid-text-color: rgb( 100, 100, 100 );
19
  -fx-dark-text-color: rgb( 20, 20, 20 );
20
  -fx-text-foreground: -fx-light-text-color;
21
  -fx-text-background: derive( -fx-control-inner-background, 7.5% );
22
  -fx-text-selection: derive( -fx-control-inner-background, 45% );
23
24
  /* Accent colors */
25
  -fx-accent: rgb( 51, 51, 52 );
26
  -fx-focus-color: rgb( 51, 51, 52 );
27
28
  /* Non-focused-selected elements */
29
  -fx-selection-bar-non-focused: rgb( 45, 45, 46 );
30
}
31
32
.glyph-icon {
33
  -fx-text-fill: -fx-light-text-color;
34
  -fx-fill: -fx-light-text-color;
35
}
36
37
.glyph-icon:hover {
38
  -fx-effect: dropshadow( three-pass-box, rgba( 0, 0, 0, 0.2 ), 4, 0, 0, 0 );
39
}
40
41
* {
42
  -fx-highlight-fill: rgba( 0, 180, 255, 0.4 );
43
}
44
45
/* Scroll */
46
.scroll-bar {
47
  -fx-background-color: rgb( 61,61,62 );
48
}
49
.scroll-bar .thumb {
50
  -fx-background-color: rgb( 91,91,92 );
51
  -fx-background-radius: 0;
52
}
53
.scroll-bar .thumb:hover,
54
.scroll-bar .thumb:pressed {
55
  -fx-background-color: rgb( 141,141,142 );
56
}
57
.scroll-bar .increment-button .increment-arrow,
58
.scroll-bar .decrement-button .decrement-arrow {
59
  -fx-background-color: rgb( 200,200,200 );
60
}
61
.corner {
62
  -fx-background-color: rgb( 61,61,62 );
63
}
64
65
/* Menu */
66
.menu-bar {
67
  -fx-background-color: rgb( 45, 45, 48 );
68
}
69
.menu {
70
  -fx-padding: 6 14 6 14;
71
  -fx-background-insets: -1;
72
}
73
.menu-item {
74
  -fx-padding: 5 11 5 11;
75
  -fx-background-insets: -1;
76
}
77
.menu:hover {
78
  -fx-background-color: rgb( 61, 61, 62 );
79
}
80
.context-menu,
81
.menu:showing {
82
  -fx-background-color: rgb( 27, 27, 28 );
83
  -fx-border-insets: -1;
84
  -fx-border-width: 1;
85
  -fx-border-color: black;
86
}
87
.context-menu {
88
  -fx-min-width: 80px;
89
  -fx-background-insets: -1;
90
  -fx-border-insets: -1;
91
  -fx-border-width: 1;
92
  -fx-border-color: black;
93
}
94
.context-menu .menu-item:focused {
95
  -fx-background-color: rgb( 61, 61, 62 );
96
}
97
.context-menu-header {
98
  /* TODO: Find a way to disable hover coloring on the menu header */
99
  -fx-opacity: 1.0;
100
  -fx-background-color: rgb( 24, 50, 95 );
101
}
102
.context-menu-header .label {
103
  -fx-opacity: 1.0;
104
}
105
106
/* Tabs */
107
.tab-pane {
108
  -fx-tab-min-width: 100px;
109
}
110
.tab-pane *.tab-header-background {
111
  -fx-background-color: rgb( 29, 29, 31 );
112
  -fx-border-width: 0 0 1 0;
113
  -fx-border-color: black;
114
}
115
.headers-region {
116
  -fx-background-color: rgb( 75, 75, 76 );
117
}
118
.tab {
119
  -fx-background-color: rgb( 36,36,37 );
120
  -fx-background-insets: 2 -1 -1 -1;
121
  -fx-background-radius: 0;
122
  -fx-padding: 2 2 1 2;
123
  -fx-border-insets: 0;
124
  -fx-border-width: 1 1 1 1;
125
  -fx-border-color: black;
126
}
127
.tab:selected {
128
  -fx-background-color: rgb( 45, 45, 46 );
129
  -fx-background-insets: 2 -1 -1 -1;
130
  -fx-padding: 2;
131
  -fx-border-insets: 0;
132
  -fx-border-width: 1 1 0 1;
133
  -fx-border-color: black;
134
}
135
.tab:selected .focus-indicator {
136
  -fx-border-color: transparent;
137
}
138
139
/* Table */
140
.table-view {
141
  -fx-selection-bar: rgb( 50, 71, 77 );
142
  -fx-selection-bar-non-focused: rgb( 46, 56, 59 );
143
  -fx-background-color: rgb( 36,36,37 );
144
  -fx-background-insets: 2 -1 -1 -1;
145
  -fx-background-radius: 0;
146
  -fx-padding: -1;
147
  -fx-border-width: 0 1 1 1;
148
  -fx-border-color: rgb( 22, 22, 23 );
149
}
150
.table-view .filler,
151
.table-view .show-hide-columns-button,
152
.column-overlay {
153
  -fx-background-color: transparent;
154
}
155
.column-header-background {
156
  -fx-background-color: rgb( 36,36,37 );
157
  -fx-background-insets: 2 -1 -1 -1;
158
  -fx-padding: -1;
159
  -fx-border-insets: 0;
160
  -fx-border-width: 0 1 0 1;
161
  -fx-border-color: rgb( 22, 22, 23 );
162
}
163
.column-header {
164
  -fx-background-color: rgb( 45, 45, 46 );
165
  -fx-background-insets: -1 -0 -1 0;
166
  -fx-padding: 2;
167
  -fx-border-insets: 1 -1 1 0;
168
  -fx-border-width: 1;
169
  -fx-border-color: rgb( 22, 22, 23 );
170
}
171
172
/* Splitpane */
173
.split-pane-divider {
174
  -fx-background-color: black;
175
  -fx-padding: 0;
176
  -fx-background-insets: -5;
177
}
178
179
/* Tree */
180
.tree-table-view,
181
.tree-view {
182
  -fx-background-color: rgb( 29, 29, 31 );
183
  -fx-background-insets: 0;
184
  -fx-border-width: 0 1 0 0;
185
  -fx-border-color: black;
186
}
187
.tree-table-cell,
188
.tree-cell {
189
  -fx-background-color: rgb( 29, 29, 31 );
190
}
191
.tree-cell:selected {
192
  -fx-background-color: rgb( 44, 48, 55 );
193
}
194
195
/* Buttons */
196
.box,
197
.button,
198
.combo-box,
199
.slider .thumb {
200
  -fx-background-radius: 0;
201
  -fx-background-color: rgb( 63, 63, 70 );
202
  -fx-background-insets: 0;
203
  -fx-border-width: 1;
204
  -fx-border-color: rgb( 85, 85, 85 );
205
}
206
.check-box:hover .box,
207
.button:hover,
208
.combo-box:hover,
209
.slider .thumb:hover {
210
  -fx-background-color: rgb( 80, 80, 85 );
211
  -fx-border-color: rgb( 0, 122, 205 );
212
}
213
.check-box:pressed .box,
214
.button:pressed,
215
.combo-box:pressed,
216
.slider .thumb:pressed {
217
  -fx-background-color: rgb( 0, 122, 205 );
218
  -fx-border-color: rgb( 0, 162, 245 );
219
}
220
.combo-box:showing {
221
  -fx-background-color: rgb( 27, 27, 28 );
222
  -fx-border-width: 1 1 0 1;
223
  -fx-border-color: black;
224
}
225
.combo-box .combo-box-popup .list-cell {
226
  -fx-background-color: rgb( 27, 27, 28 );
227
}
228
.combo-box .combo-box-popup .list-cell:hover {
229
  -fx-background-color: rgb( 61, 61, 62 );
230
}
231
.combo-box .combo-box-popup .list-view {
232
  -fx-background-color: rgb( 27, 27, 28 );
233
  -fx-border-width: 0 1 1 1;
234
  -fx-border-color: black;
235
}
236
.hyperlink {
237
  -fx-text-fill: rgb( 30, 132, 250 );
238
}
239
hyperlink:visited {
240
  -fx-text-fill: rgb( 98, 59, 217 );
241
}
242
243
/* slider */
244
.slider .track {
245
  -fx-background-radius: 0;
246
  -fx-background-color: rgb( 29, 29, 31 );
247
  -fx-background-insets: 0;
248
  -fx-border-width: 1;
249
  -fx-border-color: rgb( 65, 65, 65 );
250
}
251
.slider .thumb {
252
  -fx-padding: 5;
253
}
254
.axis-tick-mark {
255
  -fx-stroke: rgb( 100, 100, 100 );
256
}
257
258
/* Text */
259
.text-area .content,
260
.text-field {
261
  -fx-background-radius: 0;
262
  -fx-background-color: rgb( 63, 63, 70 );
263
  -fx-background-insets: 0;
264
  -fx-border-width: 1;
265
  -fx-border-color: rgb( 85, 85, 85 );
266
}
267
.text-area {
268
  -fx-background-radius: 0;
269
  -fx-background-color: rgb( 63, 63, 70 );
270
  -fx-background-insets: 0;
271
  -fx-border-width: 1;
272
  -fx-border-color: rgb( 85, 85, 85 );
273
}
274
.text-area .content {
275
  -fx-border-width: 0;
276
}
277
278
/* Popup */
279
.tooltip {
280
  -fx-background-radius: 0;
281
  -fx-background-color: rgb( 40, 40, 42 );
282
  -fx-background-insets: 0;
283
  -fx-border-width: 1;
284
  -fx-border-color: rgb( 70, 70, 72 );
285
}
2861
M src/main/resources/com/keenwrite/ui/fonts/icons/3g2.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.5-24c.4.4 1.1.7 1.7.7.9 0 1.6-.4 1.6-1.6 0-1-.7-1.5-2.3-1.5h-.9L7 12.8l2-2.5c.5-.6.9-1 .9-1s-.4.1-1.1.1H6.5v-3h7.2V9l-2.6 3.1c2 .5 3.1 2.1 3.1 4.1 0 2.4-1.4 4.8-4.7 4.8-1.3 0-2.5-.4-3.5-1.3L7.5 17zM23.1 6.1c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.7-7.6 6.5-7.6zm7.6 13c0-5 4.5-5.5 4.5-8.4 0-1-.5-1.4-1.2-1.4-.6 0-1.1.3-1.4.8l-2.2-1.8c.8-1.1 2.3-2.1 4.1-2.1 2.1 0 4.2 1.3 4.2 4.2 0 4.1-4.2 5.4-4.4 7.5h4.6v2.9H31c-.2-.7-.3-1.1-.3-1.7z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/3ga.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.5-24c.4.4 1.1.7 1.7.7.9 0 1.6-.4 1.6-1.6 0-1-.7-1.5-2.3-1.5h-.9L7 12.8l2-2.5c.5-.6.9-1 .9-1s-.4.1-1.1.1H6.5v-3h7.2V9l-2.6 3.1c2 .5 3.1 2.1 3.1 4.1 0 2.4-1.4 4.8-4.7 4.8-1.3 0-2.5-.4-3.5-1.3L7.5 17zM23.1 6.1c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.7-7.6 6.5-7.6zm10.3.3H37l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/3gp.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.5-24c.4.4 1.1.7 1.7.7.9 0 1.6-.4 1.6-1.6 0-1-.7-1.5-2.3-1.5h-.9L7 12.8l2-2.5c.5-.6.9-1 .9-1s-.4.1-1.1.1H6.5v-3h7.2V9l-2.6 3.1c2 .5 3.1 2.1 3.1 4.1 0 2.4-1.4 4.8-4.7 4.8-1.3 0-2.5-.4-3.5-1.3L7.5 17zM23.1 6.1c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.7-7.6 6.5-7.6zm7.9.3h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4H31V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/7z.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#90c}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm4.3-30.3c.4-1 .6-1.4.6-1.4H6.1V6.4h8.2v2.4L9.7 20.7H6.3l4-10zm6.3 7.8l4.2-7.9c.5-.9.8-1.3.8-1.3s-.3.1-.8.1h-4v-3h8.7v2.2l-4.2 8c-.5.9-.8 1.3-.8 1.3s.3-.1.8-.1h4.3v2.9h-8.9v-2.2z" fill="#fff"/><path class="st0" d="M51.1 57.5h-5.7v-5.7l5.7 5.7zm-15.3-5.7v20.7h15.4V58.9H44v-7.1h-8.2zm2.4-5.4h-17v4h6.7l-4.2 3.3v3.5l6.2-4.8v-1.9h21.6v-1.6l-13.3-2.5zm-8.3 8.7l-6.2 4.8v3.5l6.2-4.8v-3.5zm-6.3 14.4l6.2-4.8v-3.5L23.6 66v3.5zm6.3 1.4v-3.5l-6.2 4.8V74h-2.5v4H25v2.8h-2.2c-.4-.7-1.1-1.2-2-1.2-1.3 0-2.3 1-2.3 2.3 0 1.3 1 2.3 2.3 2.3.9 0 1.6-.5 2-1.2H25v2.1h3.4V83h2.2c.4.7 1.1 1.2 2 1.2 1.3 0 2.3-1 2.3-2.3 0-1.3-1-2.3-2.3-2.3-.9 0-1.6.5-2 1.2h-2.2V78h9.7l13.3-2.4V74H25.7l4.2-3.1z"/></svg>
1
<svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/aa.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm9.3-8.6h3.6l3.6 14.3H25l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.1-1-.3-2.5-.3-2.5h-.1s-.2 1.5-.4 2.5l-.6 2.8h2z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/aac.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm9.3-8.6h3.6l3.6 14.3H25l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.1-1-.3-2.5-.3-2.5h-.1s-.2 1.5-.4 2.5l-.6 2.8h2zm12.5-8.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ac.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm12.5-8.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4z" fill="#fff"/><path class="st0" d="M50.3 72.6v10c0 .2-.2.4-.4.4H20.1c-.2 0-.4-.2-.4-.4v-.9c0-.2.2-.4.4-.4h1.3l15.5-15.5-16.1-16.1c-.1-.1-.1-.2-.1-.3v-1c0-.2.2-.4.4-.4h28.8c.2 0 .4.2.4.4v9.9c0 .2-.2.4-.4.4h-1.1c-.2 0-.4-.2-.4-.4 0-4.2-2.5-7.7-6.9-7.7H29.9L43 63.8c.2.2.2.4 0 .6L30.2 77.2h11.3c3 0 5.6-1.9 6.6-4.7.1-.2.2-.3.4-.3H50c.2 0 .3.2.3.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M56.633 44.984V63.27c0 .363-.367.73-.735.73H1.102c-.368 0-.735-.367-.735-.73V61.62c0-.363.367-.73.735-.73h2.39l28.5-28.344L2.391 3.109c-.184-.183-.184-.367-.184-.55V.73c0-.363.367-.73.734-.73h52.957c.368 0 .735.367.735.73v18.106c0 .363-.367.73-.735.73h-2.023c-.367 0-.734-.367-.734-.73 0-7.684-4.598-14.082-12.688-14.082H19.121l24.09 24.137c.367.367.367.73 0 1.097L19.676 53.395h20.777c5.516 0 10.297-3.473 12.133-8.594.184-.367.367-.551.738-.551h2.758c.367 0 .55.367.55.734zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/accdb.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#a03537}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.4 6.5h2l2.8 14.2h-1.8l-.7-3.7H8.1l-.6 3.7H5.6L8.4 6.5zm2 8.5l-.7-3.8c-.1-.8-.3-2.2-.3-2.2s-.2 1.4-.3 2.2L8.4 15h2zm7.4-8.8c.9 0 1.9.4 2.6 1.2l-.8 2.1c-.4-.5-1.1-1-1.8-1-1.8 0-2.9 2.2-2.9 4.9 0 2.8 1.1 5.2 2.8 5.2.8 0 1.4-.5 2-1l.8 2.1c-.7.7-1.6 1.3-2.9 1.3-2.9 0-4.6-3.2-4.6-7.4.2-4.3 1.9-7.4 4.8-7.4zm7.5 0c.9 0 1.9.4 2.6 1.2l-.8 2.1c-.4-.5-1.1-1-1.8-1-1.8 0-2.9 2.2-2.9 4.9 0 2.8 1.1 5.2 2.8 5.2.8 0 1.4-.5 2-1l.8 2.1c-.7.7-1.6 1.3-2.9 1.3-2.9 0-4.6-3.2-4.6-7.4.2-4.3 1.9-7.4 4.8-7.4zm3.6.3h3c2.6 0 4.3 2.6 4.3 7.1s-1.7 7.1-4.3 7.1h-3V6.5zm2.9 12c1.6 0 2.5-1.7 2.5-4.9s-.9-4.9-2.5-4.9h-1v9.8h1zm5.4-12h2.9c1.7 0 2.9 1.3 2.9 3.7 0 1.3-.5 2.5-1.2 3 1.1.5 1.6 1.8 1.6 3.4 0 2.8-1.3 4.1-3.2 4.1h-2.9V6.5zm3 5.8c.6 0 1-.8 1-1.9s-.4-1.8-1.1-1.8h-1v3.7h1.1zm0 6.2c1 0 1.4-.9 1.4-2.1 0-1.3-.4-2.1-1.2-2.1h-1.3v4.2h1.1z" fill="#fff"/><path class="st0" d="M54.6 70.3c-.1.9-1.2 1.6-3.4 2.1s-5 .8-8.3.8h-2.8v5.2c.9.1 1.9.1 2.8.1 3.3 0 6.1-.3 8.3-.9 2.2-.6 3.4-1.3 3.5-2.1-.1-.2-.1-5.2-.1-5.2zm-11.8-3.8c-1 0-1.9 0-2.8-.1v5.3h2.8c3.3 0 6.1-.3 8.3-.9 2.2-.6 3.4-1.3 3.4-2.1v-5.1c-.1.9-1.2 1.6-3.5 2.1-2.1.6-4.9.9-8.2.8zm0-6.5c-1 0-1.9 0-2.8-.1v5.3c.9.1 1.9.1 2.8.1 3.3 0 6.1-.3 8.4-.9 2.2-.6 3.4-1.3 3.5-2.1v-5.1c-.1.9-1.2 1.6-3.5 2.1-2.3.4-5.1.7-8.4.7zm0-7.4c-1 0-1.9 0-2.8.1v5.9c.9.1 1.9.1 2.8.1 3.3 0 6.1-.3 8.4-.9 2.2-.6 3.4-1.3 3.5-2.1-.1-.9-1.2-1.6-3.5-2.2-2.3-.6-5.1-.8-8.4-.9zm-16.1 8.3c-.1.3-.3 1.3-.7 3l-.7 2.9h2.9l-.7-2.9c-.4-1.7-.7-2.7-.7-3h-.1zm-10.3-9.5v28.3L38 83.4V47.6l-21.6 3.8zm13.2 21.1l-.8-3.2-4-.1-.8 3-2.5-.2 3.8-13.5 2.9-.2 4.2 14.3-2.8-.1z"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M66.824 40.465c-.176 1.59-2.097 2.824-5.945 3.707-3.852.879-8.75 1.41-14.52 1.41h-4.898v9.172c1.574.176 3.324.176 4.898.176 5.77 0 10.668-.528 14.52-1.586 3.848-1.059 5.945-2.293 6.121-3.707-.176-.352-.176-9.172-.176-9.172zm-20.64-6.7c-1.75 0-3.325 0-4.899-.18v9.352h4.899c5.773 0 10.671-.53 14.52-1.59s5.944-2.292 5.944-3.702v-8.997c-.171 1.586-2.097 2.825-6.12 3.704-3.673 1.058-8.571 1.59-14.344 1.414zm0-11.468c-1.75 0-3.325 0-4.899-.176v9.352c1.574.175 3.324.175 4.899.175 5.773 0 10.671-.53 14.695-1.59C64.727 29 66.824 27.767 67 26.356V17.36c-.176 1.59-2.098 2.825-6.121 3.704-4.024.707-8.922 1.234-14.695 1.234zm0-13.05c-1.75 0-3.325 0-4.899.175v10.406c1.574.176 3.324.176 4.899.176 5.773 0 10.671-.527 14.695-1.586 3.848-1.059 5.945-2.293 6.121-3.703-.176-1.59-2.098-2.824-6.121-3.883-4.024-1.055-8.922-1.41-14.695-1.586zM18.02 23.886c-.176.527-.528 2.293-1.227 5.293l-1.223 5.113h5.07l-1.222-5.113c-.7-3-1.227-4.766-1.227-5.293zM0 7.129v49.918l37.785 6.527V.426zm23.09 37.219-1.399-5.645-6.996-.176-1.398 5.29-4.375-.352 6.648-23.813 5.07-.351 7.348 25.222zm0 0" fill="#a03537"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/accdt.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.3 6.5h2l2.8 14.2h-1.8l-.7-3.7H8l-.6 3.7H5.6L8.3 6.5zm2 8.5l-.7-3.8c-.1-.8-.2-2.2-.2-2.2s-.2 1.4-.3 2.2L8.3 15h2zM18 6.2c.9 0 1.9.4 2.6 1.2l-.8 2.1c-.4-.5-1.1-1-1.7-1-1.8 0-2.8 2.2-2.8 4.9 0 2.8 1.1 5.2 2.8 5.2.8 0 1.4-.5 2-1l.7 2.1c-.7.7-1.5 1.3-2.8 1.3-2.8 0-4.5-3.2-4.5-7.4-.1-4.3 1.6-7.4 4.5-7.4zm7.8 0c.9 0 1.9.4 2.6 1.2l-.8 2.1c-.4-.5-1.1-1-1.7-1-1.8 0-2.8 2.2-2.8 4.9 0 2.8 1.1 5.2 2.8 5.2.8 0 1.4-.5 2-1l.7 2.1c-.7.7-1.5 1.3-2.8 1.3-2.8 0-4.5-3.2-4.5-7.4-.1-4.3 1.6-7.4 4.5-7.4zm3.9.3h2.9c2.6 0 4.2 2.6 4.2 7.1s-1.6 7.1-4.2 7.1h-2.9V6.5zm2.8 12c1.5 0 2.4-1.7 2.4-4.9s-.9-4.9-2.4-4.9h-1v9.8h1zm7-9.8H37V6.5h6.9v2.2h-2.5v12h-1.8v-12z" fill="#fff"/><path class="st0" d="M54.6 70.3c-.1.9-1.2 1.6-3.4 2.1s-5 .8-8.3.8h-2.8v5.2c.9.1 1.9.1 2.8.1 3.3 0 6.1-.3 8.3-.9 2.2-.6 3.4-1.3 3.5-2.1-.1-.2-.1-5.2-.1-5.2zm-11.8-3.8c-1 0-1.9 0-2.8-.1v5.3h2.8c3.3 0 6.1-.3 8.3-.9 2.2-.6 3.4-1.3 3.4-2.1v-5.1c-.1.9-1.2 1.6-3.5 2.1-2.1.6-4.9.9-8.2.8zm0-6.5c-1 0-1.9 0-2.8-.1v5.3c.9.1 1.9.1 2.8.1 3.3 0 6.1-.3 8.4-.9 2.2-.6 3.4-1.3 3.5-2.1v-5.1c-.1.9-1.2 1.6-3.5 2.1-2.3.4-5.1.7-8.4.7zm0-7.4c-1 0-1.9 0-2.8.1v5.9c.9.1 1.9.1 2.8.1 3.3 0 6.1-.3 8.4-.9 2.2-.6 3.4-1.3 3.5-2.1-.1-.9-1.2-1.6-3.5-2.2-2.3-.6-5.1-.8-8.4-.9zm-16.1 8.3c-.1.3-.3 1.3-.7 3l-.7 2.9h2.9l-.7-2.9c-.4-1.7-.7-2.7-.7-3h-.1zm-10.3-9.5v28.3L38 83.4V47.6l-21.6 3.8zm13.2 21.1l-.8-3.2-4-.1-.8 3-2.5-.2 3.8-13.5 2.9-.2 4.2 14.3-2.8-.1z"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M66.824 40.465c-.176 1.59-2.097 2.824-5.945 3.707-3.852.879-8.75 1.41-14.52 1.41h-4.898v9.172c1.574.176 3.324.176 4.898.176 5.77 0 10.668-.528 14.52-1.586 3.848-1.059 5.945-2.293 6.121-3.707-.176-.352-.176-9.172-.176-9.172zm-20.64-6.7c-1.75 0-3.325 0-4.899-.18v9.352h4.899c5.773 0 10.671-.53 14.52-1.59s5.944-2.292 5.944-3.702v-8.997c-.171 1.586-2.097 2.825-6.12 3.704-3.673 1.058-8.571 1.59-14.344 1.414zm0-11.468c-1.75 0-3.325 0-4.899-.176v9.352c1.574.175 3.324.175 4.899.175 5.773 0 10.671-.53 14.695-1.59C64.727 29 66.824 27.767 67 26.356V17.36c-.176 1.59-2.098 2.825-6.121 3.704-4.024.707-8.922 1.234-14.695 1.234zm0-13.05c-1.75 0-3.325 0-4.899.175v10.406c1.574.176 3.324.176 4.899.176 5.773 0 10.671-.527 14.695-1.586 3.848-1.059 5.945-2.293 6.121-3.703-.176-1.59-2.098-2.824-6.121-3.883-4.024-1.055-8.922-1.41-14.695-1.586zM18.02 23.886c-.176.527-.528 2.293-1.227 5.293l-1.223 5.113h5.07l-1.222-5.113c-.7-3-1.227-4.766-1.227-5.293zM0 7.129v49.918l37.785 6.527V.426zm23.09 37.219-1.399-5.645-6.996-.176-1.398 5.29-4.375-.352 6.648-23.813 5.07-.351 7.348 25.222zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ace.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#90c}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm12.5-8.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4zm6.5.3H38v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4z" fill="#fff"/><path class="st0" d="M51.1 57.5h-5.7v-5.7l5.7 5.7zm-15.3-5.7v20.7h15.4V58.9H44v-7.1h-8.2zm2.4-5.4h-17v4h6.7l-4.2 3.3v3.5l6.2-4.8v-1.9h21.6v-1.6l-13.3-2.5zm-8.3 8.7l-6.2 4.8v3.5l6.2-4.8v-3.5zm-6.3 14.4l6.2-4.8v-3.5L23.6 66v3.5zm6.3 1.4v-3.5l-6.2 4.8V74h-2.5v4H25v2.8h-2.2c-.4-.7-1.1-1.2-2-1.2-1.3 0-2.3 1-2.3 2.3 0 1.3 1 2.3 2.3 2.3.9 0 1.6-.5 2-1.2H25v2.1h3.4V83h2.2c.4.7 1.1 1.2 2 1.2 1.3 0 2.3-1 2.3-2.3 0-1.3-1-2.3-2.3-2.3-.9 0-1.6.5-2 1.2h-2.2V78h9.7l13.3-2.4V74H25.7l4.2-3.1z"/></svg>
1
<svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/adn.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm6.9-8.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2H22v8.5h.8zm9.1-11.4h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4z" fill="#fff"/><path class="st0" d="M54.6 70.3c-.1.9-1.2 1.6-3.4 2.1s-5 .8-8.3.8h-2.8v5.2c.9.1 1.9.1 2.8.1 3.3 0 6.1-.3 8.3-.9 2.2-.6 3.4-1.3 3.5-2.1-.1-.2-.1-5.2-.1-5.2zm-11.8-3.8c-1 0-1.9 0-2.8-.1v5.3h2.8c3.3 0 6.1-.3 8.3-.9 2.2-.6 3.4-1.3 3.4-2.1v-5.1c-.1.9-1.2 1.6-3.5 2.1-2.1.6-4.9.9-8.2.8zm0-6.5c-1 0-1.9 0-2.8-.1v5.3c.9.1 1.9.1 2.8.1 3.3 0 6.1-.3 8.4-.9 2.2-.6 3.4-1.3 3.5-2.1v-5.1c-.1.9-1.2 1.6-3.5 2.1-2.3.4-5.1.7-8.4.7zm0-7.4c-1 0-1.9 0-2.8.1v5.9c.9.1 1.9.1 2.8.1 3.3 0 6.1-.3 8.4-.9 2.2-.6 3.4-1.3 3.5-2.1-.1-.9-1.2-1.6-3.5-2.2-2.3-.6-5.1-.8-8.4-.9zm-16.1 8.3c-.1.3-.3 1.3-.7 3l-.7 2.9h2.9l-.7-2.9c-.4-1.7-.7-2.7-.7-3h-.1zm-10.3-9.5v28.3L38 83.4V47.6l-21.6 3.8zm13.2 21.1l-.8-3.2-4-.1-.8 3-2.5-.2 3.8-13.5 2.9-.2 4.2 14.3-2.8-.1z"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M66.824 40.465c-.176 1.59-2.097 2.824-5.945 3.707-3.852.879-8.75 1.41-14.52 1.41h-4.898v9.172c1.574.176 3.324.176 4.898.176 5.77 0 10.668-.528 14.52-1.586 3.848-1.059 5.945-2.293 6.121-3.707-.176-.352-.176-9.172-.176-9.172zm-20.64-6.7c-1.75 0-3.325 0-4.899-.18v9.352h4.899c5.773 0 10.671-.53 14.52-1.59s5.944-2.292 5.944-3.702v-8.997c-.171 1.586-2.097 2.825-6.12 3.704-3.673 1.058-8.571 1.59-14.344 1.414zm0-11.468c-1.75 0-3.325 0-4.899-.176v9.352c1.574.175 3.324.175 4.899.175 5.773 0 10.671-.53 14.695-1.59C64.727 29 66.824 27.767 67 26.356V17.36c-.176 1.59-2.098 2.825-6.121 3.704-4.024.707-8.922 1.234-14.695 1.234zm0-13.05c-1.75 0-3.325 0-4.899.175v10.406c1.574.176 3.324.176 4.899.176 5.773 0 10.671-.527 14.695-1.586 3.848-1.059 5.945-2.293 6.121-3.703-.176-1.59-2.098-2.824-6.121-3.883-4.024-1.055-8.922-1.41-14.695-1.586zM18.02 23.886c-.176.527-.528 2.293-1.227 5.293l-1.223 5.113h5.07l-1.222-5.113c-.7-3-1.227-4.766-1.227-5.293zM0 7.129v49.918l37.785 6.527V.426zm23.09 37.219-1.399-5.645-6.996-.176-1.398 5.29-4.375-.352 6.648-23.813 5.07-.351 7.348 25.222zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ai.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fea500}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm6.9-8.6H22v14.3h-3.3V6.4z" fill="#fff"/><path d="M37.8 80.3l-2.7-8.7H25l-2.7 8.7h-3.7l9.7-28.9H32l9.8 28.9h-4zM31 58.4c-.3-1.1-.7-2.6-.8-3.7h-.1c-.2 1-.5 2.5-.9 3.7l-3.4 10.9h8.6L31 58.4zm16.7-5c-1.2 0-2.2-.9-2.2-2.1s1-2.1 2.2-2.1 2.2.9 2.2 2.1-1 2.1-2.2 2.1zm-1.8 26.9V57.7h3.7v22.6h-3.7z" fill="#fea500" stroke="#fea500" stroke-width="1.25" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="66" xmlns="http://www.w3.org/2000/svg"><path d="M40.266 62.762 34.922 45.55h-19.98l-5.34 17.21h-7.32L21.468 5.59h7.32l19.39 57.172zM26.813 19.438c-.594-2.176-1.387-5.145-1.583-7.32h-.199c-.394 1.98-.988 4.945-1.781 7.32L16.523 41H33.54zm33.039-9.891c-2.375 0-4.356-1.781-4.356-4.156s1.98-4.153 4.356-4.153c2.37 0 4.351 1.778 4.351 4.153 0 2.375-1.98 4.156-4.351 4.156zm-3.563 53.215V18.05h7.32v44.71zm0 0" fill="#fea500" stroke="#fea500" stroke-miterlimit="10" stroke-width="2.47295"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/aif.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm6.9-8.6H22v14.3h-3.3V6.4zm7 0h7.1v2.9H29v3.1h3.1v2.9H29v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/aifc.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm5.9-8.6H21v14.3h-3.3V6.4zm6 0h7.1v2.9H27v3.1h3.1v2.9H27v5.4h-3.3V6.4zm14.9-.3c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/aiff.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm6.4-8.6h3.3v14.3h-3.3V6.4zm6.5 0h7.1v2.9H28v3.1h3.1v2.9H28v5.4h-3.3V6.4zm9.5 0h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ait.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fea500}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm6.9-8.6H22v14.3h-3.3V6.4zm9.2 2.9h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path d="M37.8 80.3l-2.7-8.7H25l-2.7 8.7h-3.7l9.7-28.9H32l9.8 28.9h-4zM31 58.4c-.3-1.1-.7-2.6-.8-3.7h-.1c-.2 1-.5 2.5-.9 3.7l-3.4 10.9h8.6L31 58.4zm16.7-5c-1.2 0-2.2-.9-2.2-2.1s1-2.1 2.2-2.1 2.2.9 2.2 2.1-1 2.1-2.2 2.1zm-1.8 26.9V57.7h3.7v22.6h-3.7z" fill="#fea500" stroke="#fea500" stroke-width="1.25" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="66" xmlns="http://www.w3.org/2000/svg"><path d="M40.266 62.762 34.922 45.55h-19.98l-5.34 17.21h-7.32L21.468 5.59h7.32l19.39 57.172zM26.813 19.438c-.594-2.176-1.387-5.145-1.583-7.32h-.199c-.394 1.98-.988 4.945-1.781 7.32L16.523 41H33.54zm33.039-9.891c-2.375 0-4.356-1.781-4.356-4.156s1.98-4.153 4.356-4.153c2.37 0 4.351 1.778 4.351 4.153 0 2.375-1.98 4.156-4.351 4.156zm-3.563 53.215V18.05h7.32v44.71zm0 0" fill="#fea500" stroke="#fea500" stroke-miterlimit="10" stroke-width="2.47295"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/amr.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm6.4-8.6h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6L30 20.7h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H22l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1-14.3zm14.1 0h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.8v4.8h-3.3V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ani.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#8ed200}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm6.9-8.6h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4zm13.3 0h3.3v14.3H32V6.4z" fill="#fff"/><path class="st0" d="M47.9 48.5H24.1c-1.2 0-2.1.9-2.1 2.1 0 1.2.9 2.1 2.1 2.1h.1v2.1c0 4.4 2.7 8.3 6.7 9.9.2.1.4.3.4.5v.2c0 .2-.2.4-.4.5-4.1 1.6-6.8 5.5-6.7 9.9v2.1h-.1c-1.2 0-2.1.9-2.1 2.1 0 1.2.9 2.1 2.1 2.1h23.8c1.2 0 2.1-.9 2.1-2.1 0-1.2-.9-2.1-2.1-2.1h-.1v-2.1c0-4.4-2.7-8.3-6.7-9.9-.2-.1-.4-.3-.4-.5v-.2c0-.2.2-.4.4-.5 4.1-1.6 6.8-5.5 6.7-9.9v-2.1h.1c1.2 0 2.1-.9 2.1-2.1 0-1.2-.9-2.1-2.1-2.1zM45 54.8c0 3.2-2 6.1-5 7.3-1.3.5-2.2 1.7-2.2 3.1v.2c0 1.4.9 2.6 2.2 3.1 3 1.2 5 4.1 5 7.3v2.1H27v-2.1c0-3.2 2-6.1 5-7.3 1.3-.5 2.2-1.7 2.2-3.1v-.2c0-1.4-.9-2.6-2.2-3.1-3-1.2-5-4.1-5-7.3v-2.1h18v2.1zm-15.2 3.6c-.2-.3-.1-.7.2-.9.1-.1.2-.1.4-.1h11.3c.3 0 .6.3.6.6 0 .1 0 .3-.1.4-.7 1-1.6 1.7-2.7 2.1-1.2.4-2.1 1.3-2.7 2.4-.2.4-.7.6-1.1.3-.1-.1-.3-.2-.3-.3-.6-1.1-1.5-2-2.7-2.4-1.2-.5-2.2-1.2-2.9-2.1zm8 12.6c.6.5 1.4.8 2.2.8 1.5 0 2.8 1 3.1 2.5v.1c.1.3.1.6.1 1s-.3.7-.7.7H29.4c-.4 0-.7-.3-.7-.7 0-.3.1-.7.1-1v-.1c.4-1.4 1.7-2.4 3.2-2.4.8 0 1.6-.3 2.2-.8.4-.4.8-.8 1-1.3.2-.3.5-.5.9-.4.3.1.5.2.6.4.3.4.6.8 1.1 1.2z"/></svg>
1
<svg height="64" width="53" xmlns="http://www.w3.org/2000/svg"><path d="M49.023.375H3.977C1.703.375 0 2.07 0 4.328 0 6.59 1.703 8.281 3.977 8.281h.187v3.953c0 8.286 5.11 15.625 12.684 18.637.379.188.757.563.757.942v.375c0 .378-.378.753-.757.94C9.086 36.142 3.977 43.48 4.164 51.767v3.953h-.187C1.703 55.719 0 57.41 0 59.672c0 2.258 1.703 3.953 3.977 3.953h45.046c2.274 0 3.977-1.695 3.977-3.953 0-2.262-1.703-3.953-3.977-3.953h-.187v-3.953c0-8.286-5.11-15.625-12.684-18.637-.379-.188-.757-.563-.757-.941v-.376c0-.378.378-.753.757-.94 7.762-3.013 12.871-10.352 12.684-18.638V8.281h.187C51.297 8.281 53 6.59 53 4.328 53 2.07 51.297.375 49.023.375zm-5.488 11.86c0 6.023-3.785 11.484-9.465 13.742-2.46.941-4.164 3.199-4.164 5.836v.375c0 2.636 1.703 4.894 4.164 5.835 5.68 2.258 9.465 7.72 9.465 13.743v3.953H9.465v-3.953c0-6.024 3.785-11.485 9.465-13.743 2.46-.941 4.164-3.199 4.164-5.836v-.374c0-2.637-1.703-4.895-4.164-5.836-5.68-2.258-9.465-7.72-9.465-13.743V8.281h34.07zm-28.77 6.777c-.378-.567-.19-1.317.38-1.696.187-.187.375-.187.753-.187H37.29c.566 0 1.137.566 1.137 1.129 0 .187 0 .566-.192.754-1.324 1.883-3.027 3.199-5.109 3.953-2.27.754-3.977 2.445-5.11 4.515-.378.754-1.328 1.133-2.081.567-.192-.188-.57-.375-.57-.567-1.134-2.07-2.84-3.761-5.11-4.515-2.274-.942-4.164-2.258-5.488-3.953zM29.907 42.73a6.64 6.64 0 0 0 4.164 1.504c2.84 0 5.301 1.883 5.868 4.707v.188c.19.566.19 1.129.19 1.883s-.565 1.316-1.323 1.316H14.008c-.758 0-1.324-.562-1.324-1.316 0-.567.187-1.317.187-1.883v-.188c.758-2.636 3.219-4.52 6.059-4.52a6.64 6.64 0 0 0 4.164-1.503c.758-.754 1.511-1.508 1.89-2.45.38-.562.95-.937 1.703-.75.57.188.95.376 1.137.75.57.755 1.137 1.509 2.082 2.262zm0 0" fill="#8ed200"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/apk.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#333}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm6.9-8.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H22v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2H22v4.1h.6zm7.9-7h3.3v5.5h.6l2.3-5.5h3.5l-2.9 6.8 3 7.4h-3.7l-2.3-5.8h-.6v5.8h-3.3V6.4z" fill="#fff"/><path d="M26.7 75.1c0 .9.6 1.5 1.5 1.5h1.6V82c0 1.2 1.1 2.3 2.3 2.3 1.2 0 2.3-1.1 2.3-2.3v-5.4h3.1V82c0 1.2 1.1 2.3 2.3 2.3 1.2 0 2.3-1.1 2.3-2.3v-5.4h1.5c.9 0 1.5-.6 1.5-1.6V59.6H26.7v15.5zm-3.9-15.5c-1.2 0-2.3 1.1-2.3 2.3v10.8c0 1.2 1.1 2.3 2.3 2.3 1.2 0 2.3-1.1 2.3-2.3V61.9c0-1.2-1-2.3-2.3-2.3zm26.4 0c-1.2 0-2.3 1.1-2.3 2.3v10.8c0 1.2 1.1 2.3 2.3 2.3 1.2 0 2.3-1.1 2.3-2.3V61.9c0-1.2-1.1-2.3-2.3-2.3zm-7.8-9l2-2c.3-.3.3-.8 0-1.1-.3-.3-.8-.3-1.1 0L40 49.8c-1.1-.8-2.5-1.1-4-1.1-1.6 0-2.9.3-4.2.9l-2.2-2.3c-.3-.2-.9-.2-1.2 0-.2.3-.2.9 0 1.2l2 2c-2.2 1.7-3.7 4.3-3.7 7.4h18.6c0-3-1.5-5.7-3.9-7.3zm-8.5 4.3h-1.6v-1.5h1.6v1.5zm7.8 0h-1.6v-1.5h1.6v1.5z" id="android" fill="#a4ca39"/></svg>
1
<svg height="64" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M10.867 48.152c0 1.551 1.04 2.582 2.602 2.582h2.773v9.305c0 2.066 1.91 3.961 3.992 3.961s3.989-1.895 3.989-3.96v-9.306h5.379v9.305c0 2.066 1.91 3.961 3.992 3.961s3.988-1.895 3.988-3.96v-9.306h2.602c1.562 0 2.605-1.03 2.605-2.757V21.449H10.867zM4.097 21.45C2.017 21.45.11 23.344.11 25.41v18.606c0 2.066 1.907 3.96 3.989 3.96s3.992-1.894 3.992-3.96V25.41c0-2.066-1.735-3.96-3.992-3.96zm45.805 0c-2.082 0-3.992 1.895-3.992 3.961v18.606c0 2.066 1.91 3.96 3.992 3.96s3.989-1.894 3.989-3.96V25.41c0-2.066-1.907-3.96-3.989-3.96zM36.367 5.945l3.473-3.449c.52-.516.52-1.375 0-1.894a1.373 1.373 0 0 0-1.91 0L33.94 4.566c-1.91-1.379-4.34-1.894-6.941-1.894-2.777 0-5.031.515-7.285 1.55L15.898.259c-.523-.344-1.562-.344-2.082 0-.347.515-.347 1.55 0 2.066l3.47 3.446c-3.817 2.93-6.419 7.41-6.419 12.75h32.266c0-5.168-2.602-9.82-6.766-12.575zm-14.746 7.407h-2.773v-2.586h2.773zm13.531 0H32.38v-2.586h2.773zm0 0" fill="#a4ca39"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/app.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><path d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm6.9-8.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H22v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2H22v4.1h.6zm7.9-7H35c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path d="M53.8 69.2c-1.6-.5-2.7-2-2.7-3.7s1.1-3.2 2.7-3.7c.5-.2.8-.7.6-1.2-.5-1.8-1.1-3.4-2.1-5-.3-.5-.8-.6-1.3-.4-.6.3-1.2.5-1.9.5-2.2 0-3.9-1.8-3.9-3.9 0-.7.2-1.3.5-1.9.3-.5.1-1-.4-1.3-1.6-.9-3.3-1.6-5-2.1-.5-.1-1 .1-1.2.6-.5 1.6-2 2.7-3.7 2.7s-3.2-1.1-3.7-2.7c-.2-.5-.7-.8-1.2-.6-1.8.5-3.4 1.1-5 2.1-.5.3-.6.8-.4 1.3.3.6.5 1.2.5 1.9 0 2.2-1.8 3.9-3.9 3.9-.7 0-1.3-.2-1.9-.5-.5-.3-1-.1-1.3.4-.9 1.6-1.6 3.3-2.1 5-.1.5.1 1 .6 1.2 1.6.5 2.7 2 2.7 3.7 0 1.7-1.1 3.2-2.7 3.7-.5.2-.8.7-.6 1.2.5 1.8 1.1 3.4 2.1 5 .3.5.8.6 1.3.4.6-.3 1.2-.5 1.9-.5 2.2 0 3.9 1.8 3.9 3.9 0 .7-.2 1.3-.5 1.9-.3.5-.1 1 .4 1.3 1.6.9 3.3 1.6 5 2.1h.2c.4 0 .8-.3.9-.7.5-1.6 2-2.7 3.7-2.7 1.7 0 3.2 1.1 3.7 2.7.2.5.7.8 1.2.6 1.8-.5 3.4-1.1 5-2.1.5-.3.6-.8.4-1.3-.3-.6-.5-1.2-.5-1.9 0-2.2 1.8-3.9 3.9-3.9.7 0 1.3.2 1.9.5.5.3 1 .1 1.3-.4.9-1.6 1.6-3.3 2.1-5 .3-.4 0-.9-.5-1.1zm-18.3 2.2c-3.2 0-5.9-2.6-5.9-5.9 0-3.2 2.6-5.9 5.9-5.9 3.2 0 5.9 2.6 5.9 5.9 0 3.2-2.7 5.9-5.9 5.9z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M62.887 38.266c-2.684-.84-4.532-3.36-4.532-6.215 0-2.852 1.848-5.371 4.532-6.211.84-.336 1.343-1.172 1.008-2.012-.84-3.023-1.848-5.707-3.524-8.394-.504-.84-1.344-1.008-2.184-.672-1.007.504-2.015.84-3.19.84-3.692 0-6.548-3.024-6.548-6.547 0-1.176.336-2.184.84-3.188.504-.84.168-1.68-.672-2.183a40.47 40.47 0 0 0-8.39-3.528c-.84-.168-1.68.168-2.016 1.008C37.37 3.852 34.855 5.7 32 5.7s-5.371-1.847-6.21-4.535C25.452.324 24.612-.18 23.772.156c-3.02.84-5.707 1.848-8.39 3.528-.84.503-1.008 1.343-.672 2.183.504 1.004.84 2.012.84 3.188 0 3.691-3.024 6.547-6.547 6.547-1.176 0-2.184-.336-3.191-.84-.84-.504-1.68-.168-2.184.672a40.699 40.699 0 0 0-3.524 8.394c-.167.84.168 1.676 1.008 2.012 2.684.84 4.532 3.36 4.532 6.21 0 2.856-1.848 5.376-4.532 6.216-.84.332-1.343 1.172-1.008 2.011.84 3.024 1.848 5.707 3.524 8.395.504.84 1.344 1.008 2.184.672 1.007-.504 2.015-.84 3.19-.84 3.692 0 6.548 3.02 6.548 6.547 0 1.176-.336 2.183-.84 3.187-.504.84-.168 1.68.672 2.184a40.47 40.47 0 0 0 8.39 3.527h.336c.672 0 1.344-.504 1.512-1.176.84-2.687 3.356-4.535 6.211-4.535s5.371 1.848 6.211 4.535c.336.84 1.176 1.344 2.016 1.008 3.02-.84 5.707-1.847 8.39-3.527.84-.504 1.008-1.344.672-2.184-.504-1.004-.84-2.011-.84-3.187 0-3.692 3.024-6.547 6.547-6.547 1.176 0 2.184.336 3.192.84.84.504 1.68.168 2.183-.672a40.698 40.698 0 0 0 3.524-8.395c.503-.672 0-1.511-.84-1.843zm-30.719 3.691c-5.371 0-9.902-4.363-9.902-9.906 0-5.371 4.363-9.903 9.902-9.903 5.371 0 9.902 4.364 9.902 9.903 0 5.375-4.53 9.906-9.902 9.906zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/applescript.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/><path d="M51.6 33H28.3c-3.2 0-5.9 2.6-5.9 5.9v26.3h-5.9c0 3.2 2.6 5.9 5.9 5.9h23.4c3.2 0 5.9-2.6 5.9-5.9V41.7h5.9v-2.9c-.1-3.2-2.7-5.8-6-5.8zm-2.9 31.6c0 1.9-1.5 3.4-3.4 3.4H23.9c1.4-1 1.4-2.9 1.4-2.9V38.9c0-1.6 1.3-2.9 2.9-2.9s2.9 1.3 2.9 2.9v2.9h17.6v22.8zM34.1 38.9V36h17.6c2.7 0 2.9 1.7 2.9 2.9H34.1z" fill="#999" stroke="#999" stroke-width=".75" stroke-miterlimit="10"/><path class="st1" d="M33.8 60.6c-.3-.2-.6-.5-.9-.8-.3-.3-.5-.7-.7-1-.5-.8-1-1.6-1.2-2.5-.3-1-.5-2-.5-3 0-1.1.2-2 .7-2.8.3-.6.8-1.2 1.5-1.5.6-.4 1.3-.6 2-.6.2 0 .5 0 .8.1.2.1.4.1.7.3.4.1.6.2.7.3.2.1.4.1.6.1.1 0 .3 0 .4-.1.1 0 .3-.1.6-.2s.5-.2.7-.2c.3-.1.5-.1.7-.2.3 0 .5-.1.8 0 .5 0 .9.1 1.4.3.7.3 1.3.7 1.7 1.4-.2.1-.3.2-.5.4-.3.3-.6.7-.9 1-.3.5-.5 1.1-.4 1.8 0 .8.2 1.4.6 2 .3.4.6.8 1.1 1.1l.6.3c-.1.3-.2.5-.3.8-.2.6-.5 1.1-.9 1.6-.3.4-.5.8-.7 1l-.8.8c-.3.2-.7.3-1 .3-.2 0-.5 0-.7-.1s-.4-.1-.6-.2c-.2-.1-.4-.2-.6-.2-.3-.1-.5-.1-.8-.1s-.6 0-.8.1-.4.1-.6.2c-.3.1-.5.2-.6.2-.2.1-.5.1-.7.1-.8-.4-1.1-.5-1.4-.7zm4.7-12.9c-.5.2-.9.3-1.4.3-.1-.4 0-.9.2-1.4.2-.4.4-.8.7-1.2s.7-.7 1.1-.9c.5-.2.9-.4 1.3-.4.1.5 0 .9-.2 1.4-.2.4-.4.9-.7 1.2-.2.5-.5.8-1 1z"/></svg>
1
<svg height="64" width="68" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M51.6 33H28.3c-3.2 0-5.9 2.601-5.9 5.9v26.3h-5.9c0 3.2 2.599 5.9 5.9 5.9h23.4c3.2 0 5.9-2.601 5.9-5.9V41.7h5.9v-2.9a5.98 5.98 0 0 0-6-5.8zm-2.9 31.6c0 1.9-1.5 3.4-3.4 3.4H23.9c1.399-1 1.399-2.9 1.399-2.9V38.9c0-1.6 1.3-2.9 2.902-2.9 1.598 0 2.899 1.3 2.899 2.9v2.901h17.6zM34.1 38.9V36h17.6c2.7 0 2.9 1.7 2.9 2.9zm0 0" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.62485 0 0 1.6469 -26.2 -53.722)"/><path d="M28.719 46.082c-.489-.332-.973-.824-1.461-1.32-.488-.492-.813-1.153-1.137-1.645-.812-1.316-1.625-2.637-1.953-4.117-.484-1.648-.813-3.293-.813-4.941 0-1.813.329-3.293 1.141-4.61.484-.988 1.297-1.976 2.438-2.472a5.777 5.777 0 0 1 3.246-.989c.328 0 .812 0 1.3.164.325.164.653.164 1.137.496.653.164.977.329 1.14.493.325.164.65.164.973.164.165 0 .489 0 .653-.164.16 0 .484-.164.972-.328s.813-.329 1.137-.329c.488-.168.813-.168 1.137-.332.488 0 .812-.164 1.3 0 .813 0 1.466.164 2.278.496 1.137.493 2.11 1.153 2.762 2.305-.324.164-.489.328-.813.66-.488.492-.976 1.153-1.465 1.645-.484.824-.812 1.812-.648 2.965 0 1.316.324 2.304.977 3.293.484.66.972 1.32 1.785 1.812l.976.496c-.164.492-.324.82-.488 1.317-.324.988-.813 1.812-1.461 2.632-.488.66-.812 1.32-1.14 1.649l-1.297 1.316a3.095 3.095 0 0 1-1.625.496c-.329 0-.813 0-1.141-.164-.324-.164-.649-.164-.973-.332-.324-.164-.648-.328-.976-.328-.485-.164-.813-.164-1.297-.164-.488 0-.977 0-1.301.164-.324.164-.652.164-.977.328-.488.168-.812.332-.972.332-.328.164-.813.164-1.14.164-1.298-.66-1.786-.824-2.274-1.152zm7.636-21.246c-.812.328-1.46.492-2.273.492-.164-.656 0-1.48.324-2.305.324-.656.649-1.316 1.137-1.976a5.093 5.093 0 0 1 1.789-1.48c.813-.329 1.461-.66 2.11-.66.163.823 0 1.484-.325 2.304-.324.66-.648 1.484-1.137 1.977-.324.824-.812 1.32-1.625 1.648zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/asax.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d5006e}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.5 6.4h3l3.1 14.3h-2.8l-.5-3H8.7l-.5 3H5.4L8.5 6.4zm2.4 8.6l-.5-2.8c-.2-.9-.4-2.5-.4-2.5s-.2 1.5-.3 2.5L9.2 15h1.7zm5.6 1.7c.5.6 1.2 1.2 2 1.2.7 0 1.1-.6 1.1-1.2 0-2-4-2.1-4-6.2 0-2.4 1.4-4.3 3.9-4.3 1 0 2.1.3 2.9 1l-1 2.9c-.4-.4-1.2-.9-1.8-.9-.8 0-1.1.6-1.1 1.2 0 2.1 4.1 2 4.1 6.1 0 2.3-1.3 4.4-3.8 4.4-1.2 0-2.4-.5-3.4-1.4l1.1-2.8zm9.6-10.3h3l3.1 14.3h-2.8l-.5-3h-2.6l-.5 3H23l3.1-14.3zm2.3 8.6l-.4-2.9c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.3 2.5l-.5 2.9h1.7zm7-1.4l-2.9-7.2h3.1l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3.1l-2.9 7.2 2.8 7.1h-3l-.9-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3h-3l2.7-7.1z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#d5006e"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/asc.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M21.2 70.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zM24 79l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L22 79h2zm7.6 1.7c.6.6 1.4 1.2 2.3 1.2s1.3-.6 1.3-1.2c0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm15.8-10.5c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.4 2.4-7.4 6.4-7.4z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
<svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M0 61.766V2.234C0 1.004 1 0 2.223 0h53.332c.668 0 1.222.223 1.668.781l22.222 24.922c.332.445.555.89.555 1.45v34.613C80 62.996 79 64 77.777 64H2.223A2.234 2.234 0 0 1 0 61.766zm75.555-33.72-21-23.577H4.445V59.53h71.11zm0 0"/><path d="M53.332 29.055V4.469c0-1.227 1-2.235 2.223-2.235a2.236 2.236 0 0 1 2.222 2.235V26.82h17.778a2.234 2.234 0 0 1 0 4.47h-20a2.236 2.236 0 0 1-2.223-2.235zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ascx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d5006e}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.5 6.4h3l3.1 14.3h-2.8l-.5-3H8.7l-.5 3H5.4L8.5 6.4zm2.4 8.6l-.5-2.8c-.2-.9-.4-2.5-.4-2.5s-.2 1.5-.3 2.5L9.2 15h1.7zm5.6 1.7c.5.6 1.2 1.2 2 1.2.7 0 1.1-.6 1.1-1.2 0-2-4-2.1-4-6.2 0-2.4 1.4-4.3 3.9-4.3 1 0 2.1.3 2.9 1l-1 2.9c-.4-.4-1.2-.9-1.8-.9-.8 0-1.1.6-1.1 1.2 0 2.1 4.1 2 4.1 6.1 0 2.3-1.3 4.4-3.8 4.4-1.2 0-2.4-.5-3.4-1.4l1.1-2.8zM29.1 6.1c1.1 0 2.2.4 3.1 1.2L31 10.2c-.3-.5-1.1-.9-1.8-.9-1.8 0-2.7 1.9-2.7 4.2 0 2.3 1 4.4 2.7 4.4.8 0 1.4-.5 2-1l1.2 2.8c-.8.7-1.7 1.3-3.3 1.3-3.4 0-5.3-3.1-5.3-7.4-.2-4.3 1.9-7.5 5.3-7.5zm6.7 7.5l-2.9-7.2H36l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3l-3 7.2 2.8 7.1h-3l-.9-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3h-3l2.9-7.1z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#d5006e"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/asf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm7.6 1.7c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10-10.3h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ash.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm7.6 1.7c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10-10.3h3.3v5.8h3.2V6.4h3.3v14.3h-3.3V15h-3.2v5.7h-3.3V6.4z" fill="#fff"/><path d="M30.8 61.4h10.9v2.7H30.8v-2.7zm0 5.4h10.9v2.7H30.8v-2.7zm0 5.5h10.9V75H30.8v-2.7zm19-24.4H28.1c-3 0-5.4 2.4-5.4 5.4v24.4h-5.4c0 3 2.4 5.4 5.4 5.4h21.7c3 0 5.4-2.4 5.4-5.4V56h5.4v-2.7c0-3-2.4-5.4-5.4-5.4zm-2.7 29.3c0 1.8-1.4 3.2-3.2 3.2H24c1.3-.9 1.3-2.7 1.3-2.7V53.3c0-1.5 1.2-2.7 2.7-2.7s2.7 1.2 2.7 2.7V56H47l.1 21.2zM33.5 53.3v-2.7h16.3c2.5 0 2.7 1.6 2.7 2.7h-19z" fill="#999" stroke="#999" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ashx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d5006e}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.5 6.4h3l3.1 14.3h-2.8l-.5-3H8.7l-.5 3H5.4L8.5 6.4zm2.4 8.6l-.5-2.8c-.2-.9-.4-2.5-.4-2.5s-.2 1.5-.3 2.5L9.2 15h1.7zm5.6 1.7c.5.6 1.2 1.2 2 1.2.7 0 1.1-.6 1.1-1.2 0-2-4-2.1-4-6.2 0-2.4 1.4-4.3 3.9-4.3 1 0 2.1.3 2.9 1l-1 2.9c-.4-.4-1.2-.9-1.8-.9-.8 0-1.1.6-1.1 1.2 0 2.1 4.1 2 4.1 6.1 0 2.3-1.3 4.4-3.8 4.4-1.2 0-2.4-.5-3.4-1.4l1.1-2.8zm7.6-10.3h2.8v5.8h2.7V6.4h2.8v14.3h-2.8V15h-2.7v5.7h-2.8V6.4zm12.6 7.2l-2.9-7.2h3.1l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9H43l-2.9 7.2 2.8 7.1h-3l-.9-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3h-3l2.7-7.1z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#d5006e"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/asm.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm7.6 1.7c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zM29.9 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4H38s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.1 6.4h-3l.9-14.3z" fill="#fff"/><path class="st0" d="M14 48.9h37v4.3H14zm7 9.6h37v4.3H21zm-7 9.6h37v4.3H14zm7 9.6h37V82H21z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/asmx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d5006e}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.5 6.4h3l3.1 14.3h-2.8l-.5-3H8.7l-.5 3H5.4L8.5 6.4zm2.4 8.6l-.5-2.8c-.2-.9-.4-2.5-.4-2.5s-.2 1.5-.3 2.5L9.2 15h1.7zm5.2 1.7c.5.6 1.2 1.2 2 1.2.7 0 1.1-.6 1.1-1.2 0-2-4-2.1-4-6.2 0-2.4 1.4-4.3 3.9-4.3 1 0 2.1.3 2.9 1l-1 2.9c-.4-.4-1.2-.9-1.8-.9-.8 0-1.1.6-1.1 1.2 0 2.1 4.1 2 4.1 6.1 0 2.3-1.3 4.4-3.8 4.4-1.2 0-2.4-.5-3.4-1.4l1.1-2.8zm7.6-10.3h3.1l1.1 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.1-6H33l.8 14.3h-2.6l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.7 4.1H27l-.7-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.3 6.4h-2.6l.8-14.3zm13.5 7.2l-2.9-7.2h3.1l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3.1l-2.9 7.2 2.8 7.1h-3l-.9-3c-.5-.9-.6-1.7-.6-1.7s-.2.8-.5 1.7l-1 3h-3l2.8-7.1z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#d5006e"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/asp.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#c33}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm7.6 1.7c.6.6 1.4 1.2 2.3 1.2s1.3-.6 1.3-1.2c0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10-10.3h4.5c2.6 0 4.4 2 4.4 4.9s-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#c33"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/aspx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d5006e}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.5 6.4h3l3.1 14.3h-2.8l-.5-3H8.7l-.5 3H5.4L8.5 6.4zm2.4 8.6l-.5-2.8c-.2-.9-.4-2.5-.4-2.5s-.2 1.5-.3 2.5L9.2 15h1.7zm5.6 1.7c.5.6 1.2 1.2 2 1.2.7 0 1.1-.6 1.1-1.2 0-2-4-2.1-4-6.2 0-2.4 1.4-4.3 3.9-4.3 1 0 2.1.3 2.9 1l-1 2.9c-.4-.4-1.2-.9-1.8-.9-.8 0-1.1.6-1.1 1.2 0 2.1 4.1 2 4.1 6.1 0 2.3-1.3 4.4-3.8 4.4-1.2 0-2.4-.5-3.4-1.4l1.1-2.8zm7.6-10.3h3.8c2.2 0 3.7 2 3.7 4.9 0 2.9-1.5 5-3.7 5h-1v4.4h-2.8V6.4zm3.3 7c.9 0 1.4-.9 1.4-2.1s-.6-2-1.3-2h-.6v4.1h.5zm7.7.2l-2.9-7.2h3.1l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3.1l-2.9 7.2 2.8 7.1h-3l-.9-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3h-3l2.7-7.1z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#d5006e"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/asx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm7.6 1.7c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm12.3-3.1l-3.4-7.2h3.6L33 9.3l.6 1.8s.2-.9.6-1.8l1.2-2.9H39l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.2-7.1z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/au.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm6.7-8.6h3.3V16c0 1.4.6 1.9 1.5 1.9s1.5-.5 1.5-1.9V6.4H28V16c0 3-1.9 4.9-4.7 4.9-2.9 0-4.8-1.9-4.8-4.9V6.4z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/aup.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1493f6}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm6.7-8.6h3.3V16c0 1.4.6 1.9 1.5 1.9s1.5-.5 1.5-1.9V6.4H28V16c0 3-1.9 4.9-4.7 4.9-2.9 0-4.8-1.9-4.8-4.9V6.4zm13.1 0h4.5c2.6 0 4.4 2 4.4 4.9s-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path id="surface1" class="st0" d="M36 48.8c-3.6 0-6.9 1-9.4 2.8-2.5 1.8-4.2 4.4-4.2 7.4v4.4c-2 1.5-3.4 4.7-3.4 8.4 0 5.1 2.7 9.3 6 9.3.8 0 1.7-.3 2.5-.8v-17c-.5-.3-1.1-.6-1.7-.7V59c0-1.8.9-3.4 2.7-4.6 1.8-1.3 4.5-2.2 7.5-2.2s5.6.9 7.5 2.2c1.8 1.3 2.7 2.9 2.7 4.6v3.5c-.6.2-1.2.4-1.7.7V80c.8.5 1.7.8 2.5.8 3.2 0 6-4.2 6-9.3 0-3.5-1.4-6.7-3.4-8.2V59c0-3-1.7-5.7-4.2-7.4-2.5-1.7-5.8-2.8-9.4-2.8zm0 15l-3.7 7.3-2.3-3-.8 1.2v5.6l.8-1 2.9 3.7 3.1-6.3 3.1 6.3 2.9-3.7.8 1v-5.6l-.8-1.2-2.2 3.1-3.8-7.4z"/></svg>
1
<svg height="64" width="68" xmlns="http://www.w3.org/2000/svg"><path d="M34 0c-7.133 0-13.672 1.98-18.625 5.547S7.051 14.266 7.051 20.21v8.719C3.09 31.902.316 38.242.316 45.574.316 55.68 5.664 64 12.203 64c1.586 0 3.371-.594 4.953-1.586V28.73c-.988-.593-2.18-1.187-3.367-1.386V20.21c0-3.566 1.785-6.738 5.352-9.113C22.707 8.52 28.055 6.738 34 6.738s11.098 1.782 14.86 4.36c3.566 2.574 5.35 5.746 5.35 9.113v6.934c-1.187.398-2.378.793-3.366 1.386v33.29c1.582.992 3.367 1.585 4.953 1.585 6.34 0 11.887-8.324 11.887-18.43 0-6.933-2.774-13.273-6.735-16.246v-8.52c0-5.944-3.37-11.292-8.324-14.663C47.672 2.18 41.133 0 34 0zm0 29.723-7.332 14.465-4.555-5.946-1.586 2.38v11.093l1.586-1.98 5.746 7.331L34 44.582l6.14 12.484 5.747-7.332 1.586 1.98V40.622l-1.586-2.379-4.356 6.14zm0 0" fill="#1493f6"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/avi.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm5.1-8.6h3.6l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3l1.7-8.1H28l-3.9 14.3h-3.3L16.9 6.4zm13.5 0h3.3v14.3h-3.3V6.4z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/axd.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d5006e}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm9.3-1.4l-3.4-7.2h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6L25 13.6l3.3 7.1h-3.5l-1.1-3c-.5-.9-.7-1.7-.7-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.3-7.1zm9.8-7.2h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zM35 17.8c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#d5006e"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/aze.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#2e61f2}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM9 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H5.4L9 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L9.8 15h2zm6.3 3.5l4.2-7.9c.5-.9.8-1.3.8-1.3s-.3.1-.8.1h-4v-3H27v2.2l-4.2 8c-.5.9-.8 1.3-.8 1.3s.3-.1.8-.1H27v2.9h-8.9v-2.2zM30.2 6.4h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4z" fill="#fff"/><path d="M40.7 83.5c8.1-7.2 1.1-16.4-1-17.4.3 1.1.2 3-.9 4.1-.5-2.8-2.7-6.3-5.8-7.5.5 4-1.8 6.8-2.8 8.2-.8 1.3-5.6 8-.8 12.6-11.5-3.6-8.6-15.1-5.3-20.2 3.5-5.3 7.6-9.6 6.7-16.2 5.6 2 9.4 7.9 10.4 12.4 1.9-1.8 2.2-5 1.7-6.8 3.9 1.6 16.1 23.6-2.2 30.8z" fill="#ff9800"/></svg>
1
<svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M34.625 63.98c14.355-12.652 1.95-28.816-1.773-30.574.53 1.934.355 5.27-1.594 7.203-.887-4.918-4.785-11.07-10.278-13.18.883 7.032-3.19 11.95-4.964 14.41-1.418 2.286-9.922 14.06-1.418 22.141-20.38-6.328-15.239-26.535-9.391-35.496C11.41 19.172 18.676 11.617 17.078.02c9.926 3.515 16.66 13.882 18.434 21.789 3.367-3.164 3.898-8.786 3.011-11.95 6.914 2.813 28.536 41.47-3.898 54.121zm0 0" fill="#ff9800"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/bak.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3H6.6V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5H9.9v3.1H11zm9.8-11.4h3.6L28 20.7h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2zm6.9-8.6h3.3v5.5h.6l2.3-5.5h3.5l-2.9 6.8 3 7.4h-3.7l-2.3-5.8h-.6v5.8h-3.3V6.4z" fill="#fff"/><path class="st0" d="M18.5 48v20H26V55.5h12.5V48z"/><path class="st0" d="M28.5 58v25h25V58H41z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M0 0v36.57h13.715V13.715H36.57V0zm0 0"/><path d="M18.285 18.285V64H64V18.285zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/bash.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.7-34.5h3.6c2.1 0 3.6 1.3 3.6 3.7 0 1.3-.6 2.5-1.5 3 1.4.5 2 1.8 2 3.4 0 2.8-1.7 4.1-4 4.1H6.7V6.5zm3.7 5.8c.7 0 1.2-.8 1.2-1.9s-.5-1.8-1.4-1.8H9v3.7h1.4zm-.1 6.2c1.2 0 1.7-.9 1.7-2.1 0-1.3-.6-2.1-1.4-2.1H9v4.2h1.3zm8.1-12h2.5l3.5 14.2H22l-.8-3.7H18l-.8 3.7h-2.3l3.5-14.2zm2.4 8.5l-.8-3.8c-.2-.8-.4-2.2-.4-2.2h-.1s-.2 1.4-.4 2.2l-.8 3.8h2.5zm5 2.5c.6.7 1.4 1.2 2.3 1.2 1 0 1.6-.7 1.6-1.8 0-2.6-4.6-2.5-4.6-6.6 0-2.3 1.5-4 3.9-4 1 0 2.1.3 2.9.9l-.8 2.2c-.5-.4-1.4-.8-2.1-.8-1.1 0-1.7.8-1.7 1.7 0 2.6 4.7 2.4 4.7 6.5 0 2.2-1.3 4.1-3.8 4.1-1.2 0-2.5-.5-3.4-1.4l1-2zm8-11h2.3v6h4.1v-6h2.3v14.2h-2.3v-6h-4.1v6h-2.3V6.5z" fill="#fff"/><path d="M30.8 61.4h10.9v2.7H30.8v-2.7zm0 5.4h10.9v2.7H30.8v-2.7zm0 5.5h10.9V75H30.8v-2.7zm19-24.4H28.1c-3 0-5.4 2.4-5.4 5.4v24.4h-5.4c0 3 2.4 5.4 5.4 5.4h21.7c3 0 5.4-2.4 5.4-5.4V56h5.4v-2.7c0-3-2.4-5.4-5.4-5.4zm-2.7 29.3c0 1.8-1.4 3.2-3.2 3.2H24c1.3-.9 1.3-2.7 1.3-2.7V53.3c0-1.5 1.2-2.7 2.7-2.7s2.7 1.2 2.7 2.7V56H47l.1 21.2zM33.5 53.3v-2.7h16.3c2.5 0 2.7 1.6 2.7 2.7h-19z" fill="#999" stroke="#999" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/bat.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3H6.6V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5H9.9v3.1H11zm9.8-11.4h3.6L28 20.7h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2zm8.1-5.7h-3.1V6.4h9.6v2.9H35v11.4h-3.3V9.3z" fill="#fff"/><path class="st0" d="M54.8 46.8h-38v38h38v-38zm-30.4 7.5h-3.8v-3.8h3.8v3.8zm26.6 0H28.1v-3.8H51v3.8zm0 26.6H20.5V58.2H51v22.7z"/><path class="st0" d="M26.5 61.4l-2.7 2.7 4.4 4.4-4.4 4.3 2.7 2.7 7.1-7zm6.3 12.8h7.6V78h-7.6z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M64 0H0v64h64zM12.8 12.633H6.399V6.23h6.403zm44.802 0h-38.57V6.23h38.57zm0 44.797H6.23V19.2h51.372zm0 0"/><path d="m16.336 24.59-4.547 4.547 7.41 7.41-7.41 7.242 4.547 4.547 11.957-11.79zm10.613 21.558h12.797v6.399H26.95zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/bin.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3H6.6V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5H9.9v3.1H11zm7.6-11.4h3.3v14.3h-3.3V6.4zm6.9 0H29l2.4 6.6c.4 1 .7 2.4.7 2.4h.1S32 13.9 32 13V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4z" fill="#fff"/><path d="M35.8 49.7c-2.9 0-5.4 2.8-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2 2.9 0 5.4-2.8 5.4-6.2 0-3.4-2.4-6.2-5.4-6.2zm0 10.1c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9-1.3 3.9-3 3.9zM25 61V50.9c0-.7-.5-1.2-1.2-1.2s-1.2.5-1.2 1.2V61c0 .7.5 1.2 1.2 1.2S25 61.6 25 61zm-1.1 6.9c-2.9 0-5.4 2.8-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2s5.4-2.8 5.4-6.2c-.1-3.3-2.5-6.2-5.4-6.2zm0 10.2c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9c-.1 2.1-1.4 3.9-3 3.9zM37 79.2V69.1c0-.7-.5-1.2-1.2-1.2s-1.2.5-1.2 1.2v10.1c0 .7.5 1.2 1.2 1.2s1.2-.5 1.2-1.2zm12.3-17.3V51.8c0-.7-.5-1.2-1.2-1.2s-1.1.5-1.1 1.2v10.1c0 .7.5 1.2 1.2 1.2s1.1-.6 1.1-1.2zm-1.2 6.9c-2.9 0-5.4 2.8-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2 2.9 0 5.4-2.8 5.4-6.2 0-3.4-2.4-6.2-5.4-6.2zm0 10.1c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9-1.3 3.9-3 3.9z" fill="#999" stroke="#999" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M17.8.5c-2.9 0-5.4 2.801-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2 2.9 0 5.399-2.8 5.399-6.2C23.199 3.302 20.8.5 17.8.5zm0 10.1c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9-1.3 3.9-3 3.9zM7 11.8V1.7C7 1 6.5.5 5.8.5S4.6 1 4.6 1.7v10.1c0 .7.5 1.2 1.2 1.2S7 12.4 7 11.8zm-1.1 6.9C3 18.7.5 21.5.5 24.9s2.4 6.2 5.4 6.2 5.401-2.8 5.401-6.2c-.102-3.3-2.5-6.2-5.4-6.2zm0 10.2c-1.6 0-3-1.699-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9c-.1 2.1-1.4 3.9-3 3.9zM19 30V19.9c0-.7-.5-1.2-1.2-1.2s-1.2.5-1.2 1.2V30c0 .7.5 1.2 1.2 1.2S19 30.7 19 30zM31.3 12.7V2.6c0-.7-.499-1.2-1.2-1.2-.7 0-1.1.5-1.1 1.2v10.099c0 .701.5 1.2 1.2 1.2s1.1-.6 1.1-1.2zm-1.2 6.9c-2.9 0-5.401 2.8-5.401 6.2 0 3.4 2.4 6.202 5.4 6.202 2.901 0 5.402-2.802 5.402-6.202S33.1 19.6 30.1 19.6zm0 10.102c-1.6 0-3-1.7-3-3.902 0-2.099 1.3-3.9 3-3.9s3 1.7 3 3.9c0 2.202-1.3 3.902-3 3.902zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" transform="matrix(1.91667 0 0 1.9394 0 .485)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/blank.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
<svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M0 61.766V2.234C0 1.004 1 0 2.223 0h53.332c.668 0 1.222.223 1.668.781l22.222 24.922c.332.445.555.89.555 1.45v34.613C80 62.996 79 64 77.777 64H2.223A2.234 2.234 0 0 1 0 61.766zm75.555-33.72-21-23.577H4.445V59.53h71.11zm0 0"/><path d="M53.332 29.055V4.469c0-1.227 1-2.235 2.223-2.235a2.236 2.236 0 0 1 2.222 2.235V26.82h17.778a2.234 2.234 0 0 1 0 4.47h-20a2.236 2.236 0 0 1-2.223-2.235zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/bmp.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3H6.6V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5H9.9v3.1H11zm8.1-11.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.7-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1-14.3zm15 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/bowerrc.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#b4bdcc}.st3{fill:#543828}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/><g opacity=".65"><path class="st3" d="M30.7 32.1h2.6l.1.1c.8.2 1.7.3 2.5.7 2.7 1.1 4.3 3.2 5.3 5.9 0 .1.1.3.2.4.6.2 1.2.3 1.8.5l.1-.1c1.6-3.2 4.2-5 7.7-5.6.9-.2 1.8-.1 2.7.2-.1.1-.1.2-.2.2-1.2 1.3-2.1 2.7-2.3 4.4-.1.6-.2 1.1-.3 1.7-.3 1.5-.8 3-2 4.1-1.5 1.4-3.4 1.7-5.3 1.7-.1 0-.3-.1-.3-.3-.2-.3-.3-.6-.4-1-1.3.3-1.7.6-1.8 1.7.4 0 .8.1 1.2.1 3.4.4 6.8.9 10.1 1.6 1.6.4 3.1.8 4.6 1.5.8.4 1.2 1 1.4 1.9 0 .2.1.4.2.5v1.2c-.1.1-.1.3-.2.4-.2.6-.5 1.1-1 1.5-.6.5-1.3.7-2.1.8.2 1-.4 1.6-1.1 2-.5.3-1 .5-1.5.6-.8.1-1.5 0-2.3 0-.6 1.1-1.6 1.3-2.7 1.4-1.1.1-2.1-.2-3-.8-.4.5-.8.8-1.5.8-1.2.2-2.2-.1-3.2-.5l-.1-.1.1.1c.7 1.3 1.4 2.5 2 3.8.2.4.2 1 .2 1.4 0 .9-.5 1.5-1.2 1.7-.1.7-.5 1.3-1 1.7-.7.5-1.5.6-2.4.6-.1 0-.4-.1-.4 0-.4.6-1.1.8-1.7 1.1h-.9c-.6-.1-1.1-.7-1.8-.2-.1.1-.3.1-.4.1-.7 0-2-.4-2.3-1.4s-.8-2.1-1.2-3.1l-.1.1c-.9 1.8-2.9 2.5-4.8 1.6-1-.5-1.9-1.2-2.6-2-4.8-5.5-6.7-11.9-5.4-19.1 1.2-6.8 6.5-12 13.2-13.4.4-.3 1-.4 1.5-.5zm8.2 11.3c1 .1 2.1.1 3.1-.4.9-.4 1.9-.4 2.8-.3.6.1 1.3.3 1.9.4-.3-.3-.6-.6-1-.8-1.6-1.2-3.4-2-5.5-2.2-.2 0-.5 0-.5.1-.6.9-1 1.8-1 2.9-.1.7.1 1.4.4 2 1.1-.5 2.3-1 3.4-1.5v-.3c-.6.1-1.1.3-1.7.4-.7.1-1.4.2-1.9-.3zm10.4-6.8c-1.3 1.4-2.2 3-3 4.6l2.2 1.9c.7-.9.9-1.9 1.2-2.9.4-1.8.5-3.7 1.9-5.1-2.6-.1-6.4 2.6-7.2 5l1.3.7c.1-.1.1-.3.2-.4.4-.7.8-1.4 1.3-2 .6-.7 1.2-1.4 2.1-1.8zm-4.7 14.6c.8.1 1.6.2 2.4.2l7.4.8c.4 0 .7.1 1.1.1-.2-.6-.5-1.1-1-1.3s-1.1-.3-1.6-.5c-2.2-.4-4.3-.9-6.5-1.3-2.1-.3-4.3-.5-6.4-.8-.1 0-.3 0-.4.1l-1.2 1.2c-2.2 1.6-4.6 2-7.2 2 .7-.2 1.3-.4 2-.7 2.1-.8 3.9-1.9 5.2-3.7.2-.3.2-.5.1-.8-.6-1.1-.9-2.3-.9-3.5 0-1.5.5-2.8 1.6-3.9.2-.2.2-.4.1-.6-.7-1.6-1.7-2.8-3.2-3.7-1.8-1.1-3.8-1.2-5.7-.9-4.5.7-7.9 3-10.3 6.7-2.2 3.5-2.9 7.3-2.4 11.4.2 1.3.5 2.5 1.1 3.6.1.3.2.6.4.9 2.7 4.9 6.9 7.7 12.5 8.1 3.3.2 6.2-1.6 7.2-4.7.2-.7.5-1.4.1-2.1.7.6 1.6.9 2.6 1s1.8-.2 2.2-1c.1 0 .2.1.3.1.8.4 1.6.5 2.5.4 1.1-.1 1.6-.6 1.7-1.6.5.1 1.1.2 1.6.1 1.6 0 2.3-.9 2-2.2.6 0 1.3 0 1.9-.1.6-.1 1.2-.4 1.6-1.1l-6-1.2-6-1.2c-.2.2 1.2.2 1.2.2zm-1-8.1c.2.6.3 1.1.4 1.6.1.3.2.3.5.3 1-.1 1.9-.3 2.7-.7.1-.1.2-.1.5-.3l-2.4-.6-.3.5h-.1v-.6l-1.3-.2z"/><path d="M18.6 55.8c-.6-1.1-.9-2.4-1.1-3.6-.6-4.1.1-7.9 2.4-11.4 2.4-3.8 5.9-6.1 10.3-6.7 2-.3 3.9-.2 5.7.9 1.5.9 2.5 2.1 3.2 3.7.1.2.1.4-.1.6-1 1.1-1.5 2.4-1.6 3.9 0 1.2.3 2.4.9 3.5.2.3.1.5-.1.8-1.3 1.8-3.1 3-5.2 3.7-.6.2-1.3.4-2 .7 2.6 0 5.1-.4 7.2-2-.5.8-.8 1.6-1.4 2.3-2.6 3.4-6 4.9-10.4 3.7-.4-.1-.8-.2-1.2.2l-.6.3c-1.9.5-4 .3-6-.6zm13.5-17.7c-2.1 0-3.7 1.6-3.7 3.8 0 2 1.7 3.7 3.8 3.7s3.7-1.7 3.7-3.8-1.7-3.8-3.8-3.7z" fill="#e95927"/><path d="M18.6 55.8c2 .9 4.1 1 6.2.4.2-.1.5-.1.6-.3.4-.3.8-.3 1.2-.2 4.4 1.2 7.8-.3 10.4-3.7.5-.7.9-1.5 1.4-2.3l1.2-1.2c.1-.1.3-.1.4-.1 2.1.3 4.3.5 6.4.8 2.2.4 4.3.8 6.5 1.3-.1 0-.2.1-.2.1-2.7.2-5.4.4-8 .6h-1.4l6 1.2c-.1.2-.1.6-.2.7-.3.3-.7.6-1.1.7-.5.1-1 0-1.5 0 .1.5 0 1-.4 1.4-.3.2-.6.5-1 .6-.9.4-1.8.4-2.7-.1-.2.9-1 1.2-1.7 1.3-.8.1-1.5 0-2.2-.5l-.1.1.6 1.4c.4.7.1 1.4-.1 2.1-1 3.1-3.9 5-7.2 4.7-5.6-.4-9.8-3.2-12.5-8.1-.4-.3-.5-.6-.6-.9z" fill="#fbcd00"/><path d="M46.3 53.9c.5 0 1.1.1 1.5 0s.8-.4 1.1-.7c.2-.1.2-.5.2-.7l6 1.2c-.4.6-.9 1-1.6 1.1-.6.1-1.3.1-1.9.1.3 1.3-.4 2.2-2 2.2-.5 0-1.1-.1-1.6-.1-.1 1-.6 1.5-1.7 1.6-.9.1-1.7 0-2.5-.4 0-.2-.1-.2-.2-.2-.4.8-1.2 1.1-2.2 1s-1.8-.4-2.6-1l-.6-1.4.1-.1c.7.5 1.4.7 2.2.5.8-.1 1.5-.4 1.7-1.3.9.5 1.8.5 2.7.1.3-.1.7-.4 1-.6.4-.3.5-.8.4-1.3z" fill="#3daf00"/><path d="M49.3 36.6c-.9.4-1.6 1.1-2.2 1.9-.5.6-.9 1.3-1.3 2-.1.1-.1.2-.2.4l-1.3-.7c.8-2.5 4.6-5.1 7.2-5-1.4 1.5-1.4 3.4-1.9 5.1-.2 1-.5 2-1.2 2.9l-2.2-1.9c.9-1.7 1.9-3.3 3.1-4.7.2-.1 0 0 0 0z" fill="#25a7f0"/><path d="M38.7 43.2c0-1.1.3-2.1 1-2.9.1-.1.4-.1.5-.1 2.1.1 3.8 1 5.5 2.2.3.2.7.5 1 .8-.6-.1-1.3-.3-1.9-.4-1-.2-1.9-.1-2.8.3-1 .4-2 .4-3.1.4l-.2-.3z" fill="#cbcbca"/><path d="M44.6 51.2c2.7-.2 5.4-.4 8-.6.1 0 .2 0 .2-.1.5.2 1.1.3 1.6.5.6.2.8.7 1 1.3-.4 0-.8-.1-1.1-.1l-7.3-.7-2.4-.3z" fill="#3eae00"/><path d="M43.6 43.1l1.3.2v.6h.1l.3-.6 2.4.6c-.2.1-.3.2-.5.3-.9.4-1.8.6-2.7.7-.2 0-.4 0-.5-.3-.1-.4-.3-.9-.4-1.5z" fill="#25a5ec"/><path d="M38.7 43.2l.1.2c.6.5 1.3.5 1.9.4.6-.1 1.1-.3 1.7-.4v.3L39 45.2c-.1-.6-.3-1.3-.3-2z" fill="#c9c8c7"/><path d="M32.1 38.1c2.1 0 3.8 1.6 3.8 3.7s-1.7 3.8-3.7 3.8-3.8-1.7-3.8-3.7c0-2.2 1.6-3.8 3.7-3.8zm2.2 3.7c0-1.3-1-2.3-2.2-2.3s-2.2 1-2.3 2.3c0 1.2 1 2.3 2.2 2.3 1.4-.1 2.3-1 2.3-2.3z" fill="#fbcb00"/><path class="st3" d="M49.3 36.6c.1.1 0 0 0 0z"/><path d="M34.3 41.8c0 1.3-1 2.2-2.3 2.2s-2.3-1-2.2-2.3c0-1.2 1-2.3 2.3-2.3 1.3.1 2.2 1.1 2.2 2.4zm-2.2-.1c.4-.1.7-.2 1.1-.4.4-.2.4-.7 0-1-.5-.4-1.6-.4-2.1 0-.4.3-.4.8 0 1 .3.2.6.3 1 .4z" fill="#553928"/><path class="st0" d="M32.1 41.7c-.4-.1-.7-.2-1-.4-.4-.2-.4-.7 0-1 .5-.4 1.6-.4 2.1 0 .4.3.4.8 0 1s-.7.3-1.1.4z"/></g></svg>
1
<svg height="64" width="72" xmlns="http://www.w3.org/2000/svg"><filter id="a" height="100%" width="100%" x="0%" y="0%"><feColorMatrix in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/></filter><mask id="c"><g filter="url(#a)"><path d="M0 0h72v64H0z" fill-opacity=".65"/></g></mask><clipPath id="b"><path d="M0 0h72v64H0z"/></clipPath><g clip-path="url(#b)" mask="url(#c)"><path d="M25.281.082h4.356l.168.168c1.34.34 2.843.508 4.183 1.18 4.524 1.855 7.203 5.39 8.875 9.937 0 .168.168.508.336.676 1.004.336 2.008.504 3.016.84l.164-.168c2.68-5.39 7.035-8.422 12.894-9.43 1.508-.34 3.016-.172 4.524.336-.168.168-.168.336-.336.336-2.012 2.191-3.516 4.547-3.852 7.41-.168 1.012-.336 1.852-.504 2.863-.5 2.528-1.34 5.055-3.347 6.907C53.246 23.497 50.062 24 46.883 24c-.168 0-.504-.168-.504-.504-.332-.508-.5-1.012-.668-1.687-2.176.507-2.848 1.011-3.016 2.863.672 0 1.34.172 2.012.172 5.691.672 11.387 1.515 16.91 2.691 2.68.676 5.192 1.348 7.703 2.528 1.34.675 2.012 1.683 2.344 3.199 0 .34.168.675.336.843v2.02c-.168.168-.168.508-.336.676-.332 1.011-.836 1.851-1.672 2.527-1.008.84-2.18 1.176-3.52 1.348.337 1.683-.667 2.691-1.84 3.367-.835.504-1.675.84-2.51 1.012-1.34.168-2.513 0-3.852 0-1.004 1.851-2.68 2.187-4.52 2.355-1.844.168-3.52-.336-5.023-1.347-.672.843-1.34 1.347-2.512 1.347-2.012.336-3.684-.168-5.36-.84l-.167-.168.167.168c1.172 2.188 2.344 4.211 3.348 6.399.336.676.336 1.683.336 2.36 0 1.515-.836 2.523-2.008 2.862-.168 1.18-.84 2.188-1.676 2.864-1.171.84-2.511 1.007-4.02 1.007-.167 0-.667-.167-.667 0-.672 1.012-1.844 1.348-2.848 1.856h-1.507c-1.004-.168-1.84-1.18-3.016-.34-.164.172-.5.172-.668.172-1.172 0-3.348-.676-3.852-2.36s-1.34-3.538-2.007-5.222l-.168.168c-1.508 3.035-4.856 4.21-8.04 2.695a14.392 14.392 0 0 1-4.351-3.367C1.67 46.402-1.508 35.621.668 23.496 2.676 12.043 11.551 3.286 22.77.926 23.44.422 24.445.25 25.28.082zm13.73 19.035c1.676.168 3.52.168 5.192-.676 1.508-.671 3.184-.671 4.688-.504 1.007.168 2.18.504 3.183.672-.504-.504-1.004-1.011-1.676-1.347-2.68-2.02-5.691-3.367-9.207-3.703-.336 0-.84 0-.84.168-1.003 1.515-1.671 3.03-1.671 4.882-.168 1.18.164 2.36.668 3.371 1.843-.843 3.851-1.687 5.691-2.527v-.508c-1.004.172-1.84.508-2.844.676-1.172.168-2.343.336-3.183-.504zM56.427 7.664c-2.176 2.356-3.684 5.05-5.024 7.746l3.684 3.2c1.176-1.516 1.508-3.2 2.012-4.883.668-3.032.836-6.235 3.18-8.59-4.352-.168-10.715 4.379-12.055 8.422l2.175 1.175c.168-.168.168-.504.336-.671.668-1.18 1.34-2.36 2.176-3.368 1.004-1.18 2.012-2.36 3.516-3.03zm-7.867 24.59c1.34.168 2.68.336 4.015.336l12.395 1.347c.668 0 1.172.168 1.84.168-.336-1.011-.836-1.851-1.676-2.19-.836-.337-1.84-.505-2.676-.84-3.684-.677-7.203-1.516-10.887-2.192-3.515-.504-7.199-.84-10.715-1.348-.167 0-.503 0-.671.172l-2.008 2.02c-3.684 2.695-7.703 3.367-12.055 3.367a25.933 25.933 0 0 0 3.348-1.18c3.515-1.344 6.531-3.2 8.707-6.23.336-.504.336-.84.168-1.348a12.356 12.356 0 0 1-1.508-5.895c0-2.527.836-4.714 2.68-6.566.336-.34.336-.676.168-1.012-1.172-2.695-2.848-4.715-5.36-6.234-3.015-1.852-6.363-2.02-9.543-1.516-7.535 1.18-13.23 5.055-17.25 11.285-3.683 5.895-4.855 12.297-4.015 19.204.332 2.187.836 4.21 1.84 6.062.167.504.335 1.012.671 1.516 4.52 8.254 11.551 12.968 20.93 13.64 5.527.34 10.383-2.695 12.055-7.914.336-1.18.84-2.36.168-3.539 1.172 1.012 2.68 1.516 4.355 1.688 1.672.168 3.012-.34 3.684-1.688.168 0 .332.172.5.172 1.34.672 2.68.84 4.187.672 1.844-.168 2.68-1.012 2.848-2.695.836.168 1.84.336 2.68.168 2.675 0 3.851-1.516 3.347-3.704 1.004 0 2.176 0 3.18-.167 1.008-.172 2.012-.676 2.68-1.856l-10.047-2.02-10.047-2.023c-.332.34 2.012.34 2.012.34zm-1.676-13.645c.336 1.012.504 1.852.668 2.696.168.504.336.504.84.504 1.672-.168 3.18-.504 4.52-1.176.167-.172.335-.172.839-.508l-4.02-1.008-.503.84h-.168v-1.012zm0 0" fill="#543828"/><path d="M5.02 40c-1.004-1.852-1.504-4.043-1.84-6.063-1.004-6.906.168-13.304 4.02-19.203 4.015-6.398 9.878-10.273 17.245-11.28 3.348-.509 6.532-.34 9.543 1.515 2.512 1.515 4.188 3.535 5.36 6.23.168.336.168.676-.168 1.012-1.672 1.851-2.512 4.043-2.68 6.566 0 2.024.504 4.043 1.508 5.895.336.508.168.844-.168 1.348-2.176 3.03-5.192 5.054-8.707 6.234-1.004.336-2.176.672-3.348 1.176 4.352 0 8.54-.672 12.055-3.368-.836 1.348-1.34 2.696-2.344 3.875-4.351 5.727-10.047 8.254-17.414 6.231-.668-.168-1.34-.336-2.008.336l-1.008.508c-3.18.84-6.695.504-10.046-1.012zm22.605-29.813c-3.516 0-6.195 2.696-6.195 6.403 0 3.367 2.847 6.23 6.363 6.23s6.195-2.863 6.195-6.398c0-3.54-2.843-6.402-6.363-6.235zm0 0" fill="#e95927"/><path d="M5.02 40c3.351 1.516 6.867 1.684 10.382.676.336-.172.836-.172 1.004-.508.672-.504 1.34-.504 2.012-.336 7.367 2.02 13.059-.504 17.414-6.23.836-1.18 1.508-2.528 2.344-3.875l2.008-2.02c.168-.172.504-.172.671-.172 3.516.508 7.2.844 10.715 1.348 3.684.676 7.203 1.347 10.887 2.191-.168 0-.336.168-.336.168-4.523.336-9.043.672-13.394 1.012h-2.348l10.047 2.02c-.164.335-.164 1.011-.332 1.18-.504.503-1.172 1.01-1.844 1.179-.836.168-1.676 0-2.512 0 .168.84 0 1.683-.668 2.355-.504.34-1.007.844-1.675 1.012-1.508.676-3.016.676-4.52-.168-.336 1.516-1.676 2.02-2.848 2.188-1.34.171-2.511 0-3.683-.84l-.168.168 1.004 2.359c.672 1.176.168 2.355-.168 3.535-1.672 5.223-6.528 8.422-12.055 7.918-9.379-.676-16.41-5.39-20.93-13.644-.672-.504-.84-1.012-1.007-1.516zm0 0" fill="#fbcd00"/><path d="M51.402 36.8c.84 0 1.844.169 2.512 0 .672-.167 1.34-.675 1.844-1.179.336-.168.336-.844.336-1.18l10.047 2.024c-.672 1.008-1.508 1.683-2.68 1.851-1.004.168-2.176.168-3.184.168.504 2.192-.668 3.707-3.347 3.707-.836 0-1.844-.171-2.68-.171-.168 1.687-1.004 2.527-2.848 2.695-1.504.168-2.843 0-4.183-.672 0-.336-.168-.336-.336-.336-.668 1.348-2.008 1.852-3.684 1.684s-3.015-.676-4.355-1.684l-1.004-2.36.168-.167c1.172.84 2.344 1.18 3.683.84 1.34-.168 2.512-.672 2.848-2.188 1.508.844 3.012.844 4.52.168.504-.168 1.171-.672 1.675-1.012.668-.504.836-1.347.668-2.187zm0 0" fill="#3daf00"/><path d="M56.426 7.664c-1.504.672-2.676 1.852-3.684 3.2-.836 1.011-1.504 2.187-2.176 3.366-.168.168-.168.336-.336.676l-2.175-1.18c1.34-4.21 7.703-8.59 12.054-8.421-2.343 2.527-2.343 5.726-3.18 8.59-.335 1.683-.835 3.367-2.007 4.882l-3.684-3.199c1.504-2.863 3.18-5.558 5.188-7.914.336-.172 0 0 0 0zm0 0" fill="#25a7f0"/><path d="M38.68 18.777c0-1.851.5-3.535 1.672-4.882.168-.168.671-.168.84-.168 3.515.168 6.359 1.683 9.206 3.703.504.34 1.172.843 1.676 1.347-1.004-.168-2.176-.504-3.183-.672-1.672-.335-3.18-.167-4.688.504-1.672.676-3.348.676-5.191.676zm0 0" fill="#cbcbca"/><path d="M48.559 32.254c4.52-.34 9.039-.676 13.394-1.012.168 0 .336 0 .336-.168.836.336 1.84.504 2.68.84 1.004.34 1.34 1.18 1.672 2.191-.668 0-1.34-.167-1.84-.167l-12.227-1.18zm0 0" fill="#3eae00"/><path d="m46.883 18.61 2.176.335v1.012h.168l.503-1.012 4.02 1.012c-.336.168-.504.336-.84.504-1.508.676-3.012 1.012-4.52 1.18-.335 0-.671 0-.84-.504-.163-.676-.5-1.516-.667-2.528zm0 0" fill="#25a5ec"/><path d="m38.68 18.777.164.34c1.008.84 2.18.84 3.183.672 1.004-.168 1.84-.504 2.848-.672v.504l-5.695 2.527c-.168-1.011-.5-2.191-.5-3.37zm0 0" fill="#c9c8c7"/><path d="M27.625 10.188c3.52 0 6.363 2.695 6.363 6.234 0 3.535-2.843 6.398-6.195 6.398-3.348 0-6.363-2.863-6.363-6.23 0-3.707 2.68-6.403 6.195-6.403zm3.684 6.234c0-2.192-1.672-3.875-3.684-3.875-2.008 0-3.684 1.683-3.852 3.875 0 2.02 1.676 3.871 3.688 3.871 2.344-.168 3.848-1.684 3.848-3.871zm0 0" fill="#fbcb00"/><path d="M56.426 7.664c.168.168 0 0 0 0zm0 0" fill="#543828"/><path d="M31.309 16.422c0 2.187-1.672 3.703-3.848 3.703-2.18 0-3.852-1.684-3.688-3.871 0-2.024 1.676-3.875 3.852-3.875 2.18.168 3.684 1.851 3.684 4.043zm-3.684-.168a8.37 8.37 0 0 0 1.844-.676c.668-.336.668-1.18 0-1.683-.836-.676-2.68-.676-3.516 0-.672.503-.672 1.347 0 1.683.5.336 1.004.504 1.672.676zm0 0" fill="#553928"/><path d="M27.625 16.254c-.668-.172-1.172-.34-1.672-.676-.672-.336-.672-1.18 0-1.683.836-.676 2.68-.676 3.516 0 .668.503.668 1.347 0 1.683a8.37 8.37 0 0 1-1.844.676zm0 0" fill="#fff"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/bpg.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3H6.6V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5H9.9v3.1H11zm7.6-11.4h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zM36 6.1c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1H38v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3 0-4.5 2.5-7.6 6.3-7.6z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/browser.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M26.8 50.3c2.2-.9 4.5-1.5 6.9-1.6v-6.4h-8.4c.1 2.7.6 5.5 1.5 8zm-4.6-24.6c1 1 2.2 1.8 3.3 2.5 1-2.3 2.3-4.5 3.9-6.5-2.7.8-5.1 2.1-7.2 4zm21 6c-2.2.9-4.5 1.5-6.9 1.6v6.4h8.4c-.1-2.7-.6-5.5-1.5-8zm-9.4 1.5c-2.4-.2-4.8-.7-6.9-1.6-.9 2.6-1.4 5.3-1.5 8.1h8.4v-6.5zm-6-3.9c1.9.8 3.9 1.2 6 1.4v-9.8h-.2l-1.1 1.2c-2.1 2.1-3.6 4.6-4.7 7.2zm16.9 12.9h-8.4v6.4c2.4.2 4.8.7 6.9 1.6.9-2.4 1.4-5.2 1.5-8zm-8.5-11.4c2.1-.2 4.1-.6 6-1.4-1.2-2.7-2.8-5.1-4.7-7.3l-.8-1.1h-.4l-.1 9.8zm11.7-5.2c-2.1-1.8-4.6-3.2-7.3-3.9 1.6 2 2.9 4.2 3.9 6.5 1.2-.7 2.3-1.5 3.4-2.6zM33.8 51.2c-2.1.2-4.1.6-6 1.4 1.2 2.6 2.7 5.1 4.6 7.2l1 1.1h.3l.1-9.7zm-11-11.4c.1-3.2.8-6.2 1.7-9.2-1.5-.8-2.8-1.8-4.2-3.1l-.1-.1c-3 3.3-5 7.6-5.2 12.4h7.8zm24.4 2.4c-.1 3.2-.8 6.2-1.7 9.2 1.5.8 2.8 1.8 4.2 3.1l.2.2c3-3.3 5-7.6 5.3-12.4-.2-.1-8-.1-8-.1zm2.4-14.7c-1.2 1.2-2.7 2.2-4.2 3.1 1.1 2.9 1.7 6 1.7 9.2H55c-.3-4.8-2.2-9.1-5.3-12.4l-.1.1zm-1.8 28.8c-1-1-2.2-1.8-3.3-2.5-1 2.3-2.3 4.5-3.9 6.5 2.7-.8 5.2-2.1 7.2-4zm-27.4-1.8c1.2-1.2 2.7-2.2 4.1-3.1-1.1-2.9-1.7-6-1.8-9.2H15c.3 4.8 2.2 9.1 5.2 12.4l.2-.1zm5.1-.7c-1.2.7-2.3 1.6-3.3 2.5 2.1 1.8 4.6 3.2 7.3 3.9-1.7-1.9-3-4-4-6.4zm16.7-1.1c-1.9-.8-3.9-1.2-6-1.4v9.8h.3l1.1-1.2c2-2.1 3.5-4.7 4.6-7.2z"/><path d="M7.7 70.4h3.1c1.9 0 3.2 1.3 3.2 3.7 0 1.2-.4 2.4-1.2 3 1.2.5 1.6 1.9 1.6 3.2 0 3.1-1.5 4.3-3.3 4.3H7.7V70.4zm3.1 5.6c.5 0 .7-.6.7-1.4 0-.7-.2-1.3-.7-1.3h-.6V76h.6zm.2 5.8c.6 0 .9-.7.9-1.6s-.2-1.5-.8-1.5h-.9v3.1h.8zm4.5-11.4h3.4c.4 0 1 .1 1.4.4 1.1.6 1.8 2.1 1.8 4 0 1.7-.6 3.3-1.5 4 0 0 .1.2.4.9l1.7 5H20l-1.5-4.8H18v4.8h-2.5V70.4zm3 6.6c.6 0 1.2-.7 1.2-1.9 0-.7-.2-1.2-.4-1.5-.2-.2-.5-.3-.6-.3H18V77h.5zm9-6.8c2.8 0 4.4 3.1 4.4 7.3 0 4.2-1.6 7.5-4.4 7.5s-4.4-3.2-4.4-7.5c.1-4.2 1.6-7.3 4.4-7.3zm0 11.6c1.3 0 1.8-1.8 1.8-4.3s-.6-4.2-1.8-4.2-1.9 1.7-1.9 4.2c.1 2.5.7 4.3 1.9 4.3zm4.8-11.4h2.4l.9 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1-8.9h2.3l1 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l.9-8.9h2.4l-1.9 14.3h-2.8l-.8-7.2c-.3-.9-.3-1.7-.3-1.7s0 .8-.1 1.7l-.9 7.2h-2.8l-1.9-14.3zM45 80.7c.4.6 1 1.2 1.7 1.2s1-.6 1-1.2c0-2-3.6-2.1-3.6-6.2 0-2.4 1.3-4.3 3.4-4.3.9 0 1.8.3 2.6 1l-.9 2.9c-.4-.4-1.1-.9-1.6-.9-.7 0-1 .6-1 1.2 0 2.1 3.6 2 3.6 6.1 0 2.3-1.1 4.4-3.3 4.4-1 0-2.2-.5-3-1.4l1.1-2.8zm6.3-10.3h5.4v2.9h-2.9V76h2.3v2.9h-2.3v2.9h3.1v2.9h-5.5l-.1-14.3zm6.8 0h3.4c.4 0 1 .1 1.4.4 1.1.6 1.8 2.1 1.8 4 0 1.7-.6 3.3-1.5 4 0 0 .2.2.4.9l1.7 5h-2.7l-1.5-4.8h-.6v4.8H58l.1-14.3zM61 77c.6 0 1.2-.7 1.2-1.9 0-.7-.2-1.2-.4-1.5-.2-.2-.4-.3-.6-.3h-.6V77h.4z" fill="#666"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/bz2.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#90c}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3H6.6V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5H9.9v3.1H11zm7 .7l4.2-7.9c.4-.9.8-1.3.8-1.3s-.3.1-.8.1h-4v-3h8.7v2.2l-4.2 8c-.5.9-.8 1.3-.8 1.3s.3-.1.8-.1H27v2.9h-9v-2.2zm11.8.6c0-5 4.5-5.5 4.5-8.4 0-1-.5-1.4-1.2-1.4-.6 0-1.1.3-1.4.8l-2.2-1.8c.8-1.1 2.3-2.1 4.1-2.1 2.1 0 4.2 1.3 4.2 4.2 0 4.1-4.2 5.4-4.4 7.5H38v2.9h-8c-.1-.7-.2-1.1-.2-1.7z" fill="#fff"/><path class="st0" d="M51.1 57.5h-5.7v-5.7l5.7 5.7zm-15.3-5.7v20.7h15.4V58.9H44v-7.1h-8.2zm2.4-5.4h-17v4h6.7l-4.2 3.3v3.5l6.2-4.8v-1.9h21.6v-1.6l-13.3-2.5zm-8.3 8.7l-6.2 4.8v3.5l6.2-4.8v-3.5zm-6.3 14.4l6.2-4.8v-3.5L23.6 66v3.5zm6.3 1.4v-3.5l-6.2 4.8V74h-2.5v4H25v2.8h-2.2c-.4-.7-1.1-1.2-2-1.2-1.3 0-2.3 1-2.3 2.3 0 1.3 1 2.3 2.3 2.3.9 0 1.6-.5 2-1.2H25v2.1h3.4V83h2.2c.4.7 1.1 1.2 2 1.2 1.3 0 2.3-1 2.3-2.3 0-1.3-1-2.3-2.3-2.3-.9 0-1.6.5-2 1.2h-2.2V78h9.7l13.3-2.4V74H25.7l4.2-3.1z"/></svg>
1
<svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/bzempty.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M8.5 74.7h2.9c1.7 0 3 .9 3 2.6 0 .8-.4 1.7-1.2 2.1 1.1.4 1.5 1.4 1.5 2.3 0 2.2-1.4 3-3.1 3H8.5v-10zm3 3.9c.4 0 .6-.4.6-1s-.2-.9-.7-.9h-.6v1.9h.7zm.1 4.1c.6 0 .8-.5.8-1.1 0-.6-.2-1.1-.7-1.1h-.8v2.2h.7zm4.5.5l2.9-5.5c.3-.6.6-.9.6-.9h-3.4v-2h6.1v1.5l-2.9 5.6c-.3.6-.6.9-.6.9h3.6v2h-6.2v-1.6zm8.2-8.5h5v2h-2.7v1.9h2.2v2h-2.2v2h2.9v2h-5.2v-9.9zm7.3 0h2.5l.9 4.2c.1.7.3 1.7.3 1.7s.2-1 .3-1.7l.9-4.2H39l.6 10h-2.1l-.3-4.5c-.1-.8 0-1.7 0-1.7h-.1s-.2 1.1-.3 1.7l-.6 2.9H34l-.6-2.9c-.2-.6-.3-1.7-.3-1.7H33s.1.9 0 1.7l-.3 4.5h-2.1l1-10zm10.2 0H45c1.8 0 3.1 1.4 3.1 3.4s-1.2 3.5-3.1 3.5h-.9v3.1h-2.3v-10zm2.7 4.9c.7 0 1.1-.6 1.1-1.4 0-.8-.5-1.4-1.1-1.4H44v2.9h.5zm6.7-2.9H49v-2h6.7v2h-2.2v8h-2.3v-8zm7.7 3.9l-2.5-5.9h2.5l.8 2.4.4 1.4h.1s.1-.8.4-1.4l.7-2.4h2.5l-2.5 5.9v4.1H59v-4.1z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm3.4 20c5.9 8.1 2.2 18.6-7.8 20.9-4.8-7 2.9-13.2 7.8-20.9zm-26 18.8l.3.2c1.8 1.2 3.9 1.9 6.1 2-1.9-3.9-1.5-8.6.9-12.2l7-10.2c3.8-5.7 2.3-13.5-3.4-17.3l-.4-.3c-1.8-1.2-3.9-1.9-6.1-2 1.9 4 1.5 8.6-.9 12.2l-7 10.2c-3.8 5.8-2.3 13.6 3.5 17.4zM43.3 53s2-2.7 3-4.3l2.9-4.3c3.6-5.3-2.7-9.5-3.5-9.6.8 1.6 0 4.9-1 6.5l-2.9 4.3c-1.6 2.5-1 5.8 1.5 7.4z"/></svg>
1
<svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M47.734 32c8.914 12.195 3.325 28-11.785 31.46C28.695 52.927 40.33 43.59 47.734 32zM8.45 60.3l.453.302a18.118 18.118 0 0 0 9.215 3.011c-2.867-5.87-2.265-12.945 1.363-18.367l10.575-15.355c5.742-8.578 3.476-20.32-5.137-26.043l-.605-.45A18.106 18.106 0 0 0 15.098.387c2.87 6.02 2.265 12.945-1.36 18.367L3.16 34.109c-5.742 8.73-3.472 20.473 5.29 26.192zm27.047-17.76s3.02-4.067 4.531-6.474l4.383-6.476c5.438-7.977-4.082-14.3-5.289-14.45 1.207 2.407 0 7.376-1.512 9.786l-4.382 6.472c-2.414 3.762-1.508 8.73 2.27 11.141zm0 0" fill="#bababa"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/c.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4z" fill="#fff"/><path class="st0" d="M14 48.9h37v4.3H14zm7 9.6h37v4.3H21zm-7 9.6h37v4.3H14zm7 9.6h37V82H21z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cab.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#4d1b9b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm8.9.3H25l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2zm6.9-8.6h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1z" fill="#fff"/><path class="st0" d="M51.1 57.5h-5.7v-5.7l5.7 5.7zm-15.3-5.7v20.7h15.4V58.9H44v-7.1h-8.2zm2.4-5.4h-17v4h6.7l-4.2 3.3v3.5l6.2-4.8v-1.9h21.6v-1.6l-13.3-2.5zm-8.3 8.7l-6.2 4.8v3.5l6.2-4.8v-3.5zm-6.3 14.4l6.2-4.8v-3.5L23.6 66v3.5zm6.3 1.4v-3.5l-6.2 4.8V74h-2.5v4H25v2.8h-2.2c-.4-.7-1.1-1.2-2-1.2-1.3 0-2.3 1-2.3 2.3 0 1.3 1 2.3 2.3 2.3.9 0 1.6-.5 2-1.2H25v2.1h3.4V83h2.2c.4.7 1.1 1.2 2 1.2 1.3 0 2.3-1 2.3-2.3 0-1.3-1-2.3-2.3-2.3-.9 0-1.6.5-2 1.2h-2.2V78h9.7l13.3-2.4V74H25.7l4.2-3.1z"/></svg>
1
<svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#4d1b9b"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cad.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#369}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm8.9.3H25l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2zm6.9-8.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z" fill="#fff"/><path d="M51.6 65.9c-.5-.2-1.1 0-1.3.5-1.1 2.5-2.9 4.7-5.1 6.4l-6.7-13.6c1-.8 1.6-2 1.6-3.4 0-2.1-1.5-3.9-3.5-4.3v-3.4c0-.5-.4-1-1-1-.5 0-1 .4-1 1v3.4c-2 .4-3.5 2.2-3.5 4.3 0 1.4.6 2.6 1.6 3.4L26 72.8c-2.2-1.7-4-3.8-5.1-6.4-.2-.5-.8-.7-1.3-.5-.5.2-.7.8-.5 1.3 1.3 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.1 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2s6-.8 8.7-2.2l3.8 7.8c.1.3.5.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.7-4.4 6-7.3.6-.5.4-1.1 0-1.3zm-16-12.6c1.4 0 2.5 1.1 2.5 2.5s-1.1 2.5-2.5 2.5-2.5-1.1-2.5-2.5 1.2-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.8-2l6.8-13.7c.3.1.7.1 1.1.1s.7 0 1.1-.1l6.8 13.7c-2.5 1.3-5.2 2-8 2z" fill="#369" stroke="#369" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M33.325 19.55c-.498-.2-1.1 0-1.299.5-1.1 2.5-2.901 4.7-5.1 6.4l-6.7-13.601c1-.8 1.6-1.999 1.6-3.4 0-2.099-1.501-3.899-3.501-4.3v-3.4a1 1 0 0 0-2 0v3.4c-2 .401-3.5 2.201-3.5 4.3 0 1.401.6 2.6 1.601 3.4l-6.7 13.602c-2.201-1.7-4-3.801-5.1-6.401-.201-.5-.8-.7-1.301-.5-.499.199-.7.8-.499 1.3 1.299 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.098 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2 3.1 0 6-.8 8.699-2.2l3.8 7.8c.1.3.501.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.701-4.4 6-7.3.6-.5.401-1.101 0-1.3zM17.326 6.95c1.4 0 2.5 1.1 2.5 2.499 0 1.401-1.1 2.502-2.5 2.502s-2.5-1.1-2.5-2.502c0-1.4 1.199-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.801-2l6.8-13.7c.3.1.701.1 1.1.1.402 0 .701 0 1.1-.1l6.8 13.7c-2.5 1.3-5.199 2-7.999 2zm0 0" fill="#369" stroke="#369" stroke-miterlimit="10" stroke-width="1.5" transform="matrix(1.6544 0 0 1.63607 0 .154)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/caf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm8.9.3H25l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2zm6.9-8.6h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cal.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#c11e07}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm8.9.3H25l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2zm6.9-8.6h3.3v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><path id="path1156" d="M20 80.5v-5.7h6.6v5.7H20zm8 0v-5.7h7.3v5.7H28zm-8-7v-6.4h6.6v6.4H20zm8 0v-6.4h7.3v6.4H28zm-8-7.7v-5.7h6.6v5.7H20zm16.8 14.7v-5.7h7.3v5.7h-7.3zM28 65.8v-5.7h7.3v5.7H28zm17.6 14.7v-5.7h6.6v5.7h-6.6zm-8.8-7v-6.4h7.3v6.4h-7.3zm-8-17.2c0 .3-.3.6-.7.6h-1.5c-.4 0-.7-.3-.7-.6v-5.7c0-.3.3-.6.7-.6H28c.4 0 .7.3.7.6v5.7zm16.8 17.2v-6.4h6.6v6.4h-6.6zm-8.8-7.7v-5.7h7.3v5.7h-7.3zm8.8 0v-5.7h6.6v5.7h-6.6zm.8-9.5c0 .3-.3.6-.7.6h-1.5c-.4 0-.7-.3-.7-.6v-5.7c0-.3.3-.6.7-.6h1.5c.4 0 .7.3.7.6v5.7zm8.8-1.3c0-1.4-1.3-2.5-2.9-2.5h-2.9v-1.9c0-1.7-1.6-3.2-3.7-3.2h-1.5c-2 0-3.7 1.4-3.7 3.2v1.9h-8.8v-1.9c0-1.7-1.6-3.2-3.7-3.2h-1.5c-2 0-3.7 1.4-3.7 3.2v1.9H20c-1.6 0-2.9 1.2-2.9 2.5v25.4c0 1.4 1.3 2.5 2.9 2.5h32.2c1.6 0 2.9-1.2 2.9-2.5V55z" fill="#111"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M5.102 59.219v-10.11h11.605v10.11zm14.066 0v-10.11h12.836v10.11zM5.102 46.805V35.457h11.605v11.348zm14.066 0V35.457h12.836v11.348zM5.102 33.152V23.047h11.605v10.105zM34.645 59.22v-10.11H47.48v10.11zM19.168 33.152V23.047h12.836v10.105zm30.95 26.067v-10.11h11.605v10.11zM34.644 46.805V35.457H47.48v11.348zm-14.07-30.496c0 .53-.528 1.062-1.231 1.062h-2.637c-.703 0-1.23-.531-1.23-1.062V6.203c0-.535.527-1.066 1.23-1.066h2.461c.703 0 1.23.531 1.23 1.066V16.31zm29.542 30.496V35.457h11.606v11.348zM34.645 33.152V23.047H47.48v10.105zm15.472 0V23.047h11.606v10.105zm1.406-16.843c0 .53-.527 1.062-1.23 1.062h-2.637c-.703 0-1.23-.531-1.23-1.062V6.203c0-.535.527-1.066 1.23-1.066h2.637c.703 0 1.23.531 1.23 1.066zM67 14.004c0-2.484-2.285-4.434-5.102-4.434h-5.097V6.203c0-3.016-2.813-5.676-6.508-5.676h-2.637c-3.515 0-6.508 2.48-6.508 5.676V9.57H25.676V6.203c0-3.016-2.817-5.676-6.508-5.676h-2.637c-3.52 0-6.508 2.48-6.508 5.676V9.57H5.102C2.285 9.57 0 11.7 0 14.004v45.035c0 2.484 2.285 4.434 5.102 4.434h56.62c2.817 0 5.102-2.13 5.102-4.434V14.004zm0 0" fill="#111"/></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/cd.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm6.5.3h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H19V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z" fill="#fff"/><path class="st0" d="M42.7 70.8c.2-.5.4-.9.5-1.4l2.5-7.8c.3-1 .7-2 1.3-2.8 1-1.4 2.4-2.1 4-2.3.6-.1 1.3-.2 1.9-.2h6.2c-.1.1-.1.2-.1.2-.7 1.3-1.5 2.5-2.1 3.8-1.3 2.2-2.6 4.5-3.9 6.6-.8 1.4-1.8 2.8-2.8 4-.8.9-1.6 1.8-2.6 2.5-.7.5-1.5.7-2.3.7h-9.1c-.9 0-1.7-.3-2.3-.9-.9-.8-1.5-2-2-3.1-.8-2.1-1.3-4.4-1.8-6.6-.2-1.1-.5-2.1-.8-3.1 0-.1-.1-.2-.1-.2l-.2.2c-1.2 1.2-2.2 2.5-3.1 3.8-.2.4-.3.8-.5 1.3-.5 1.6-1 3.3-1.5 4.9-.5 1.5-1.5 2.8-3 3.5-.9.5-1.8.7-2.8.7-1.5 0-2.9 0-4.4.1-.4 0-.4 0-.3-.4.6-2.3 1.4-4.6 2.4-6.8s2.2-4.5 3.8-6.4c1-1.3 2.1-2.6 3.6-3.5.7-.5 1.5-.8 2.4-.9h9.8c1.7 0 2.8.7 3.8 2 .5.8 1 1.8 1.3 2.7.7 1.9 1.1 3.8 1.6 5.8.3 1.2.6 2.2.8 3.4-.3 0-.3.1-.2.2z"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/cdda.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.4-34.8c1 0 2.2.4 2.9 1.2l-.9 2.1c-.4-.5-1.3-1-2-1-2.1 0-3.2 2.2-3.2 4.9 0 2.8 1.2 5.2 3.2 5.2.9 0 1.6-.5 2.2-1l.9 2.1c-.8.7-1.8 1.3-3.2 1.3-3.3 0-5.2-3.2-5.2-7.4 0-4.3 1.9-7.4 5.3-7.4zm4.5.3h3.3c3 0 4.9 2.6 4.9 7.1s-1.9 7.1-4.9 7.1h-3.3V6.5zm3.2 12c1.8 0 2.8-1.7 2.8-4.9s-1.1-4.9-2.8-4.9h-1.2v9.8h1.2zm6.6-12H29c3 0 4.9 2.6 4.9 7.1S32 20.7 29 20.7h-3.3V6.5zm3.3 12c1.8 0 2.8-1.7 2.8-4.9S30.7 8.7 29 8.7h-1.2v9.8H29zm8.6-12h2.2L43 20.7h-2.1l-.7-3.7h-3l-.7 3.7h-2.1l3.2-14.2zm2.3 8.5l-.8-3.8c-.2-.8-.4-2.2-.4-2.2h-.1s-.2 1.4-.3 2.2l-.7 3.8h2.3z" fill="#fff"/><path class="st0" d="M41 77.6V64.1l7.9-1.3C47.7 56.1 41.8 51 34.7 51c-8 0-14.5 6.5-14.5 14.5S26.7 80 34.7 80c.8 0 1.5-.1 2.3-.2.6-1 1.6-1.7 2.9-2.1.4-.1.8-.1 1.1-.1zm-3.6-25.4L35.8 59h-1.5l-1.1-6.8c1.6-.8 4.2 0 4.2 0zm-2.7 18.7c-3 0-5.4-2.4-5.4-5.4s2.4-5.4 5.4-5.4c3 0 5.4 2.4 5.4 5.4 0 3-2.4 5.4-5.4 5.4zm0-9.5c-2.3 0-4.1 1.8-4.1 4.1s1.8 4.1 4.1 4.1 4.1-1.8 4.1-4.1-1.8-4.1-4.1-4.1zm0 7c-1.6 0-2.9-1.3-2.9-2.9 0-1.6 1.3-2.9 2.9-2.9 1.6 0 2.9 1.3 2.9 2.9.1 1.6-1.3 2.9-2.9 2.9zm1.9 13.9c.1.4.2.7.4 1.1-.8.1-1.5.2-2.3.2-9.9 0-18-8.1-18-18s8.1-18 18-18c8.8 0 16.2 6.4 17.7 14.7l-1.7.3c-1.4-7.5-8-13.3-16-13.3-8.9 0-16.2 7.3-16.2 16.2 0 8.9 7.3 16.2 16.2 16.2.6 0 1.2 0 1.8-.1 0 .2 0 .5.1.7zm17.7-19.1v15.6c0 1.3-1 2.3-2.5 2.7-1.6.4-3.2-.3-3.6-1.5-.3-1.3.8-2.6 2.4-3 .7-.2 1.5-.1 2.1.1v-9.4l-8.4 1.5v11.7c0 1.1-1 2.2-2.4 2.6-1.6.4-3.3-.4-3.5-1.5-.3-1.3.8-2.6 2.4-3 .7-.2 1.5-.1 2.1.1v-14l11.4-1.9z"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M43.195 53.328v-24l13.93-2.308C55.008 15.11 44.605 6.043 32.09 6.043c-14.106 0-25.563 11.555-25.563 25.773 0 14.223 11.457 25.778 25.563 25.778 1.41 0 2.644-.18 4.055-.356 1.058-1.777 2.82-3.023 5.113-3.734.703-.176 1.41-.176 1.937-.176zM36.848 8.176l-2.82 12.09h-2.645l-1.938-12.09c2.82-1.422 7.403 0 7.403 0zM32.09 41.418c-5.29 0-9.52-4.266-9.52-9.602 0-5.332 4.23-9.597 9.52-9.597 5.289 0 9.52 4.265 9.52 9.597 0 5.336-4.231 9.602-9.52 9.602zm0-16.887c-4.055 0-7.227 3.2-7.227 7.285 0 4.09 3.172 7.29 7.227 7.29s7.226-3.2 7.226-7.29c0-4.086-3.171-7.285-7.226-7.285zm0 12.442c-2.82 0-5.113-2.309-5.113-5.157 0-2.843 2.293-5.152 5.113-5.152 2.82 0 5.113 2.309 5.113 5.152.176 2.848-2.293 5.157-5.113 5.157zm3.347 24.707c.18.71.356 1.246.708 1.957-1.41.175-2.645.355-4.055.355C14.637 63.992.355 49.594.355 31.996S14.637 0 32.09 0c15.512 0 28.558 11.375 31.203 26.129l-2.996.535C57.828 13.332 46.19 3.024 32.09 3.024 16.398 3.023 3.53 15.995 3.53 31.815c0 15.82 12.867 28.797 28.559 28.797 1.058 0 2.117 0 3.172-.175 0 .355 0 .886.175 1.242zm31.208-33.95v27.73c0 2.31-1.766 4.087-4.41 4.798-2.82.71-5.641-.531-6.344-2.664-.532-2.313 1.41-4.621 4.23-5.332 1.234-.356 2.645-.18 3.703.175V35.73l-14.808 2.665V59.19c0 1.957-1.766 3.91-4.235 4.621-2.82.711-5.816-.71-6.168-2.664-.531-2.312 1.41-4.62 4.23-5.332 1.235-.355 2.645-.18 3.704.176V31.105zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cer.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#696}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm6.5.3h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9H19V6.4zm10.5 0H34c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.8v4.8h-3.3V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6z" fill="#fff"/><path class="st0" d="M49.2 62.2h-2.6v-5C46.6 51.5 42 47 36.4 47s-10.2 4.6-10.2 10.2v5h-2.6c-1 0-1.8.8-1.8 1.8v17.4c0 1 .8 1.8 1.8 1.8h25.6c1 0 1.8-.8 1.8-1.8V63.9c0-.9-.8-1.7-1.8-1.7zM38.6 76.6c.2.6-.3 1.1-.9 1.1H35c-.6 0-1-.6-.9-1.1l.8-3.2c-1-.5-1.7-1.5-1.7-2.8 0-1.7 1.4-3.1 3.1-3.1 1.7 0 3.1 1.4 3.1 3.1 0 1.2-.7 2.3-1.7 2.8l.9 3.2zm2.9-14.4H31.3v-5c0-2.8 2.3-5.1 5.1-5.1s5.1 2.3 5.1 5.1v5z"/></svg>
1
<svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#696"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cfg.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2s1.2 4.4 3.2 4.4c1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm6.5.3h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4H19V6.4zm15.8-.3c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7H35v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.1-4.5 2.5-7.6 6.4-7.6z" fill="#fff"/><path class="st0" d="M41.4 60.3c0-2.3-1.4-4.1-3.3-4.9v-6.6c0-1.1-.8-1.9-1.9-1.9-1.1 0-1.9.8-1.9 1.9v6.6c-2 .7-3.3 2.6-3.3 4.9 0 2.3 1.4 4.1 3.3 4.9 0 .1-.1.3-.1.4v16.6c0 1.1.8 1.9 1.9 1.9 1.1 0 1.9-.8 1.9-1.9V65.5c0-.2 0-.3-.1-.4 2.1-.6 3.5-2.5 3.5-4.8zm-5.3 1.5c-.8 0-1.4-.6-1.4-1.4 0-.8.6-1.4 1.4-1.4.8 0 1.4.6 1.4 1.4.1.7-.6 1.4-1.4 1.4zM51.3 49c0-1.1-.8-1.9-1.9-1.9-1.1 0-1.9.8-1.9 1.9v15.5c-2 .7-3.3 2.6-3.3 4.9s1.4 4.1 3.3 4.9c0 .1-.1.3-.1.4v7.6c0 1.1.8 1.9 1.9 1.9 1.1 0 1.9-.8 1.9-1.9v-7.6c0-.2 0-.3-.1-.4 2-.7 3.3-2.6 3.3-4.9s-1.4-4.1-3.3-4.9V49h.2zm-1.9 21.8c-.8 0-1.4-.6-1.4-1.4s.6-1.4 1.4-1.4c.8 0 1.4.6 1.4 1.4s-.6 1.4-1.4 1.4zM21 82.1c0 1.1.8 1.9 1.9 1.9s1.9-.8 1.9-1.9v-7.6c0-.2 0-.3-.1-.4 2-.7 3.3-2.6 3.3-4.9s-1.4-4.1-3.3-4.9V49c0-1.1-.8-1.9-1.9-1.9s-1.9.8-1.9 1.9v15.5c-2 .7-3.3 2.6-3.3 4.9s1.4 4.1 3.3 4.9c0 .1-.1.3-.1.4v7.6c0-.2.2-.2.2-.2zm1.9-14.2c.8 0 1.4.6 1.4 1.4s-.6 1.4-1.4 1.4-1.4-.6-1.4-1.4.6-1.4 1.4-1.4z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M41.266 22.992c0-3.945-2.403-7.035-5.664-8.406V3.262C35.602 1.372 34.23 0 32.344 0s-3.262 1.371-3.262 3.262v11.324c-3.43 1.2-5.66 4.46-5.66 8.406 0 3.945 2.402 7.035 5.66 8.406 0 .172-.172.516-.172.688V60.57c0 1.887 1.375 3.258 3.262 3.258s3.258-1.371 3.258-3.258V31.914c0-.344 0-.516-.168-.687 3.601-1.028 6.004-4.29 6.004-8.235zm-9.094 2.574c-1.371 0-2.402-1.03-2.402-2.402 0-1.375 1.03-2.402 2.402-2.402s2.402 1.027 2.402 2.402c.172 1.2-1.031 2.402-2.402 2.402zM58.254 3.602c0-1.887-1.375-3.258-3.262-3.258s-3.262 1.37-3.262 3.258v26.597c-3.43 1.2-5.66 4.461-5.66 8.406 0 3.946 2.403 7.036 5.66 8.407 0 .172-.171.515-.171.687v13.04c0 1.89 1.375 3.261 3.261 3.261 1.887 0 3.262-1.371 3.262-3.262V47.7c0-.344 0-.515-.172-.687 3.43-1.2 5.66-4.461 5.66-8.407 0-3.945-2.402-7.035-5.66-8.406V3.602zm-3.262 37.406c-1.37 0-2.402-1.028-2.402-2.403 0-1.37 1.031-2.402 2.402-2.402 1.371 0 2.403 1.031 2.403 2.402 0 1.375-1.032 2.403-2.403 2.403zm-48.73 19.39c0 1.887 1.375 3.258 3.261 3.258 1.887 0 3.258-1.37 3.258-3.258V47.355c0-.343 0-.511-.172-.683 3.434-1.203 5.664-4.461 5.664-8.41 0-3.946-2.402-7.035-5.664-8.407V3.602c0-1.887-1.37-3.258-3.257-3.258S6.09 1.714 6.09 3.602v26.597C2.66 31.4.43 34.66.43 38.605c0 3.946 2.402 7.036 5.66 8.407 0 .172-.172.515-.172.687v13.04c0-.34.344-.34.344-.34zm3.261-24.367c1.372 0 2.403 1.032 2.403 2.403 0 1.375-1.031 2.402-2.403 2.402-1.375 0-2.402-1.027-2.402-2.402 0-1.371 1.027-2.403 2.402-2.403zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cfm.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#679eb2}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm6.5.3h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4H19V6.4zm10.5 0h3.6l1.3 6c.2.9.4 2.4.4 2.4h.2s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3z" fill="#fff"/><path d="M31.5 81.8c-7.4 0-10.8-7.1-10.8-14.9C20.6 59.2 24 52 31.5 52c2.3 0 4.2.6 5.7 1.6l-1 2.4c-1.1-.7-2.6-1.2-4.2-1.2-5.2 0-7.3 6-7.3 12.1 0 6 2.1 12 7.2 12 1.6 0 3.2-.5 4.2-1.2l1 2.5c-1.5 1-3.3 1.6-5.6 1.6zM46.4 61v20.3h-3.7V61h-2.6v-2.3h2.6v-3.2c0-4.3 2.4-7.2 6.9-7.2h.8v2.4h-.3c-2 0-3.7 1-3.7 4.6v3.3h3.9V61h-3.9z" fill="#679eb2" stroke="#679eb2" stroke-width="1.25" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M11.427 34.125c-7.399 0-10.8-7.1-10.8-14.9-.099-7.7 3.3-14.9 10.8-14.9 2.3 0 4.2.6 5.7 1.6l-1 2.4c-1.1-.7-2.6-1.2-4.2-1.2-5.2 0-7.3 6-7.3 12.1 0 6 2.1 12 7.2 12 1.6 0 3.2-.5 4.2-1.2l1 2.5c-1.5 1-3.3 1.6-5.6 1.6zm14.901-20.8v20.3h-3.701v-20.3h-2.599v-2.3h2.599v-3.2c0-4.3 2.4-7.2 6.9-7.2h.8v2.4h-.3c-2 0-3.699 1-3.699 4.6v3.3h3.899v2.4zm0 0" fill="#679eb2" stroke="#679eb2" stroke-miterlimit="10" stroke-width="1.25" transform="matrix(1.84155 0 0 1.8314 0 .18)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cfml.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#679eb2}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.9-34.8c1.1 0 2.3.4 3.2 1.2l-.9 2.1c-.4-.5-1.4-1-2.2-1-2.3 0-3.5 2.2-3.5 4.9 0 2.8 1.3 5.2 3.5 5.2 1 0 1.8-.5 2.4-1l.9 2.1c-.8.7-1.9 1.3-3.5 1.3-3.5 0-5.6-3.2-5.6-7.4-.1-4.3 2.1-7.4 5.7-7.4zm4.8.3h6.1v2.2H19v4.1h3.2V15H19v5.8h-2.2V6.5zm8.1 0h2.5l1.8 6.9c.2.9.4 2.2.4 2.2h.1s.2-1.3.4-2.2l1.8-6.9h2.5l.8 14.2H33l-.4-7.9c-.1-.9 0-2.2 0-2.2h-.1s-.2 1.4-.4 2.3l-1.4 5.4h-2.2L27 12.9c-.2-.8-.4-2.3-.4-2.3h-.1s.1 1.3 0 2.2l-.5 7.9h-2.1l.9-14.2zm12.1 0h2.2v12h4.2v2.2h-6.5V6.5z" fill="#fff"/><path d="M31.5 81.8c-7.4 0-10.8-7.1-10.8-14.9C20.6 59.2 24 52 31.5 52c2.3 0 4.2.6 5.7 1.6l-1 2.4c-1.1-.7-2.6-1.2-4.2-1.2-5.2 0-7.3 6-7.3 12.1 0 6 2.1 12 7.2 12 1.6 0 3.2-.5 4.2-1.2l1 2.5c-1.5 1-3.3 1.6-5.6 1.6zM46.4 61v20.3h-3.7V61h-2.6v-2.3h2.6v-3.2c0-4.3 2.4-7.2 6.9-7.2h.8v2.4h-.3c-2 0-3.7 1-3.7 4.6v3.3h3.9V61h-3.9z" fill="#679eb2" stroke="#679eb2" stroke-width="1.25" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M11.427 34.125c-7.399 0-10.8-7.1-10.8-14.9-.099-7.7 3.3-14.9 10.8-14.9 2.3 0 4.2.6 5.7 1.6l-1 2.4c-1.1-.7-2.6-1.2-4.2-1.2-5.2 0-7.3 6-7.3 12.1 0 6 2.1 12 7.2 12 1.6 0 3.2-.5 4.2-1.2l1 2.5c-1.5 1-3.3 1.6-5.6 1.6zm14.901-20.8v20.3h-3.701v-20.3h-2.599v-2.3h2.599v-3.2c0-4.3 2.4-7.2 6.9-7.2h.8v2.4h-.3c-2 0-3.699 1-3.699 4.6v3.3h3.899v2.4zm0 0" fill="#679eb2" stroke="#679eb2" stroke-miterlimit="10" stroke-width="1.25" transform="matrix(1.84155 0 0 1.8314 0 .18)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cgi.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm11.8 0c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.7-7.6 6.5-7.6zm7.9.3h3.3v14.3h-3.3V6.4z" fill="#fff"/><path class="st0" d="M16.1 74.1l14.6 9.4v-6.9h25v-5h-25v-6.8zm25.2-18.7h-25v5h25v6.9l14.6-9.4-14.6-9.4z"/></svg>
1
<svg height="64" width="73" xmlns="http://www.w3.org/2000/svg"><path d="M.184 46.813 26.828 64V51.383h45.625v-9.145H26.828V29.805zm45.988-34.196H.547v9.145h45.625v12.617l26.644-17.191L46.172 0zm0 0" fill="#666"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/chm.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#c93}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm5.2.3H21v5.8h3.2V6.4h3.3v14.3h-3.3V15H21v5.7h-3.3V6.4zm12.6 0H34l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H34l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1.1-14.3z"/><path class="st0" d="M52.5 47H27c-3.8 0-7.5 1.5-7.5 6v30h27V53H23.2c0-2.2 1.5-3 3-3h23.2v30l3-3V47z"/><path class="st1" d="M31.8 69.6c0-3.1 3.6-3.6 3.6-5.9 0-1-.9-1.8-2.1-1.8-1.3.1-2.3 1-2.3 1L29.5 61s1.5-1.6 4.1-1.6c2.4 0 4.7 1.5 4.7 4.1 0 3.6-3.8 4-3.8 6.3v.8h-2.7v-1zm0 2.9h2.7V75h-2.7v-2.5z"/></svg>
1
<svg height="64" width="59" xmlns="http://www.w3.org/2000/svg"><path d="M59 0H13.41C6.613 0 0 2.668 0 10.668V64h48.273V10.668H6.613c0-3.914 2.684-5.336 5.367-5.336h41.477v53.336l5.363-5.336V0zm0 0" fill="#c93"/><path d="M21.992 40.18c0-5.512 6.434-6.403 6.434-10.493 0-1.777-1.61-3.199-3.754-3.199-2.324.18-4.11 1.778-4.11 1.778L17.88 24.89s2.683-2.848 7.332-2.848c4.289 0 8.402 2.668 8.402 7.289 0 6.402-6.797 7.113-6.797 11.203v1.422h-4.824zm0 5.152h4.824v4.445h-4.824zm0 0" fill="#fff"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/class.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st3{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path d="M15.1 43v-4.7c1-.1 1.7-.2 2.2-.5.5-.2.9-.7 1.2-1.1.4-.6.6-1.2.8-2.1.1-.7.2-1.7.2-3.3 0-2.6.1-4.3.4-5.4.2-1 .7-1.8 1.2-2.4.6-.6 1.5-1.1 2.7-1.4.8-.2 2-.4 3.7-.4h1.1v4.7c-1.4 0-2.4.1-2.8.3-.4.2-.7.4-1 .8-.2.3-.3.9-.3 1.7 0 .9-.1 2.4-.2 4.7-.1 1.3-.2 2.4-.5 3.3-.3.8-.7 1.4-1.1 2-.4.5-1.1 1.1-1.9 1.6.8.5 1.4 1 1.9 1.5.5.6.9 1.3 1.1 2.2s.5 2 .5 3.4c.1 2.2.1 3.5.1 4.2 0 .9.1 1.4.3 1.8.2.4.6.6 1 .8s1.3.3 2.8.3v4.7h-1.1c-1.7 0-3.2-.1-4-.4-1-.3-1.7-.8-2.4-1.4-.7-.7-1.1-1.4-1.3-2.4-.2-1-.3-2.5-.3-4.6 0-2.4-.1-4-.3-4.7-.3-1.1-.8-1.8-1.3-2.3-.6-.5-1.5-.9-2.7-.9zm42.4 0c-1 .1-1.7.2-2.2.5-.5.2-.9.7-1.2 1.1-.4.6-.6 1.2-.8 2.1-.1.7-.2 1.7-.2 3.3 0 2.6-.1 4.3-.4 5.4-.2 1.1-.7 1.8-1.2 2.4s-1.5 1.1-2.7 1.4c-.8.2-2 .4-3.7.4H44v-4.7c1.4 0 2.3-.1 2.8-.3.5-.2.8-.5 1-.8.2-.3.3-.9.3-1.7 0-.8.1-2.3.2-4.6.1-1.3.3-2.5.6-3.3.3-.9.7-1.5 1.1-2.1.5-.6 1.1-1.1 1.8-1.5-1-.7-1.7-1.2-2.1-1.8-.6-.9-1.1-2-1.2-3.3-.2-1-.3-3-.3-6 0-1-.1-1.6-.3-2-.2-.3-.5-.6-.9-.8-.4-.2-1.3-.3-2.9-.3v-4.6h1.1c1.7 0 3.2.1 4 .4 1 .3 1.7.8 2.4 1.4.7.7 1.1 1.4 1.3 2.4.2 1 .4 2.5.4 4.6 0 2.4.1 3.9.3 4.7.3 1.1.8 1.8 1.3 2.2.6.5 1.5.7 2.7.8-.1 0-.1 4.7-.1 4.7z" fill="#bababa" stroke="#bababa" stroke-miterlimit="10"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M15.1 70.2c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.4 2.4-7.4 6.4-7.4zm6.6.2H25v11.4h4.3v2.9h-7.6V70.4zm12.7 0H38l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2zm7.6 1.7c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10.7 0c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L61 74.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#666"/><path class="st3" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st3" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
<svg height="64" width="48" xmlns="http://www.w3.org/2000/svg"><g fill="#f60" stroke="#f60" stroke-miterlimit="10" stroke-width=".5"><path d="M44.2 75.3c7.2-3.701 3.9-7.3 1.5-6.799-.6.099-.801.2-.801.2s.2-.3.601-.5C50.1 66.6 53.6 73 44 75.5zM37.8 64.8c1.801 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.101 0 .101-13.1 3.401-6.8 10.6" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M39.8 46.499s3.999 4-3.8 10.102c-6.2 4.898-1.4 7.7 0 10.899-3.601-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.201M31 76.8s-1.5.9 1 1.1c3 .299 4.6.299 7.9-.3 0 0 .9.599 2.1 1-7.4 3.3-16.901-.1-11-1.8m-.9-4.2s-1.6 1.199.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.599 1-9.1 2.6-19.199.2-12.698-2" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M47.7 79.9s1.1.9-1.2 1.599c-4.3 1.302-18 1.702-21.8.101-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.199 23.9-3M31.7 68.3s-7 1.702-2.499 2.301c1.9.301 5.699.2 9.2-.101 2.9-.2 5.799-.8 5.799-.8s-1 .4-1.8.901c-7.1 1.9-20.7.999-16.8-.9 3.4-1.6 6.1-1.401 6.1-1.401" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M32.399 85.4c6.901.4 17.502-.2 17.7-3.5 0 0-.499 1.2-5.699 2.2-5.899 1.1-13.101 1-17.5.3.1 0 1 .7 5.499 1" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cmd.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.1-34.9c1.2 0 2.5.4 3.4 1.2l-1.3 2.8c-.4-.5-1.2-.9-2-.9-2 0-3.1 1.9-3.1 4.2 0 2.3 1.1 4.4 3 4.4.9 0 1.6-.5 2.2-1l1.3 2.8c-.9.7-1.9 1.3-3.7 1.3-3.8 0-6-3.1-6-7.4.1-4.2 2.4-7.4 6.2-7.4zm6.2.3h3.5l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.5l.9 14.3h-2.9l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1h-3l-.8-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-2.9l.9-14.3zm13.9 0h4c3.5 0 5.6 2.6 5.6 7.1s-2.1 7.2-5.6 7.2h-4V6.4zM36 17.8c1.6 0 2.5-1.5 2.5-4.3s-.9-4.2-2.5-4.2h-.8v8.5h.8z" fill="#fff"/><path class="st0" d="M54.8 46.8h-38v38h38v-38zm-30.4 7.5h-3.8v-3.8h3.8v3.8zm26.6 0H28.1v-3.8H51v3.8zm0 26.6H20.5V58.2H51v22.7z"/><path class="st0" d="M26.5 61.4l-2.7 2.7 4.4 4.4-4.4 4.3 2.7 2.7 7.1-7zm6.3 12.8h7.6V78h-7.6z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M64 0H0v64h64zM12.8 12.633H6.399V6.23h6.403zm44.802 0h-38.57V6.23h38.57zm0 44.797H6.23V19.2h51.372zm0 0"/><path d="m16.336 24.59-4.547 4.547 7.41 7.41-7.41 7.242 4.547 4.547 11.957-11.79zm10.613 21.558h12.797v6.399H26.95zm0 0"/></g></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/code-workspace.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M29.5 51.6c-1.2 1-2.4 1.8-3.5 2.7-2.4 1.8-4.7 3.5-7.1 5.4-.3.3-.6.3-.9.1-.5-.3-1-.5-1.5-.8-.3-.1-.4-.4-.4-.7V39.7c0-.2.2-.5.4-.6.6-.3 1.1-.6 1.6-.9.3-.2.6 0 .8.2 1.9 1.5 3.9 3 5.8 4.4l4.8 3.6.3-.3c5.8-5.6 11.6-11.3 17.4-16.9.3-.3.6-.3 1-.2 2.5 1 4.9 2 7.4 3 .2.1.3.3.4.5.1.1 0 .3 0 .5v32.1c0 .8 0 .8-.8 1.1-2.3 1-4.7 1.8-7 2.8-.4.2-.7.1-1-.2C41.4 63.1 35.7 57.5 30 52c-.1-.1-.3-.2-.5-.4zm16.7 5.1V41.4c-3.4 2.6-6.8 5-10.2 7.6 3.4 2.6 6.8 5.1 10.2 7.7zM24.8 49c-1.7-1.5-3.3-3.1-5.1-4.6v9.2c1.8-1.5 3.4-3 5.1-4.6z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
D src/main/resources/com/keenwrite/ui/fonts/icons/codekit.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M13 74.5c.9 0 1.8.3 2.5.8l-1 2c-.3-.3-.9-.6-1.5-.6-1.5 0-2.3 1.3-2.3 2.9s.8 3.1 2.2 3.1c.7 0 1.2-.3 1.6-.7l1 1.9c-.6.5-1.4.9-2.8.9-2.8 0-4.4-2.2-4.4-5.2.2-2.9 1.8-5.1 4.7-5.1zm8 0c2.6 0 4.1 2.2 4.1 5.1 0 3-1.5 5.2-4.1 5.2s-4.1-2.3-4.1-5.2c0-2.9 1.4-5.1 4.1-5.1zm0 8.2c1.2 0 1.7-1.3 1.7-3 0-1.8-.5-2.9-1.7-2.9s-1.7 1.2-1.7 2.9c-.1 1.7.5 3 1.7 3zm6.2-8h3c2.6 0 4.1 1.8 4.1 5s-1.6 5-4.1 5h-3v-10zm2.9 8c1.2 0 1.8-1 1.8-3 0-1.9-.7-3-1.8-3h-.6v6h.6zm6.4-8h5v2h-2.7v1.9H41v2h-2.2v2h2.9v2h-5.2v-9.9zm7.3 0h2.3v3.9h.4l1.6-3.9h2.5l-2 4.8 2.1 5.2h-2.6l-1.6-4.1h-.4v4.1h-2.3v-10zm8.7 0h2.3v10h-2.3v-10zm6.5 2h-2.2v-2h6.7v2h-2.2v8H59v-8z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/><path d="M25.2 60.2c-.7 0-1.4-.3-1.9-.8L12.8 48.9c-1-1-1-2.7 0-3.7l10.6-10.6c1-1 2.7-1 3.7 0s1 2.7 0 3.7L18.4 47l8.7 8.7c1 1 1 2.7 0 3.7-.5.5-1.2.8-1.9.8zm21.6 0c-.7 0-1.4-.3-1.9-.8-1-1-1-2.7 0-3.7l8.7-8.7-8.7-8.7c-1-1-1-2.7 0-3.7s2.7-1 3.7 0l10.6 10.6c1 1 1 2.7 0 3.7L48.7 59.4c-.6.5-1.2.8-1.9.8z" fill="#bababa" stroke="#bababa" stroke-width=".5" stroke-miterlimit="10"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/coffee.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#28334c}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M14.9 70.2c1.1 0 2.4.4 3.2 1.2l-1.2 2.8c-.4-.5-1.2-.9-1.9-.9-1.9 0-2.9 1.9-2.9 4.2 0 2.3 1 4.4 2.9 4.4.9 0 1.5-.5 2.1-1l1.2 2.8c-.8.7-1.8 1.3-3.5 1.3-3.6 0-5.7-3.1-5.7-7.4 0-4.4 2.2-7.4 5.8-7.4zm9.3 0c3.4 0 5.3 3.1 5.3 7.3 0 4.2-1.9 7.5-5.3 7.5s-5.3-3.2-5.3-7.5c.1-4.2 2-7.3 5.3-7.3zm0 11.6c1.5 0 2.2-1.8 2.2-4.3s-.7-4.2-2.2-4.2S22 75 22 77.5s.7 4.3 2.2 4.3zm7.2-11.4h6.4v2.9h-3.5v3.1h2.9v2.9h-2.8v5.4h-3V70.4zm8.2 0H46v2.9h-3.5v3.1h2.8v2.9h-2.8v5.4h-3l.1-14.3zm8.1 0h6.5v2.9h-3.5V76h2.8v2.9h-2.8v2.9h3.7v2.9h-6.6V70.4h-.1zm8.5 0h6.5v2.9h-3.5V76H62v2.9h-2.8v2.9h3.7v2.9h-6.7V70.4z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm-17.1 7.5c4-.3 5.1-2.9 9.8-3.3 2.3-.2 3.7.3 3.9 1.1.1.7-1 1.3-2.4 1.4-1.9.2-2.7-.5-2.9-1.2-1.4.1-1.6.7-1.6 1.2.1.8 1.9 1.6 4.8 1.3 3.3-.3 4.4-1.6 4.2-2.9-.3-1.7-2.9-3.1-7.5-2.7-5.9.5-5.9 3.2-9.8 3.6-1.6.1-2.6-.2-2.7-.9-.1-.6.7-1 1.6-1 .9-.1 1.9.1 2.5.3.4-.2.5-.4.4-.6-.1-.6-1.4-.9-2.9-.7-3 .3-3 1.6-2.9 2.2.4 1.4 2.6 2.4 5.5 2.2zm19.9 6.7c-3.7.9-8.4 1.4-14 1.4-5.8 0-10.5-.6-14.1-1.4-3.3-.9-5-1.8-5.7-2.7.3 2.1.9 4.2 1.6 6.2-.8.5-1.6 1.2-2.3 2-1.3 1.6-1.9 3.5-1.8 5.4.1 1.9 1 3.4 2.5 4.6 1.5 1.2 3.2 1.5 5 1.2.7-.1 1.5-.5 2.2-.7-1.5 0-2.8-.5-4.1-1.5-1.4-1-2.4-2.5-2.6-4.2-.3-1.6 0-3.2.9-4.5.2-.3.4-.5.6-.7.5 1.3 1.1 2.5 1.8 3.7 1.4 2.1 2.8 4 4.2 6 .6 1.2 1 2.4 1.3 3.5.9 1.3 2.2 2.2 3.9 2.7 2 .7 4.1 1 6.3 1h.2c2.1 0 4.4-.3 6.5-1 1.5-.5 2.8-1.4 3.8-2.7h.1c.2-1 .6-2.3 1.2-3.5 1.4-2 2.8-3.9 4.2-6 1.9-3.4 3.2-7.3 3.9-11.5-.6 1.1-2.4 2-5.6 2.7zm-28.1-2.9c3.7.9 8.4 1.4 14 1.4 5.8 0 10.4-.5 14-1.4 3.9-.9 5.8-2.1 5.8-3.3 0-.9-.9-1.6-2.4-2.2.3.2.6.6.6 1 0 1.2-1.8 2.1-5.3 2.9-3.3.7-7.5 1.2-12.6 1.2-4.9 0-9.3-.5-12.5-1.2-3.4-.9-5.2-1.8-5.2-2.9 0-.5.2-.9.9-1.4-2.1.9-3.3 1.5-3.3 2.6.1 1.2 2 2.4 6 3.3z"/></svg>
1
<svg height="64" width="79" xmlns="http://www.w3.org/2000/svg"><path d="M30.86 9.86c7.523-.567 9.59-5.458 18.43-6.212 4.323-.375 6.956.567 7.331 2.07.188 1.317-1.879 2.446-4.512 2.634-3.574.378-5.078-.938-5.453-2.258-2.633.187-3.008 1.32-3.008 2.258.188 1.507 3.57 3.011 9.024 2.449 6.207-.567 8.277-3.012 7.898-5.457-.562-3.2-5.453-5.836-14.101-5.082-11.098.941-11.098 6.02-18.43 6.773-3.008.188-4.89-.375-5.078-1.691-.188-1.13 1.316-1.883 3.008-1.883 1.695-.188 3.574.187 4.703.562.754-.375.941-.75.754-1.128-.192-1.13-2.633-1.692-5.457-1.317-5.64.567-5.64 3.012-5.453 4.14.754 2.634 4.89 4.516 10.343 4.141zM68.28 22.468c-6.957 1.691-15.797 2.633-26.328 2.633-10.906 0-19.742-1.13-26.512-2.633-6.207-1.696-9.402-3.39-10.718-5.082.562 3.953 1.691 7.902 3.007 11.668-1.503.941-3.007 2.257-4.324 3.761C.961 35.828-.168 39.402.02 42.98c.187 3.575 1.882 6.399 4.703 8.657 2.82 2.258 6.015 2.824 9.402 2.258 1.316-.188 2.82-.942 4.137-1.317-2.82 0-5.266-.941-7.711-2.824-2.633-1.883-4.512-4.703-4.89-7.902-.563-3.012 0-6.024 1.694-8.47.375-.566.75-.94 1.125-1.316.942 2.446 2.07 4.704 3.387 6.961 2.633 3.953 5.266 7.528 7.899 11.293 1.129 2.258 1.879 4.516 2.445 6.586 1.691 2.446 4.137 4.14 7.332 5.082 3.762 1.317 7.71 1.88 11.848 1.88h.375c3.949 0 8.273-.563 12.222-1.88a14.826 14.826 0 0 0 7.149-5.082h.187a27.312 27.312 0 0 1 2.258-6.586c2.629-3.765 5.262-7.34 7.895-11.293 3.574-6.398 6.02-13.738 7.335-21.64-1.128 2.07-4.515 3.761-10.53 5.082zm-52.84-5.457c6.957 1.691 15.793 2.633 26.325 2.633 10.906 0 19.558-.942 26.328-2.633C75.426 15.316 79 13.059 79 10.8c0-1.696-1.691-3.012-4.512-4.14.563.374 1.125 1.128 1.125 1.882 0 2.258-3.383 3.95-9.965 5.457-6.207 1.316-14.101 2.258-23.695 2.258-9.21 0-17.488-.942-23.504-2.258-6.394-1.695-9.777-3.387-9.777-5.457 0-.941.375-1.695 1.691-2.637-3.949 1.696-6.207 2.824-6.207 4.895.188 2.258 3.762 4.515 11.285 6.21zm0 0" fill="#28334c"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/coffeelintignore.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm2.5 10c-8-8-21-8-29 0s-8 21 0 29 21 8 29 0 8-21 0-29zM23.3 58.7c-3.8-5.9-3.1-13.8 2-18.9s13-5.8 18.9-2L23.3 58.7zm4.5 4.5l20.9-20.9c3.8 5.9 3.1 13.8-2 18.9s-13 5.8-18.9 2z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M54.633 9.367C42.145-3.12 21.855-3.12 9.367 9.367s-12.488 32.778 0 45.266 32.778 12.488 45.266 0 12.488-32.778 0-45.266zM12.176 44.801c-5.934-9.211-4.84-21.543 3.12-29.504s20.294-9.055 29.505-3.121zm7.023 7.023L51.824 19.2c5.934 9.211 4.84 21.543-3.12 29.504s-20.294 9.055-29.505 3.121zm0 0" fill="#bababa"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/com.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm10.3 0c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5S17 17.7 17 13.4c-.1-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm8.4-11.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H42l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H35l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1-14.3z" fill="#fff"/><path class="st0" d="M54.8 46.8h-38v38h38v-38zm-30.4 7.5h-3.8v-3.8h3.8v3.8zm26.6 0H28.1v-3.8H51v3.8zm0 26.6H20.5V58.2H51v22.7z"/><path class="st0" d="M26.5 61.4l-2.7 2.7 4.4 4.4-4.4 4.3 2.7 2.7 7.1-7zm6.3 12.8h7.6V78h-7.6z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M64 0H0v64h64zM12.8 12.633H6.399V6.23h6.403zm44.802 0h-38.57V6.23h38.57zm0 44.797H6.23V19.2h51.372zm0 0"/><path d="m16.336 24.59-4.547 4.547 7.41 7.41-7.41 7.242 4.547 4.547 11.957-11.79zm10.613 21.558h12.797v6.399H26.95zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/compile.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M12.8 70.2c1 0 2.1.4 2.9 1.2l-1.1 2.8c-.3-.5-1-.9-1.7-.9-1.7 0-2.6 1.9-2.6 4.2 0 2.3.9 4.4 2.5 4.4.8 0 1.3-.5 1.8-1l1.1 2.8c-.7.7-1.6 1.3-3.2 1.3-3.2 0-5-3.1-5-7.4.1-4.4 2-7.4 5.3-7.4zm7.9 0c3 0 4.7 3.1 4.7 7.3 0 4.2-1.7 7.5-4.7 7.5S16 81.7 16 77.5s1.7-7.3 4.7-7.3zm0 11.6c1.4 0 2-1.8 2-4.3s-.6-4.2-2-4.2-2 1.7-2 4.2.6 4.3 2 4.3zm6.4-11.4H30l1.1 6c.2.9.3 2.4.3 2.4s.2-1.5.3-2.4l1.1-6h2.9l.7 14.3H34l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.7 4.1H30l-.7-4.1c-.2-.9-.4-2.4-.4-2.4h.1s.1 1.3 0 2.4l-.3 6.4h-2.4l.8-14.3zm10.8 0h3.6c2.1 0 3.5 2 3.5 4.9s-1.4 5-3.5 5h-1v4.4h-2.6V70.4zm3.1 7c.8 0 1.3-.9 1.3-2.1s-.5-2-1.2-2h-.5v4.1h.4zm5.1-7h2.6v14.3h-2.6V70.4zm4.4 0h2.6v11.4h3.4v2.9h-6.1l.1-14.3zm7 0h5.7v2.9h-3.1V76h2.5v2.9h-2.5v2.9h3.3v2.9h-5.9V70.4z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm4 27.4H15m37.5 4.5V35.2H57v27.3H16V35.2h4.5v22.7h32zM25.3 23.7h22.3L36.4 34.9c-3.6-3.6-7.4-7.4-11.1-11.2z"/><path class="st2" d="M29.7 44.2v-4.5h4.5v4.5h-4.5zm13.6 0h-4.5v-4.5h4.5v4.5zm-18.2 4.6h4.5v4.5h-4.5v-4.5zm18.3 4.5v-4.5h4.5v4.5h-4.5zm-4.7-4.5v4.5h-4.5v-4.5h4.5z"/></svg>
1
<svg height="64" width="68" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M59.906 48.902H0m60.715 7.387V19.035H68v44.8H1.617v-44.8h7.29V56.29zM16.675.164h36.106L34.648 18.543C28.82 12.637 22.668 6.398 16.676.164zm0 0"/><path d="M23.8 33.805v-7.383h7.286v7.383zm22.02 0h-7.285v-7.383h7.285zm-29.468 7.55h7.285v7.383h-7.285zm29.628 7.383v-7.383h7.286v7.383zm-7.609-7.383v7.383h-7.285v-7.383zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/conf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm5.6-34.8c1.1 0 2.2.4 3 1.2l-.9 2.1c-.4-.5-1.3-1-2.1-1-2.2 0-3.3 2.2-3.3 4.9 0 2.8 1.2 5.2 3.3 5.2.9 0 1.7-.5 2.3-1l.9 2.1c-.8.7-1.8 1.3-3.4 1.3-3.4 0-5.3-3.2-5.3-7.4 0-4.3 2-7.4 5.5-7.4zm8.8 0c3.1 0 5 3 5 7.3s-2 7.4-5 7.4c-3.1 0-5-3.1-5-7.4-.1-4.2 1.9-7.3 5-7.3zm0 12.4c1.8 0 2.8-2 2.8-5.1 0-3-1.1-4.9-2.8-4.9-1.8 0-2.8 1.9-2.8 4.9-.1 3.1 1 5.1 2.8 5.1zm6.7-12.1h2.3l3.2 8c.3.9.6 2.2.6 2.2h.1s-.1-1.3-.1-2.2v-8h2v14.2H33l-3.2-8.1c-.3-.9-.6-2.2-.6-2.2H29s.1 1.3.1 2.2v8h-2V6.5zm10.3 0h5.8v2.2h-3.6v4.1h3V15h-3v5.8h-2.1V6.5h-.1z" fill="#fff"/><path class="st0" d="M41.4 60.3c0-2.3-1.4-4.1-3.3-4.9v-6.6c0-1.1-.8-1.9-1.9-1.9-1.1 0-1.9.8-1.9 1.9v6.6c-2 .7-3.3 2.6-3.3 4.9 0 2.3 1.4 4.1 3.3 4.9 0 .1-.1.3-.1.4v16.6c0 1.1.8 1.9 1.9 1.9 1.1 0 1.9-.8 1.9-1.9V65.5c0-.2 0-.3-.1-.4 2.1-.6 3.5-2.5 3.5-4.8zm-5.3 1.5c-.8 0-1.4-.6-1.4-1.4 0-.8.6-1.4 1.4-1.4.8 0 1.4.6 1.4 1.4.1.7-.6 1.4-1.4 1.4zM51.3 49c0-1.1-.8-1.9-1.9-1.9-1.1 0-1.9.8-1.9 1.9v15.5c-2 .7-3.3 2.6-3.3 4.9s1.4 4.1 3.3 4.9c0 .1-.1.3-.1.4v7.6c0 1.1.8 1.9 1.9 1.9 1.1 0 1.9-.8 1.9-1.9v-7.6c0-.2 0-.3-.1-.4 2-.7 3.3-2.6 3.3-4.9s-1.4-4.1-3.3-4.9V49h.2zm-1.9 21.8c-.8 0-1.4-.6-1.4-1.4s.6-1.4 1.4-1.4c.8 0 1.4.6 1.4 1.4s-.6 1.4-1.4 1.4zM21 82.1c0 1.1.8 1.9 1.9 1.9s1.9-.8 1.9-1.9v-7.6c0-.2 0-.3-.1-.4 2-.7 3.3-2.6 3.3-4.9s-1.4-4.1-3.3-4.9V49c0-1.1-.8-1.9-1.9-1.9s-1.9.8-1.9 1.9v15.5c-2 .7-3.3 2.6-3.3 4.9s1.4 4.1 3.3 4.9c0 .1-.1.3-.1.4v7.6c0-.2.2-.2.2-.2zm1.9-14.2c.8 0 1.4.6 1.4 1.4s-.6 1.4-1.4 1.4-1.4-.6-1.4-1.4.6-1.4 1.4-1.4z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M41.266 22.992c0-3.945-2.403-7.035-5.664-8.406V3.262C35.602 1.372 34.23 0 32.344 0s-3.262 1.371-3.262 3.262v11.324c-3.43 1.2-5.66 4.46-5.66 8.406 0 3.945 2.402 7.035 5.66 8.406 0 .172-.172.516-.172.688V60.57c0 1.887 1.375 3.258 3.262 3.258s3.258-1.371 3.258-3.258V31.914c0-.344 0-.516-.168-.687 3.601-1.028 6.004-4.29 6.004-8.235zm-9.094 2.574c-1.371 0-2.402-1.03-2.402-2.402 0-1.375 1.03-2.402 2.402-2.402s2.402 1.027 2.402 2.402c.172 1.2-1.031 2.402-2.402 2.402zM58.254 3.602c0-1.887-1.375-3.258-3.262-3.258s-3.262 1.37-3.262 3.258v26.597c-3.43 1.2-5.66 4.461-5.66 8.406 0 3.946 2.403 7.036 5.66 8.407 0 .172-.171.515-.171.687v13.04c0 1.89 1.375 3.261 3.261 3.261 1.887 0 3.262-1.371 3.262-3.262V47.7c0-.344 0-.515-.172-.687 3.43-1.2 5.66-4.461 5.66-8.407 0-3.945-2.402-7.035-5.66-8.406V3.602zm-3.262 37.406c-1.37 0-2.402-1.028-2.402-2.403 0-1.37 1.031-2.402 2.402-2.402 1.371 0 2.403 1.031 2.403 2.402 0 1.375-1.032 2.403-2.403 2.403zm-48.73 19.39c0 1.887 1.375 3.258 3.261 3.258 1.887 0 3.258-1.37 3.258-3.258V47.355c0-.343 0-.511-.172-.683 3.434-1.203 5.664-4.461 5.664-8.41 0-3.946-2.402-7.035-5.664-8.407V3.602c0-1.887-1.37-3.258-3.257-3.258S6.09 1.714 6.09 3.602v26.597C2.66 31.4.43 34.66.43 38.605c0 3.946 2.402 7.036 5.66 8.407 0 .172-.172.515-.172.687v13.04c0-.34.344-.34.344-.34zm3.261-24.367c1.372 0 2.403 1.032 2.403 2.403 0 1.375-1.031 2.402-2.403 2.402-1.375 0-2.402-1.027-2.402-2.402 0-1.371 1.027-2.403 2.402-2.403zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/config.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M42.3 35.7c0-2.5-1.5-4.5-3.7-5.4V23c0-1.2-.9-2.1-2.1-2.1s-2.1.9-2.1 2.1v7.3c-2.2.8-3.7 2.9-3.7 5.4s1.5 4.6 3.7 5.4c0 .1-.1.3-.1.4v18.4c0 1.2.9 2.1 2.1 2.1s2.1-.9 2.1-2.1V41.5c0-.2 0-.3-.1-.4 2.4-.8 3.9-2.9 3.9-5.4zm-5.8 1.6c-.9 0-1.6-.7-1.6-1.6s.7-1.6 1.6-1.6 1.6.7 1.6 1.6-.7 1.6-1.6 1.6zm16.8-14.2c0-1.2-.9-2.1-2.1-2.1s-2.1.9-2.1 2.1v17.2c-2.2.8-3.7 2.9-3.7 5.4s1.5 4.6 3.7 5.4c0 .1-.1.3-.1.4v8.4c0 1.2.9 2.1 2.1 2.1s2.1-.9 2.1-2.1v-8.4c0-.2 0-.3-.1-.4 2.2-.8 3.7-2.9 3.7-5.4s-1.5-4.5-3.7-5.4V23.1h.2zm-2.1 24.2c-.9 0-1.6-.7-1.6-1.6s.7-1.6 1.6-1.6 1.6.7 1.6 1.6-.7 1.6-1.6 1.6zM19.7 59.9c0 1.2.9 2.1 2.1 2.1s2.1-.9 2.1-2.1v-8.4c0-.2 0-.3-.1-.4 2.2-.8 3.7-2.9 3.7-5.4s-1.5-4.5-3.7-5.4V23.1c0-1.2-.9-2.1-2.1-2.1s-2.1.9-2.1 2.1v17.2c-2.2.8-3.7 2.9-3.7 5.4s1.5 4.6 3.7 5.4c0 .1-.1.3-.1.4v8.4h.2zm2.1-15.8c.9 0 1.6.7 1.6 1.6s-.7 1.6-1.6 1.6-1.6-.7-1.6-1.6.7-1.6 1.6-1.6z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M13.2 70.2c1.1 0 2.4.4 3.2 1.2l-1.2 2.8c-.4-.5-1.2-.9-1.9-.9-1.9 0-2.9 1.9-2.9 4.2 0 2.3 1 4.4 2.9 4.4.9 0 1.5-.5 2.1-1l1.2 2.8c-.8.7-1.8 1.3-3.5 1.3-3.6 0-5.7-3.1-5.7-7.4 0-4.4 2.1-7.4 5.8-7.4zm9.3 0c3.4 0 5.3 3.1 5.3 7.3 0 4.2-1.9 7.5-5.3 7.5s-5.3-3.2-5.3-7.5c.1-4.2 1.9-7.3 5.3-7.3zm0 11.6c1.5 0 2.2-1.8 2.2-4.3s-.7-4.2-2.2-4.2-2.2 1.7-2.2 4.2.7 4.3 2.2 4.3zm7.2-11.4h3.1L35 77c.4 1 .6 2.4.6 2.4h.1s-.2-1.5-.2-2.4v-6.6h2.8v14.3h-3.1L33 78.1c-.3-1-.6-2.4-.6-2.4h-.1s.2 1.5.2 2.4v6.6h-2.8V70.4zm11.1 0h6.4v2.9h-3.5v3.1h2.8v2.9h-2.8v5.4h-3l.1-14.3zm8.1 0h3v14.3h-3V70.4zm10.5-.2c1.2 0 2.6.4 3.5 1.3l-1.3 2.8c-.5-.6-1.3-.9-2.1-.9-2 0-2.8 1.9-2.8 4.2 0 2.6 1.1 4.3 2.6 4.3.6 0 1.1-.2 1.5-.6v-1.7h-1.3v-2.9h3.9v8.1h-2.3v-.9c-.5.7-1.4 1.2-2.4 1.2-2.5 0-5-2.7-5-7.3s2.2-7.6 5.7-7.6z" fill="#666"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M41.266 22.992c0-3.945-2.403-7.035-5.664-8.406V3.262C35.602 1.372 34.23 0 32.344 0s-3.262 1.371-3.262 3.262v11.324c-3.43 1.2-5.66 4.46-5.66 8.406 0 3.945 2.402 7.035 5.66 8.406 0 .172-.172.516-.172.688V60.57c0 1.887 1.375 3.258 3.262 3.258s3.258-1.371 3.258-3.258V31.914c0-.344 0-.516-.168-.687 3.601-1.028 6.004-4.29 6.004-8.235zm-9.094 2.574c-1.371 0-2.402-1.03-2.402-2.402 0-1.375 1.03-2.402 2.402-2.402s2.402 1.027 2.402 2.402c.172 1.2-1.031 2.402-2.402 2.402zM58.254 3.602c0-1.887-1.375-3.258-3.262-3.258s-3.262 1.37-3.262 3.258v26.597c-3.43 1.2-5.66 4.461-5.66 8.406 0 3.946 2.403 7.036 5.66 8.407 0 .172-.171.515-.171.687v13.04c0 1.89 1.375 3.261 3.261 3.261 1.887 0 3.262-1.371 3.262-3.262V47.7c0-.344 0-.515-.172-.687 3.43-1.2 5.66-4.461 5.66-8.407 0-3.945-2.402-7.035-5.66-8.406V3.602zm-3.262 37.406c-1.37 0-2.402-1.028-2.402-2.403 0-1.37 1.031-2.402 2.402-2.402 1.371 0 2.403 1.031 2.403 2.402 0 1.375-1.032 2.403-2.403 2.403zm-48.73 19.39c0 1.887 1.375 3.258 3.261 3.258 1.887 0 3.258-1.37 3.258-3.258V47.355c0-.343 0-.511-.172-.683 3.434-1.203 5.664-4.461 5.664-8.41 0-3.946-2.402-7.035-5.664-8.407V3.602c0-1.887-1.37-3.258-3.257-3.258S6.09 1.714 6.09 3.602v26.597C2.66 31.4.43 34.66.43 38.605c0 3.946 2.402 7.036 5.66 8.407 0 .172-.172.515-.172.687v13.04c0-.34.344-.34.344-.34zm3.261-24.367c1.372 0 2.403 1.032 2.403 2.403 0 1.375-1.031 2.402-2.403 2.402-1.375 0-2.402-1.027-2.402-2.402 0-1.371 1.027-2.403 2.402-2.403zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cpp.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><g fill="#999"><path d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/></g><path fill="#FFF" d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2s1.2 4.4 3.2 4.4c1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm6.5.3h4.5c2.6 0 4.4 2 4.4 4.9s-1.7 5-4.4 5h-1.2v4.4H19V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm7.8-7h4.5c2.6 0 4.4 2 4.4 4.9s-1.7 5-4.4 5H34v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2H34v4.1h.6z"/><path fill="#999" d="M24.6 54c5.6 0 8.3 3.1 8.3 3.1l-2.5 5.4s-2.2-2.2-5.3-2.2c-3.8 0-5.6 2.6-5.6 5.6 0 3 1.9 5.8 5.6 5.8 3.5 0 5.5-2.7 5.5-2.7l3 5.2s-2.9 3.7-8.9 3.7c-7.1 0-11.8-5-11.8-11.9-.1-6.8 4.7-12 11.7-12zm10.8 10.3h4v-4.5h3.3v4.5h4v3.4h-4v4.5h-3.3v-4.5h-4v-3.4zm12.7 0h4v-4.5h3.3v4.5h4v3.4h-4v4.5H52v-4.5h-4l.1-3.4z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="43"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M21.02 0c9.93 0 14.718 5.578 14.718 5.578l-4.433 9.715s-3.903-3.957-9.399-3.957c-6.738 0-9.93 4.676-9.93 10.074 0 5.395 3.368 10.434 9.93 10.434 6.207 0 9.754-4.856 9.754-4.856l5.32 9.356S31.836 43 21.195 43C8.605 43 .273 34.004.273 21.59.093 9.355 8.605 0 21.02 0zm19.152 18.531h7.094v-8.093h5.851v8.093h7.094v6.117h-7.094v8.098h-5.851v-8.098h-7.094zm22.523 0h7.094v-8.093h5.852v8.093h7.093v6.117h-7.093v8.098h-6.032v-8.098h-7.093zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cptx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#63b763}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm5.8-34.9c1.1 0 2.4.4 3.2 1.2l-1.2 2.8c-.4-.5-1.2-.9-1.9-.9-1.9.1-2.9 2-2.9 4.2 0 2.3 1 4.4 2.9 4.4.9 0 1.5-.5 2.1-1l1.2 2.8c-.8.7-1.8 1.3-3.5 1.3-3.6 0-5.7-3.1-5.7-7.4 0-4.2 2.1-7.4 5.8-7.4zm4.6.3h4.1c2.4 0 3.9 2 3.9 4.9s-1.6 5-3.9 5h-1.1v4.4h-3V6.4zm3.5 7c.9 0 1.5-.9 1.5-2.1s-.6-2-1.4-2h-.6v4.1h.5zm7.8-4.1h-2.8V6.4h8.6v2.9h-2.8v11.4h-2.9V9.3h-.1zm9.2 4.3l-3.1-7.2H37l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3.2l-3.1 7.2 3 7.1h-3.2l-1-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3h-3.2l3.2-7.1z" fill="#fff"/><path d="M27.9 76.2c-7.4 0-10.9-6.5-10.9-13.5s3.4-13.5 10.9-13.5c2.3 0 4.2.6 5.6 1.4l-1 2.1c-1-.6-2.7-1.1-4.2-1.1-5.2 0-7.2 5.5-7.2 11 0 5.4 2.1 10.9 7.2 10.9 1.6 0 3.1-.5 4.2-1.1l1 2.3c-1.4 1.1-3.2 1.5-5.6 1.5zm17.2 0c-1.3 0-2.7-.2-3.5-.5v8.4H38V56.4c1.9-1 4.4-1.4 7-1.4 6.5 0 10 4 10 10.3 0 6.8-3.9 10.9-9.9 10.9zM44.8 57c-1.1 0-2.4.2-3.2.6v16.1c.7.2 1.6.4 2.8.4 4.6 0 7-3.1 7-8.6-.1-5.2-1.9-8.5-6.6-8.5z" fill="#63b763" stroke="#63b763" stroke-width="2" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M11.9 28C4.5 28 1 21.501 1 14.5 1 7.5 4.4 1 11.9 1c2.3 0 4.2.6 5.6 1.4l-1 2.1c-1-.6-2.7-1.1-4.2-1.1-5.2 0-7.2 5.5-7.2 11 0 5.4 2.101 10.9 7.2 10.9 1.6 0 3.1-.5 4.2-1.1l1 2.3c-1.4 1.1-3.2 1.5-5.6 1.5zM29.1 28c-1.302 0-2.702-.2-3.5-.501v8.4H22V8.2c1.9-1 4.4-1.4 7-1.4 6.5 0 10 4 10 10.3C39 23.9 35.1 28 29.1 28zM28.8 8.8c-1.1 0-2.4.199-3.2.601v16.1c.7.198 1.601.4 2.799.4 4.601 0 7.002-3.102 7.002-8.6-.102-5.201-1.9-8.5-6.601-8.5zm0 0" fill="#63b763" stroke="#63b763" stroke-miterlimit="10" stroke-width="2" transform="matrix(1.725 0 0 1.72973 0 .086)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cr2.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm6.5.3h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5H25l-2-4.8h-.8v4.8H19V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm8.1 6.1c0-5 4.5-5.5 4.5-8.4 0-1-.5-1.4-1.2-1.4-.6 0-1.1.3-1.4.8l-2.2-1.8c.8-1.1 2.3-2.1 4.1-2.1 2.1 0 4.2 1.3 4.2 4.2 0 4.1-4.2 5.4-4.4 7.5h4.6v2.9h-7.9c-.3-.7-.3-1.1-.3-1.7z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/crdownload.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#b4bdcc}</style><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/><path d="M19.7 36c10-11.6 28.5-9.3 35.5 4.3H38.5c-3 0-4.9-.1-7 1-2.5 1.3-4.3 3.7-5 6.5L19.7 36z" opacity=".55" fill="#f44336"/><path d="M28.8 50c0 3.9 3.2 7.1 7.1 7.1S43 53.9 43 50s-3.2-7.1-7.1-7.1c-3.8-.1-7.1 3.2-7.1 7.1z" opacity=".55" fill="#2196f3"/><path d="M38.8 59.4c-4 1.2-8.7-.1-11.3-4.6-2-3.4-7.1-12.4-9.5-16.5C9.7 51 16.9 68.2 31.8 71.1l7-11.7z" opacity=".55" fill="#4caf50"/><path d="M42.6 42.8c3.3 3.1 4.1 8.1 1.8 12-1.7 2.9-7.1 12.1-9.8 16.6 15.4 1 26.7-14.2 21.6-28.6H42.6z" opacity=".55" fill="#ffc107"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/crt.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#696}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm6.5.3h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5H25l-2-4.8h-.8v4.8H19V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm10.4-3.7h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path class="st0" d="M49.2 62.2h-2.6v-5C46.6 51.5 42 47 36.4 47s-10.2 4.6-10.2 10.2v5h-2.6c-1 0-1.8.8-1.8 1.8v17.4c0 1 .8 1.8 1.8 1.8h25.6c1 0 1.8-.8 1.8-1.8V63.9c0-.9-.8-1.7-1.8-1.7zM38.6 76.6c.2.6-.3 1.1-.9 1.1H35c-.6 0-1-.6-.9-1.1l.8-3.2c-1-.5-1.7-1.5-1.7-2.8 0-1.7 1.4-3.1 3.1-3.1 1.7 0 3.1 1.4 3.1 3.1 0 1.2-.7 2.3-1.7 2.8l.9 3.2zm2.9-14.4H31.3v-5c0-2.8 2.3-5.1 5.1-5.1s5.1 2.3 5.1 5.1v5z"/></svg>
1
<svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#696"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/crypt.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M14.8 70.2c1.3 0 2.6.4 3.6 1.2L17 74.2c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.4 2.3-7.4 6.4-7.4zm6 .2h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8H24v4.8h-3.3l.1-14.3zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V77h.6zm9.9 1.8L31 70.4h3.6l1.1 3.4c.3 1 .5 2.1.5 2.1h.1s.2-1.1.5-2.1l1.1-3.4h3.6l-3.6 8.4v5.9h-3.3v-5.9zm8.8-8.4h4.5c2.6 0 4.4 2 4.4 4.9s-1.7 5-4.4 5h-1.2v4.4h-3.3V70.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm9.6-4.1h-3.1v-2.9h9.6v2.9h-3.2v11.4h-3.3V73.3z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm1.9 13.2h-2.6v-5c0-5.7-4.6-10.2-10.2-10.2-5.7 0-10.2 4.6-10.2 10.2v5h-2.6c-1 0-1.8.8-1.8 1.8v17.4c0 1 .8 1.8 1.8 1.8h25.6c1 0 1.8-.8 1.8-1.8V40.9c0-.9-.8-1.7-1.8-1.7zM39.3 53.6c.2.6-.3 1.1-.9 1.1h-2.7c-.6 0-1-.6-.9-1.1l.8-3.2c-1-.5-1.7-1.5-1.7-2.8 0-1.7 1.4-3.1 3.1-3.1s3.1 1.4 3.1 3.1c0 1.2-.7 2.3-1.7 2.8l.9 3.2zm2.9-14.4H32v-5c0-2.8 2.3-5.1 5.1-5.1s5.1 2.3 5.1 5.1v5z"/></svg>
1
<svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#a03537"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cs.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d5006e}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm7.2 10.6c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#d5006e"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/csh.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm7.2 10.6c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10-10.3H33v5.8h3.2V6.4h3.3v14.3h-3.3V15H33v5.7h-3.3V6.4z" fill="#fff"/><path d="M30.8 61.4h10.9v2.7H30.8v-2.7zm0 5.4h10.9v2.7H30.8v-2.7zm0 5.5h10.9V75H30.8v-2.7zm19-24.4H28.1c-3 0-5.4 2.4-5.4 5.4v24.4h-5.4c0 3 2.4 5.4 5.4 5.4h21.7c3 0 5.4-2.4 5.4-5.4V56h5.4v-2.7c0-3-2.4-5.4-5.4-5.4zm-2.7 29.3c0 1.8-1.4 3.2-3.2 3.2H24c1.3-.9 1.3-2.7 1.3-2.7V53.3c0-1.5 1.2-2.7 2.7-2.7s2.7 1.2 2.7 2.7V56H47l.1 21.2zM33.5 53.3v-2.7h16.3c2.5 0 2.7 1.6 2.7 2.7h-19z" fill="#999" stroke="#999" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cson.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm5.4-34.7c1 0 2.2.4 2.9 1.2l-.9 2.1c-.4-.5-1.3-1-2-1-2.1 0-3.2 2.2-3.2 4.9 0 2.8 1.2 5.2 3.2 5.2.9 0 1.6-.5 2.2-1l.9 2.1c-.8.7-1.8 1.3-3.2 1.3-3.3 0-5.2-3.2-5.2-7.4 0-4.4 1.9-7.4 5.3-7.4zm4.7 11.2c.5.7 1.3 1.2 2.1 1.2.9 0 1.5-.7 1.5-1.8 0-2.6-4.2-2.5-4.2-6.6 0-2.3 1.3-4 3.6-4 .9 0 1.9.3 2.7.9l-.7 2.2c-.4-.4-1.3-.8-1.9-.8-1 0-1.5.8-1.5 1.7 0 2.6 4.3 2.4 4.3 6.5 0 2.2-1.2 4.1-3.5 4.1-1.1 0-2.3-.5-3.1-1.4l.7-2zM27.7 6.3c3 0 4.9 3 4.9 7.3S30.7 21 27.7 21s-4.9-3.1-4.9-7.4c.1-4.3 1.9-7.3 4.9-7.3zm0 12.3c1.7 0 2.7-2 2.7-5.1 0-3-1-4.9-2.7-4.9S25 10.5 25 13.5c0 3.1 1 5.1 2.7 5.1zm6.5-12.1h2.2l3.1 8c.3.9.6 2.2.6 2.2h.1s-.1-1.3-.1-2.2v-8H42v14.2h-2.2l-3.1-8.1c-.3-.9-.6-2.2-.6-2.2H36s.1 1.3.1 2.2v8h-2V6.5h.1z" fill="#fff"/><path class="st0" d="M14 48.9h37v4.3H14v-4.3zm7 9.6h37v4.3H21v-4.3zm-7 9.6h37v4.3H14v-4.3zm7 9.6h37V82H21v-4.3z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/csproj.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M28.3 44.7c-1.3 1-2.5 1.9-3.7 2.8-2.5 1.9-4.9 3.7-7.4 5.6-.3.3-.6.3-.9.1-.5-.3-1-.5-1.6-.8-.3-.1-.4-.4-.4-.7V32.2c0-.2.2-.5.4-.6.6-.3 1.2-.6 1.7-.9.3-.2.6 0 .8.2 2 1.6 4.1 3.1 6.1 4.6 1.7 1.3 3.3 2.5 5 3.8l.3-.3c6.1-5.9 12.1-11.8 18.2-17.7.3-.3.6-.3 1-.2 2.6 1 5.1 2.1 7.7 3.1.2.1.3.3.4.5.1.1 0 .3 0 .5v33.6c0 .8 0 .8-.8 1.1-2.4 1-4.9 1.9-7.3 2.9-.4.2-.7.1-1-.2-6-5.9-12-11.7-18-17.5-.1-.1-.3-.2-.5-.4zM45.8 50V34c-3.6 2.7-7.1 5.3-10.7 8 3.6 2.7 7.1 5.3 10.7 8zm-22.4-8c-1.8-1.6-3.5-3.2-5.3-4.8v9.6c1.8-1.6 3.5-3.2 5.3-4.8z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M13.6 70.2c1.1 0 2.2.4 3.1 1.2l-1.2 2.8c-.3-.5-1.1-.9-1.8-.9-1.8 0-2.7 1.9-2.7 4.2 0 2.3 1 4.4 2.7 4.4.8 0 1.4-.5 2-1l1.2 2.8c-.8.7-1.7 1.3-3.3 1.3-3.4 0-5.3-3.1-5.3-7.4-.2-4.4 1.9-7.4 5.3-7.4zm5.3 10.5c.5.6 1.2 1.2 2 1.2.7 0 1.1-.6 1.1-1.2 0-2-4-2.1-4-6.2 0-2.4 1.4-4.3 3.9-4.3 1 0 2.1.3 2.9 1l-1 2.9c-.4-.4-1.2-.9-1.8-.9-.8 0-1.1.6-1.1 1.2 0 2.1 4.1 2 4.1 6.1 0 2.3-1.3 4.4-3.8 4.4-1.2 0-2.4-.5-3.4-1.4l1.1-2.8zm7.6-10.3h3.8c2.2 0 3.7 2 3.7 4.9s-1.5 5-3.7 5h-1v4.4h-2.8V70.4zm3.3 7c.9 0 1.4-.9 1.4-2.1s-.6-2-1.3-2h-.6v4.1h.5zm5.9-7h3.8c.5 0 1.1.1 1.6.4 1.2.6 2 2.1 2 4 0 1.7-.7 3.3-1.7 4 0 0 .2.2.4.9l2 5h-3.1L39 79.9h-.7v4.8h-2.8V70.4h.2zM39 77c.7 0 1.3-.7 1.3-1.9 0-.7-.2-1.2-.5-1.5-.2-.2-.5-.3-.7-.3h-.6V77h.5zm10.7-6.8c3.2 0 5 3.1 5 7.3 0 4.2-1.8 7.5-5 7.5s-5-3.2-5-7.5c0-4.2 1.8-7.3 5-7.3zm0 11.6c1.4 0 2.1-1.8 2.1-4.3s-.6-4.2-2.1-4.2c-1.4 0-2.1 1.7-2.1 4.2s.6 4.3 2.1 4.3zm6-2.5h2.8v1.1c0 1.5.3 1.6.6 1.6.4 0 .6-.3.6-1.6v-7h-2.3v-2.9h5.1v9.9c0 3.3-1.7 4.6-3.4 4.6-1.8 0-3.4-1.4-3.4-4.6v-1.1z" fill="#666"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/css.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#72a536}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2s1.2 4.4 3.2 4.4c1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm7.2 10.6c.6.6 1.4 1.2 2.3 1.2s1.3-.6 1.3-1.2c0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10.7 0c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L36 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.5-2.8z" fill="#fff"/><path d="M16.4 67.5v-4.1c.9-.1 1.6-.2 2-.4s.8-.6 1.2-1c.4-.5.5-1.1.7-1.9.1-.6.2-1.5.2-2.8 0-2.2.1-3.7.4-4.6.2-.8.6-1.6 1.2-2 .5-.5 1.4-.9 2.5-1.2.7-.2 1.9-.4 3.5-.4h.9V53c-1.3 0-2.2.1-2.6.3s-.6.4-.9.6c-.2.3-.3.7-.3 1.5s-.1 2-.2 4.1c-.1 1.2-.2 2-.4 2.8-.3.6-.6 1.2-1 1.8-.4.4-1 .9-1.8 1.4.7.4 1.3.8 1.8 1.3s.8 1.2 1.1 1.9c.3.7.4 1.8.4 3 .1 1.9.1 3.1.1 3.6 0 .7.1 1.2.3 1.6.2.4.5.5.9.6.4.2 1.2.3 2.6.3v4.1h-1c-1.6 0-2.9-.1-3.7-.4-.9-.3-1.6-.6-2.2-1.2s-1-1.2-1.2-2-.3-2.1-.3-4c0-2-.1-3.5-.3-4.1-.3-.9-.7-1.6-1.2-2-.7-.5-1.5-.7-2.7-.7zm39.1 0c-.9.1-1.6.2-2 .4-.4.2-.8.6-1.2 1-.4.5-.5 1.1-.7 1.9-.1.6-.2 1.5-.2 2.8 0 2.2-.1 3.7-.4 4.6-.2.9-.6 1.6-1.2 2-.5.5-1.4.9-2.5 1.2-.7.2-1.9.4-3.5.4h-1v-4.1c1.3 0 2.1-.1 2.6-.3s.7-.4.9-.6c.2-.3.3-.7.3-1.5 0-.6.1-2 .2-4 .1-1.2.3-2.1.5-2.8.3-.7.6-1.3 1.1-1.9.4-.5 1-.9 1.7-1.3-.9-.6-1.6-1.1-2-1.6-.5-.7-1-1.8-1.2-2.8-.2-.8-.3-2.6-.3-5.2 0-.8-.1-1.4-.3-1.8-.2-.3-.4-.5-.8-.6-.2-.3-1-.3-2.5-.3v-4h1c1.6 0 2.9.1 3.7.4.9.3 1.6.6 2.2 1.2s1 1.2 1.2 2 .4 2.1.4 4c0 2 .1 3.4.3 4.1.3.9.7 1.6 1.2 1.9.5.4 1.4.6 2.5.6.1.1 0 4.3 0 4.3z" fill="#72a536" stroke="#72a536" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="75" xmlns="http://www.w3.org/2000/svg"><path d="M.5 19v-4.1c.9-.1 1.6-.2 2-.4.4-.2.8-.6 1.2-1.001.4-.5.5-1.1.7-1.9.1-.6.2-1.499.2-2.799 0-2.201.1-3.7.4-4.6.2-.8.6-1.6 1.2-2 .5-.5 1.4-.9 2.5-1.2.7-.2 1.9-.4 3.5-.4h.9v3.9c-1.3 0-2.2.1-2.6.3-.4.2-.6.4-.9.6-.2.3-.3.7-.3 1.501 0 .8-.1 2-.2 4.099-.101 1.2-.2 2-.4 2.801-.301.6-.6 1.2-1 1.8-.4.4-1 .9-1.8 1.399.7.4 1.3.8 1.8 1.3s.8 1.2 1.1 1.899c.3.702.4 1.802.4 3.001.1 1.9.1 3.1.1 3.599 0 .702.1 1.202.3 1.602.2.4.5.5.9.6.4.2 1.2.3 2.6.3v4.098h-1c-1.6 0-2.9-.1-3.701-.4-.9-.3-1.6-.6-2.2-1.2-.6-.6-.999-1.2-1.2-1.999-.198-.8-.299-2.1-.299-4 0-2-.1-3.5-.3-4.1-.3-.9-.7-1.601-1.201-2-.698-.5-1.5-.7-2.7-.7zm39.1 0c-.9.1-1.6.2-2 .4s-.8.6-1.2 1.001c-.4.5-.5 1.1-.7 1.9-.099.6-.2 1.499-.2 2.799 0 2.201-.1 3.7-.4 4.6-.2.9-.6 1.6-1.2 2-.5.5-1.4.9-2.5 1.2-.7.2-1.9.4-3.5.4h-.999v-4.1c1.298 0 2.1-.1 2.599-.3s.7-.4.899-.6c.2-.3.301-.7.301-1.501 0-.6.1-2 .2-3.999.099-1.2.3-2.1.5-2.8.3-.7.6-1.3 1.1-1.9.4-.5 1-.9 1.7-1.3-.901-.6-1.6-1.1-2-1.6-.5-.7-1-1.801-1.201-2.8-.199-.8-.299-2.6-.299-5.2 0-.8-.1-1.4-.301-1.8-.199-.3-.4-.5-.799-.6-.2-.3-1-.3-2.5-.3v-4h.999c1.602 0 2.9.1 3.7.4.902.3 1.6.6 2.2 1.2.6.6 1.002 1.2 1.2 2 .201.8.402 2.1.402 4 0 2 .098 3.4.299 4.1.299.9.7 1.601 1.2 1.9.5.4 1.401.6 2.5.6.1.1 0 4.3 0 4.3zm0 0" fill="#72a536" stroke="#72a536" stroke-miterlimit="10" transform="matrix(1.86825 0 0 1.87558 0 .209)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/csv.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1f7244}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm7.2 10.6c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm8.7-10.3H32l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L36 6.4h3.5l-3.9 14.3h-3.3L28.4 6.4z" fill="#fff"/><path d="M14 54h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H58m-44 5.9h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H58m-44 5.9h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H58m-44 5.9h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H58m-44 5.9h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H58" fill="none" stroke="#1f7244" stroke-width="3" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="52"><path style="fill:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1f7244;stroke-opacity:1;stroke-miterlimit:10" d="M0 1.5h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 7.4h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 13.3h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 19.2h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 25.1h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44" transform="matrix(1.9091 0 0 1.92593 0 .385)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cue.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#eab41b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm6.4.3h3.3V16c0 1.4.6 1.9 1.5 1.9s1.5-.5 1.5-1.9V6.4h3.3V16c0 3-1.9 4.9-4.7 4.9-2.9 0-4.8-1.9-4.8-4.9V6.4zm13.1 0h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9H32V6.4z" fill="#fff"/><path class="st0" d="M33.7 65.5c0 .6.2 1.2.7 1.6.9.9 2.4.9 3.3 0 .4-.4.7-1 .7-1.6 0-.6-.2-1.2-.7-1.6-.4-.4-1-.7-1.6-.7s-1.2.2-1.6.7c-.6.4-.8 1-.8 1.6z"/><path class="st0" d="M22.9 52.4c-7.2 7.2-7.2 18.9 0 26.2 7.2 7.2 18.9 7.2 26.2 0 7.2-7.2 7.2-18.9 0-26.2-7.2-7.2-19-7.2-26.2 0zm27.4 20.9c-.7 1.2-1.6 2.4-2.6 3.4s-2.2 1.9-3.4 2.6L40 71.1s.4-.1 1.2-.9c.8-.8 1-1.2 1-1.2l8.1 4.3zm-11-11.1c.9.9 1.4 2.1 1.4 3.3 0 1.2-.5 2.4-1.4 3.3-1.8 1.8-4.7 1.8-6.5 0-.9-.9-1.4-2.1-1.4-3.3 0-1.2.4-2.4 1.4-3.3 1.7-1.8 4.7-1.8 6.5 0zM33 59s-.9.5-1.6 1.3c-.7.8-.7.9-1 1.3l-8.2-4.4c.7-1.2 1.6-2.4 2.6-3.4 1.1-1 2.2-1.9 3.4-2.6L33 59z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#eab41b"><path d="M28.023 32c0 1.04.344 2.074 1.211 2.766 1.555 1.558 4.149 1.558 5.707 0 .692-.692 1.211-1.727 1.211-2.766s-.347-2.074-1.21-2.766c-.692-.695-1.731-1.21-2.77-1.21-1.035 0-2.074.343-2.766 1.21-1.039.692-1.383 1.727-1.383 2.766zm0 0"/><path d="M9.34 9.34c-12.453 12.453-12.453 32.691 0 45.32 12.453 12.453 32.691 12.453 45.32 0 12.453-12.453 12.453-32.691 0-45.32-12.453-12.453-32.867-12.453-45.32 0zm47.394 36.152c-1.21 2.074-2.765 4.153-4.496 5.88-1.73 1.73-3.804 3.288-5.883 4.5l-7.437-14.184s.691-.176 2.078-1.56c1.383-1.382 1.727-2.073 1.727-2.073zM37.707 26.293c1.559 1.555 2.422 3.633 2.422 5.707s-.863 4.152-2.422 5.707a7.933 7.933 0 0 1-11.242 0c-1.559-1.555-2.422-3.633-2.422-5.707s.691-4.152 2.422-5.707c2.941-3.113 8.129-3.113 11.242 0zm-10.895-5.535s-1.558.863-2.769 2.246c-1.211 1.387-1.211 1.558-1.73 2.25l-14.184-7.61c1.21-2.078 2.77-4.152 4.5-5.882 1.902-1.73 3.805-3.285 5.879-4.496zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/cur.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#8ed200}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.5-34.9c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4zm6.4.3h3.3V16c0 1.4.6 1.9 1.5 1.9s1.5-.5 1.5-1.9V6.4h3.3V16c0 3-1.9 4.9-4.7 4.9-2.9 0-4.8-1.9-4.8-4.9V6.4zm13.1 0h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5H38l-2-4.8h-.8v4.8H32V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6z" fill="#fff"/><path class="st0" d="M59.3 26.3l4 .5-.6 6.1 3.6-.4-7 14.2-4.1-15.5 3.5 1.2.6-6.1z" transform="matrix(-1.52199 1.52234 -1.40668 -1.40636 178.231 24.105)"/></svg>
1
<svg height="64" width="55" xmlns="http://www.w3.org/2000/svg"><path d="M54.652 53.883 41.801 64 27.289 46.172l-9.3 11.351L.347 0l53.07 29.219-13.277 6.836zm0 0" fill="#8ed200"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dart.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#0091ea}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.5-34.6h3.8c3.3 0 5.3 2.6 5.3 7.1s-2 7.2-5.3 7.2H6.5V6.4zm3.7 11.4c1.5 0 2.3-1.5 2.3-4.3s-.9-4.2-2.3-4.2h-.7v8.5h.7zm8.9-11.4h3.2l3.2 14.3h-3l-.5-3h-2.7l-.5 3h-3l3.3-14.3zm2.5 8.6l-.5-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.4 2.8h1.8zm4.9-8.6h4.1c.5 0 1.2.1 1.7.4 1.3.6 2.2 2.1 2.2 4 0 1.7-.7 3.3-1.8 4 0 0 .2.2.4.9l2.1 5H32l-1.8-4.8h-.7v4.8h-3V6.4zm3.6 6.6c.8 0 1.4-.7 1.4-1.9 0-.7-.2-1.2-.5-1.5-.2-.2-.5-.3-.8-.3h-.7V13h.6zm8-3.7h-2.8V6.4h8.6v2.9h-2.8v11.4h-2.9V9.3z" fill="#fff"/><path class="st0" d="M23.2 49.3l7.1 5.8c-.2-2.1-1.1-4.4-2.5-5.8-1-1-1.9-1.4-2.8-1.2-.8.1-1.4.6-1.8 1.2zm-4.9 9.5c1.5 1.5 3.8 2.3 5.9 2.5l-5.8-7.1c-.7.5-1.2 1-1.3 1.8-.2.9.2 1.8 1.2 2.8zm28.6 12.7l-6.4 6.4c.8.8 2.1 1.5 3.4 1.7.4.1.7.1 1.1.1.6 0 1.2-.1 1.7-.4l4.3 4.3c.2.2.5.3.8.3.3 0 .6-.1.8-.3.4-.4.4-1.2 0-1.6l-4.3-4.3c.9-2 0-4.8-1.4-6.2zM19.8 52.4L39 76.2l6.2-6.2-23.8-19.2c-.4-.4-1.1-.3-1.5.1-.5.4-.5 1-.1 1.5z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="m10.98 2.23 12.672 10.356c-.355-3.75-1.96-7.856-4.46-10.356-1.786-1.785-3.391-2.5-5-2.14-1.426.18-2.5 1.07-3.212 2.14zM2.23 19.191c2.68 2.676 6.786 4.106 10.536 4.461L2.41 10.98c-1.25.891-2.14 1.786-2.32 3.211-.36 1.61.355 3.215 2.14 5zm51.06 22.672L41.862 53.29c1.43 1.43 3.75 2.676 6.07 3.035.715.18 1.25.18 1.965.18 1.07 0 2.141-.18 3.036-.715l7.675 7.676c.356.355.891.535 1.426.535s1.07-.18 1.43-.535c.715-.715.715-2.145 0-2.856l-7.676-7.675c1.606-3.575 0-8.57-2.5-11.07zM4.91 7.766l34.274 42.488 11.07-11.07L7.766 4.91c-.715-.715-1.965-.535-2.68.176-.89.715-.89 1.789-.176 2.68zm0 0" fill="#0091ea"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dat.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zM22 6.4h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3L22 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2zm8.1-5.7h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path d="M35.8 49.7c-2.9 0-5.4 2.8-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2 2.9 0 5.4-2.8 5.4-6.2 0-3.4-2.4-6.2-5.4-6.2zm0 10.1c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9-1.3 3.9-3 3.9zM25 61V50.9c0-.7-.5-1.2-1.2-1.2s-1.2.5-1.2 1.2V61c0 .7.5 1.2 1.2 1.2S25 61.6 25 61zm-1.1 6.9c-2.9 0-5.4 2.8-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2s5.4-2.8 5.4-6.2c-.1-3.3-2.5-6.2-5.4-6.2zm0 10.2c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9c-.1 2.1-1.4 3.9-3 3.9zM37 79.2V69.1c0-.7-.5-1.2-1.2-1.2s-1.2.5-1.2 1.2v10.1c0 .7.5 1.2 1.2 1.2s1.2-.5 1.2-1.2zm12.3-17.3V51.8c0-.7-.5-1.2-1.2-1.2s-1.1.5-1.1 1.2v10.1c0 .7.5 1.2 1.2 1.2s1.1-.6 1.1-1.2zm-1.2 6.9c-2.9 0-5.4 2.8-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2 2.9 0 5.4-2.8 5.4-6.2 0-3.4-2.4-6.2-5.4-6.2zm0 10.1c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9-1.3 3.9-3 3.9z" fill="#999" stroke="#999" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M17.8.5c-2.9 0-5.4 2.801-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2 2.9 0 5.399-2.8 5.399-6.2C23.199 3.302 20.8.5 17.8.5zm0 10.1c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9-1.3 3.9-3 3.9zM7 11.8V1.7C7 1 6.5.5 5.8.5S4.6 1 4.6 1.7v10.1c0 .7.5 1.2 1.2 1.2S7 12.4 7 11.8zm-1.1 6.9C3 18.7.5 21.5.5 24.9s2.4 6.2 5.4 6.2 5.401-2.8 5.401-6.2c-.102-3.3-2.5-6.2-5.4-6.2zm0 10.2c-1.6 0-3-1.699-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9c-.1 2.1-1.4 3.9-3 3.9zM19 30V19.9c0-.7-.5-1.2-1.2-1.2s-1.2.5-1.2 1.2V30c0 .7.5 1.2 1.2 1.2S19 30.7 19 30zM31.3 12.7V2.6c0-.7-.499-1.2-1.2-1.2-.7 0-1.1.5-1.1 1.2v10.099c0 .701.5 1.2 1.2 1.2s1.1-.6 1.1-1.2zm-1.2 6.9c-2.9 0-5.401 2.8-5.401 6.2 0 3.4 2.4 6.202 5.4 6.202 2.901 0 5.402-2.802 5.402-6.202S33.1 19.6 30.1 19.6zm0 10.102c-1.6 0-3-1.7-3-3.902 0-2.099 1.3-3.9 3-3.9s3 1.7 3 3.9c0 2.202-1.3 3.902-3 3.902zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" transform="matrix(1.91667 0 0 1.9394 0 .485)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/data.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.5-34.6h3.9c3.4 0 5.5 2.6 5.5 7.1s-2.1 7.2-5.5 7.2H6.5V6.4zm3.9 11.4c1.6 0 2.4-1.5 2.4-4.3s-.9-4.2-2.4-4.2h-.8v8.5h.8zm9-11.4h3.3L26 20.7h-3.1l-.6-3h-2.8l-.5 3h-3.1l3.5-14.3zm2.7 8.6l-.5-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h1.9zm6.1-5.7h-2.9V6.4h8.9v2.9h-2.9v11.4h-3V9.3zm8.4-2.9h3.3l3.3 14.3h-3.1l-.6-3h-2.8l-.5 3h-3.1l3.5-14.3zm2.6 8.6l-.5-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h1.9z" fill="#fff"/><path d="M35.8 49.7c-2.9 0-5.4 2.8-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2 2.9 0 5.4-2.8 5.4-6.2 0-3.4-2.4-6.2-5.4-6.2zm0 10.1c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9-1.3 3.9-3 3.9zM25 61V50.9c0-.7-.5-1.2-1.2-1.2s-1.2.5-1.2 1.2V61c0 .7.5 1.2 1.2 1.2S25 61.6 25 61zm-1.1 6.9c-2.9 0-5.4 2.8-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2s5.4-2.8 5.4-6.2c-.1-3.3-2.5-6.2-5.4-6.2zm0 10.2c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9c-.1 2.1-1.4 3.9-3 3.9zM37 79.2V69.1c0-.7-.5-1.2-1.2-1.2s-1.2.5-1.2 1.2v10.1c0 .7.5 1.2 1.2 1.2s1.2-.5 1.2-1.2zm12.3-17.3V51.8c0-.7-.5-1.2-1.2-1.2s-1.1.5-1.1 1.2v10.1c0 .7.5 1.2 1.2 1.2s1.1-.6 1.1-1.2zm-1.2 6.9c-2.9 0-5.4 2.8-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2 2.9 0 5.4-2.8 5.4-6.2 0-3.4-2.4-6.2-5.4-6.2zm0 10.1c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9-1.3 3.9-3 3.9z" fill="#999" stroke="#999" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M17.8.5c-2.9 0-5.4 2.801-5.4 6.2 0 3.4 2.4 6.2 5.4 6.2 2.9 0 5.399-2.8 5.399-6.2C23.199 3.302 20.8.5 17.8.5zm0 10.1c-1.6 0-3-1.7-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9-1.3 3.9-3 3.9zM7 11.8V1.7C7 1 6.5.5 5.8.5S4.6 1 4.6 1.7v10.1c0 .7.5 1.2 1.2 1.2S7 12.4 7 11.8zm-1.1 6.9C3 18.7.5 21.5.5 24.9s2.4 6.2 5.4 6.2 5.401-2.8 5.401-6.2c-.102-3.3-2.5-6.2-5.4-6.2zm0 10.2c-1.6 0-3-1.699-3-3.9 0-2.1 1.3-3.9 3-3.9s3 1.7 3 3.9c-.1 2.1-1.4 3.9-3 3.9zM19 30V19.9c0-.7-.5-1.2-1.2-1.2s-1.2.5-1.2 1.2V30c0 .7.5 1.2 1.2 1.2S19 30.7 19 30zM31.3 12.7V2.6c0-.7-.499-1.2-1.2-1.2-.7 0-1.1.5-1.1 1.2v10.099c0 .701.5 1.2 1.2 1.2s1.1-.6 1.1-1.2zm-1.2 6.9c-2.9 0-5.401 2.8-5.401 6.2 0 3.4 2.4 6.202 5.4 6.202 2.901 0 5.402-2.802 5.402-6.202S33.1 19.6 30.1 19.6zm0 10.102c-1.6 0-3-1.7-3-3.902 0-2.099 1.3-3.9 3-3.9s3 1.7 3 3.9c0 2.202-1.3 3.902-3 3.902zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" transform="matrix(1.91667 0 0 1.9394 0 .485)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/db.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.1-11.4H24c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zM24 12c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6s-.3-1.5-1.1-1.5h-1.2v3.1h1.1z" fill="#fff"/><path class="st0" d="M34.9 84.7c-4.8-.2-9.1-1.7-11.4-4-.7-.6-1.4-1.5-1.7-2.1l-.2-.4v-4.5c0-4.5 0-4.5.1-4.1.2 1 .8 2 1.7 2.8.6.5 1.8 1.4 2.8 1.9 1.7.9 3.9 1.5 6.2 1.8 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.5-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.2.4c-.7 1.4-1.9 2.6-3.5 3.6-3.1 1.8-7.8 2.8-12.4 2.6zm0-11.2c-4.2-.2-8.1-1.4-10.6-3.2-.6-.4-1.4-1.2-1.7-1.6-.3-.4-.6-.9-.8-1.4l-.2-.4v-4.4c0-4.4 0-4.4.1-4.1.2.7.5 1.5 1.1 2.1.3.4.8.9 1.1 1.1.1.1.4.2.6.4 2 1.4 4.8 2.4 8 2.9 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.4-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.3.6c-.5.9-.8 1.4-1.4 2s-1.2 1.1-2 1.5c-3.2 1.8-7.9 2.8-12.5 2.5zm-.3-11.1c-2.8-.2-5-.7-7.1-1.5-2.5-1-4.3-2.3-5.2-3.9-.2-.3-.4-.7-.5-1.2-.1-.4-.2-1.4-.1-2 .6-3.2 4.9-5.8 10.7-6.7 1.4-.2 1.9-.2 3.9-.2s2.5 0 3.9.2c2.3.3 4.4 1 6.2 1.8 2.6 1.3 4.2 3 4.5 4.8.1.5.1 1.6-.1 2-.3 1-.7 1.6-1.5 2.4-2.1 2.2-5.8 3.6-10.4 4.1-.6.2-3.7.2-4.3.2z"/></svg>
1
<svg height="64" width="51" xmlns="http://www.w3.org/2000/svg"><path d="M23.023 63.957c-8.199-.34-15.543-2.875-19.468-6.77-1.196-1.011-2.39-2.535-2.903-3.55L.31 52.96v-7.617c0-7.614 0-7.614.171-6.934.34 1.692 1.368 3.383 2.903 4.735 1.023.847 3.074 2.37 4.781 3.214 2.906 1.524 6.66 2.54 10.59 3.047 2.39.34 3.246.34 6.66.34 3.418 0 4.27 0 6.66-.34 3.93-.508 7.516-1.691 10.59-3.047 1.707-.843 3.758-2.199 4.781-3.214 1.368-1.352 2.563-3.043 2.903-4.735.172-.508.172-.508.172 6.934v7.445l-.34.68c-1.196 2.367-3.246 4.398-5.98 6.09-5.294 3.046-13.321 4.738-21.177 4.398zm0-18.95c-7.171-.339-13.832-2.37-18.101-5.413-1.027-.68-2.39-2.032-2.906-2.707-.512-.68-1.024-1.524-1.364-2.371L.31 33.84v-7.445c0-7.446 0-7.446.171-6.938.34 1.184.852 2.54 1.88 3.555.511.675 1.367 1.523 1.878 1.86.168.171.684.339 1.024.679 3.414 2.367 8.199 4.058 13.664 4.906 2.39.336 3.242.336 6.66.336 3.414 0 4.27 0 6.66-.336 3.93-.508 7.516-1.691 10.59-3.047 1.707-.847 3.758-2.2 4.781-3.215 1.367-1.351 2.39-3.047 2.903-4.738.171-.508.171-.508.171 6.938v7.445l-.511 1.015c-.856 1.524-1.368 2.368-2.39 3.383-1.028 1.016-2.052 1.864-3.419 2.54-5.465 3.046-13.492 4.738-21.348 4.23zm-.511-18.78c-4.782-.34-8.54-1.184-12.125-2.54-4.27-1.69-7.344-3.89-8.883-6.597a5.594 5.594 0 0 1-.852-2.031C.48 14.383.31 12.69.48 11.676 1.504 6.262 8.848 1.859 18.754.34 21.144 0 22 0 25.414 0c3.418 0 4.27 0 6.66.34 3.93.508 7.516 1.691 10.59 3.043 4.441 2.199 7.172 5.078 7.684 8.12.172.849.172 2.708-.168 3.388-.512 1.691-1.196 2.707-2.563 4.058-3.586 3.723-9.906 6.094-17.762 6.938-1.023.34-6.32.34-7.343.34zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dbf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#a03537}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.1-11.4H24c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zM24 12c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1zm7.6-11.4h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M-4938.1 722.8c-4.8-.2-9.1-1.7-11.4-4-.7-.6-1.4-1.5-1.7-2.1l-.2-.4v-4.5c0-4.5 0-4.5.1-4.1.2 1 .8 2 1.7 2.8.6.5 1.8 1.4 2.8 1.9 1.7.9 3.9 1.5 6.2 1.8 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.5-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.2.4c-.7 1.4-1.9 2.6-3.5 3.6-3.1 1.8-7.8 2.8-12.4 2.6zm0-11.2c-4.2-.2-8.1-1.4-10.6-3.2-.6-.4-1.4-1.2-1.7-1.6-.3-.4-.6-.9-.8-1.4l-.2-.4v-4.4c0-4.4 0-4.4.1-4.1.2.7.5 1.5 1.1 2.1.3.4.8.9 1.1 1.1.1.1.4.2.6.4 2 1.4 4.8 2.4 8 2.9 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.4-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.3.6c-.5.9-.8 1.4-1.4 2-.6.6-1.2 1.1-2 1.5-3.2 1.8-7.9 2.8-12.5 2.5zm-.3-11.1c-2.8-.2-5-.7-7.1-1.5-2.5-1-4.3-2.3-5.2-3.9-.2-.3-.4-.7-.5-1.2-.1-.4-.2-1.4-.1-2 .6-3.2 4.9-5.8 10.7-6.7 1.4-.2 1.9-.2 3.9-.2s2.5 0 3.9.2c2.3.3 4.4 1 6.2 1.8 2.6 1.3 4.2 3 4.5 4.8.1.5.1 1.6-.1 2-.3 1-.7 1.6-1.5 2.4-2.1 2.2-5.8 3.6-10.4 4.1-.6.2-3.7.2-4.3.2z" transform="translate(4973.037 -638.07)"/></svg>
1
<svg height="64" width="51" xmlns="http://www.w3.org/2000/svg"><path d="M23.023 63.957c-8.199-.34-15.543-2.875-19.468-6.77-1.196-1.011-2.39-2.535-2.903-3.55L.31 52.96v-7.617c0-7.614 0-7.614.171-6.934.34 1.692 1.368 3.383 2.903 4.735 1.023.847 3.074 2.37 4.781 3.214 2.906 1.524 6.66 2.54 10.59 3.047 2.39.34 3.246.34 6.66.34 3.418 0 4.27 0 6.66-.34 3.93-.508 7.516-1.691 10.59-3.047 1.707-.843 3.758-2.199 4.781-3.214 1.368-1.352 2.563-3.043 2.903-4.735.172-.508.172-.508.172 6.934v7.445l-.34.68c-1.196 2.367-3.246 4.398-5.98 6.09-5.294 3.046-13.321 4.738-21.177 4.398zm0-18.95c-7.171-.339-13.832-2.37-18.101-5.413-1.027-.68-2.39-2.032-2.906-2.707-.512-.68-1.024-1.524-1.364-2.371L.31 33.84v-7.445c0-7.446 0-7.446.171-6.938.34 1.184.852 2.54 1.88 3.555.511.675 1.367 1.523 1.878 1.86.168.171.684.339 1.024.679 3.414 2.367 8.199 4.058 13.664 4.906 2.39.336 3.242.336 6.66.336 3.414 0 4.27 0 6.66-.336 3.93-.508 7.516-1.691 10.59-3.047 1.707-.847 3.758-2.2 4.781-3.215 1.367-1.351 2.39-3.047 2.903-4.738.171-.508.171-.508.171 6.938v7.445l-.511 1.015c-.856 1.524-1.368 2.368-2.39 3.383-1.028 1.016-2.052 1.864-3.419 2.54-5.465 3.046-13.492 4.738-21.348 4.23zm-.511-18.78c-4.782-.34-8.54-1.184-12.125-2.54-4.27-1.69-7.344-3.89-8.883-6.597a5.594 5.594 0 0 1-.852-2.031C.48 14.383.31 12.69.48 11.676 1.504 6.262 8.848 1.859 18.754.34 21.144 0 22 0 25.414 0c3.418 0 4.27 0 6.66.34 3.93.508 7.516 1.691 10.59 3.043 4.441 2.199 7.172 5.078 7.684 8.12.172.849.172 2.708-.168 3.388-.512 1.691-1.196 2.707-2.563 4.058-3.586 3.723-9.906 6.094-17.762 6.938-1.023.34-6.32.34-7.343.34zm0 0" fill="#a03537"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/deb.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#4d1b9b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.1-11.4H27v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4zm10.5 0h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1z" fill="#fff"/><path class="st0" d="M43.6 68.3l-7.3-3.4L51 58l7.3 3.4-7.3 3.5-7.4 3.4zM51 51.2l-7.3-3.4-7.3 3.4L51 58.1l7.3-3.4-7.3-3.5zM28.9 61.4L21.6 58l-7.3 3.4L29 68.3l7.3-3.4-7.4-3.5zm0-6.8l7.3-3.4-7.3-3.4-14.7 6.9 7.3 3.4 7.4-3.5zM51 66.9l-6.6 3-.8.4-.8-.4-6.6-3-6.6 3-.8.4-.8-.4-6.6-3v10.7l14.7 7.7L51 77.6V66.9z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#4d1b9b"/></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/default.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st3{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path d="M51.9 26.5H28c-3.3 0-6 2.6-6 6v26.9h-6c0 3.3 2.6 6 6 6h24c3.3 0 6-2.7 6-6v-24h6v-3c-.1-3.2-2.7-5.9-6.1-5.9zm-3 32.4c0 1.9-1.6 3.5-3.5 3.5h-22c1.5-1 1.5-3 1.5-3v-27c0-1.6 1.3-3 3-3 1.6 0 3 1.3 3 3v3h18v23.5zM34 32.5v-3h18c2.7 0 3 1.7 3 3H34zm2.8 8.3c.1-.2.1-.2.2 0l1.8 5.5c.1.2.2.3.4.3H45c.2 0 .2.1.1.2l-4.7 3.4c-.1.1-.2.3-.2.5l1.8 5.6c.1.2 0 .2-.2.1L37.1 53c-.2-.1-.3-.1-.5 0L32 56.3c-.1.1-.2.1-.2-.1l1.8-5.6c0-.2 0-.3-.2-.5l-4.7-3.4c-.1-.1-.1-.2.1-.2h5.8c.2 0 .3-.1.4-.3 0 .1 1.8-5.4 1.8-5.4z" fill="#bababa" stroke="#bababa" stroke-width=".75" stroke-miterlimit="10"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M9.9 74.7h2.9c2.6 0 4.1 1.8 4.1 5s-1.6 5-4.1 5H9.9v-10zm2.9 8c1.2 0 1.8-1 1.8-3 0-1.9-.7-3-1.8-3h-.6v6h.6zm6.4-8h5v2h-2.7v1.9h2.2v2h-2.2v2h2.9v2h-5.2v-9.9zm7.3 0h5v2h-2.7v2.2H31v2h-2.2v3.8h-2.3v-10zm8.3 0h2.5l2.5 10h-2.3l-.4-2.1H35l-.4 2.1h-2.3l2.5-10zm1.9 6l-.4-2c-.1-.7-.2-1.7-.2-1.7H36s-.1 1.1-.3 1.7l-.4 2h1.4zm4.7-6h2.3v6.7c0 1 .4 1.3 1.1 1.3.6 0 1-.4 1-1.3v-6.7h2.3v6.7c0 2.1-1.3 3.5-3.3 3.5-2.1 0-3.4-1.3-3.4-3.5v-6.7zm9.2 0h2.3v8h3v2h-5.3v-10zm7.6 2H56v-2h6.7v2h-2.2v8h-2.3v-8z" fill="#666"/><path class="st3" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st3" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/dgn.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#369}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zM24.6 6.1c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9H29v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.6-7.6 6.5-7.6zm6.8.3h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4H41v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4z" fill="#fff"/><path d="M51.6 65.9c-.5-.2-1.1 0-1.3.5-1.1 2.5-2.9 4.7-5.1 6.4l-6.7-13.6c1-.8 1.6-2 1.6-3.4 0-2.1-1.5-3.9-3.5-4.3v-3.4c0-.5-.4-1-1-1-.5 0-1 .4-1 1v3.4c-2 .4-3.5 2.2-3.5 4.3 0 1.4.6 2.6 1.6 3.4L26 72.8c-2.2-1.7-4-3.8-5.1-6.4-.2-.5-.8-.7-1.3-.5-.5.2-.7.8-.5 1.3 1.3 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.1 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2s6-.8 8.7-2.2l3.8 7.8c.1.3.5.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.7-4.4 6-7.3.6-.5.4-1.1 0-1.3zm-16-12.6c1.4 0 2.5 1.1 2.5 2.5s-1.1 2.5-2.5 2.5-2.5-1.1-2.5-2.5 1.2-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.8-2l6.8-13.7c.3.1.7.1 1.1.1s.7 0 1.1-.1l6.8 13.7c-2.5 1.3-5.2 2-8 2z" fill="#369" stroke="#369" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M33.325 19.55c-.498-.2-1.1 0-1.299.5-1.1 2.5-2.901 4.7-5.1 6.4l-6.7-13.601c1-.8 1.6-1.999 1.6-3.4 0-2.099-1.501-3.899-3.501-4.3v-3.4a1 1 0 0 0-2 0v3.4c-2 .401-3.5 2.201-3.5 4.3 0 1.401.6 2.6 1.601 3.4l-6.7 13.602c-2.201-1.7-4-3.801-5.1-6.401-.201-.5-.8-.7-1.301-.5-.499.199-.7.8-.499 1.3 1.299 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.098 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2 3.1 0 6-.8 8.699-2.2l3.8 7.8c.1.3.501.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.701-4.4 6-7.3.6-.5.401-1.101 0-1.3zM17.326 6.95c1.4 0 2.5 1.1 2.5 2.499 0 1.401-1.1 2.502-2.5 2.502s-2.5-1.1-2.5-2.502c0-1.4 1.199-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.801-2l6.8-13.7c.3.1.701.1 1.1.1.402 0 .701 0 1.1-.1l6.8 13.7c-2.5 1.3-5.199 2-7.999 2zm0 0" fill="#369" stroke="#369" stroke-miterlimit="10" stroke-width="1.5" transform="matrix(1.6544 0 0 1.63607 0 .154)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dist.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm8.1-11.4h3.3v14.3h-3.3V6.4zm6.7 10.3c.6.6 1.4 1.2 2.3 1.2s1.3-.6 1.3-1.2c0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L31 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm11.2-7.4h-3.1V6.4h9.6v2.9H40v11.4h-3.3V9.3z" fill="#fff"/><path d="M23.7 76c-.5 0-1.1-.2-1.5-.6L13.8 67c-.8-.8-.8-2.1 0-3l8.4-8.4c.8-.8 2.1-.8 3 0 .8.8.8 2.1 0 3l-6.9 6.9 6.9 6.9c.8.8.8 2.1 0 3-.4.4-1 .6-1.5.6zm25.1 0c-.5 0-1.1-.2-1.5-.6-.8-.8-.8-2.1 0-3l6.9-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 3 0l8.4 8.4c.8.8.8 2.1 0 3l-8.4 8.4c-.4.4-1 .6-1.5.6zm-16.7 4.1c-.2 0-.4 0-.7-.1-1.1-.4-1.7-1.5-1.3-2.6l8.4-25.1c.4-1.1 1.5-1.7 2.6-1.3s1.7 1.5 1.3 2.6L34 78.7c-.2.9-1.1 1.4-1.9 1.4z" fill="#999" stroke="#999" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="54"><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M11.242 25.867c-.5 0-1.1-.2-1.498-.6l-8.4-8.401c-.802-.799-.802-2.099 0-3l8.4-8.398c.8-.8 2.098-.8 2.999 0 .8.8.8 2.098 0 2.999l-6.9 6.9 6.9 6.9c.8.801.8 2.1 0 3-.401.4-1 .6-1.5.6zm25.1 0c-.499 0-1.099-.2-1.5-.6-.8-.8-.8-2.099 0-3.002l6.9-6.898-6.9-6.9c-.8-.8-.8-2.101 0-3 .8-.8 2.1-.8 3.001 0l8.398 8.4c.802.8.802 2.1 0 3l-8.398 8.4c-.4.4-1.001.6-1.5.6zm-16.7 4.1c-.199 0-.398 0-.698-.1-1.102-.401-1.702-1.5-1.301-2.6l8.398-25.1c.4-1.1 1.5-1.699 2.6-1.301 1.102.4 1.702 1.5 1.301 2.601l-8.398 25.1c-.202.899-1.102 1.4-1.901 1.4zm0 0" transform="matrix(1.74425 0 0 1.75713 0 .013)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/diz.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.1-11.4h3.3v14.3h-3.3V6.4zm6.4 12.1l4.2-7.9c.5-.9.8-1.3.8-1.3s-.3.1-.8.1h-4v-3H35v2.2l-4.2 8c-.5.9-.8 1.3-.8 1.3s.3-.1.8-.1h4.3v2.9h-8.9v-2.2z" fill="#fff"/><path class="st0" d="M52 50.2c-2.6 0-1.9 2.6-2.4 3.7-.2.4-.5 1.2-.8 1.9l.2-.4c-.2.4-.3.5-.7.8 0 0-1.8 1.1-3.4 2-1.9-3.3-5.3-5.2-9-5.2s-7.2 2-9 5.2c-1.7-1-3.5-2-3.5-2-.4-.3-.6-.4-.7-.8l.2.4c-.3-.7-.6-1.4-.8-1.9-.4-1.2.3-3.7-2.4-3.7-2.6 0-2.1 3.5-2.9 4.9-.5.9-2 1.8-2.7 2.8-.1.1-.1.2-.1.3-.3.5-.4 1.2.1 1.9 1.3 2.2 3.2.4 4.4.2.5-.1 1.2-.1 2-.3l-.5.1c.4-.1.6 0 1.1.3 0 0 1.9 1.1 4.4 2.5v.6c0 1.9.5 3.9 1.6 5.5-3.4 2-6.3 3.8-6.3 3.8-.4.3-.6.4-1 .3h.4-1.9c-1.2 0-2.7-1.4-4.2.5-1.4 1.9 1.5 2.8 2.1 3.9.6 1.1-.2 4.1 2.3 3.8 2.4-.3 2-2.3 2.6-3.4.3-.4.6-1 .9-1.6l-.2.4c.2-.3.4-.4.8-.7 0 0 2.8-1.5 6-3.4v4.6c.9.4 1.8.6 2.7.8v-2.5l1.3.3v2.5c.9.2 1.8.3 2.7.3v-2.5h1.2v2.4c.9 0 1.8-.1 2.7-.3v-2.5l1.3-.3V78c.9-.2 1.8-.4 2.7-.8v-4.6c3.3 1.8 6 3.4 6 3.4.4.3.6.4.8.7.3.4.5.9.7 1.2.5 1 .2 3.1 2.6 3.4s1.7-2.7 2.3-3.8c.6-1.1 3.5-1.9 2.1-3.9-1.4-1.9-3-.6-4.2-.5h-1.9.4c-.4 0-.5 0-1-.3 0 0-2.9-1.8-6.3-3.8 1.1-1.7 1.6-3.5 1.6-5.5v-.6c2.5-1.4 4.4-2.5 4.4-2.5.4-.3.7-.3 1.1-.3l-.3-.1c.8.1 1.5.2 2 .3 1.2.2 3.1 2 4.4-.2 1.3-2.2-1.9-3.6-2.7-5-.5-.9-.4-2.7-1.1-3.8 0-.1-.1-.2-.1-.2-.7-.6-1.2-.8-2-.9zM31.9 62.3c.3 0 .4 0 .7.1 1.4.4 1.8 1.7 1.4 3.2-.4 1.4-1.9 2.3-3.3 1.9-1.4-.4-1.9-1.8-1.4-3.2.3-1.2 1.4-2 2.6-2zm7.8 0c1.2 0 2.4.8 2.7 1.9.4 1.4 0 2.7-1.4 3.2-1.4.4-2.9-.4-3.3-1.9-.4-1.4 0-2.7 1.4-3.2.2.1.4.1.6 0zM35.8 69c.4 0 2.1 2.2 1.9 2.5s-3.6.3-3.8 0c-.2-.3 1.6-2.5 1.9-2.5z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#bababa;fill-opacity:1" d="M72.277.21c-4.906 0-3.586 4.978-4.53 7.083-.376.77-.946 2.297-1.509 3.64l.375-.765c-.375.762-.566.953-1.32 1.527 0 0-3.398 2.11-6.422 3.832C55.285 9.211 48.863 5.57 41.875 5.57c-6.984 0-13.594 3.828-16.992 9.957-3.207-1.914-6.61-3.832-6.61-3.832-.753-.574-1.128-.765-1.32-1.527l.375.762c-.566-1.34-1.129-2.68-1.508-3.637C15.066 5 16.383.211 11.29.211c-4.915 0-3.97 6.7-5.477 9.379-.946 1.726-3.778 3.445-5.098 5.363-.192.188-.192.379-.192.574-.566.957-.753 2.297.192 3.637 2.453 4.211 6.039.766 8.305.383.945-.192 2.27-.192 3.777-.574l-.945.191c.757-.191 1.136 0 2.078.574 0 0 3.59 2.106 8.308 4.785v1.149c0 3.64.946 7.469 3.024 10.527a656.505 656.505 0 0 0-11.895 7.278c-.758.574-1.137.765-1.89.574h.753-3.585c-2.27 0-5.102-2.68-7.93.957-2.649 3.637 2.828 5.36 3.965 7.469 1.133 2.105-.38 7.843 4.34 7.27 4.535-.571 3.777-4.403 4.91-6.505.566-.765 1.136-1.918 1.699-3.062l-.375.765c.375-.578.754-.765 1.508-1.343 0 0 5.289-2.868 11.332-6.508v8.804c1.699.766 3.398 1.153 5.097 1.532v-4.785l2.454.574v4.785c1.699.387 3.402.578 5.101.578v-4.789h2.266v4.598c1.695 0 3.398-.196 5.097-.578v-4.786l2.453-.574v4.977c1.7-.38 3.399-.766 5.098-1.532v-8.804a396.942 396.942 0 0 1 11.332 6.508c.754.578 1.133.765 1.512 1.343.566.762.941 1.72 1.32 2.297.946 1.914.375 5.934 4.91 6.504 4.536.578 3.211-5.164 4.344-7.27 1.133-2.109 6.61-3.64 3.965-7.468-2.645-3.637-5.664-1.149-7.93-.957h-3.59.754c-.754 0-.941 0-1.886-.574 0 0-5.477-3.446-11.899-7.278 2.078-3.25 3.024-6.695 3.024-10.527v-1.149c4.722-2.68 8.308-4.785 8.308-4.785.754-.574 1.32-.574 2.078-.574l-.57-.191c1.516.191 2.836.382 3.781.574 2.266.383 5.852 3.828 8.309-.383 2.453-4.21-3.59-6.89-5.098-9.574-.945-1.719-.758-5.164-2.078-7.27 0-.195-.191-.386-.191-.386C74.735.785 73.793.402 72.277.21zM34.324 23.376c.567 0 .758 0 1.32.191 2.645.766 3.403 3.254 2.645 6.125-.754 2.684-3.586 4.403-6.23 3.637-2.645-.766-3.59-3.445-2.645-6.121.57-2.3 2.645-3.832 4.91-3.832zm14.73 0c2.266 0 4.532 1.531 5.098 3.637.754 2.68 0 5.172-2.644 6.129-2.645.761-5.477-.77-6.23-3.641-.755-2.68 0-5.168 2.644-6.125a1.19 1.19 0 0 0 1.133 0zm-7.363 12.824c.754 0 3.961 4.215 3.586 4.79-.379.574-6.797.574-7.175 0-.38-.575 3.02-4.79 3.59-4.79zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dll.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.1-11.4h3.3v11.4h4.3v2.9h-7.6V6.4zm10.4 0h3.3v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><path class="st0" d="M54.2 1083.7l-17.1 2.3v13.5h17.1v-15.8zm-20.1 2.6l-17.1 2.3v10.9h17.1v-13.2zm-17 16.3v10.9l17.1 2.3v-13.1l-17.1-.1zm20 0v13.5l17.1 2.3v-15.8H37.1z" transform="translate(0 -1036.362)"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M67 .445 36.203 4.63v24.55H67zM30.797 5.172 0 9.355V29.18h30.797zM.18 34.82v19.825l30.797 4.183V35zm36.023 0v24.551L67 63.555V34.82zm0 0" fill="#666"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dmg.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#4d1b9b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm8.1-11.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4H21s.1 1.3 0 2.4l-.4 6.4h-3l1.2-14.3zm19.3-.3c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.7-7.6 6.5-7.6z" fill="#fff"/><path class="st0" d="M50.9 70.8c1.4 0 2.6.6 3.5 1.4l-3-21.8c-.2-1.8-1.8-3-3.5-3H25.1c-1.8 0-3.3 1.2-3.6 3l-3 21.8c1-.8 2.2-1.4 3.6-1.4h28.8zm0 1.7H22.1c-2 0-3.6 1.6-3.6 3.6v3.6c0 2 1.6 3.6 3.6 3.6h28.8c2 0 3.6-1.6 3.6-3.6v-3.6c0-2-1.6-3.6-3.6-3.6zm-3.1 6.9h-2.2c-.6 0-1.1-.5-1.1-1.1 0-.6.5-1.1 1.1-1.1h2.2c.6 0 1.1.5 1.1 1.1 0 .6-.5 1.1-1.1 1.1zm2.9 0c-.6 0-1.1-.5-1.1-1.1 0-.6.5-1.1 1.1-1.1s1.1.5 1.1 1.1c.1.6-.4 1.1-1.1 1.1z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M57.602 41.688c2.488 0 4.62 1.066 6.218 2.492L58.488 5.422C58.133 2.222 55.29.09 52.266.09H11.734c-3.199 0-5.867 2.133-6.402 5.332L0 44.18c1.777-1.426 3.91-2.493 6.398-2.493zm0 3.023H6.398A6.372 6.372 0 0 0 0 51.109v6.403a6.372 6.372 0 0 0 6.398 6.398h51.204A6.372 6.372 0 0 0 64 57.512v-6.403a6.372 6.372 0 0 0-6.398-6.398zM52.09 56.977h-3.91a1.97 1.97 0 0 1-1.957-1.954c0-1.066.886-1.957 1.957-1.957h3.91c1.066 0 1.953.891 1.953 1.957a1.97 1.97 0 0 1-1.953 1.954zm5.156 0a1.972 1.972 0 0 1-1.957-1.954c0-1.066.89-1.957 1.957-1.957s1.953.891 1.953 1.957c.18 1.067-.71 1.954-1.953 1.954zm0 0" fill="#4d1b9b"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dng.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zM19 6.4h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4s.2 1.5.2 2.4v6.6H19V6.4zm18.3-.3c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.1-4.5 2.6-7.6 6.5-7.6z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/doc.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1a75ce}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zM24.1 6.1c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2.1-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zM38 6.1c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.2 2.3-7.4 6.4-7.4z" fill="#fff"/><path class="st0" d="M19.5 67.1l-4.8-14.8c-.2-.6-.3-.8-.4-.8-.1-.1-.2-.1-.3-.2l-1.7-.5-.1-2.1h9l.2 2.1-1.7.5v.2c0 .2.1.6.3 1l1.8 5.7 3.2-9.5 2.4-.1 2.9 9.5 2-5.7c.1-.4.3-.8.3-1v-.1l-1.5-.4-.1-2.2h7l.2 2.1-1.9.6c-.1 0-.2.1-.3.1 0 .1-.2.2-.3.7l-5.3 14.7-2.5.2-2.7-9.1-3.2 8.9-2.5.2z"/><path d="M42.4 48.6H60v2.8H42.4zm0 7.4H60v2.8H42.4zm0 7.7H60v2.8H42.4zM13 71.5h47v2.8H13zm0 7.6h47v2.8H13z" fill="#1a75ce" stroke="#1a75ce" stroke-width=".5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/docb.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1a75ce}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.3-34.6h3.1c2.7 0 4.4 2.6 4.4 7.1s-1.7 7.2-4.4 7.2H6.3V6.4zm3.1 11.4c1.3 0 1.9-1.5 1.9-4.3s-.7-4.2-1.9-4.2h-.6v8.5h.6zM19.5 6.1c2.8 0 4.4 3.1 4.4 7.3 0 4.2-1.6 7.5-4.4 7.5s-4.4-3.2-4.4-7.5c0-4.1 1.5-7.3 4.4-7.3zm0 11.7c1.3 0 1.8-1.8 1.8-4.3s-.6-4.2-1.8-4.2-1.9 1.7-1.9 4.2.6 4.3 1.9 4.3zM29.8 6.1c.9 0 2 .4 2.7 1.2l-1 2.8c-.3-.5-1-.9-1.6-.9-1.6 0-2.4 1.9-2.4 4.2 0 2.3.9 4.4 2.4 4.4.7 0 1.3-.5 1.7-1l1 2.8c-.7.7-1.5 1.3-3 1.3-3 0-4.7-3.1-4.7-7.4.1-4.2 1.9-7.4 4.9-7.4zm4.2.3h3.1c1.9 0 3.2 1.3 3.2 3.7 0 1.2-.4 2.4-1.2 3 1.2.5 1.6 1.9 1.6 3.2 0 3.1-1.5 4.3-3.3 4.3H34V6.4zm3.1 5.6c.5 0 .7-.6.7-1.4s-.2-1.3-.8-1.3h-.6V12h.7zm.2 5.8c.6 0 .9-.7.9-1.6 0-.9-.2-1.5-.8-1.5h-.9v3.1h.8z" fill="#fff"/><path class="st0" d="M19.5 67.1l-4.8-14.8c-.2-.6-.3-.8-.4-.8-.1-.1-.2-.1-.3-.2l-1.7-.5-.1-2.1h9l.2 2.1-1.7.5v.2c0 .2.1.6.3 1l1.8 5.7 3.2-9.5 2.4-.1 2.9 9.5 2-5.7c.1-.4.3-.8.3-1v-.1l-1.5-.4-.1-2.2h7l.2 2.1-1.9.6c-.1 0-.2.1-.3.1 0 .1-.2.2-.3.7l-5.3 14.7-2.5.2-2.7-9.1-3.2 8.9-2.5.2z"/><path d="M42.4 48.6H60v2.8H42.4zm0 7.4H60v2.8H42.4zm0 7.7H60v2.8H42.4zM13 71.5h47v2.8H13zm0 7.6h47v2.8H13z" fill="#1a75ce" stroke="#1a75ce" stroke-width=".5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/docm.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1a75ce}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.3-34.6h3.1c2.7 0 4.4 2.6 4.4 7.1s-1.7 7.2-4.4 7.2H6.3V6.4zm3.1 11.4c1.3 0 1.9-1.5 1.9-4.3s-.7-4.2-1.9-4.2h-.6v8.5h.6zM19.5 6.1c2.8 0 4.4 3.1 4.4 7.3 0 4.2-1.6 7.5-4.4 7.5s-4.4-3.2-4.4-7.5c0-4.1 1.5-7.3 4.4-7.3zm0 11.7c1.3 0 1.8-1.8 1.8-4.3s-.6-4.2-1.8-4.2-1.9 1.7-1.9 4.2.6 4.3 1.9 4.3zM29.8 6.1c.9 0 2 .4 2.7 1.2l-1 2.8c-.3-.5-1-.9-1.6-.9-1.6 0-2.4 1.9-2.4 4.2 0 2.3.9 4.4 2.4 4.4.7 0 1.3-.5 1.7-1l1 2.8c-.7.7-1.5 1.3-3 1.3-3 0-4.7-3.1-4.7-7.4.1-4.2 1.9-7.4 4.9-7.4zm4.6.3h2.7l1 6c.1.9.3 2.4.3 2.4s.2-1.5.3-2.4l1-6h2.7l.7 14.3h-2.3l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.3 2.4l-.6 4.1h-2.4l-.6-4.1c-.2-.9-.3-2.4-.3-2.4h-.1s.1 1.3 0 2.4l-.3 6.4h-2.3l.9-14.3z" fill="#fff"/><path class="st0" d="M19.5 67.1l-4.8-14.8c-.2-.6-.3-.8-.4-.8-.1-.1-.2-.1-.3-.2l-1.7-.5-.1-2.1h9l.2 2.1-1.7.5v.2c0 .2.1.6.3 1l1.8 5.7 3.2-9.5 2.4-.1 2.9 9.5 2-5.7c.1-.4.3-.8.3-1v-.1l-1.5-.4-.1-2.2h7l.2 2.1-1.9.6c-.1 0-.2.1-.3.1 0 .1-.2.2-.3.7l-5.3 14.7-2.5.2-2.7-9.1-3.2 8.9-2.5.2z"/><path d="M42.4 48.6H60v2.8H42.4zm0 7.4H60v2.8H42.4zm0 7.7H60v2.8H42.4zM13 71.5h47v2.8H13zm0 7.6h47v2.8H13z" fill="#1a75ce" stroke="#1a75ce" stroke-width=".5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/docx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1a75ce}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.4-34.6h3.3c2.9 0 4.7 2.6 4.7 7.1s-1.8 7.2-4.7 7.2H6.4V6.4zm3.3 11.4c1.3 0 2.1-1.5 2.1-4.3S11 9.3 9.7 9.3H9v8.5h.7zM20 6.1c3 0 4.7 3.1 4.7 7.3 0 4.2-1.7 7.5-4.7 7.5s-4.7-3.2-4.7-7.5c0-4.1 1.7-7.3 4.7-7.3zm0 11.7c1.4 0 2-1.8 2-4.3s-.6-4.2-2-4.2-2 1.7-2 4.2.6 4.3 2 4.3zM30.7 6.1c1 0 2.1.4 2.9 1.2l-1.1 2.8c-.3-.5-1-.9-1.7-.9-1.7 0-2.6 1.9-2.6 4.2 0 2.3.9 4.4 2.5 4.4.8 0 1.3-.5 1.8-1l1.1 2.8c-.7.7-1.6 1.3-3.2 1.3-3.2 0-5-3.1-5-7.4.1-4.2 2-7.4 5.3-7.4zm5.9 7.5l-2.8-7.2h2.9l.9 2.9c.3.9.4 1.8.4 1.8s.2-.9.5-1.8l.9-2.9h2.9l-2.8 7.2 2.7 7.1h-2.8l-.9-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.4 1.7l-.9 3h-2.8l2.7-7.1z" fill="#fff"/><path class="st0" d="M19.5 67.1l-4.8-14.8c-.2-.6-.3-.8-.4-.8-.1-.1-.2-.1-.3-.2l-1.7-.5-.1-2.1h9l.2 2.1-1.7.5v.2c0 .2.1.6.3 1l1.8 5.7 3.2-9.5 2.4-.1 2.9 9.5 2-5.7c.1-.4.3-.8.3-1v-.1l-1.5-.4-.1-2.2h7l.2 2.1-1.9.6c-.1 0-.2.1-.3.1 0 .1-.2.2-.3.7l-5.3 14.7-2.5.2-2.7-9.1-3.2 8.9-2.5.2z"/><path d="M42.4 48.6H60v2.8H42.4zm0 7.4H60v2.8H42.4zm0 7.7H60v2.8H42.4zM13 71.5h47v2.8H13zm0 7.6h47v2.8H13z" fill="#1a75ce" stroke="#1a75ce" stroke-width=".5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dot.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1a75ce}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zM24.6 6.1c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2.1-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm10-8.5h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path class="st0" d="M19.5 67.1l-4.8-14.8c-.2-.6-.3-.8-.4-.8-.1-.1-.2-.1-.3-.2l-1.7-.5-.1-2.1h9l.2 2.1-1.7.5v.2c0 .2.1.6.3 1l1.8 5.7 3.2-9.5 2.4-.1 2.9 9.5 2-5.7c.1-.4.3-.8.3-1v-.1l-1.5-.4-.1-2.2h7l.2 2.1-1.9.6c-.1 0-.2.1-.3.1 0 .1-.2.2-.3.7l-5.3 14.7-2.5.2-2.7-9.1-3.2 8.9-2.5.2z"/><path d="M42.4 48.6H60v2.8H42.4zm0 7.4H60v2.8H42.4zm0 7.7H60v2.8H42.4zM13 71.5h47v2.8H13zm0 7.6h47v2.8H13z" fill="#1a75ce" stroke="#1a75ce" stroke-width=".5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dotm.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1a75ce}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.3-34.6h3.1c2.7 0 4.4 2.6 4.4 7.1s-1.7 7.2-4.4 7.2H6.3V6.4zm3.1 11.4c1.3 0 1.9-1.5 1.9-4.3s-.7-4.2-1.9-4.2h-.6v8.5h.6zM19.5 6.1c2.8 0 4.4 3.1 4.4 7.3 0 4.2-1.6 7.5-4.4 7.5s-4.4-3.2-4.4-7.5c0-4.1 1.5-7.3 4.4-7.3zm0 11.7c1.3 0 1.8-1.8 1.8-4.3s-.6-4.2-1.8-4.2-1.9 1.7-1.9 4.2.6 4.3 1.9 4.3zm7.1-8.5h-2.4V6.4h7.2v2.9H29v11.4h-2.4V9.3zm6.5-2.9h2.7l1 6c.2.9.3 2.4.3 2.4s.2-1.5.3-2.4l1-6h2.7l.7 14.3h-2.3l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.3 2.4l-.6 4.1H36l-.6-4.1c-.2-.9-.3-2.4-.3-2.4H35s.1 1.3 0 2.4l-.3 6.4h-2.3l.7-14.3z" fill="#fff"/><path class="st0" d="M19.5 67.1l-4.8-14.8c-.2-.6-.3-.8-.4-.8-.1-.1-.2-.1-.3-.2l-1.7-.5-.1-2.1h9l.2 2.1-1.7.5v.2c0 .2.1.6.3 1l1.8 5.7 3.2-9.5 2.4-.1 2.9 9.5 2-5.7c.1-.4.3-.8.3-1v-.1l-1.5-.4-.1-2.2h7l.2 2.1-1.9.6c-.1 0-.2.1-.3.1 0 .1-.2.2-.3.7l-5.3 14.7-2.5.2-2.7-9.1-3.2 8.9-2.5.2z"/><path d="M42.4 48.6H60v2.8H42.4zm0 7.4H60v2.8H42.4zm0 7.7H60v2.8H42.4zM13 71.5h47v2.8H13zm0 7.6h47v2.8H13z" fill="#1a75ce" stroke="#1a75ce" stroke-width=".5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dotx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1a75ce}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.5-34.6H10c3.1 0 5 2.6 5 7.1s-1.9 7.2-5 7.2H6.5V6.4zm3.4 11.4c1.4 0 2.2-1.5 2.2-4.3s-.8-4.2-2.2-4.2h-.7v8.5h.7zm11-11.7c3.2 0 5 3.1 5 7.3 0 4.2-1.8 7.5-5 7.5s-5-3.2-5-7.5c0-4.1 1.8-7.3 5-7.3zm0 11.7c1.4 0 2.1-1.8 2.1-4.3s-.6-4.2-2.1-4.2-2.1 1.7-2.1 4.2.7 4.3 2.1 4.3zm7.7-8.5h-2.7V6.4H34v2.9h-2.7v11.4h-2.8V9.3zm8.5 4.3l-2.9-7.2h3.1l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3.1l-2.9 7.2 2.8 7.1h-3l-.9-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.5 1.7l-1 3h-3l2.8-7.1z" fill="#fff"/><path class="st0" d="M19.5 67.1l-4.8-14.8c-.2-.6-.3-.8-.4-.8-.1-.1-.2-.1-.3-.2l-1.7-.5-.1-2.1h9l.2 2.1-1.7.5v.2c0 .2.1.6.3 1l1.8 5.7 3.2-9.5 2.4-.1 2.9 9.5 2-5.7c.1-.4.3-.8.3-1v-.1l-1.5-.4-.1-2.2h7l.2 2.1-1.9.6c-.1 0-.2.1-.3.1 0 .1-.2.2-.3.7l-5.3 14.7-2.5.2-2.7-9.1-3.2 8.9-2.5.2z"/><path d="M42.4 48.6H60v2.8H42.4zm0 7.4H60v2.8H42.4zm0 7.7H60v2.8H42.4zM13 71.5h47v2.8H13zm0 7.6h47v2.8H13z" fill="#1a75ce" stroke="#1a75ce" stroke-width=".5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/download.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#b4bdcc}</style><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/><path d="M55.2 55.5c1.7 1.6 2.8 4 2.8 6.6 0 5-4.1 9.1-9.1 9.1s-9.1-4.1-9.1-9.1c0-.3 0-.7.1-1 .5-4.5 4.4-8.1 9.1-8.1 2.4-.1 4.6 1 6.2 2.5z" opacity=".6" fill="#ef806f"/><path d="M55.9 52c0 .7-.1 1.4-.2 2.2-1.9-1.6-4.3-2.5-6.8-2.5-5.3 0-9.8 4-10.4 9.3H21.2c-4 0-7.2-3.2-7.2-7.2 0-3.1 2-5.8 4.7-6.8v-.4c0-3.7 3-6.7 6.7-6.7 1.2 0 2.3.3 3.3.8 1-4.5 5.1-8 10-8C44.4 32.7 49 37.3 49 43v.2c4 .9 6.9 4.5 6.9 8.8z" opacity=".6" fill="#1ea6c6"/><path class="st0" d="M53.7 62.2l-4.6 4.7-4.7-4.7h2.8v-6.5h3.7v6.5h2.8z"/></svg>
1
<svg height="64" width="72" xmlns="http://www.w3.org/2000/svg"><filter id="a" height="100%" width="100%" x="0%" y="0%"><feColorMatrix in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/></filter><mask id="c"><g filter="url(#a)"><path d="M0 0h72v64H0z" fill-opacity=".6"/></g></mask><clipPath id="b"><path d="M0 0h72v64H0z"/></clipPath><mask id="e"><g filter="url(#a)"><path d="M0 0h72v64H0z" fill-opacity=".6"/></g></mask><clipPath id="d"><path d="M0 0h72v64H0z"/></clipPath><g clip-path="url(#b)" mask="url(#c)"><path d="M67.418 37.824C70.199 40.454 72 44.391 72 48.656c0 8.207-6.71 14.934-14.89 14.934-8.184 0-14.891-6.727-14.891-14.934 0-.492 0-1.148.164-1.64.816-7.387 7.199-13.293 14.89-13.293 3.926-.164 7.528 1.64 10.145 4.101zm0 0" fill="#ef806f"/></g><g clip-path="url(#d)" mask="url(#e)"><path d="M68.563 32.082c0 1.148-.165 2.297-.325 3.61-3.11-2.626-7.039-4.102-11.129-4.102-8.672 0-16.035 6.562-17.02 15.262H11.782C5.238 46.852 0 41.602 0 35.035c0-5.086 3.273-9.515 7.691-11.16v-.656c0-6.07 4.91-10.992 10.965-10.992 1.961 0 3.762.492 5.399 1.312C25.69 6.152 32.398.41 40.418.41c9.328 0 16.855 7.547 16.855 16.902v.329c6.543 1.476 11.29 7.386 11.29 14.441zm0 0" fill="#1ea6c6"/></g><path d="m64.965 48.82-7.528 7.715-7.69-7.715h4.581V38.152h6.055V48.82zm0 0" fill="#fff"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dpj.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.1-11.4h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2H23v4.1h.7zm6.3 1.9h3.3v1.1c0 1.5.4 1.6.7 1.6.5 0 .7-.3.7-1.6v-7H32v-3h6v9.9c0 3.3-2 4.6-4 4.6-2.1 0-4-1.4-4-4.6v-1z" fill="#fff"/><path d="M45 67.1c2.2-.7 4.4.7 4.2 2.8-.2 2.4-3.3 3.6-5.1 4.2l.1-.1-.1-.1c1.3-1 3.9-2.2 3.7-4.6-.1-1.2-1-2.1-2.7-2v-.2H45zm-16.1.4l.1-.1c-1 0-1.9.4-2.7.7-.8.3-1.8.4-2.2 1.3.4.7 1.4.7 2.4.8 3.4.5 8.3.4 11.7 0 1.8-.2 3.4-.4 4.2-1.2l-.1-.1.1-.1c-3.4.4-7.8 1-11.9.8-1.3-.1-3-.1-3.7-.8.4-.7 1.4-.9 2.1-1.3zm19.9 14.1v-.1c-5.1 2.5-13.2 2.8-20.5 2.2l.1.1-.1.2c3 .5 6.9.7 10.7.4 3.7-.2 8.2-.7 9.9-2.7l-.1-.1zM34.4 66.2h.1c-.8-1.8-2.3-2.6-2.5-4.7-.2-1.9.7-3.1 1.6-4 1.1-1.2 2.7-2.2 3.9-3.5 1.6-1.8 3.4-4.5 1.9-7.1l-.1.1-.3-.1c.4 2.5-.6 4.1-1.9 5.4-1 1.2-2.6 2.2-4 3.3-1.6 1.3-3.7 2.9-3.1 5.3.5 2.3 2.8 3.9 4.1 5.4l.3-.1zm8-11.6l-.1-.1c-2.7 1-6.7 2.6-7.1 5.7-.1 1.5.4 2.6.9 3.4.4.6 1.1 1 1.3 1.9.2.8 0 1.6-.2 2.2h.1l.1.1c1.1-.8 2.2-1.9 1.9-3.4-.2-1.5-1.9-2.5-2.1-3.9-.1-.8.1-1.5.4-1.9 1.1-1.7 3.5-2.9 4.8-4zM28.6 72l-.1-.1c-.5.3-1.5.4-1.4 1.2s1.5 1 2.2 1.2c3.7.8 9.2.3 11.9-.6l-.1-.1.1-.1c-.3-.1-.7-.7-1.3-.7-.5-.1-1.6.3-2.6.4-1.6.2-3.3.3-4.8.2-1.1-.1-4.5-.1-3.9-1.4zm.9 4.1l.1-.1c-.6.2-1.3.4-1.3 1.1 0 .6 1.2 1 1.9 1.3 3.3 1 8.5.4 10.9-.7-.2-.3-.6-.4-.9-.6-.4-.1-.7-.3-1.1-.5-2 .5-5.1.7-7.5.4-.7-.1-1.7-.1-1.9-.8l-.2-.1zm17.7 3.2l-.1-.1c-.1 1-1.3 1.1-2.1 1.3-.9.2-1.9.4-3 .5-4.9.6-11.5.9-16.3 0-.9-.1-2.2-.4-2.5-1.1.4-.7 1.5-.8 2.4-1.2l-.1-.1.1-.1c-1.2.1-2.1.4-3 .7-.7.3-1.7.7-1.9 1.5.6.8 1.8.8 2.8 1 6.6 1 15.7 1.2 21.4-.7 1-.4 3.1-1 2.1-1.9l.2.2zm-3.7-5.1c.2 0 .4-.1.7-.2m.9-6.8c-.2 0-.4.1-.7.1M42.2 69c.1 0 .2-.1.4-.1m-12.5-1.6c-.4.1-.8.1-1.3.2m-2.2 15.9c.5.2 1.1.2 1.7.4m20.5-2.2c.1-.1.2-.2.3-.4m-9.9-34.3c0-.1-.1-.3-.1-.4m-4.7 19.7c.1.1.3.4.4.5m2.3 1.2c.1-.1.2-.2.3-.4m5.7-13.2c-.3.1-.5.2-.7.4m-1.2 18.8h.2m-12.6-1.8c0 .1-.2.1-.2.2m.9 4.2l.1-.1m-2.8 2.7c-.4 0-.7.1-1 .1m21.4.5c0-.1-.1-.1-.1-.1H47" fill="#666" stroke="#666" stroke-miterlimit="10"/></svg>
1
<svg height="63" width="49" xmlns="http://www.w3.org/2000/svg"><path d="M24.842 21.014c2.2-.7 4.4.7 4.202 2.8-.2 2.4-3.302 3.601-5.1 4.2l.1-.099-.1-.101c1.3-1 3.898-2.199 3.7-4.6-.1-1.2-1.001-2.098-2.702-2v-.2zm-16.099.401.1-.101c-1 0-1.901.4-2.701.7-.798.3-1.8.401-2.198 1.3.399.7 1.4.7 2.398.802 3.4.5 8.302.398 11.701 0 1.799-.201 3.4-.401 4.2-1.201l-.1-.101.1-.1c-3.4.402-7.8 1-11.9.8-1.301-.099-3-.099-3.7-.8.4-.7 1.4-.9 2.1-1.299zm19.9 14.099v-.1c-5.1 2.5-13.201 2.8-20.5 2.201l.1.1-.1.2c2.999.5 6.9.7 10.7.398 3.7-.198 8.199-.698 9.9-2.698zm-14.4-15.398h.1c-.8-1.802-2.3-2.602-2.499-4.7-.2-1.902.7-3.102 1.598-4 1.101-1.201 2.702-2.201 3.901-3.5 1.6-1.803 3.4-4.5 1.9-7.102l-.101.101-.299-.101c.4 2.5-.6 4.101-1.901 5.4-.999 1.201-2.6 2.201-4 3.3-1.6 1.3-3.7 2.901-3.1 5.3.502 2.302 2.8 3.9 4.102 5.4zm8-11.602-.1-.099c-2.7 1-6.701 2.6-7.1 5.698-.1 1.503.399 2.602.9 3.401.4.602 1.1 1 1.3 1.901.2.8 0 1.6-.2 2.2h.1l.1.1c1.099-.8 2.2-1.901 1.899-3.401-.198-1.5-1.9-2.5-2.1-3.899-.1-.802.1-1.5.401-1.9 1.1-1.701 3.5-2.902 4.8-4zm-13.8 17.401-.101-.101c-.5.301-1.5.4-1.4 1.2.1.8 1.5 1 2.2 1.2 3.7.8 9.2.3 11.902-.599l-.1-.101.1-.099c-.301-.101-.7-.7-1.3-.7-.502-.1-1.6.299-2.602.4-1.6.199-3.299.3-4.799.199-1.101-.1-4.5-.1-3.9-1.399zm.9 4.099.1-.1c-.6.201-1.3.4-1.3 1.1 0 .601 1.2 1 1.9 1.3 3.299 1 8.5.4 10.9-.699-.2-.302-.6-.4-.9-.601-.4-.1-.7-.3-1.1-.5-2.001.5-5.1.7-7.5.4-.7-.1-1.701-.1-1.9-.799zm17.699 3.2-.1-.099c-.098 1-1.3 1.1-2.1 1.3-.898.2-1.9.398-2.998.5-4.902.599-11.5.898-16.302 0-.898-.102-2.2-.401-2.499-1.102.4-.698 1.5-.8 2.399-1.198l-.098-.101.098-.1c-1.2.1-2.1.4-2.998.701-.7.3-1.701.698-1.902 1.5.6.8 1.801.8 2.8 1 6.6 1 15.7 1.198 21.402-.7.998-.401 3.098-1 2.1-1.901zm-3.7-5.099c.2 0 .4-.101.702-.2m.898-6.8c-.198 0-.399.1-.7.1m-2.2 1.7c.1 0 .2-.101.401-.101m-12.5-1.6c-.4.1-.8.1-1.3.201m-2.2 15.898c.499.2 1.099.2 1.7.401m20.5-2.2c.1-.1.2-.2.3-.399M19.043.814c0-.099-.098-.3-.098-.399m-4.702 19.7c.1.1.301.4.402.5m2.298 1.199c.1-.1.2-.198.3-.399m5.7-13.2c-.3.099-.499.2-.7.398m-1.198 18.802h.198m-12.6-1.8c0 .1-.2.1-.2.199m.9 4.2.101-.1m-2.8 2.701c-.4 0-.7.1-1 .1m21.399.5c0-.1-.1-.1-.1-.1h-.098" fill="#666" stroke="#666" stroke-miterlimit="10" transform="matrix(1.63519 0 0 1.61722 .336 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ds_store.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#b4bdcc}</style><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/><path d="M55.4 32.3H16.6c-1.5 0-2.6 1.2-2.6 2.6v26.9c0 1.5 1.2 2.6 2.6 2.6h38.7c1.5 0 2.6-1.2 2.6-2.6V35c.2-1.5-1-2.7-2.5-2.7z" fill="#ced2d8"/><path d="M16.6 38.8h38.8v23H16.6v-23z" fill="#f2f2f2"/><circle cx="23.7" cy="35.8" r=".9" fill="#54b845"/><circle cx="20.6" cy="35.8" r=".9" fill="#fbd303"/><circle cx="17.7" cy="35.8" r=".9" fill="#f0582f"/><path d="M49.2 56l-2.6-.7c-.2-1.1-.7-2.1-1.2-3l1.3-2.2c.2-.2.1-.6-.1-.8l-1.9-1.9c-.2-.2-.5-.2-.8-.1l-2.2 1.3c-.9-.5-1.9-1-3-1.2l-.7-2.5c-.1-.3-.3-.5-.6-.5h-2.6c-.3 0-.5.2-.6.5l-.8 2.5c-1.1.2-2.1.7-3 1.2l-2.3-1.2c-.2-.2-.6-.1-.8.1l-1.9 1.9c-.2.2-.2.5-.1.8l1.3 2.2c-.5.9-1 1.9-1.2 3l-2.5.6c-.3.1-.5.3-.5.6v2.6c0 .3.2.5.5.6l2.6.7c.2 1.1.7 2.1 1.2 3l-1.3 2.3c-.2.2-.1.6.1.8l1.9 1.9c.2.2.5.2.8.1l2.2-1.3c.9.5 1.9 1 3 1.2l.7 2.6c.1.3.3.5.6.5h2.6c.3 0 .5-.2.6-.5l.7-2.6c1.1-.2 2.1-.7 3-1.2l2.2 1.3c.2.2.6.1.8-.1l1.9-1.9c.2-.2.2-.5.1-.8l-1.3-2.2c.5-.9 1-1.9 1.2-3L49 60c.3-.1.5-.3.5-.6v-2.7c.1-.3 0-.5-.3-.7zM36 62.9c-2.7 0-4.9-2.2-4.9-4.9s2.2-4.9 4.9-4.9 4.9 2.2 4.9 4.9-2.2 4.9-4.9 4.9z" fill="#6eb1e1"/></svg>
1
<svg height="64" width="72" xmlns="http://www.w3.org/2000/svg"><path d="M67.566 0H4.56C2.125 0 .339 1.953.339 4.234V48.04c0 2.445 1.946 4.234 4.22 4.234h62.843c2.438 0 4.223-1.953 4.223-4.234V4.4C71.949 1.952 70.004 0 67.566 0zm0 0" fill="#ced2d8"/><path d="M4.559 10.586h63.007v37.453H4.56zm0 0" fill="#f2f2f2"/><path d="M17.55 5.7a1.462 1.462 0 1 1-2.921 0 1.462 1.462 0 1 1 2.922 0zm0 0" fill="#54b845"/><path d="M12.516 5.7c0 .808-.653 1.464-1.461 1.464a1.465 1.465 0 0 1 0-2.93c.808 0 1.46.657 1.46 1.465zm0 0" fill="#fbd303"/><path d="M7.809 5.7c0 .808-.657 1.464-1.461 1.464-.809 0-1.461-.656-1.461-1.465 0-.808.652-1.465 1.46-1.465.805 0 1.462.657 1.462 1.465zm0 0" fill="#f0582f"/><path d="m57.5 38.594-4.223-1.137c-.324-1.793-1.136-3.422-1.949-4.887l2.11-3.582c.324-.328.164-.976-.16-1.304L50.19 24.59c-.324-.324-.812-.324-1.3-.164l-3.57 2.117c-1.462-.813-3.087-1.625-4.872-1.953l-1.136-4.07c-.165-.489-.489-.817-.977-.817h-4.223c-.484 0-.808.328-.972.817l-1.301 4.07c-1.785.328-3.41 1.14-4.871 1.953l-3.735-1.953c-.324-.324-.972-.164-1.297.164l-3.085 3.094c-.325.324-.325.812-.164 1.3l2.113 3.586c-.813 1.465-1.625 3.094-1.95 4.883l-4.062.977c-.484.164-.809.488-.809.98v4.23c0 .493.325.817.81.981l4.222 1.137c.324 1.793 1.136 3.422 1.949 4.887l-2.11 3.746c-.324.324-.164.976.16 1.304l3.087 3.094c.324.324.812.324 1.3.16l3.57-2.117c1.462.816 3.087 1.629 4.872 1.957l1.137 4.234c.164.489.488.813.976.813h4.223c.484 0 .812-.324.972-.813l1.137-4.234c1.785-.328 3.41-1.14 4.871-1.957l3.574 2.117c.325.328.973.164 1.297-.16l3.086-3.094c.325-.328.325-.816.164-1.304l-2.113-3.582c.813-1.465 1.625-3.094 1.95-4.887l4.058-.977c.488-.164.812-.488.812-.976v-4.399c.164-.488 0-.812-.484-1.14zM36.062 49.832c-4.382 0-7.957-3.582-7.957-7.98 0-4.395 3.575-7.98 7.957-7.98 4.387 0 7.958 3.585 7.958 7.98 0 4.398-3.57 7.98-7.958 7.98zm0 0" fill="#6eb1e1"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dsn.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.8-1.1c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L26 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10-10.3H34l2.4 6.6c.4 1 .7 2.4.7 2.4h.1S37 13.9 37 13V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4z" fill="#fff"/><path class="st0" d="M24.7 63L41 60.3l-.6-2.6-16.3 2.7.6 2.6zm2.5 11.1l.6 2.8 6.6-1.3v-2.8l-7.2 1.3zm-.9-4.2l8.1-1.5v-2.2c0-.2 0-.4.1-.6l-8.8 1.6.6 2.7zm8.1 10l-8.2 1.7L20.8 57 42 53.6l1.7 7.5c.4 0 .8 0 1.1-.1l-3.2-14.1-23.5 3.4 7.2 32.9 9.2-1.9v-.1l-.1-1.3zm10.9-4.3c-5.1 0-9.3-1.7-9.3-3.7v3.7c0 2.1 4.2 3.7 9.3 3.7 5.1 0 9.3-1.7 9.3-3.7v-3.7c0 2-4.2 3.7-9.3 3.7zm0 5.5c-5.1 0-9.3-1.7-9.3-3.7v3.7c0 2.1 4.2 3.7 9.3 3.7 5.1 0 9.3-1.7 9.3-3.7v-3.7c0 2.1-4.2 3.7-9.3 3.7zm0-18.6c-5.1 0-9.3 1.7-9.3 3.7V70c0 2.1 4.2 3.7 9.3 3.7 5.1 0 9.3-1.7 9.3-3.7v-3.7c0-2.1-4.2-3.8-9.3-3.8z"/><path class="st0" d="M45.3 69.1c-5.1 0-8.4-1.7-8.4-2.8 0-1.1 3.3-2.8 8.4-2.8 5.1 0 8.4 1.7 8.4 2.8 0 1.1-3.3 2.8-8.4 2.8z"/></svg>
1
<svg height="63" width="62" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="m11.426 26.762 27.386-4.489-1.007-4.32-27.387 4.488zm4.203 18.453 1.008 4.652 11.086-2.16v-4.652zm-1.516-6.985 13.61-2.492v-3.656c0-.332 0-.664.168-.996l-14.786 2.656zm13.61 16.625L13.945 57.68l-9.07-40.89 35.617-5.653 2.856 12.468c.672 0 1.343 0 1.847-.168L39.82 0 .34 5.652 12.434 60.34l15.457-3.156v-.168zm18.312-7.148c-8.566 0-15.625-2.824-15.625-6.148v6.148c0 3.492 7.059 6.152 15.625 6.152 8.57 0 15.625-2.828 15.625-6.152v-6.148c0 3.324-7.055 6.148-15.625 6.148zm0 9.14c-8.566 0-15.625-2.824-15.625-6.148v6.149C30.41 60.34 37.47 63 46.035 63c8.57 0 15.625-2.824 15.625-6.152v-6.149c0 3.492-7.055 6.149-15.625 6.149zm0-30.917c-8.566 0-15.625 2.828-15.625 6.152v6.316c0 3.493 7.059 6.149 15.625 6.149 8.57 0 15.625-2.824 15.625-6.149v-6.152c0-3.488-7.055-6.316-15.625-6.316zm0 0"/><path d="M46.035 36.902c-8.566 0-14.11-2.824-14.11-4.656 0-1.828 5.544-4.652 14.11-4.652 8.57 0 14.113 2.824 14.113 4.652 0 1.832-5.543 4.656-14.113 4.656zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dtd.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm10.7-8.5h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3zm9.2-2.9h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z" fill="#fff"/><path d="M30.2 64.4l-11-5.5v-.1l11-5.4v-3.8l-14.6 7.8v3l14.6 7.7zm7.5-3.2l.7-12.8h-4.8l.7 12.8zm-1.7 8c1.6 0 2.7-1.4 2.7-3.1 0-1.9-1.1-3.1-2.7-3.1s-2.7 1.3-2.7 3.1c-.1 1.7 1 3.1 2.7 3.1zm5.8-19.6v3.8L53 58.8v.1l-11.2 5.5v3.7l14.6-7.7v-3.1zM17.8 73h36.5v2.5H17.8zm0 7.1h36.5v2.5H17.8z" fill="#999" stroke="#999" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><path d="m14.974 16.374-11-5.5v-.1l11-5.398V1.574L.374 9.375v3l14.6 7.7zm7.502-3.2L23.174.376h-4.798l.698 12.8zm-1.701 8.002c1.6 0 2.701-1.401 2.701-3.102 0-1.898-1.102-3.1-2.701-3.1s-2.701 1.3-2.701 3.1c-.1 1.7 1 3.102 2.701 3.102zm5.8-19.602v3.802l11.2 5.399v.1l-11.2 5.5v3.7l14.6-7.7v-3.1zm-24 23.401h36.5v2.5h-36.5zm0 7.1h36.5v2.5h-36.5zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.81211 0 0 1.83119 .353 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dwg.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#369}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4c3.5 0 5.6 2.6 5.6 7.1s-2.1 7.2-5.6 7.2h-4V6.4zm3.9 11.4c1.6 0 2.5-1.5 2.5-4.3s-.9-4.2-2.5-4.2h-.8v8.5h.8zm6.6-11.4h3.1l1.1 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.2-8.9h2.9l1.2 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.1-8.9h3.1L29 20.7h-3.5l-1.1-7.2c-.1-.9-.2-1.7-.2-1.7h-.1s0 .8-.1 1.7l-1 7.2h-3.6L17.1 6.4zm21.2-.3c1.3 0 2.8.4 3.7 1.3l-1.3 2.8c-.5-.6-1.3-.9-2.2-.9-2.1 0-3 1.9-3 4.2 0 2.6 1.1 4.3 2.7 4.3.6 0 1.2-.2 1.6-.6v-1.7h-1.4v-2.9h4.1v8.1h-2.4v-.9c-.5.7-1.5 1.2-2.6 1.2-2.6 0-5.3-2.7-5.3-7.3.1-4.5 2.5-7.6 6.1-7.6z" fill="#fff"/><path d="M51.6 65.9c-.5-.2-1.1 0-1.3.5-1.1 2.5-2.9 4.7-5.1 6.4l-6.7-13.6c1-.8 1.6-2 1.6-3.4 0-2.1-1.5-3.9-3.5-4.3v-3.4c0-.5-.4-1-1-1-.5 0-1 .4-1 1v3.4c-2 .4-3.5 2.2-3.5 4.3 0 1.4.6 2.6 1.6 3.4L26 72.8c-2.2-1.7-4-3.8-5.1-6.4-.2-.5-.8-.7-1.3-.5-.5.2-.7.8-.5 1.3 1.3 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.1 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2s6-.8 8.7-2.2l3.8 7.8c.1.3.5.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.7-4.4 6-7.3.6-.5.4-1.1 0-1.3zm-16-12.6c1.4 0 2.5 1.1 2.5 2.5s-1.1 2.5-2.5 2.5-2.5-1.1-2.5-2.5 1.2-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.8-2l6.8-13.7c.3.1.7.1 1.1.1s.7 0 1.1-.1l6.8 13.7c-2.5 1.3-5.2 2-8 2z" fill="#369" stroke="#369" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M33.325 19.55c-.498-.2-1.1 0-1.299.5-1.1 2.5-2.901 4.7-5.1 6.4l-6.7-13.601c1-.8 1.6-1.999 1.6-3.4 0-2.099-1.501-3.899-3.501-4.3v-3.4a1 1 0 0 0-2 0v3.4c-2 .401-3.5 2.201-3.5 4.3 0 1.401.6 2.6 1.601 3.4l-6.7 13.602c-2.201-1.7-4-3.801-5.1-6.401-.201-.5-.8-.7-1.301-.5-.499.199-.7.8-.499 1.3 1.299 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.098 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2 3.1 0 6-.8 8.699-2.2l3.8 7.8c.1.3.501.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.701-4.4 6-7.3.6-.5.401-1.101 0-1.3zM17.326 6.95c1.4 0 2.5 1.1 2.5 2.499 0 1.401-1.1 2.502-2.5 2.502s-2.5-1.1-2.5-2.502c0-1.4 1.199-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.801-2l6.8-13.7c.3.1.701.1 1.1.1.402 0 .701 0 1.1-.1l6.8 13.7c-2.5 1.3-5.199 2-7.999 2zm0 0" fill="#369" stroke="#369" stroke-miterlimit="10" stroke-width="1.5" transform="matrix(1.6544 0 0 1.63607 0 .154)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/dxf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#369}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H6.6V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm11.2-4.2l-3.4-7.2h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.2-7.1zm9.9-7.2h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path d="M51.6 65.9c-.5-.2-1.1 0-1.3.5-1.1 2.5-2.9 4.7-5.1 6.4l-6.7-13.6c1-.8 1.6-2 1.6-3.4 0-2.1-1.5-3.9-3.5-4.3v-3.4c0-.5-.4-1-1-1-.5 0-1 .4-1 1v3.4c-2 .4-3.5 2.2-3.5 4.3 0 1.4.6 2.6 1.6 3.4L26 72.8c-2.2-1.7-4-3.8-5.1-6.4-.2-.5-.8-.7-1.3-.5-.5.2-.7.8-.5 1.3 1.3 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.1 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2s6-.8 8.7-2.2l3.8 7.8c.1.3.5.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.7-4.4 6-7.3.6-.5.4-1.1 0-1.3zm-16-12.6c1.4 0 2.5 1.1 2.5 2.5s-1.1 2.5-2.5 2.5-2.5-1.1-2.5-2.5 1.2-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.8-2l6.8-13.7c.3.1.7.1 1.1.1s.7 0 1.1-.1l6.8 13.7c-2.5 1.3-5.2 2-8 2z" fill="#369" stroke="#369" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M33.325 19.55c-.498-.2-1.1 0-1.299.5-1.1 2.5-2.901 4.7-5.1 6.4l-6.7-13.601c1-.8 1.6-1.999 1.6-3.4 0-2.099-1.501-3.899-3.501-4.3v-3.4a1 1 0 0 0-2 0v3.4c-2 .401-3.5 2.201-3.5 4.3 0 1.401.6 2.6 1.601 3.4l-6.7 13.602c-2.201-1.7-4-3.801-5.1-6.401-.201-.5-.8-.7-1.301-.5-.499.199-.7.8-.499 1.3 1.299 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.098 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2 3.1 0 6-.8 8.699-2.2l3.8 7.8c.1.3.501.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.701-4.4 6-7.3.6-.5.401-1.101 0-1.3zM17.326 6.95c1.4 0 2.5 1.1 2.5 2.499 0 1.401-1.1 2.502-2.5 2.502s-2.5-1.1-2.5-2.502c0-1.4 1.199-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.801-2l6.8-13.7c.3.1.701.1 1.1.1.402 0 .701 0 1.1-.1l6.8 13.7c-2.5 1.3-5.199 2-7.999 2zm0 0" fill="#369" stroke="#369" stroke-miterlimit="10" stroke-width="1.5" transform="matrix(1.6544 0 0 1.63607 0 .154)"/></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/editorconfig.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M42.3 44.7c0-2.5-1.5-4.5-3.7-5.4V32c0-1.2-.9-2.1-2.1-2.1s-2.1.9-2.1 2.1v7.3c-2.2.8-3.7 2.9-3.7 5.4s1.5 4.6 3.7 5.4c0 .1-.1.3-.1.4v18.4c0 1.2.9 2.1 2.1 2.1s2.1-.9 2.1-2.1V50.5c0-.2 0-.3-.1-.4 2.4-.8 3.9-2.9 3.9-5.4zm-5.8 1.6c-.9 0-1.6-.7-1.6-1.6s.7-1.6 1.6-1.6 1.6.7 1.6 1.6-.7 1.6-1.6 1.6zm16.8-14.2c0-1.2-.9-2.1-2.1-2.1s-2.1.9-2.1 2.1v17.2c-2.2.8-3.7 2.9-3.7 5.4s1.5 4.6 3.7 5.4c0 .1-.1.3-.1.4v8.4c0 1.2.9 2.1 2.1 2.1s2.1-.9 2.1-2.1v-8.4c0-.2 0-.3-.1-.4 2.2-.8 3.7-2.9 3.7-5.4s-1.5-4.5-3.7-5.4V32.1h.2zm-2.1 24.2c-.9 0-1.6-.7-1.6-1.6s.7-1.6 1.6-1.6 1.6.7 1.6 1.6-.7 1.6-1.6 1.6zM19.7 68.9c0 1.2.9 2.1 2.1 2.1s2.1-.9 2.1-2.1v-8.4c0-.2 0-.3-.1-.4 2.2-.8 3.7-2.9 3.7-5.4s-1.5-4.5-3.7-5.4V32.1c0-1.2-.9-2.1-2.1-2.1s-2.1.9-2.1 2.1v17.2c-2.2.8-3.7 2.9-3.7 5.4s1.5 4.6 3.7 5.4c0 .1-.1.3-.1.4v8.4h.2zm2.1-15.8c.9 0 1.6.7 1.6 1.6s-.7 1.6-1.6 1.6-1.6-.7-1.6-1.6.7-1.6 1.6-1.6z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/el.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h7.2v2.9H9.9V12H13v2.9H9.9v2.9H14v2.9H6.6V6.4zm10.5 0h3.3v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><path id="path10" d="M47.9 75h.8c0 2.4-.4 4.2-1.2 5.3-.8 1.1-1.8 1.7-3 1.7-1 0-1.9-.4-2.8-1.1-.9-.7-1.7-2.7-2.4-5.9l-2-8.9-6.9 15.6H26l9.9-21.2c-.5-2.7-1.2-4.8-1.9-6.1s-1.7-2-2.7-2c-.9 0-1.6.3-2.3 1-.6.7-1 1.7-1.1 3.1h-.8c0-2.3.5-4.1 1.4-5.4s1.9-2 3.2-2c.8 0 1.6.3 2.3 1 .7.7 1.4 1.8 1.9 3.5.6 1.7 1.4 5.1 2.6 10.3l1.6 7.3c.7 3 1.4 5 2.1 6.1.7 1 1.6 1.5 2.6 1.5 1.9-.1 2.9-1.3 3.1-3.8z" fill="#999" stroke="#999" stroke-miterlimit="10"/></svg>
1
<svg height="63" width="45" xmlns="http://www.w3.org/2000/svg"><path d="M22.686 26.4h.8c0 2.401-.4 4.2-1.2 5.3-.801 1.1-1.8 1.7-3 1.7-1.001 0-1.9-.4-2.8-1.1-.9-.699-1.701-2.7-2.4-5.9l-2-8.9-6.902 15.599h-4.4l9.901-21.2c-.5-2.698-1.2-4.799-1.899-6.098-.701-1.3-1.7-2.002-2.7-2.002-.902 0-1.601.301-2.3 1-.6.7-1 1.701-1.1 3.1h-.8c0-2.299.5-4.1 1.4-5.4.899-1.3 1.898-2 3.2-2 .8 0 1.599.302 2.3 1.002.7.699 1.4 1.799 1.9 3.499.599 1.7 1.4 5.1 2.6 10.3l1.599 7.3c.701 3 1.4 5 2.1 6.1.7 1 1.6 1.5 2.6 1.5 1.9-.1 2.901-1.3 3.101-3.8zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" transform="matrix(1.87615 0 0 1.85407 0 .073)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/elf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h7.2v2.9H9.9V12H13v2.9H9.9v2.9H14v2.9H6.6V6.4zm10.5 0h3.3v11.4h4.3v2.9h-7.6V6.4zm10.3 0h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M49 49.8H23.5v3.5h-5.2v1.1h-2.8v1h2.8v1.3h5.2v6.1h-5.2V64h-2.8v1h2.8v1.1h5.2v6.6h-5.2v1.2h-2.8v1h2.8V76h5.2v4.7H49V76h4.7v-1.2h2.8v-1h-2.8v-1.2H49V66h4.7v-1h2.8v-1h-2.8v-1.3H49v-6.1h4.7v-1.3h2.8v-1h-2.8v-1.1H49v-3.4zm-4.9 8.3c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2c0 1.2-.9 2-2 2z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M68.633.102H16.39v7.226H5.738v2.274H0v2.062h5.738v2.684h10.653V26.94H5.738v2.477H0v2.066h5.738v2.27h10.653v13.625H5.738v2.48H0v2.063h5.738v2.273h10.653v9.703h52.242v-9.703h9.629v-2.48H84v-2.063h-5.738v-2.476h-9.63v-13.63h9.63v-2.062H84v-2.066h-5.738v-2.684h-9.63V14.141h9.63v-2.684H84V9.395h-5.738V7.12h-9.63zm-10.04 17.136c-2.253 0-4.097-1.86-4.097-4.129S56.34 8.98 58.594 8.98s4.097 1.86 4.097 4.13c0 2.476-1.843 4.128-4.097 4.128zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/eml.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#7e57c2}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h7.2v2.9H9.9V12H13v2.9H9.9v2.9H14v2.9H6.6V6.4zm11 0h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.2-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4H20s.1 1.3 0 2.4l-.4 6.4h-3l1-14.3zm15.1 0H36v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><path d="M21.9 77.2h28.3l-9.7-9.3-4.5 3.8-4.5-3.8-9.6 9.3zM56 52v28H16V52h40zM42.6 66.2l10.7 10.3V57.2l-10.7 9zM18.4 76.5l10.7-10.3-10.7-9v19.3zm1.4-21.7l15.9 13.4 15.9-13.4H19.8z" fill="#7e57c2" stroke="#7e57c2" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="fill-rule:nonzero;fill:#7e57c2;fill-opacity:1;stroke-width:.75;stroke-linecap:butt;stroke-linejoin:miter;stroke:#7e57c2;stroke-opacity:1;stroke-miterlimit:10" d="M6.274 25.574h28.3l-9.698-9.3-4.501 3.802-4.5-3.802zm34.1-25.2v28.002H.376V.374zM26.976 14.576l10.7 10.298v-19.3zm-24.2 10.298 10.7-10.298-10.7-9.002zm1.4-21.7 15.9 13.4 15.9-13.4zm0 0" transform="matrix(2.06135 0 0 2.08166 0 .076)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/enc.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#696}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h7.2v2.9H9.9V12H13v2.9H9.9v2.9H14v2.9H6.6V6.4zm10.5 0h3.5L23 13c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4H20s.2 1.5.2 2.4v6.6h-3.1V6.4zm19.1-.3c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4z" fill="#fff"/><path class="st0" d="M49.2 62.2h-2.6v-5C46.6 51.5 42 47 36.4 47s-10.2 4.6-10.2 10.2v5h-2.6c-1 0-1.8.8-1.8 1.8v17.4c0 1 .8 1.8 1.8 1.8h25.6c1 0 1.8-.8 1.8-1.8V63.9c0-.9-.8-1.7-1.8-1.7zM38.6 76.6c.2.6-.3 1.1-.9 1.1H35c-.6 0-1-.6-.9-1.1l.8-3.2c-1-.5-1.7-1.5-1.7-2.8 0-1.7 1.4-3.1 3.1-3.1 1.7 0 3.1 1.4 3.1 3.1 0 1.2-.7 2.3-1.7 2.8l.9 3.2zm2.9-14.4H31.3v-5c0-2.8 2.3-5.1 5.1-5.1s5.1 2.3 5.1 5.1v5z"/></svg>
1
<svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#696"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/eot.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#36454d}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h7.2v2.9H9.9V12H13v2.9H9.9v2.9H14v2.9H6.6V6.4zm15.5-.3c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2.1-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2c.1 2.5.8 4.3 2.5 4.3zm10.6-8.5h-3.1V6.4h9.6v2.9H36v11.4h-3.3V9.3z" fill="#fff"/><path d="M28.1 68.3h-8.9l-1.1 2.4c-.3.8-.5 1.4-.5 2 0 .7.3 1.2.9 1.5.3.2 1.2.3 2.5.4v.7h-8.4v-.7c.9-.1 1.6-.5 2.2-1.1.6-.6 1.3-1.8 2.1-3.7l9-19.4h.4l9.1 19.9c.9 1.9 1.6 3.1 2.1 3.6.4.4 1 .6 1.8.6v.7H27.2v-.7h.5c1 0 1.7-.1 2.1-.4.3-.2.4-.5.4-.8 0-.2 0-.4-.1-.7 0-.1-.2-.6-.6-1.3l-1.4-3zm-.6-1.3l-3.7-8.4-3.9 8.4h7.6z" fill="#7291a1"/><path class="st0" d="M58.2 59.2l-3.6 11.9-.4 1.5c0 .2-.1.3-.1.4 0 .1.1.3.2.4.1.1.2.2.3.2.3 0 .6-.2 1.1-.6.2-.2.6-.7 1.3-1.6l.6.3c-.9 1.6-1.8 2.7-2.8 3.4-1 .7-2.1 1.1-3.2 1.1-.7 0-1.2-.2-1.6-.5-.4-.4-.6-.8-.6-1.3s.2-1.3.6-2.6l.4-1.5c-1.4 2.4-2.8 4.1-4.1 5.1-.8.6-1.6.9-2.4.9-1.1 0-2-.5-2.5-1.4s-.8-1.9-.8-3.1c0-1.7.5-3.6 1.6-5.8 1.1-2.2 2.5-3.9 4.2-5.3 1.4-1.1 2.8-1.6 4-1.6.7 0 1.2.2 1.7.6.4.4.7 1.1.9 2.1l.7-2.2 4.5-.4zm-5.9 3.5c0-1-.2-1.7-.5-2.1-.2-.3-.5-.4-.9-.4s-.8.2-1.2.5c-.8.7-1.7 2.2-2.7 4.5-1 2.3-1.4 4.2-1.4 5.9 0 .6.1 1.1.3 1.4.2.3.5.4.7.4.6 0 1.1-.3 1.7-.9.8-.9 1.6-2 2.2-3.2 1.2-2.4 1.8-4.4 1.8-6.1z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="48"><path style="stroke:none;fill-rule:nonzero;fill:#7291a1;fill-opacity:1" d="M28.621 33.172h-16.32l-2.012 4.45c-.55 1.483-.918 2.593-.918 3.706 0 1.297.547 2.223 1.649 2.781.55.371 2.203.555 4.582.743v1.293H.203v-1.293c1.652-.188 2.934-.93 4.035-2.04 1.098-1.113 2.383-3.34 3.848-6.859L24.586 0h.73L42 36.879c1.648 3.52 2.934 5.746 3.852 6.672.73.742 1.832 1.113 3.296 1.113v1.297h-22.18v-1.297h.919c1.832 0 3.113-.184 3.847-.742.551-.371.735-.926.735-1.48 0-.372 0-.743-.184-1.301 0-.184-.367-1.11-1.101-2.407zm-1.101-2.406-6.786-15.57-7.148 15.57zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#36454d;fill-opacity:1" d="m83.797 16.309-6.602 22.054-.734 2.778c0 .375-.184.558-.184.742 0 .187.184.558.371.742.184.188.368.371.547.371.551 0 1.102-.371 2.016-1.113.371-.367 1.102-1.297 2.387-2.965l1.097.559c-1.648 2.964-3.3 5.003-5.132 6.3-1.833 1.297-3.852 2.04-5.864 2.04-1.285 0-2.203-.372-2.933-.93-.735-.742-1.102-1.485-1.102-2.407 0-.93.367-2.41 1.102-4.82l.73-2.781c-2.562 4.45-5.133 7.601-7.516 9.453C60.516 47.442 59.05 48 57.582 48c-2.016 0-3.668-.926-4.582-2.594-.918-1.668-1.465-3.523-1.465-5.746 0-3.152.914-6.672 2.934-10.75 2.011-4.074 4.582-7.226 7.695-9.82 2.566-2.04 5.133-2.965 7.332-2.965 1.285 0 2.203.367 3.121 1.11.73.742 1.281 2.038 1.649 3.89l1.28-4.074zM72.98 22.797c0-1.856-.367-3.152-.918-3.895-.367-.554-.914-.742-1.648-.742-.734 0-1.469.375-2.2.93-1.464 1.297-3.116 4.074-4.948 8.336-1.832 4.265-2.57 7.785-2.57 10.937 0 1.11.183 2.035.554 2.594.363.559.914.742 1.281.742 1.098 0 2.016-.558 3.117-1.668 1.465-1.668 2.934-3.707 4.032-5.93 2.199-4.449 3.3-8.156 3.3-11.304zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/eps.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fea500}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h7.2v2.9H9.9V12H13v2.9H9.9v2.9H14v2.9H6.6V6.4zm10.5 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm8.5 3.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L35 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path class="st0" d="M27.1 60.2L18 79.4l1.7 1.7L31 69.8c-.4-.9-.3-2 .5-2.8 1-1 2.5-1 3.5 0s1 2.5 0 3.5c-.7.7-1.9.9-2.8.5L20.9 82.3l1.7 1.7 19.2-9.1L46 63.4 38.6 56l-11.5 4.2zm26.3-2.3L44 48.5c-.8-.8-2-.8-2.8 0L39 50.7c-.8.8-.8 2 0 2.8l9.4 9.4c.8.8 2 .8 2.8 0l2.2-2.2c.8-.8.8-2 0-2.8z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M16.223 21.805.09 55.844l3.012 3.015 20.035-20.035c-.711-1.594-.532-3.543.886-4.96 1.774-1.774 4.43-1.774 6.204 0 1.773 1.769 1.773 4.429 0 6.202-1.243 1.243-3.368 1.594-4.965.887L5.23 60.984 8.242 64l34.04-16.133L49.73 27.48 36.61 14.36zm46.625-4.075L46.184 1.062c-1.418-1.417-3.547-1.417-4.965 0L37.32 4.966c-1.422 1.418-1.422 3.543 0 4.965l16.664 16.664c1.418 1.418 3.543 1.418 4.965 0l3.899-3.903c1.418-1.418 1.418-3.543 0-4.96zm0 0" fill="#fea500"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/epub.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#963}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.5-34.6H13v2.9H9.5V12h2.8v2.9H9.5v2.9h3.7v2.9H6.5V6.4zm8.1 0h4.1c2.4 0 3.9 2 3.9 4.9s-1.6 5-3.9 5h-1.1v4.4h-3V6.4zm3.5 7c.9 0 1.5-.9 1.5-2.1s-.6-2-1.4-2h-.6v4.1h.5zm5.6-7h3V16c0 1.4.5 1.9 1.4 1.9.8 0 1.3-.5 1.3-1.9V6.4h3V16c0 3-1.7 4.9-4.3 4.9S23.8 19 23.8 16V6.4h-.1zm10.5 0H38c2.2 0 3.8 1.3 3.8 3.7 0 1.2-.5 2.4-1.5 3 1.5.5 1.9 1.9 1.9 3.2 0 3.1-1.8 4.3-4 4.3h-4V6.4zM38 12c.6 0 .8-.6.8-1.4s-.3-1.3-.9-1.3h-.7V12h.8zm.1 5.8c.7 0 1-.7 1-1.6s-.3-1.5-1-1.5H37v3.1h1.1z" fill="#fff"/><path id="path1236" class="st0" d="M56.6 61.3c-.2-.5-.6-.9-1-1.3-.1.4-.2.8-.5 1.2L42.6 80.5c-.5.7-1.5.9-2.3.7l-20-5.6c-1.2-.3-2.6-1-2.7-2.4 0-.5 0-.7.3-.9.3-.2.6-.2.9-.1l18.8 5.2c2.7.8 3.5.2 5.5-2.8L54.5 57c.6-.9.7-2 .4-2.9s-1.1-1.6-2.1-1.9l-16.5-4.6c-.4-.1-.8-.1-1.2-.1v-.1c-2.5-1.5-3.5 1.3-4.8 2.4-.5.4-1.1.7-1.3 1.1-.2.4-.1.8-.2 1.1-.5 1.1-1.9 2.9-2.6 3.4-.4.3-1 .4-1.3.9-.2.3-.2.9-.3 1.3-.4 1-1.7 2.7-2.6 3.5-.3.3-.8.5-1 .9-.2.3-.1.9-.4 1.2-.6 1-1.8 2.6-2.7 3.5-.5.5-1.1.7-1.3 1.2-.1.2 0 .6-.1.9-.2.5-.4.9-.5 1.3-.5.7-.8 1.7-.7 2.7.2 2.4 2 4.8 4.2 5.4l20 5.6c1.9.5 4.2-.4 5.2-2l11.5-17.7c.6-.8.7-1.9.4-2.8zm-23.1-6.4l.8-1.2c.2-.3.7-.5 1.1-.4L48.6 57c.4.1.5.5.3.8l-.8 1.2c-.2.3-.7.5-1.1.4l-13.2-3.7c-.4-.1-.5-.4-.3-.8zm-3.3 5l.8-1.2c.2-.3.7-.5 1.1-.4L45.3 62c.4.1.5.5.3.8l-.8 1.2c-.2.3-.7.5-1.1.4l-13.2-3.7c-.4-.1-.6-.5-.3-.8z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><path d="M69.723 24.898c-.336-.851-1.012-1.535-1.688-2.222-.168.687-.336 1.37-.844 2.054L46.098 57.723c-.844 1.199-2.532 1.539-3.88 1.199l-33.75-9.574c-2.023-.512-4.386-1.711-4.554-4.106 0-.851 0-1.195.504-1.535.508-.344 1.016-.344 1.52-.172l31.726 8.89c4.555 1.368 5.902.34 9.277-4.788l19.239-30.09a5.83 5.83 0 0 0 .675-4.957c-.507-1.54-1.855-2.735-3.543-3.246L35.47 1.48c-.676-.171-1.352-.171-2.024-.171v-.172c-4.218-2.563-5.906 2.222-8.101 4.101-.844.684-1.856 1.2-2.196 1.883-.336.684-.168 1.367-.336 1.879-.843 1.883-3.207 4.957-4.386 5.813-.676.515-1.688.683-2.196 1.539-.335.511-.335 1.539-.503 2.222-.676 1.711-2.872 4.617-4.387 5.985-.508.511-1.352.855-1.688 1.539-.34.511-.172 1.539-.675 2.05-1.012 1.711-3.04 4.446-4.559 5.985-.844.855-1.856 1.195-2.191 2.05-.168.34 0 1.028-.168 1.54-.34.855-.676 1.539-.844 2.222C.37 41.141-.137 42.852.03 44.56c.34 4.105 3.375 8.207 7.09 9.234l33.746 9.574c3.207.852 7.09-.683 8.778-3.422l19.402-30.258c1.016-1.367 1.183-3.25.676-4.789zm-38.98-10.941 1.35-2.05c.337-.512 1.18-.856 1.856-.684l22.274 6.324c.675.172.843.855.507 1.371l-1.351 2.05c-.336.512-1.18.856-1.856.684L31.25 15.328c-.676-.172-.844-.687-.508-1.371zm-5.567 8.55 1.347-2.054c.34-.512 1.184-.851 1.86-.683l22.273 6.328c.676.172.844.855.504 1.367l-1.347 2.05c-.34.512-1.184.856-1.856.684L25.68 23.875c-.672-.172-1.012-.855-.504-1.367zm0 0" fill="#963"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/eslintignore.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm2.5 10c-8-8-21-8-29 0s-8 21 0 29 21 8 29 0 8-21 0-29zM23.3 58.7c-3.8-5.9-3.1-13.8 2-18.9s13-5.8 18.9-2L23.3 58.7zm4.5 4.5l20.9-20.9c3.8 5.9 3.1 13.8-2 18.9s-13 5.8-18.9 2z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M54.633 9.367C42.145-3.12 21.855-3.12 9.367 9.367s-12.488 32.778 0 45.266 32.778 12.488 45.266 0 12.488-32.778 0-45.266zM12.176 44.801c-5.934-9.211-4.84-21.543 3.12-29.504s20.294-9.055 29.505-3.121zm7.023 7.023L51.824 19.2c5.934 9.211 4.84 21.543-3.12 29.504s-20.294 9.055-29.505 3.121zm0 0" fill="#bababa"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/exe.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><path d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h7.2v2.9H9.9V12H13v2.9H9.9v2.9H14v2.9H6.6V6.4zm12.8 7.2L16 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.2-7.1zm9.9-7.2h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4z" fill="#fff"/><path d="M53.8 69.2c-1.6-.5-2.7-2-2.7-3.7s1.1-3.2 2.7-3.7c.5-.2.8-.7.6-1.2-.5-1.8-1.1-3.4-2.1-5-.3-.5-.8-.6-1.3-.4-.6.3-1.2.5-1.9.5-2.2 0-3.9-1.8-3.9-3.9 0-.7.2-1.3.5-1.9.3-.5.1-1-.4-1.3-1.6-.9-3.3-1.6-5-2.1-.5-.1-1 .1-1.2.6-.5 1.6-2 2.7-3.7 2.7s-3.2-1.1-3.7-2.7c-.2-.5-.7-.8-1.2-.6-1.8.5-3.4 1.1-5 2.1-.5.3-.6.8-.4 1.3.3.6.5 1.2.5 1.9 0 2.2-1.8 3.9-3.9 3.9-.7 0-1.3-.2-1.9-.5-.5-.3-1-.1-1.3.4-.9 1.6-1.6 3.3-2.1 5-.1.5.1 1 .6 1.2 1.6.5 2.7 2 2.7 3.7 0 1.7-1.1 3.2-2.7 3.7-.5.2-.8.7-.6 1.2.5 1.8 1.1 3.4 2.1 5 .3.5.8.6 1.3.4.6-.3 1.2-.5 1.9-.5 2.2 0 3.9 1.8 3.9 3.9 0 .7-.2 1.3-.5 1.9-.3.5-.1 1 .4 1.3 1.6.9 3.3 1.6 5 2.1h.2c.4 0 .8-.3.9-.7.5-1.6 2-2.7 3.7-2.7 1.7 0 3.2 1.1 3.7 2.7.2.5.7.8 1.2.6 1.8-.5 3.4-1.1 5-2.1.5-.3.6-.8.4-1.3-.3-.6-.5-1.2-.5-1.9 0-2.2 1.8-3.9 3.9-3.9.7 0 1.3.2 1.9.5.5.3 1 .1 1.3-.4.9-1.6 1.6-3.3 2.1-5 .3-.4 0-.9-.5-1.1zm-18.3 2.2c-3.2 0-5.9-2.6-5.9-5.9 0-3.2 2.6-5.9 5.9-5.9 3.2 0 5.9 2.6 5.9 5.9 0 3.2-2.7 5.9-5.9 5.9z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M62.887 38.266c-2.684-.84-4.532-3.36-4.532-6.215 0-2.852 1.848-5.371 4.532-6.211.84-.336 1.343-1.172 1.008-2.012-.84-3.023-1.848-5.707-3.524-8.394-.504-.84-1.344-1.008-2.184-.672-1.007.504-2.015.84-3.19.84-3.692 0-6.548-3.024-6.548-6.547 0-1.176.336-2.184.84-3.188.504-.84.168-1.68-.672-2.183a40.47 40.47 0 0 0-8.39-3.528c-.84-.168-1.68.168-2.016 1.008C37.37 3.852 34.855 5.7 32 5.7s-5.371-1.847-6.21-4.535C25.452.324 24.612-.18 23.772.156c-3.02.84-5.707 1.848-8.39 3.528-.84.503-1.008 1.343-.672 2.183.504 1.004.84 2.012.84 3.188 0 3.691-3.024 6.547-6.547 6.547-1.176 0-2.184-.336-3.191-.84-.84-.504-1.68-.168-2.184.672a40.699 40.699 0 0 0-3.524 8.394c-.167.84.168 1.676 1.008 2.012 2.684.84 4.532 3.36 4.532 6.21 0 2.856-1.848 5.376-4.532 6.216-.84.332-1.343 1.172-1.008 2.011.84 3.024 1.848 5.707 3.524 8.395.504.84 1.344 1.008 2.184.672 1.007-.504 2.015-.84 3.19-.84 3.692 0 6.548 3.02 6.548 6.547 0 1.176-.336 2.183-.84 3.187-.504.84-.168 1.68.672 2.184a40.47 40.47 0 0 0 8.39 3.527h.336c.672 0 1.344-.504 1.512-1.176.84-2.687 3.356-4.535 6.211-4.535s5.371 1.848 6.211 4.535c.336.84 1.176 1.344 2.016 1.008 3.02-.84 5.707-1.847 8.39-3.527.84-.504 1.008-1.344.672-2.184-.504-1.004-.84-2.011-.84-3.187 0-3.692 3.024-6.547 6.547-6.547 1.176 0 2.184.336 3.192.84.84.504 1.68.168 2.183-.672a40.698 40.698 0 0 0 3.524-8.395c.503-.672 0-1.511-.84-1.843zm-30.719 3.691c-5.371 0-9.902-4.363-9.902-9.906 0-5.371 4.363-9.903 9.902-9.903 5.371 0 9.902 4.364 9.902 9.903 0 5.375-4.53 9.906-9.902 9.906zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/f4v.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d10407}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h7.1v2.9H9.9v3.1H13v2.9H9.9v5.4H6.6V6.4zm9.3 8.8l3.7-8.8h4.2v8.1H25v3h-1.2v3.2h-3.2v-3.2h-4.7v-2.3zm4.7-.7v-3.4c0-.8.1-1.3.1-1.3s-.1.6-.3 1.2L19 14.5h1.6zm6.1-8.1h3.6l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3l1.7-8.1h3.5l-3.9 14.3h-3.3L26.7 6.4z" fill="#fff"/><path class="st0" d="M47.2 55.6c1-.4 2.1-.5 3.2-.5V48c-4.8-.1-9.4 2-12.4 5.8-1.2 1.6-2.3 3.3-3.1 5.2l-2.3 5.7c-.6 1.7-1.3 3.5-2.1 5.1-.6 1.4-1.3 2.6-2.2 3.8-.7 1-1.7 1.8-2.8 2.3-1.2.6-2.6.9-4 .9V84c4.8.1 9.4-2 12.4-5.8.9-1.3 1.8-2.7 2.5-4.1l1.9-4.5h8.3v-7.1h-5.5c.4-1.1 1-2.1 1.7-3.1.5-.9 1.2-1.6 1.9-2.2.9-.8 1.7-1.3 2.5-1.6z"/></svg>
1
<svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M46.168 13.516c1.793-.711 3.766-.891 5.738-.891V.008c-8.605-.18-16.851 3.554-22.23 10.308-2.153 2.844-4.125 5.864-5.559 9.243l-4.12 10.128c-1.079 3.024-2.333 6.223-3.767 9.067a31.916 31.916 0 0 1-3.945 6.754c-1.254 1.777-3.047 3.199-5.02 4.09-2.152 1.066-4.66 1.597-7.171 1.597v12.797c8.605.18 16.851-3.554 22.23-10.308 1.613-2.309 3.227-4.797 4.485-7.286l3.406-8h14.879v-12.62h-9.86c.715-1.954 1.793-3.731 3.047-5.508.895-1.602 2.153-2.844 3.407-3.91 1.613-1.422 3.046-2.313 4.48-2.844zm0 0" fill="#d10407"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/fax.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fea500}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h7.1v2.9H9.9v3.1H13v2.9H9.9v5.4H6.6V6.4zm11.4 0h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3L18 6.4zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.6 2.8h2.1zm8.7-1.4L26 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.3-7.1z" fill="#fff"/><path class="st0" d="M30.9 60.7V50.2c0-1.1.9-1.9 1.9-1.9h11.9l6.1 6.1v6.2c0 .2-.2.4-.4.4h-2.1c-.2 0-.4-.2-.4-.4v-4.2H44c-.8 0-1.4-.6-1.4-1.4v-3.8h-8.8v9.4c0 .2-.2.4-.4.4h-2.1c-.2.1-.4-.1-.4-.3zm0 22.6V64.7c0-.4.3-.7.7-.7h20.6c.4 0 .7.3.7.7v15.6c0 2-1.7 3.7-3.7 3.7H31.7c-.5 0-.8-.3-.8-.7zm14.5-14.4c0 .9.7 1.5 1.5 1.5s1.5-.7 1.5-1.5c0-.9-.7-1.5-1.5-1.5-.8-.1-1.5.6-1.5 1.5zm0 5.1c0 .9.7 1.5 1.5 1.5.9 0 1.5-.7 1.5-1.5s-.7-1.5-1.5-1.6c-.8 0-1.5.7-1.5 1.6zm-5.1-5.1c0 .8.7 1.5 1.5 1.5s1.5-.7 1.5-1.5-.7-1.5-1.5-1.5c-.8-.1-1.5.6-1.5 1.5zm0 5.1c0 .8.7 1.5 1.5 1.5.9 0 1.5-.7 1.5-1.5 0-.9-.7-1.5-1.5-1.6-.8 0-1.5.7-1.5 1.6zm0 5.1c0 .8.7 1.5 1.5 1.5.9 0 1.5-.7 1.5-1.5s-.7-1.5-1.5-1.5-1.5.7-1.5 1.5zm-5.1-10.2c0 .9.7 1.5 1.5 1.5s1.5-.7 1.5-1.5c0-.9-.7-1.5-1.5-1.5-.9-.1-1.5.6-1.5 1.5zm0 5.1c0 .9.7 1.5 1.5 1.5.9 0 1.5-.7 1.5-1.5 0-.9-.7-1.5-1.5-1.6-.8 0-1.5.7-1.5 1.6zm0 5.1c0 .8.7 1.5 1.5 1.5.9 0 1.5-.7 1.5-1.5s-.7-1.5-1.5-1.5c-.9 0-1.5.7-1.5 1.5zM22.3 84h4.9c.4 0 .7-.3.7-.7V60c0-.4-.3-.7-.7-.7h-3.9c-2.6 0-4.7 2.1-4.7 4.7v16.4c0 1.9 1.6 3.6 3.7 3.6z"/></svg>
1
<svg height="63" width="60" xmlns="http://www.w3.org/2000/svg"><path d="M21.516 22.047V3.832c0-1.91 1.574-3.297 3.324-3.297h20.816l10.672 10.582v10.754c0 .348-.351.695-.703.695h-3.672c-.351 0-.7-.347-.7-.695v-7.285H44.43c-1.399 0-2.446-1.04-2.446-2.43v-6.59H26.59v16.305c0 .348-.352.695-.7.695h-3.675c-.348.172-.7-.171-.7-.52zm0 39.203V28.984c0-.695.523-1.214 1.226-1.214h36.035c.7 0 1.223.52 1.223 1.214v27.063c0 3.469-2.973 6.418-6.473 6.418H22.914c-.875 0-1.398-.52-1.398-1.215zm25.363-24.98c0 1.562 1.226 2.601 2.625 2.601 1.398 0 2.625-1.215 2.625-2.601 0-1.56-1.227-2.602-2.625-2.602-1.399-.172-2.625 1.043-2.625 2.602zm0 8.847c0 1.563 1.226 2.602 2.625 2.602 1.574 0 2.625-1.215 2.625-2.602 0-1.387-1.227-2.601-2.625-2.773-1.399 0-2.625 1.21-2.625 2.773zM37.96 36.27c0 1.386 1.223 2.601 2.621 2.601 1.402 0 2.625-1.215 2.625-2.601s-1.223-2.602-2.625-2.602c-1.398-.172-2.621 1.043-2.621 2.602zm0 8.847c0 1.387 1.223 2.602 2.621 2.602 1.574 0 2.625-1.215 2.625-2.602 0-1.562-1.223-2.601-2.625-2.773-1.398 0-2.621 1.21-2.621 2.773zm0 8.848c0 1.387 1.223 2.601 2.621 2.601 1.574 0 2.625-1.214 2.625-2.601s-1.223-2.602-2.625-2.602c-1.398 0-2.621 1.215-2.621 2.602zM29.039 36.27c0 1.562 1.223 2.601 2.621 2.601 1.403 0 2.625-1.215 2.625-2.601 0-1.56-1.222-2.602-2.625-2.602-1.574-.172-2.62 1.043-2.62 2.602zm0 8.847c0 1.563 1.223 2.602 2.621 2.602 1.574 0 2.625-1.215 2.625-2.602 0-1.562-1.222-2.601-2.625-2.773-1.398 0-2.62 1.21-2.62 2.773zm0 8.848c0 1.387 1.223 2.601 2.621 2.601 1.574 0 2.625-1.214 2.625-2.601s-1.222-2.602-2.625-2.602c-1.574 0-2.62 1.215-2.62 2.602zm-22.566 8.5h8.57c.7 0 1.227-.52 1.227-1.215V20.832c0-.695-.528-1.215-1.227-1.215h-6.82C3.672 19.617 0 23.262 0 27.77v28.449c0 3.297 2.8 6.246 6.473 6.246zm0 0" fill="#fea500"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/fb2.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#963}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h7.1v2.9H9.9v3.1H13v2.9H9.9v5.4H6.6V6.4zm10.1 0h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zm4.1 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1H21zm7.4 1.3c0-5 4.5-5.5 4.5-8.4 0-1-.5-1.4-1.2-1.4-.6 0-1.1.3-1.4.8L28 8.3c.8-1.1 2.3-2.1 4.1-2.1 2.1 0 4.2 1.3 4.2 4.2 0 4.1-4.2 5.4-4.4 7.5h4.6v2.9h-7.9c-.2-.7-.2-1.1-.2-1.7z" fill="#fff"/><path id="path1236" class="st0" d="M56.6 61.3c-.2-.5-.6-.9-1-1.3-.1.4-.2.8-.5 1.2L42.6 80.5c-.5.7-1.5.9-2.3.7l-20-5.6c-1.2-.3-2.6-1-2.7-2.4 0-.5 0-.7.3-.9.3-.2.6-.2.9-.1l18.8 5.2c2.7.8 3.5.2 5.5-2.8L54.5 57c.6-.9.7-2 .4-2.9-.3-.9-1.1-1.6-2.1-1.9l-16.5-4.6c-.4-.1-.8-.1-1.2-.1v-.1c-2.5-1.5-3.5 1.3-4.8 2.4-.5.4-1.1.7-1.3 1.1-.2.4-.1.8-.2 1.1-.5 1.1-1.9 2.9-2.6 3.4-.4.3-1 .4-1.3.9-.2.3-.2.9-.3 1.3-.4 1-1.7 2.7-2.6 3.5-.3.3-.8.5-1 .9-.2.3-.1.9-.4 1.2-.6 1-1.8 2.6-2.7 3.5-.5.5-1.1.7-1.3 1.2-.1.2 0 .6-.1.9-.2.5-.4.9-.5 1.3-.5.7-.8 1.7-.7 2.7.2 2.4 2 4.8 4.2 5.4l20 5.6c1.9.5 4.2-.4 5.2-2l11.5-17.7c.6-.8.7-1.9.4-2.8zm-23.1-6.4l.8-1.2c.2-.3.7-.5 1.1-.4L48.6 57c.4.1.5.5.3.8l-.8 1.2c-.2.3-.7.5-1.1.4l-13.2-3.7c-.4-.1-.5-.4-.3-.8zm-3.3 5l.8-1.2c.2-.3.7-.5 1.1-.4L45.3 62c.4.1.5.5.3.8l-.8 1.2c-.2.3-.7.5-1.1.4l-13.2-3.7c-.4-.1-.6-.5-.3-.8z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><path d="M69.723 24.898c-.336-.851-1.012-1.535-1.688-2.222-.168.687-.336 1.37-.844 2.054L46.098 57.723c-.844 1.199-2.532 1.539-3.88 1.199l-33.75-9.574c-2.023-.512-4.386-1.711-4.554-4.106 0-.851 0-1.195.504-1.535.508-.344 1.016-.344 1.52-.172l31.726 8.89c4.555 1.368 5.902.34 9.277-4.788l19.239-30.09a5.83 5.83 0 0 0 .675-4.957c-.507-1.54-1.855-2.735-3.543-3.246L35.47 1.48c-.676-.171-1.352-.171-2.024-.171v-.172c-4.218-2.563-5.906 2.222-8.101 4.101-.844.684-1.856 1.2-2.196 1.883-.336.684-.168 1.367-.336 1.879-.843 1.883-3.207 4.957-4.386 5.813-.676.515-1.688.683-2.196 1.539-.335.511-.335 1.539-.503 2.222-.676 1.711-2.872 4.617-4.387 5.985-.508.511-1.352.855-1.688 1.539-.34.511-.172 1.539-.675 2.05-1.012 1.711-3.04 4.446-4.559 5.985-.844.855-1.856 1.195-2.191 2.05-.168.34 0 1.028-.168 1.54-.34.855-.676 1.539-.844 2.222C.37 41.141-.137 42.852.03 44.56c.34 4.105 3.375 8.207 7.09 9.234l33.746 9.574c3.207.852 7.09-.683 8.778-3.422l19.402-30.258c1.016-1.367 1.183-3.25.676-4.789zm-38.98-10.941 1.35-2.05c.337-.512 1.18-.856 1.856-.684l22.274 6.324c.675.172.843.855.507 1.371l-1.351 2.05c-.336.512-1.18.856-1.856.684L31.25 15.328c-.676-.172-.844-.687-.508-1.371zm-5.567 8.55 1.347-2.054c.34-.512 1.184-.851 1.86-.683l22.273 6.328c.676.172.844.855.504 1.367l-1.347 2.05c-.34.512-1.184.856-1.856.684L25.68 23.875c-.672-.172-1.012-.855-.504-1.367zm0 0" fill="#963"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/fla.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d10407}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h7.1v2.9H9.9v3.1H13v2.9H9.9v5.4H6.6V6.4zm10.1 0H20v11.4h4.3v2.9h-7.6V6.4zm12.7 0H33l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2z" fill="#fff"/><path d="M28.2 54v10.1h8.5v2.6h-8.5v13.7h-3.9v-29h13.3V54h-9.4zm14.4 26.3V51.6h3.7v28.7h-3.7z" fill="#d10407" stroke="#d10407" stroke-width="1.25" stroke-miterlimit="10"/></svg>
1
<svg height="63" width="49" xmlns="http://www.w3.org/2000/svg"><path d="M4.524 3.224v10.102h8.5v2.598h-8.5v13.7h-3.9V.626h13.301v2.598zm14.402 26.3V.826h3.7v28.7zm0 0" fill="#d10407" stroke="#d10407" stroke-miterlimit="10" stroke-width="1.25" transform="matrix(2.10753 0 0 2.07742 0 .079)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/flac.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zm.6-34.6h6.8v2.9H9.7v3.1h3v2.9h-3v5.4H6.6V6.4zm8.1 0h3.1v11.4h4.1v2.9h-7.2V6.4z"/><path class="st1" d="M25.4 6.4h3.4l3.4 14.3H29l-.6-3h-2.9l-.6 3h-3.1l3.6-14.3zM28 15l-.5-2.8c-.2-.9-.4-2.5-.4-2.5H27s-.2 1.5-.4 2.5l-.5 2.8H28zm10.4-8.9c1.2 0 2.5.4 3.4 1.2l-1.3 2.8c-.4-.5-1.2-.9-2-.9-2 0-3.1 1.9-3.1 4.2 0 2.3 1.1 4.4 3 4.4.9 0 1.6-.5 2.2-1l1.3 2.8c-.9.7-1.9 1.3-3.7 1.3-3.8 0-6-3.1-6-7.4.1-4.2 2.4-7.4 6.2-7.4z"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/flv.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d10407}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h7.1v2.9H9.9v3.1H13v2.9H9.9v5.4H6.6V6.4zm10.1 0H20v11.4h4.3v2.9h-7.6V6.4zm7.7 0H28l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L32 6.4h3.5l-3.9 14.3h-3.3L24.4 6.4z" fill="#fff"/><path class="st0" d="M47.2 55.6c1-.4 2.1-.5 3.2-.5V48c-4.8-.1-9.4 2-12.4 5.8-1.2 1.6-2.3 3.3-3.1 5.2l-2.3 5.7c-.6 1.7-1.3 3.5-2.1 5.1-.6 1.4-1.3 2.6-2.2 3.8-.7 1-1.7 1.8-2.8 2.3-1.2.6-2.6.9-4 .9V84c4.8.1 9.4-2 12.4-5.8.9-1.3 1.8-2.7 2.5-4.1l1.9-4.5h8.3v-7.1h-5.5c.4-1.1 1-2.1 1.7-3.1.5-.9 1.2-1.6 1.9-2.2.9-.8 1.7-1.3 2.5-1.6z"/></svg>
1
<svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M46.168 13.516c1.793-.711 3.766-.891 5.738-.891V.008c-8.605-.18-16.851 3.554-22.23 10.308-2.153 2.844-4.125 5.864-5.559 9.243l-4.12 10.128c-1.079 3.024-2.333 6.223-3.767 9.067a31.916 31.916 0 0 1-3.945 6.754c-1.254 1.777-3.047 3.199-5.02 4.09-2.152 1.066-4.66 1.597-7.171 1.597v12.797c8.605.18 16.851-3.554 22.23-10.308 1.613-2.309 3.227-4.797 4.485-7.286l3.406-8h14.879v-12.62h-9.86c.715-1.954 1.793-3.731 3.047-5.508.895-1.602 2.153-2.844 3.407-3.91 1.613-1.422 3.046-2.313 4.48-2.844zm0 0" fill="#d10407"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/fnt.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#36454d}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h7.1v2.9H9.9v3.1H13v2.9H9.9v5.4H6.6V6.4zm10.1 0h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4zm15.5 2.9H29V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3h.1z" fill="#fff"/><path d="M28.1 68.3h-8.9l-1.1 2.4c-.3.8-.5 1.4-.5 2 0 .7.3 1.2.9 1.5.3.2 1.2.3 2.5.4v.7h-8.4v-.7c.9-.1 1.6-.5 2.2-1.1s1.3-1.8 2.1-3.7l9-19.4h.4l9.1 19.9c.9 1.9 1.6 3.1 2.1 3.6.4.4 1 .6 1.8.6v.7H27.2v-.7h.5c1 0 1.7-.1 2.1-.4.3-.2.4-.5.4-.8 0-.2 0-.4-.1-.7 0-.1-.2-.6-.6-1.3l-1.4-3zm-.6-1.3l-3.7-8.4-3.9 8.4h7.6z" fill="#7291a1"/><path class="st0" d="M58.2 59.2l-3.6 11.9-.4 1.5c0 .2-.1.3-.1.4 0 .1.1.3.2.4s.2.2.3.2c.3 0 .6-.2 1.1-.6.2-.2.6-.7 1.3-1.6l.6.3c-.9 1.6-1.8 2.7-2.8 3.4s-2.1 1.1-3.2 1.1c-.7 0-1.2-.2-1.6-.5-.4-.4-.6-.8-.6-1.3s.2-1.3.6-2.6l.4-1.5c-1.4 2.4-2.8 4.1-4.1 5.1-.8.6-1.6.9-2.4.9-1.1 0-2-.5-2.5-1.4-.5-.9-.8-1.9-.8-3.1 0-1.7.5-3.6 1.6-5.8 1.1-2.2 2.5-3.9 4.2-5.3 1.4-1.1 2.8-1.6 4-1.6.7 0 1.2.2 1.7.6.4.4.7 1.1.9 2.1l.7-2.2 4.5-.4zm-5.9 3.5c0-1-.2-1.7-.5-2.1-.2-.3-.5-.4-.9-.4s-.8.2-1.2.5c-.8.7-1.7 2.2-2.7 4.5-1 2.3-1.4 4.2-1.4 5.9 0 .6.1 1.1.3 1.4.2.3.5.4.7.4.6 0 1.1-.3 1.7-.9.8-.9 1.6-2 2.2-3.2 1.2-2.4 1.8-4.4 1.8-6.1z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="48"><path style="stroke:none;fill-rule:nonzero;fill:#7291a1;fill-opacity:1" d="M28.621 33.172h-16.32l-2.012 4.45c-.55 1.483-.918 2.593-.918 3.706 0 1.297.547 2.223 1.649 2.781.55.371 2.203.555 4.582.743v1.293H.203v-1.293c1.652-.188 2.934-.93 4.035-2.04 1.098-1.113 2.383-3.34 3.848-6.859L24.586 0h.73L42 36.879c1.648 3.52 2.934 5.746 3.852 6.672.73.742 1.832 1.113 3.296 1.113v1.297h-22.18v-1.297h.919c1.832 0 3.113-.184 3.847-.742.551-.371.735-.926.735-1.48 0-.372 0-.743-.184-1.301 0-.184-.367-1.11-1.101-2.407zm-1.101-2.406-6.786-15.57-7.148 15.57zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#36454d;fill-opacity:1" d="m83.797 16.309-6.602 22.054-.734 2.778c0 .375-.184.558-.184.742 0 .187.184.558.371.742.184.188.368.371.547.371.551 0 1.102-.371 2.016-1.113.371-.367 1.102-1.297 2.387-2.965l1.097.559c-1.648 2.964-3.3 5.003-5.132 6.3-1.833 1.297-3.852 2.04-5.864 2.04-1.285 0-2.203-.372-2.933-.93-.735-.742-1.102-1.485-1.102-2.407 0-.93.367-2.41 1.102-4.82l.73-2.781c-2.562 4.45-5.133 7.601-7.516 9.453C60.516 47.442 59.05 48 57.582 48c-2.016 0-3.668-.926-4.582-2.594-.918-1.668-1.465-3.523-1.465-5.746 0-3.152.914-6.672 2.934-10.75 2.011-4.074 4.582-7.226 7.695-9.82 2.566-2.04 5.133-2.965 7.332-2.965 1.285 0 2.203.367 3.121 1.11.73.742 1.281 2.038 1.649 3.89l1.28-4.074zM72.98 22.797c0-1.856-.367-3.152-.918-3.895-.367-.554-.914-.742-1.648-.742-.734 0-1.469.375-2.2.93-1.464 1.297-3.116 4.074-4.948 8.336-1.832 4.265-2.57 7.785-2.57 10.937 0 1.11.183 2.035.554 2.594.363.559.914.742 1.281.742 1.098 0 2.016-.558 3.117-1.668 1.465-1.668 2.934-3.707 4.032-5.93 2.199-4.449 3.3-8.156 3.3-11.304zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/folder-link.svg
1
<?xml version="1.0" encoding="UTF-8"?>
2
<svg version="1.1" viewBox="0 0 72 63" xmlns="http://www.w3.org/2000/svg">
3
<path d="M69.5 63h-67C1.1 63 0 61.9 0 60.5V21h72v39.5c0 1.4-1.1 2.5-2.5 2.5z" fill="#efce4a"/>
4
<path d="M32.3 9.9V2.5c0-1.4-1.1-2.5-2.5-2.5H2.5C1.1 0 0 1.1 0 2.5V21h72v-8.6c0-1.4-1.1-2.5-2.5-2.5H32.3z" fill="#ebba16"/>
5
<path class="st0" d="m46.9 42-10.6-9.6v6.4h-11.2v6.4h11.2v6.4z" fill="#fff"/>
6
</svg>
7
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M81.227 64H2.773a2.514 2.514 0 0 1-2.535-2.54V21.333h83.524v40.129A2.514 2.514 0 0 1 81.227 64zm0 0" fill="#efce4a"/><path d="M33.008 10.059v-7.52A2.514 2.514 0 0 0 30.468 0H2.774A2.514 2.514 0 0 0 .238 2.54v18.792h83.524v-8.734a2.514 2.514 0 0 0-2.535-2.54zm0 0" fill="#ebba16"/><path d="m53.059 42.668-10.754-9.754v6.5H30.94v6.504h11.364v6.5zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/folder-up.svg
1
<?xml version="1.0" encoding="UTF-8"?>
2
<svg version="1.1" viewBox="0 0 72 63" xmlns="http://www.w3.org/2000/svg">
3
<path d="M69.5 63h-67C1.1 63 0 61.9 0 60.5V21h72v39.5c0 1.4-1.1 2.5-2.5 2.5z" fill="#efce4a"/>
4
<path d="M32.3 9.9V2.5c0-1.4-1.1-2.5-2.5-2.5H2.5C1.1 0 0 1.1 0 2.5V21h72v-8.6c0-1.4-1.1-2.5-2.5-2.5H32.3z" fill="#ebba16"/>
5
<path class="st0" d="m36 31.1-9.6 10.6h6.4v11.2h6.4v-11.2h6.4z" fill="#fff"/>
6
</svg>
7
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M81.227 64H2.773a2.514 2.514 0 0 1-2.535-2.54V21.333h83.524v40.129A2.514 2.514 0 0 1 81.227 64zm0 0" fill="#efce4a"/><path d="M33.008 10.059v-7.52A2.514 2.514 0 0 0 30.468 0H2.774A2.514 2.514 0 0 0 .238 2.54v18.792h83.524v-8.734a2.514 2.514 0 0 0-2.535-2.54zm0 0" fill="#ebba16"/><path d="m42 31.594-9.738 10.77h6.492v11.374h6.492V42.363h6.492zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/folder.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 63"><path d="M69.5 63h-67C1.1 63 0 61.9 0 60.5V21h72v39.5c0 1.4-1.1 2.5-2.5 2.5z" fill="#efce4a"/><path d="M32.3 9.9V2.5c0-1.4-1.1-2.5-2.5-2.5H2.5C1.1 0 0 1.1 0 2.5V21h72v-8.6c0-1.4-1.1-2.5-2.5-2.5H32.3z" fill="#ebba16"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M81.227 64H2.773a2.514 2.514 0 0 1-2.535-2.54V21.333h83.524v40.129A2.514 2.514 0 0 1 81.227 64zm0 0" fill="#efce4a"/><path d="M33.008 10.059v-7.52A2.514 2.514 0 0 0 30.468 0H2.774A2.514 2.514 0 0 0 .238 2.54v18.792h83.524v-8.734a2.514 2.514 0 0 0-2.535-2.54zm0 0" fill="#ebba16"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/fon.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#36454d}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h7.1v2.9H9.9v3.1H13v2.9H9.9v5.4H6.6V6.4zm15.3-.3c3.8 0 5.9 3.1 5.9 7.3s-2.1 7.5-5.9 7.5-5.8-3.2-5.8-7.5c0-4.1 2.1-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2c.1 2.5.8 4.3 2.5 4.3zm9-11.4h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4z" fill="#fff"/><path d="M28.1 68.3h-8.9l-1.1 2.4c-.3.8-.5 1.4-.5 2 0 .7.3 1.2.9 1.5.3.2 1.2.3 2.5.4v.7h-8.4v-.7c.9-.1 1.6-.5 2.2-1.1s1.3-1.8 2.1-3.7l9-19.4h.4l9.1 19.9c.9 1.9 1.6 3.1 2.1 3.6.4.4 1 .6 1.8.6v.7H27.2v-.7h.5c1 0 1.7-.1 2.1-.4.3-.2.4-.5.4-.8 0-.2 0-.4-.1-.7 0-.1-.2-.6-.6-1.3l-1.4-3zm-.6-1.3l-3.7-8.4-3.9 8.4h7.6z" fill="#7291a1"/><path class="st0" d="M58.2 59.2l-3.6 11.9-.4 1.5c0 .2-.1.3-.1.4 0 .1.1.3.2.4s.2.2.3.2c.3 0 .6-.2 1.1-.6.2-.2.6-.7 1.3-1.6l.6.3c-.9 1.6-1.8 2.7-2.8 3.4s-2.1 1.1-3.2 1.1c-.7 0-1.2-.2-1.6-.5-.4-.4-.6-.8-.6-1.3s.2-1.3.6-2.6l.4-1.5c-1.4 2.4-2.8 4.1-4.1 5.1-.8.6-1.6.9-2.4.9-1.1 0-2-.5-2.5-1.4-.5-.9-.8-1.9-.8-3.1 0-1.7.5-3.6 1.6-5.8 1.1-2.2 2.5-3.9 4.2-5.3 1.4-1.1 2.8-1.6 4-1.6.7 0 1.2.2 1.7.6.4.4.7 1.1.9 2.1l.7-2.2 4.5-.4zm-5.9 3.5c0-1-.2-1.7-.5-2.1-.2-.3-.5-.4-.9-.4s-.8.2-1.2.5c-.8.7-1.7 2.2-2.7 4.5-1 2.3-1.4 4.2-1.4 5.9 0 .6.1 1.1.3 1.4.2.3.5.4.7.4.6 0 1.1-.3 1.7-.9.8-.9 1.6-2 2.2-3.2 1.2-2.4 1.8-4.4 1.8-6.1z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="48"><path style="stroke:none;fill-rule:nonzero;fill:#7291a1;fill-opacity:1" d="M28.621 33.172h-16.32l-2.012 4.45c-.55 1.483-.918 2.593-.918 3.706 0 1.297.547 2.223 1.649 2.781.55.371 2.203.555 4.582.743v1.293H.203v-1.293c1.652-.188 2.934-.93 4.035-2.04 1.098-1.113 2.383-3.34 3.848-6.859L24.586 0h.73L42 36.879c1.648 3.52 2.934 5.746 3.852 6.672.73.742 1.832 1.113 3.296 1.113v1.297h-22.18v-1.297h.919c1.832 0 3.113-.184 3.847-.742.551-.371.735-.926.735-1.48 0-.372 0-.743-.184-1.301 0-.184-.367-1.11-1.101-2.407zm-1.101-2.406-6.786-15.57-7.148 15.57zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#36454d;fill-opacity:1" d="m83.797 16.309-6.602 22.054-.734 2.778c0 .375-.184.558-.184.742 0 .187.184.558.371.742.184.188.368.371.547.371.551 0 1.102-.371 2.016-1.113.371-.367 1.102-1.297 2.387-2.965l1.097.559c-1.648 2.964-3.3 5.003-5.132 6.3-1.833 1.297-3.852 2.04-5.864 2.04-1.285 0-2.203-.372-2.933-.93-.735-.742-1.102-1.485-1.102-2.407 0-.93.367-2.41 1.102-4.82l.73-2.781c-2.562 4.45-5.133 7.601-7.516 9.453C60.516 47.442 59.05 48 57.582 48c-2.016 0-3.668-.926-4.582-2.594-.918-1.668-1.465-3.523-1.465-5.746 0-3.152.914-6.672 2.934-10.75 2.011-4.074 4.582-7.226 7.695-9.82 2.566-2.04 5.133-2.965 7.332-2.965 1.285 0 2.203.367 3.121 1.11.73.742 1.281 2.038 1.649 3.89l1.28-4.074zM72.98 22.797c0-1.856-.367-3.152-.918-3.895-.367-.554-.914-.742-1.648-.742-.734 0-1.469.375-2.2.93-1.464 1.297-3.116 4.074-4.948 8.336-1.832 4.265-2.57 7.785-2.57 10.937 0 1.11.183 2.035.554 2.594.363.559.914.742 1.281.742 1.098 0 2.016-.558 3.117-1.668 1.465-1.668 2.934-3.707 4.032-5.93 2.199-4.449 3.3-8.156 3.3-11.304zm0 0"/></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/gadget.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M57.2 22.7l-19.3 2.6v15.3h19.3V22.7zm-22.8 3l-19.3 2.6v12.3h19.3V25.7zM15.2 44.1v12.3L34.5 59V44.2l-19.3-.1zm22.7 0v15.3L57.2 62V44.1H37.9z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M13 70.2c1.1 0 2.3.4 3.2 1.3l-1.1 2.8c-.4-.6-1.1-.9-1.9-.9-1.8 0-2.5 1.9-2.5 4.2 0 2.6 1 4.3 2.3 4.3.5 0 1-.2 1.4-.6v-1.7h-1.2v-2.9h3.5v8.1h-2v-.9c-.4.7-1.3 1.2-2.2 1.2-2.2 0-4.5-2.7-4.5-7.3s1.9-7.6 5-7.6zm7.8.2h2.8l2.9 14.3h-2.6l-.5-3H21l-.5 3H18l2.8-14.3zm2.3 8.6l-.4-2.8c-.2-.9-.3-2.5-.3-2.5h-.1s-.2 1.5-.3 2.5l-.5 2.8h1.6zm5.1-8.6h3.3c2.9 0 4.7 2.6 4.7 7.1s-1.8 7.2-4.7 7.2h-3.3V70.4zm3.3 11.4c1.3 0 2.1-1.5 2.1-4.3s-.8-4.2-2.1-4.2h-.7v8.5h.7zM43 70.2c1.1 0 2.3.4 3.2 1.3L45 74.2c-.4-.6-1.1-.9-1.9-.9-1.8 0-2.5 1.9-2.5 4.2 0 2.6 1 4.3 2.3 4.3.5 0 1-.2 1.4-.6v-1.7h-1.2v-2.9h3.5v8.1h-2v-.9c-.4.7-1.3 1.2-2.2 1.2-2.2 0-4.5-2.7-4.5-7.3 0-4.5 2-7.5 5.1-7.5zm5.8.2h5.7v2.9h-3.1V76h2.5v2.9h-2.5v2.9h3.3v2.9h-5.9V70.4zm9.8 2.9h-2.5v-2.9h7.7v2.9h-2.5v11.4h-2.6V73.3h-.1z" fill="#666"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/gdp.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.4-34.9c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.1-4.5 2.6-7.6 6.5-7.6zm7.8.3h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.1-11.4h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path class="st0" d="M41.9 79.8H22.7c-2.1 0-3.8-1.7-3.8-3.8s1.7-3.8 3.8-3.8h7.5c3.4 0 6.2-2.8 6.2-6.2 0-3.4-2.8-6.2-6.2-6.2h-4.1c.1.4.1.8.1 1.2s0 .8-.1 1.2h4.1c2.1 0 3.8 1.7 3.8 3.8 0 2.1-1.7 3.8-3.8 3.8h-7.5c-3.4 0-6.2 2.8-6.2 6.2s2.8 6.2 6.2 6.2H42c-.1-.4-.1-.8-.1-1.2v-1.2zm5.9-2.5c-2 0-3.7 1.6-3.7 3.7s1.6 3.7 3.7 3.7 3.7-1.6 3.7-3.7-1.6-3.7-3.7-3.7zm-20.1-30h-7.5c-.6 0-1.2.5-1.2 1.2v9c-1.5.5-2.5 1.9-2.5 3.5 0 2 1.6 3.7 3.7 3.7s3.7-1.6 3.7-3.7c0-1.6-1-3-2.5-3.5v-2.8h6.3c.6 0 1.2-.5 1.2-1.2v-5c-.1-.6-.6-1.2-1.2-1.2zm20.1 2.5c-4.8 0-8.7 3.9-8.7 8.7 0 2.6 1.1 5 3.1 6.6l4.5 8.9c.4.9 1.7.9 2.1 0l4.5-8.9c2-1.7 3.1-4.1 3.1-6.6.1-4.8-3.8-8.7-8.6-8.7zm0 12.4c-2 0-3.7-1.6-3.7-3.7s1.6-3.7 3.7-3.7 3.7 1.6 3.7 3.7-1.6 3.7-3.7 3.7z"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M43.8 55.613H11.036c-3.586 0-6.488-2.906-6.488-6.5s2.902-6.504 6.488-6.504h12.797c5.8 0 10.582-4.793 10.582-10.609s-4.781-10.61-10.582-10.61h-6.996c.172.684.172 1.368.172 2.055 0 .684 0 1.368-.172 2.051h6.996c3.586 0 6.484 2.91 6.484 6.504s-2.898 6.504-6.484 6.504H11.035C5.23 38.504.453 43.293.453 49.114c0 5.816 4.777 10.609 10.582 10.609H43.97c-.168-.684-.168-1.371-.168-2.055zm10.067-4.277c-3.414 0-6.312 2.738-6.312 6.332S50.285 64 53.867 64c3.586 0 6.317-2.738 6.317-6.332s-2.73-6.332-6.317-6.332zM19.567 0H6.765C5.742 0 4.719.855 4.719 2.055v15.398C2.16 18.31.453 20.707.453 23.445c0 3.422 2.73 6.332 6.313 6.332 3.586 0 6.316-2.738 6.316-6.332 0-2.738-1.707-5.136-4.266-5.992v-4.789h10.75c1.024 0 2.047-.855 2.047-2.055V2.055C21.441 1.027 20.59 0 19.566 0zm34.3 4.277c-8.191 0-14.847 6.676-14.847 14.887 0 4.45 1.878 8.559 5.292 11.297l7.68 15.23c.68 1.54 2.899 1.54 3.582 0l7.68-15.23c3.414-2.91 5.289-7.016 5.289-11.297.172-8.21-6.484-14.887-14.676-14.887zm0 21.22c-3.414 0-6.312-2.74-6.312-6.333s2.73-6.328 6.312-6.328c3.586 0 6.317 2.734 6.317 6.328s-2.73 6.332-6.317 6.332zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/gem.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.4-34.9c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.1-4.5 2.6-7.6 6.5-7.6zm7.3.3h7.2v2.9H23V12h3.1v2.9H23v2.9h4.1v2.9h-7.4V6.4zm10.5 0h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H41l1 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H34l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1-14.3z" fill="#fff"/><path class="st0" d="M52 47.5v36l-9-27 9-9zm-36 36h36l-27-9-9 9zm9-9l27 9-18-18-9 9zm9-9l18 18-9-27-9 9zm-18 9v9l9-9h-9zm18-9h-9v9l9-9zm9-9h-9v9l9-9zm9-9h-9v9l9-9zm-27 18l-9 9h9v-9zm9-9l-9 9h9v-9zm9-9l-9 9h9v-9z"/><path d="M52 47.5v36l-9-27 9-9zm-36 36h36l-27-9-9 9zm9-9l27 9-18-18-9 9zm9-9l18 18-9-27-9 9zm-18 9v9l9-9h-9zm18-9h-9v9l9-9zm9-9h-9v9l9-9zm9-9h-9v9l9-9zm-27 18l-9 9h9v-9zm9-9l-9 9h9v-9zm9-9l-9 9h9v-9z" fill="#666" fill-opacity="0" stroke="#fff"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M61.988 2.012v59.976L46.996 17.004zM2.012 61.988h59.976L17.004 46.996zm14.992-14.992 44.984 14.992L32 32zM32 32l29.988 29.988-14.992-44.984zM2.012 46.996v14.992l14.992-14.992zM32 32H17.004v14.996zm14.996-14.996H32V32zM61.988 2.012H46.996v14.992zM17.004 32 2.012 46.996h14.992zM32 17.004 17.004 32H32zM46.996 2.012 32 17.004h14.996zm0 0" fill="#666" stroke="#fff" stroke-width="1.66605"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/gif.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.4-34.9c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.1-4.5 2.6-7.6 6.5-7.6zm7.8.3h3.3v14.3h-3.3V6.4zm7 0h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/gitattributes.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm9.7 24L38.9 31.2c-1.1-1.1-2.8-1.1-3.9 0l-3.9 3.9L36 40c1.1-.4 2.5-.1 3.4.8.9.9 1.2 2.3.8 3.4L45 49c1.2-.4 2.5-.1 3.4.8 1.3 1.3 1.3 3.4 0 4.7a3.32 3.32 0 0 1-4.7 0c-1-1-1.2-2.4-.7-3.6l-4.4-4.4v11.7l.9.6c1.3 1.3 1.3 3.4 0 4.7a3.32 3.32 0 0 1-4.7 0c-1.3-1.3-1.4-3.4-.1-4.7.3-.3.6-.6 1-.7V46.2c-.3-.2-.7-.4-1-.7-1-1-1.2-2.4-.7-3.6L29.2 37 16.3 49.9c-1.1 1.1-1.1 2.8 0 3.9l18.8 18.8c1.1 1.1 2.8 1.1 3.9 0l18.7-18.7c1.1-1.1 1.1-2.9 0-3.9z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M62.773 29.176 34.824 1.226c-1.636-1.636-4.164-1.636-5.797 0L23.23 7.024l7.282 7.286c1.636-.594 3.718-.149 5.054 1.191 1.34 1.336 1.786 3.418 1.192 5.055l7.137 7.133a4.905 4.905 0 0 1 5.054 1.19 4.942 4.942 0 0 1-6.988 6.99c-1.488-1.49-1.785-3.571-1.043-5.356l-6.54-6.54v17.395l1.337.89a4.935 4.935 0 0 1 0 6.99 4.937 4.937 0 0 1-6.985 0c-1.933-1.934-2.082-5.056-.148-6.99.445-.444.89-.89 1.484-1.038V23.527c-.445-.297-1.039-.597-1.484-1.043-1.488-1.484-1.785-3.566-1.043-5.351l-7.137-7.285-19.175 19.18c-1.637 1.632-1.637 4.16 0 5.796l27.949 27.95c1.636 1.636 4.164 1.636 5.797 0l27.8-27.801c1.637-1.633 1.637-4.313 0-5.797zm0 0" fill="#bababa"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/gitignore.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm2.5 10c-8-8-21-8-29 0s-8 21 0 29 21 8 29 0 8-21 0-29zM23.3 58.7c-3.8-5.9-3.1-13.8 2-18.9s13-5.8 18.9-2L23.3 58.7zm4.5 4.5l20.9-20.9c3.8 5.9 3.1 13.8-2 18.9s-13 5.8-18.9 2z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M54.633 9.367C42.145-3.12 21.855-3.12 9.367 9.367s-12.488 32.778 0 45.266 32.778 12.488 45.266 0 12.488-32.778 0-45.266zM12.176 44.801c-5.934-9.211-4.84-21.543 3.12-29.504s20.294-9.055 29.505-3.121zm7.023 7.023L51.824 19.2c5.934 9.211 4.84 21.543-3.12 29.504s-20.294 9.055-29.505 3.121zm0 0" fill="#bababa"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/go.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#2dbcaf}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm6.4-34.9c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.1-4.5 2.6-7.6 6.5-7.6zm13.1 0c3.8 0 5.9 3.1 5.9 7.3s-2.1 7.5-5.9 7.5-5.8-3.2-5.8-7.5c-.1-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2S23 11 23 13.5s.8 4.3 2.5 4.3z" fill="#fff"/><path class="st0" d="M35.5 60.9c-1.9.5-3.2.9-5.1 1.4-.5.1-.5.1-.9-.2-.5-.5-.7-.9-1.4-1.1-1.9-1-3.7-.6-5.5.5-2.1 1.4-3.1 3.4-3.1 5.7s1.7 4.5 4.1 4.7c2.1.2 3.7-.5 5.1-2 .2-.4.5-.7.9-1.1h-5.9c-.6 0-.7-.4-.6-.9.4-1 1.1-2.5 1.5-3.4.1-.1.2-.5.7-.5h11.1c0 .9 0 1.6-.1 2.5-.4 2.2-1.1 4.2-2.5 6-2.2 2.9-5 4.6-8.6 5.1-3 .4-5.7-.1-8.1-2-2.2-1.7-3.5-4-3.9-6.7-.4-3.4.6-6.2 2.6-8.8 2.1-2.9 5-4.6 8.5-5.2 2.9-.5 5.6-.1 8.1 1.5 1.6 1.1 2.7 2.5 3.5 4.2 0 0 0 .1-.4.3z"/><path class="st0" d="M45.4 77.6c-2.7 0-5.2-.9-7.3-2.6-1.7-1.5-2.9-3.5-3.2-5.9-.5-3.5.4-6.5 2.5-9.2 2.2-2.9 4.9-4.5 8.5-5.1 3.1-.5 6-.2 8.6 1.5 2.4 1.6 3.9 3.9 4.2 6.7.5 4.1-.6 7.5-3.5 10.3-2 2-4.5 3.4-7.2 3.9-.9.2-1.8.4-2.6.4zm7.3-12.2c0-.4 0-.7-.1-1-.5-3-3.4-4.7-6.2-4-2.9.6-4.6 2.4-5.4 5.2-.5 2.4.6 4.7 2.7 5.7 1.6.7 3.4.6 5-.1 2.5-1.2 3.8-3.2 4-5.8z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="42"><path style="stroke:none;fill-rule:nonzero;fill:#2dbcaf;fill-opacity:1" d="M41.156 11.465c-3.449.906-5.804 1.633-9.254 2.539-.906.184-.906.184-1.632-.36-.907-.91-1.27-1.636-2.54-2-3.449-1.812-6.714-1.085-9.98.91-3.809 2.54-5.625 6.169-5.625 10.344 0 4.172 3.086 8.165 7.441 8.528 3.809.363 6.711-.906 9.254-3.63.36-.726.907-1.273 1.633-1.995H19.746c-1.09 0-1.27-.727-1.09-1.633.727-1.816 1.996-4.535 2.723-6.168.183-.184.363-.91 1.27-.91h20.14c0 1.633 0 2.902-.18 4.535-.726 3.996-1.996 7.621-4.535 10.887-3.992 5.265-9.074 8.347-15.61 9.258-5.44.722-10.339-.184-14.694-3.63C3.777 35.056 1.422 30.88.695 25.98c-.73-6.168 1.086-11.246 4.715-15.968C9.223 4.754 14.484 1.668 20.832.578c5.266-.906 10.164-.18 14.7 2.723 2.902 1.996 4.898 4.535 6.35 7.62 0 0 0 .18-.726.544zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#2dbcaf;fill-opacity:1" d="M59.117 41.766c-4.898 0-9.433-1.633-13.242-4.715-3.086-2.723-5.262-6.352-5.809-10.707-.906-6.352.727-11.793 4.54-16.692 3.988-5.265 8.89-8.168 15.421-9.254 5.625-.91 10.887-.363 15.606 2.723 4.351 2.902 7.074 7.074 7.62 12.156.907 7.438-1.089 13.61-6.35 18.688-3.63 3.629-8.165 6.168-13.063 7.078-1.633.363-3.266.723-4.723.723zm13.25-22.133c0-.727 0-1.274-.183-1.817-.907-5.445-6.168-8.527-11.25-7.257-5.262 1.086-8.348 4.351-9.797 9.433-.907 4.356 1.09 8.528 4.898 10.344 2.903 1.27 6.172 1.09 9.07-.184 4.54-2.175 6.899-5.804 7.262-10.52zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/gpg.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#696}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.4-34.9c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.1-4.5 2.6-7.6 6.5-7.6zm7.3.3h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H23v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2H23v4.1h.6zm13.1-7.3c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.6-7.6 6.5-7.6z" fill="#fff"/><path class="st0" d="M35.9 1003.6c2.8 2.8 3.6 6.7 2.6 10.2l14.8 14.8.3 6.6-8.3-.7v-4.2h-4.2v-4.2H37l-5.4-5.4c-3.5 1-7.5.2-10.2-2.6-4-4-4-10.6 0-14.6s10.5-4 14.5.1zm-7.6 2.8c-1.2-1.2-3-1.2-4.2 0-1.2 1.2-1.2 3 0 4.2 1.2 1.2 3 1.2 4.2 0 1.2-1.2 1.2-3.1 0-4.2z" transform="translate(0 -952.362)"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M31.816 6.078c5.094 5.094 6.547 12.184 4.73 18.547l26.907 26.91.547 12-15.09-1.273v-7.637h-7.637v-7.637h-7.457L24 37.172c-6.363 1.816-13.637.363-18.547-4.73-7.27-7.27-7.27-19.27 0-26.544a18.494 18.494 0 0 1 26.363.18zM18 11.172c-2.184-2.184-5.453-2.184-7.637 0-2.18 2.18-2.18 5.453 0 7.637 2.184 2.18 5.453 2.18 7.637 0 2.184-2.184 2.184-5.637 0-7.637zm0 0" fill="#696"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/gpl.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#af7931}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm6.4-34.9c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.1-4.5 2.6-7.6 6.5-7.6zm7.8.3h4.5c2.6 0 4.4 2 4.4 4.9s-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm7.8-7h3.3v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><path class="st0" d="M29.7 83.4c-.1 0-.2 0-.3-.1-7.2-2.7-12-9.7-12-17.3 0-10.2 8.3-18.5 18.5-18.5S54.4 55.8 54.4 66c0 7.6-4.8 14.6-12 17.3-.2.1-.4.1-.6 0-.2-.1-.3-.2-.4-.4l-4-10.5c-.2-.4.1-.9.5-1 2.2-.8 3.6-2.9 3.6-5.3 0-3.1-2.5-5.6-5.6-5.6s-5.6 2.5-5.6 5.6c0 2.3 1.5 4.4 3.6 5.3.4.2.6.6.5 1l-4 10.5c-.1.2-.2.4-.4.4 0 .1-.1.1-.3.1z" id="surface1"/></svg>
1
<svg height="64" width="65" xmlns="http://www.w3.org/2000/svg"><path d="M21.61 63.91c-.176 0-.352 0-.528-.176C8.434 58.934 0 46.488 0 32.977 0 14.844 14.582.09 32.5.09S65 14.844 65 32.977c0 13.511-8.434 25.957-21.082 30.757a1.12 1.12 0 0 1-1.055 0c-.351-.18-.527-.355-.699-.71l-7.027-18.669c-.352-.71.175-1.601.875-1.777 3.867-1.422 6.324-5.156 6.324-9.422 0-5.511-4.39-9.957-9.836-9.957s-9.836 4.446-9.836 9.957c0 4.09 2.633 7.82 6.324 9.422.7.356 1.051 1.067.875 1.777l-7.027 18.668c-.172.356-.348.711-.7.711 0 .176-.175.176-.527.176zm0 0" fill="#af7931"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/gradle.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#02303a}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M12.8 73.1c1.1 0 2.3.4 3.2 1l-1.1 2.2c-.4-.4-1.1-.7-1.9-.7-1.8 0-2.5 1.5-2.5 3.4 0 2 1 3.4 2.3 3.4.5 0 1-.2 1.4-.5v-1.3H13v-2.3h3.5v6.5h-2v-.7c-.4.6-1.3.9-2.2.9-2.2 0-4.5-2.1-4.5-5.9-.1-3.6 1.9-6 5-6zm6.3.1h3.6c.4 0 1 .1 1.5.3 1.1.5 1.9 1.7 1.9 3.2 0 1.4-.7 2.6-1.6 3.2 0 0 .2.2.4.7l1.8 4h-2.9l-1.6-3.9h-.6v3.9H19V73.2h.1zm3.1 5.3c.7 0 1.2-.5 1.2-1.5 0-.5-.2-1-.5-1.2-.2-.2-.5-.2-.7-.2h-.6v3h.6v-.1zm8.6-5.3h2.8l2.9 11.4h-2.6l-.5-2.4H31l-.5 2.4h-2.6l2.9-11.4zm2.2 6.9l-.4-2.3c-.2-.7-.3-2-.3-2h-.1s-.2 1.2-.3 2l-.4 2.3H33zm5.5-6.9h3.3c2.9 0 4.7 2.1 4.7 5.7s-1.8 5.7-4.7 5.7h-3.3V73.2zm3.3 9.2c1.3 0 2.1-1.2 2.1-3.4s-.8-3.4-2.1-3.4h-.7v6.8h.7zm7.3-9.2h2.6v9.1h3.4v2.3H49l.1-11.4zm8.2 0H63v2.3h-3v2.2h2.5V80H60v2.3h3.3v2.3h-5.9l-.1-11.4z" fill="#666"/><path class="st2" d="M56.9 34.1c-1.5-2.7-4.1-3.5-6-3.5-2.3 0-4.2 1.2-3.8 2.1.1.2.5 1.1.8 1.5.4.6 1.1.1 1.3 0 .7-.4 1.5-.5 2.3-.4s1.9.6 2.7 2c1.7 3.3-3.6 10.2-10.3 5.4-6.8-4.7-13.3-3.2-16.3-2.2s-4.3 1.9-3.1 4.1c1.6 3 1.1 2.1 2.6 4.6 2.4 4 7.8-1.8 7.8-1.8-4 5.9-7.4 4.5-8.7 2.4-1.2-1.8-2.1-4-2.1-4-10.1 3.6-7.4 19.3-7.4 19.3h5c1.3-5.8 5.8-5.6 6.6 0h3.8c3.4-11.3 11.9 0 11.9 0h5c-1.4-7.7 2.8-10.1 5.4-14.6 2.8-4.6 5.3-10.1 2.5-14.9zM44 49c-2.6-.9-1.7-3.5-1.7-3.5s2.3.7 5.4 1.8c-.1.7-1.7 2.3-3.7 1.7z"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z" fill="#143b56"/></svg>
1
<svg height="64" width="81" xmlns="http://www.w3.org/2000/svg"><path d="M78.398 6.79C75.508 1.55 70.492 0 66.828 0c-4.437 0-8.101 2.328-7.328 4.074.191.387.965 2.133 1.543 2.906.77 1.165 2.121.196 2.508 0 1.347-.773 2.89-.968 4.433-.773 1.543.191 3.664 1.164 5.207 3.879 3.278 6.398-6.941 19.781-19.863 10.473-13.113-9.118-25.652-6.207-31.437-4.27-5.786 1.941-8.293 3.688-5.977 7.953 3.086 5.82 2.121 4.074 5.012 8.922 4.629 7.758 15.043-3.492 15.043-3.492-7.711 11.441-14.27 8.726-16.778 4.656-2.312-3.492-4.05-7.758-4.05-7.758C-4.336 33.55.87 64 .87 64h9.64C13.02 52.75 21.7 53.14 23.243 64h7.328c6.559-21.914 22.95 0 22.95 0h9.644c-2.7-14.934 5.398-19.586 10.414-28.316 5.399-8.922 10.223-19.586 4.82-28.895zM53.52 35.683c-5.012-1.746-3.278-6.786-3.278-6.786s4.434 1.356 10.414 3.489c-.191 1.36-3.277 4.46-7.136 3.297zm0 0" fill="#02303a"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/gz.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#90c}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm6.4-34.9c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.1-4.5 2.6-7.6 6.5-7.6zm7.2 12.4l4.2-7.9c.5-.9.8-1.3.8-1.3s-.3.1-.8.1h-4v-3h8.7v2.2l-4.2 8c-.5.9-.8 1.3-.8 1.3s.3-.1.8-.1h4.3v2.9h-8.9v-2.2z" fill="#fff"/><path class="st0" d="M51.1 57.5h-5.7v-5.7l5.7 5.7zm-15.3-5.7v20.7h15.4V58.9H44v-7.1h-8.2zm2.4-5.4h-17v4h6.7l-4.2 3.3v3.5l6.2-4.8v-1.9h21.6v-1.6l-13.3-2.5zm-8.3 8.7l-6.2 4.8v3.5l6.2-4.8v-3.5zm-6.3 14.4l6.2-4.8v-3.5L23.6 66v3.5zm6.3 1.4v-3.5l-6.2 4.8V74h-2.5v4H25v2.8h-2.2c-.4-.7-1.1-1.2-2-1.2-1.3 0-2.3 1-2.3 2.3 0 1.3 1 2.3 2.3 2.3.9 0 1.6-.5 2-1.2H25v2.1h3.4V83h2.2c.4.7 1.1 1.2 2 1.2 1.3 0 2.3-1 2.3-2.3 0-1.3-1-2.3-2.3-2.3-.9 0-1.6.5-2 1.2h-2.2V78h9.7l13.3-2.4V74H25.7l4.2-3.1z"/></svg>
1
<svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/h.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2{fill:#999}.st2{stroke:#999;stroke-width:.25;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v5.8h3.2V6.4h3.3v14.3h-3.3V15H9.9v5.7H6.6V6.4z" fill="#fff"/><path class="st2" d="M53.1 48h-35v35h35V48zm-1.9 33h-31V54.8h31V81z"/><path class="st2" d="M23.1 57.9h25v3.5h-25zm4.1 5.7h15.3V65H27.2v-1.4zm2.2 4.3h15.3v1.5H29.4v-1.5zm-2.2 4.5h15.3v1.5H27.2v-1.5zm2.2 4.6h15.3v1.5H29.4V77z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".25"><path d="M63.773.227H.227v63.546h63.546zM60.324 60.14H4.04V12.574h56.285zm0 0" stroke-width=".4539"/><path d="M9.305 18.203h45.39v6.352H9.305zm7.445 10.348h27.777v2.543H16.75zm3.992 7.808h27.781v2.723h-27.78zm-3.992 8.168h27.777v2.723H16.75zm3.992 8.352h27.781v2.723h-27.78zm0 0" stroke-width=".4539"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/handlebars.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#c19770}</style><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zM29.7 53.8c1.6-.1 3.3.5 4.6 1.6.6.5 1.2 1.2 1.6 2 .8-1.3 2-2.4 3.5-3 1.8-.6 3.8-.6 5.6 0 1.6.6 3 1.5 4.2 2.7.9.9 1.9 1.8 2.9 2.6.5.5 1.1.8 1.7 1 .9.3 1.9 0 2.5-.6.5-.6.5-1.6-.1-2.3-.4-.3-.9-.3-1.3.1 0 0 0 .1-.1.1-.2.4-.2.9.1 1.2-.5-.3-.9-.9-1-1.6-.1-.8.5-1.5 1.2-1.7 1.4-.5 3.1-.1 3.9 1.1.7 1.2 1 2.6.8 3.9-.2 1.3-.9 2.4-2 3.2-1.5 1-3.3 1.5-5.2 1.3-1.7-.1-3.5-.4-5-1.1-2.7-1.1-5.2-2.5-7.9-3.4-.9-.2-2-.5-2.9-.6h-2.2c-.9.1-1.8.3-2.6.6-2.8.9-5.3 2.4-8 3.5-2.3.9-4.8 1.3-7.2.8-1.4-.2-2.7-.9-3.6-2-.8-.9-1.2-2.1-1.1-3.3-.1-1.2.2-2.3.9-3.2s1.8-1.3 2.9-1.2c.7 0 1.3.3 1.8.9.3.5.4 1 .2 1.6-.2.5-.5.9-.9 1.1.2-.3.3-.8.1-1.2-.3-.4-.9-.5-1.3-.2-.1 0-.1.1-.2.1-.5.5-.5 1.3-.2 1.9.4.6 1 1 1.7 1.1 1 0 2-.5 2.7-1.2 1.5-1.5 3.1-2.8 4.8-4.1 1.6-1.1 3.4-1.6 5.1-1.7zm0-17.1c1.6-.1 3.3.5 4.6 1.6.6.5 1.2 1.2 1.6 2 .8-1.3 2-2.4 3.5-3 1.8-.6 3.8-.6 5.6 0 1.6.6 3 1.5 4.2 2.7.9.9 1.9 1.8 2.9 2.6.5.5 1.1.8 1.7 1 .9.3 1.9 0 2.5-.6.5-.6.5-1.6-.1-2.3-.4-.3-.9-.3-1.3.1 0 0 0 .1-.1.1-.2.4-.2.9.1 1.2-.5-.3-.9-.9-1-1.6-.1-.8.5-1.5 1.2-1.7 1.4-.5 3.1-.1 3.9 1.1.7 1.2 1 2.6.8 3.9-.2 1.3-.9 2.4-2 3.2-1.5 1-3.3 1.5-5.2 1.3-1.7-.1-3.5-.4-5-1.1-2.7-1.1-5.2-2.5-7.9-3.4-.9-.2-2-.5-2.9-.6h-2.2c-.9.1-1.8.3-2.6.6-2.8.9-5.3 2.4-8 3.5-2.3.9-4.8 1.3-7.2.8-1.4-.2-2.7-.9-3.6-2-.8-.9-1.2-2.1-1.1-3.3-.1-1.2.2-2.3.9-3.2s1.8-1.3 2.9-1.2c.7 0 1.3.3 1.8.9.3.5.4 1 .2 1.6-.2.5-.5.9-.9 1.1.2-.3.3-.8.1-1.2-.3-.4-.9-.5-1.3-.2-.1 0-.1.1-.2.1-.5.5-.5 1.3-.2 1.9.4.6 1 1 1.7 1.1 1 0 2-.5 2.7-1.2 1.5-1.5 3.1-2.8 4.8-4.1 1.6-1.1 3.4-1.6 5.1-1.7z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="51"><path style="stroke:none;fill-rule:nonzero;fill:#c19770;fill-opacity:1" d="M30.605 30.332c2.782-.18 5.735.879 7.993 2.824 1.039.883 2.086 2.121 2.777 3.535 1.39-2.296 3.477-4.242 6.082-5.3a15.304 15.304 0 0 1 9.73 0 20.188 20.188 0 0 1 7.293 4.77 62.33 62.33 0 0 0 5.04 4.593c.867.883 1.91 1.41 2.953 1.766 1.562.53 3.297 0 4.343-1.06.868-1.058.868-2.827-.175-4.062-.696-.53-1.563-.53-2.258.176 0 0 0 .176-.176.176-.348.707-.348 1.59.176 2.121-.867-.531-1.563-1.59-1.738-2.828-.172-1.414.87-2.648 2.085-3.004 2.43-.883 5.387-.176 6.774 1.945 1.219 2.118 1.738 4.59 1.39 6.887-.347 2.3-1.566 4.242-3.472 5.656-2.606 1.766-5.734 2.649-9.035 2.297-2.953-.176-6.078-.707-8.688-1.945-4.687-1.941-9.031-4.414-13.722-6.008-1.563-.351-3.473-.879-5.04-1.059h-3.82c-1.562.18-3.125.532-4.515 1.06-4.864 1.593-9.207 4.241-13.899 6.187-3.996 1.59-8.336 2.296-12.504 1.414-2.433-.356-4.691-1.594-6.258-3.535a7.888 7.888 0 0 1-1.906-5.829c-.176-2.12.344-4.066 1.563-5.656 1.214-1.59 3.129-2.297 5.035-2.121 1.215 0 2.262.531 3.129 1.59.52.887.695 1.77.347 2.828-.347.883-.87 1.59-1.566 1.945.352-.53.523-1.414.172-2.12-.516-.708-1.559-.884-2.254-.356-.176 0-.176.18-.348.18-.87.882-.87 2.296-.347 3.355.695 1.059 1.738 1.766 2.949 1.945 1.742 0 3.48-.886 4.691-2.125 2.606-2.648 5.387-4.945 8.34-7.242 2.781-1.941 5.906-2.828 8.86-3zm0-30.215c2.782-.176 5.735.887 7.993 2.828 1.039.883 2.086 2.118 2.777 3.532 1.39-2.297 3.477-4.239 6.082-5.297a15.25 15.25 0 0 1 9.73 0 20.22 20.22 0 0 1 7.293 4.77 62.33 62.33 0 0 0 5.04 4.593c.867.883 1.91 1.414 2.953 1.766 1.562.53 3.297 0 4.343-1.059.868-1.063.868-2.828-.175-4.066-.696-.528-1.563-.528-2.258.18 0 0 0 .175-.176.175-.348.707-.348 1.59.176 2.121-.867-.531-1.563-1.59-1.738-2.828-.172-1.414.87-2.652 2.085-3.004 2.43-.883 5.387-.176 6.778 1.942 1.215 2.12 1.734 4.597 1.387 6.894-.348 2.297-1.563 4.238-3.473 5.652-2.606 1.77-5.734 2.649-9.035 2.297-2.953-.175-6.078-.707-8.684-1.941-4.691-1.945-9.035-4.418-13.723-6.008-1.562-.355-3.476-.887-5.039-1.062h-3.82c-1.566.175-3.129.53-4.52 1.062-4.863 1.59-9.206 4.238-13.898 6.18-3.992 1.593-8.336 2.297-12.504 1.414-2.433-.352-4.691-1.586-6.258-3.531a7.913 7.913 0 0 1-1.906-5.832C-.14 8.773.38 6.832 1.598 5.242c1.214-1.59 3.129-2.297 5.035-2.12 1.215 0 2.262.53 3.129 1.589.52.887.695 1.766.347 2.828-.347.883-.87 1.59-1.566 1.941.352-.527.523-1.41.172-2.117-.516-.707-1.559-.886-2.254-.351-.176 0-.176.172-.348.172-.87.882-.87 2.296-.347 3.359.695 1.059 1.738 1.766 2.949 1.941 1.742 0 3.48-.882 4.691-2.117 2.606-2.648 5.387-4.949 8.34-7.246 2.781-1.941 5.91-2.824 8.86-3.004zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/hbs.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#c19770}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v5.8h3.2V6.4h3.3v14.3h-3.3V15H9.9v5.7H6.6V6.4zm12.4 0h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3H19V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1zm7.3-1.1c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path class="st0" d="M29.8 69c1.6-.1 3.3.5 4.6 1.6.6.5 1.2 1.2 1.6 2 .8-1.3 2-2.4 3.5-3 1.8-.6 3.8-.6 5.6 0 1.6.6 3 1.5 4.2 2.7.9.9 1.9 1.8 2.9 2.6.5.5 1.1.8 1.7 1 .9.3 1.9 0 2.5-.6.5-.6.5-1.6-.1-2.3-.4-.3-.9-.3-1.3.1 0 0 0 .1-.1.1-.2.4-.2.9.1 1.2-.5-.3-.9-.9-1-1.6-.1-.8.5-1.5 1.2-1.7 1.4-.5 3.1-.1 3.9 1.1.7 1.2 1 2.6.8 3.9-.2 1.3-.9 2.4-2 3.2-1.5 1-3.3 1.5-5.2 1.3-1.7-.1-3.5-.4-5-1.1-2.7-1.1-5.2-2.5-7.9-3.4-.9-.2-2-.5-2.9-.6h-2.2c-.9.1-1.8.3-2.6.6-2.8.9-5.3 2.4-8 3.5-2.3.9-4.8 1.3-7.2.8-1.4-.2-2.7-.9-3.6-2-.8-.9-1.2-2.1-1.1-3.3-.1-1.2.2-2.3.9-3.2.7-.9 1.8-1.3 2.9-1.2.7 0 1.3.3 1.8.9.3.5.4 1 .2 1.6-.2.5-.5.9-.9 1.1.2-.3.3-.8.1-1.2-.3-.4-.9-.5-1.3-.2-.1 0-.1.1-.2.1-.5.5-.5 1.3-.2 1.9.4.6 1 1 1.7 1.1 1 0 2-.5 2.7-1.2 1.5-1.5 3.1-2.8 4.8-4.1 1.6-1 3.4-1.6 5.1-1.7zm0-17.1c1.6-.1 3.3.5 4.6 1.6.6.5 1.2 1.2 1.6 2 .8-1.3 2-2.4 3.5-3 1.8-.6 3.8-.6 5.6 0 1.6.6 3 1.5 4.2 2.7.9.9 1.9 1.8 2.9 2.6.5.5 1.1.8 1.7 1 .9.3 1.9 0 2.5-.6.5-.6.5-1.6-.1-2.3-.4-.3-.9-.3-1.3.1 0 0 0 .1-.1.1-.2.4-.2.9.1 1.2-.5-.3-.9-.9-1-1.6-.1-.8.5-1.5 1.2-1.7 1.4-.5 3.1-.1 3.9 1.1.7 1.2 1 2.6.8 3.9-.2 1.3-.9 2.4-2 3.2-1.5 1-3.3 1.5-5.2 1.3-1.7-.1-3.5-.4-5-1.1-2.7-1.1-5.2-2.5-7.9-3.4-.9-.2-2-.5-2.9-.6h-2.2c-.9.1-1.8.3-2.6.6-2.8.9-5.3 2.4-8 3.5-2.3.9-4.8 1.3-7.2.8-1.4-.2-2.7-.9-3.6-2-.8-.9-1.2-2.1-1.1-3.3-.1-1.2.2-2.3.9-3.2.7-.9 1.8-1.3 2.9-1.2.7 0 1.3.3 1.8.9.3.5.4 1 .2 1.6-.2.5-.5.9-.9 1.1.2-.3.3-.8.1-1.2-.3-.4-.9-.5-1.3-.2-.1 0-.1.1-.2.1-.5.5-.5 1.3-.2 1.9.4.6 1 1 1.7 1.1 1 0 2-.5 2.7-1.2 1.5-1.5 3.1-2.8 4.8-4.1 1.6-1 3.4-1.6 5.1-1.7z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="51"><path style="stroke:none;fill-rule:nonzero;fill:#c19770;fill-opacity:1" d="M30.605 30.332c2.782-.18 5.735.879 7.993 2.824 1.039.883 2.086 2.121 2.777 3.535 1.39-2.296 3.477-4.242 6.082-5.3a15.304 15.304 0 0 1 9.73 0 20.188 20.188 0 0 1 7.293 4.77 62.33 62.33 0 0 0 5.04 4.593c.867.883 1.91 1.41 2.953 1.766 1.562.53 3.297 0 4.343-1.06.868-1.058.868-2.827-.175-4.062-.696-.53-1.563-.53-2.258.176 0 0 0 .176-.176.176-.348.707-.348 1.59.176 2.121-.867-.531-1.563-1.59-1.738-2.828-.172-1.414.87-2.648 2.085-3.004 2.43-.883 5.387-.176 6.774 1.945 1.219 2.118 1.738 4.59 1.39 6.887-.347 2.3-1.566 4.242-3.472 5.656-2.606 1.766-5.734 2.649-9.035 2.297-2.953-.176-6.078-.707-8.688-1.945-4.687-1.941-9.031-4.414-13.722-6.008-1.563-.351-3.473-.879-5.04-1.059h-3.82c-1.562.18-3.125.532-4.515 1.06-4.864 1.593-9.207 4.241-13.899 6.187-3.996 1.59-8.336 2.296-12.504 1.414-2.433-.356-4.691-1.594-6.258-3.535a7.888 7.888 0 0 1-1.906-5.829c-.176-2.12.344-4.066 1.563-5.656 1.214-1.59 3.129-2.297 5.035-2.121 1.215 0 2.262.531 3.129 1.59.52.887.695 1.77.347 2.828-.347.883-.87 1.59-1.566 1.945.352-.53.523-1.414.172-2.12-.516-.708-1.559-.884-2.254-.356-.176 0-.176.18-.348.18-.87.882-.87 2.296-.347 3.355.695 1.059 1.738 1.766 2.949 1.945 1.742 0 3.48-.886 4.691-2.125 2.606-2.648 5.387-4.945 8.34-7.242 2.781-1.766 5.906-2.828 8.86-3zm0-30.215c2.782-.176 5.735.887 7.993 2.828 1.039.883 2.086 2.118 2.777 3.532 1.39-2.297 3.477-4.239 6.082-5.297a15.25 15.25 0 0 1 9.73 0 20.22 20.22 0 0 1 7.293 4.77 62.33 62.33 0 0 0 5.04 4.593c.867.883 1.91 1.414 2.953 1.766 1.562.53 3.297 0 4.343-1.059.868-1.063.868-2.828-.175-4.066-.696-.528-1.563-.528-2.258.18 0 0 0 .175-.176.175-.348.707-.348 1.59.176 2.121-.867-.531-1.563-1.59-1.738-2.828-.172-1.414.87-2.652 2.085-3.004 2.43-.883 5.387-.176 6.778 1.942 1.215 2.12 1.734 4.597 1.387 6.894-.348 2.297-1.563 4.238-3.473 5.652-2.606 1.77-5.734 2.649-9.035 2.297-2.953-.175-6.078-.707-8.684-1.941-4.691-1.945-9.035-4.418-13.723-6.008-1.562-.355-3.476-.887-5.039-1.062h-3.82c-1.566.175-3.129.53-4.52 1.062-4.863 1.59-9.206 4.238-13.898 6.18-3.992 1.593-8.336 2.297-12.504 1.414-2.433-.352-4.691-1.586-6.258-3.531a7.913 7.913 0 0 1-1.906-5.832C-.14 8.773.38 6.832 1.598 5.242c1.214-1.59 3.129-2.297 5.035-2.12 1.215 0 2.262.53 3.129 1.589.52.887.695 1.766.347 2.828-.347.883-.87 1.59-1.566 1.941.352-.527.523-1.41.172-2.117-.516-.707-1.559-.886-2.254-.351-.176 0-.176.172-.348.172-.87.882-.87 2.296-.347 3.359.695 1.059 1.738 1.766 2.949 1.941 1.742 0 3.48-.882 4.691-2.117 2.606-2.648 5.387-4.949 8.34-7.246 2.781-1.766 5.91-2.824 8.86-3.004zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/heic.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v5.8h3.2V6.4h3.3v14.3h-3.3V15H9.9v5.7H6.6V6.4zm11.9 0h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4zm9 0h3.3v14.3h-3.3V6.4zm11.3-.3c1.3 0 2.6.4 3.6 1.2L41 10.1c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/hlp.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#c93}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zm.6-34.6h3.3v5.8h3.2V6.4h3.3v14.3h-3.3V15H9.9v5.7H6.6V6.4zm13.4 0h3.3v11.4h4.3v2.9H20V6.4zm10.4 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z"/><path class="st0" d="M52.5 47H27c-3.8 0-7.5 1.5-7.5 6v30h27V53H23.2c0-2.2 1.5-3 3-3h23.2v30l3-3V47z"/><path class="st1" d="M31.8 69.6c0-3.1 3.6-3.6 3.6-5.9 0-1-.9-1.8-2.1-1.8-1.3.1-2.3 1-2.3 1L29.5 61s1.5-1.6 4.1-1.6c2.4 0 4.7 1.5 4.7 4.1 0 3.6-3.8 4-3.8 6.3v.8h-2.7v-1zm0 2.9h2.7V75h-2.7v-2.5z"/></svg>
1
<svg height="64" width="59" xmlns="http://www.w3.org/2000/svg"><path d="M59 0H13.41C6.613 0 0 2.668 0 10.668V64h48.273V10.668H6.613c0-3.914 2.684-5.336 5.367-5.336h41.477v53.336l5.363-5.336V0zm0 0" fill="#c93"/><path d="M21.992 40.18c0-5.512 6.434-6.403 6.434-10.493 0-1.777-1.61-3.199-3.754-3.199-2.324.18-4.11 1.778-4.11 1.778L17.88 24.89s2.683-2.848 7.332-2.848c4.289 0 8.402 2.668 8.402 7.289 0 6.402-6.797 7.113-6.797 11.203v1.422h-4.824zm0 5.152h4.824v4.445h-4.824zm0 0" fill="#fff"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/hs.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#8f4e8b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v5.8h3.2V6.4h3.3v14.3h-3.3V15H9.9v5.7H6.6V6.4zm14.1 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path class="st0" d="M14.6 80.5l10.1-15.1-10.1-15.1h7.5l10.1 15.1-10.1 15.1z"/><path class="st0" d="M24.7 80.5l10.1-15.1-10.1-15.1h7.5l20.2 30.2h-7.6l-6.3-9.4-6.3 9.4zM49 71.7l-3.3-5.1h11.7v5.1zm-5-7.5l-3.4-5.1h16.8v5.1z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="59"><path style="stroke:none;fill-rule:nonzero;fill:#8f4e8b;fill-opacity:1" d="m.469 59 19.367-29.5L.469 0h14.379l19.367 29.5L14.848 59zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#8f4e8b;fill-opacity:1" d="m19.836 59 19.363-29.5L19.836 0h14.379l38.73 59h-14.57L46.293 40.633 34.215 59zm46.59-17.191-6.328-9.965H82.53v9.965zm-9.59-14.653-6.516-9.965h32.211v9.965zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/hsl.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#8f4e8b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v5.8h3.2V6.4h3.3v14.3h-3.3V15H9.9v5.7H6.6V6.4zm14.1 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10-10.3H34v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><path class="st0" d="M14.6 80.5l10.1-15.1-10.1-15.1h7.5l10.1 15.1-10.1 15.1z"/><path class="st0" d="M24.7 80.5l10.1-15.1-10.1-15.1h7.5l20.2 30.2h-7.6l-6.3-9.4-6.3 9.4zM49 71.7l-3.3-5.1h11.7v5.1zm-5-7.5l-3.4-5.1h16.8v5.1z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="59"><path style="stroke:none;fill-rule:nonzero;fill:#8f4e8b;fill-opacity:1" d="m.469 59 19.367-29.5L.469 0h14.379l19.367 29.5L14.848 59zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#8f4e8b;fill-opacity:1" d="m19.836 59 19.363-29.5L19.836 0h14.379l38.73 59h-14.57L46.293 40.633 34.215 59zm46.59-17.191-6.328-9.965H82.53v9.965zm-9.59-14.653-6.516-9.965h32.211v9.965zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/htm.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d75b26}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v5.8h3.2V6.4h3.3v14.3h-3.3V15H9.9v5.7H6.6V6.4zm14.7 2.9h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3zm8.6-2.9h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4H38s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.1 6.4h-3l.9-14.3z" fill="#fff"/><path d="M23.5 75c-.5 0-1.1-.2-1.5-.6L13.6 66c-.8-.8-.8-2.1 0-3l8.4-8.4c.8-.8 2.1-.8 3 0 .8.8.8 2.1 0 3l-7 6.9 6.9 6.9c.8.8.8 2.1 0 3-.4.4-.9.6-1.4.6zm25 0c-.5 0-1.1-.2-1.5-.6-.8-.8-.8-2.1 0-3l6.9-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 3 0l8.4 8.4c.8.8.8 2.1 0 3L50 74.3c-.4.5-.9.7-1.5.7zm-16.7 4.1c-.2 0-.4 0-.7-.1-1.1-.4-1.7-1.5-1.3-2.6l8.4-25.1c.4-1.1 1.5-1.7 2.6-1.3 1.1.4 1.7 1.5 1.3 2.6l-8.4 25.1c-.2.9-1 1.4-1.9 1.4z" fill="#d75b26" stroke="#d75b26" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="55"><path style="fill-rule:nonzero;fill:#d75b26;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#d75b26;stroke-opacity:1;stroke-miterlimit:10" d="M11.241 25.867c-.498 0-1.1-.2-1.5-.6l-8.398-8.4c-.8-.799-.8-2.1 0-3.001l8.398-8.4c.8-.798 2.101-.798 3.002 0 .8.801.8 2.1 0 3.001l-7 6.9 6.9 6.9c.8.8.8 2.098 0 3-.4.4-.9.6-1.402.6zm25 0c-.5 0-1.099-.2-1.499-.6-.8-.8-.8-2.1 0-3l6.901-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 2.998 0l8.4 8.399c.801.8.801 2.102 0 3l-8.4 8.3c-.4.5-.898.7-1.5.7zm-16.698 4.1c-.2 0-.402 0-.7-.1-1.1-.399-1.7-1.5-1.3-2.599l8.399-25.1c.402-1.101 1.5-1.702 2.6-1.302 1.1.4 1.7 1.502 1.3 2.6l-8.4 25.101c-.198.901-1 1.4-1.899 1.4zm0 0" transform="matrix(1.74792 0 0 1.75607 0 .53)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/html.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d75b26}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.5-34.6h2.8v5.8H12V6.4h2.8v14.3H12V15H9.2v5.7H6.5V6.4zm12 2.9h-2.7V6.4h8.1v2.9h-2.7v11.4h-2.8V9.3zm6.9-2.9h3.1l1.1 6c.2.9.4 2.4.4 2.4s.2-1.5.4-2.4l1.1-6h3.1l.8 14.3h-2.6l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.7 4.1h-2.7l-.7-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.3 6.4h-2.6l.9-14.3zm11.5 0h2.8v11.4h3.7v2.9H37V6.4z" fill="#fff"/><path d="M23.5 75c-.5 0-1.1-.2-1.5-.6L13.6 66c-.8-.8-.8-2.1 0-3l8.4-8.4c.8-.8 2.1-.8 3 0 .8.8.8 2.1 0 3l-7 6.9 6.9 6.9c.8.8.8 2.1 0 3-.4.4-.9.6-1.4.6zm25 0c-.5 0-1.1-.2-1.5-.6-.8-.8-.8-2.1 0-3l6.9-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 3 0l8.4 8.4c.8.8.8 2.1 0 3L50 74.3c-.4.5-.9.7-1.5.7zm-16.7 4.1c-.2 0-.4 0-.7-.1-1.1-.4-1.7-1.5-1.3-2.6l8.4-25.1c.4-1.1 1.5-1.7 2.6-1.3 1.1.4 1.7 1.5 1.3 2.6l-8.4 25.1c-.2.9-1 1.4-1.9 1.4z" fill="#d75b26" stroke="#d75b26" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="55"><path style="fill-rule:nonzero;fill:#d75b26;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#d75b26;stroke-opacity:1;stroke-miterlimit:10" d="M11.241 25.867c-.498 0-1.1-.2-1.5-.6l-8.398-8.4c-.8-.799-.8-2.1 0-3.001l8.398-8.4c.8-.798 2.101-.798 3.002 0 .8.801.8 2.1 0 3.001l-7 6.9 6.9 6.9c.8.8.8 2.098 0 3-.4.4-.9.6-1.402.6zm25 0c-.5 0-1.099-.2-1.499-.6-.8-.8-.8-2.1 0-3l6.901-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 2.998 0l8.4 8.399c.801.8.801 2.102 0 3l-8.4 8.3c-.4.5-.898.7-1.5.7zm-16.698 4.1c-.2 0-.402 0-.7-.1-1.1-.399-1.7-1.5-1.3-2.599l8.399-25.1c.402-1.101 1.5-1.702 2.6-1.302 1.1.4 1.7 1.502 1.3 2.6l-8.4 25.101c-.198.901-1 1.4-1.899 1.4zm0 0" transform="matrix(1.74792 0 0 1.75607 0 .53)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ibooks.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#963}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.3-34.5h1.6v14.2H6.3V6.5zm3.2 0H12c1.4 0 2.5 1.3 2.5 3.7 0 1.3-.4 2.5-1.1 3 .9.5 1.4 1.8 1.4 3.4 0 2.8-1.1 4.1-2.7 4.1H9.5V6.5zm2.6 5.8c.5 0 .8-.8.8-1.9s-.3-1.8-1-1.8h-.8v3.7h1zm-.1 6.2c.8 0 1.2-.9 1.2-2.1 0-1.3-.4-2.1-1-2.1h-1.1v4.2h.9zm7.3-12.3c2.2 0 3.7 3 3.7 7.3s-1.4 7.4-3.7 7.4c-2.3 0-3.7-3.1-3.7-7.4 0-4.2 1.4-7.3 3.7-7.3zm0 12.4c1.3 0 2-2 2-5.1 0-3-.8-4.9-2-4.9-1.3 0-2.1 1.9-2.1 4.9 0 3.1.8 5.1 2.1 5.1zm8.2-12.4c2.2 0 3.7 3 3.7 7.3s-1.4 7.4-3.7 7.4c-2.3 0-3.7-3.1-3.7-7.4 0-4.2 1.4-7.3 3.7-7.3zm0 12.4c1.3 0 2-2 2-5.1 0-3-.8-4.9-2-4.9-1.3 0-2.1 1.9-2.1 4.9 0 3.1.8 5.1 2.1 5.1zm4.9-12.1H34v5.8h.7l1.7-5.8h1.7L36 13.3l2 7.4h-1.8l-1.7-6.2H34v6.2h-1.6V6.5zm6.8 11c.4.7 1 1.2 1.6 1.2.7 0 1.1-.7 1.1-1.8 0-2.6-3.2-2.5-3.2-6.6 0-2.3 1-4 2.7-4 .7 0 1.4.3 2 .9l-.6 2.2c-.3-.4-.9-.8-1.4-.8-.8 0-1.2.8-1.2 1.7 0 2.6 3.2 2.4 3.2 6.5 0 2.2-.9 4.1-2.6 4.1-.8 0-1.7-.5-2.4-1.4l.8-2z" fill="#fff"/><path id="path1236" class="st0" d="M56.6 61.3c-.2-.5-.6-.9-1-1.3-.1.4-.2.8-.5 1.2L42.6 80.5c-.5.7-1.5.9-2.3.7l-20-5.6c-1.2-.3-2.6-1-2.7-2.4 0-.5 0-.7.3-.9.3-.2.6-.2.9-.1l18.8 5.2c2.7.8 3.5.2 5.5-2.8L54.5 57c.6-.9.7-2 .4-2.9-.3-.9-1.1-1.6-2.1-1.9l-16.5-4.6c-.4-.1-.8-.1-1.2-.1v-.1c-2.5-1.5-3.5 1.3-4.8 2.4-.5.4-1.1.7-1.3 1.1-.2.4-.1.8-.2 1.1-.5 1.1-1.9 2.9-2.6 3.4-.4.3-1 .4-1.3.9-.2.3-.2.9-.3 1.3-.4 1-1.7 2.7-2.6 3.5-.3.3-.8.5-1 .9-.2.3-.1.9-.4 1.2-.6 1-1.8 2.6-2.7 3.5-.5.5-1.1.7-1.3 1.2-.1.2 0 .6-.1.9-.2.5-.4.9-.5 1.3-.5.7-.8 1.7-.7 2.7.2 2.4 2 4.8 4.2 5.4l20 5.6c1.9.5 4.2-.4 5.2-2l11.5-17.7c.6-.8.7-1.9.4-2.8zm-23.1-6.4l.8-1.2c.2-.3.7-.5 1.1-.4L48.6 57c.4.1.5.5.3.8l-.8 1.2c-.2.3-.7.5-1.1.4l-13.2-3.7c-.4-.1-.5-.4-.3-.8zm-3.3 5l.8-1.2c.2-.3.7-.5 1.1-.4L45.3 62c.4.1.5.5.3.8l-.8 1.2c-.2.3-.7.5-1.1.4l-13.2-3.7c-.4-.1-.6-.5-.3-.8z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><path d="M69.723 24.898c-.336-.851-1.012-1.535-1.688-2.222-.168.687-.336 1.37-.844 2.054L46.098 57.723c-.844 1.199-2.532 1.539-3.88 1.199l-33.75-9.574c-2.023-.512-4.386-1.711-4.554-4.106 0-.851 0-1.195.504-1.535.508-.344 1.016-.344 1.52-.172l31.726 8.89c4.555 1.368 5.902.34 9.277-4.788l19.239-30.09a5.83 5.83 0 0 0 .675-4.957c-.507-1.54-1.855-2.735-3.543-3.246L35.47 1.48c-.676-.171-1.352-.171-2.024-.171v-.172c-4.218-2.563-5.906 2.222-8.101 4.101-.844.684-1.856 1.2-2.196 1.883-.336.684-.168 1.367-.336 1.879-.843 1.883-3.207 4.957-4.386 5.813-.676.515-1.688.683-2.196 1.539-.335.511-.335 1.539-.503 2.222-.676 1.711-2.872 4.617-4.387 5.985-.508.511-1.352.855-1.688 1.539-.34.511-.172 1.539-.675 2.05-1.012 1.711-3.04 4.446-4.559 5.985-.844.855-1.856 1.195-2.191 2.05-.168.34 0 1.028-.168 1.54-.34.855-.676 1.539-.844 2.222C.37 41.141-.137 42.852.03 44.56c.34 4.105 3.375 8.207 7.09 9.234l33.746 9.574c3.207.852 7.09-.683 8.778-3.422l19.402-30.258c1.016-1.367 1.183-3.25.676-4.789zm-38.98-10.941 1.35-2.05c.337-.512 1.18-.856 1.856-.684l22.274 6.324c.675.172.843.855.507 1.371l-1.351 2.05c-.336.512-1.18.856-1.856.684L31.25 15.328c-.676-.172-.844-.687-.508-1.371zm-5.567 8.55 1.347-2.054c.34-.512 1.184-.851 1.86-.683l22.273 6.328c.676.172.844.855.504 1.367l-1.347 2.05c-.34.512-1.184.856-1.856.684L25.68 23.875c-.672-.172-1.012-.855-.504-1.367zm0 0" fill="#963"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/icns.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#8ed200}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v14.3H6.6V6.4zm11.5-.3c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4zm5.3.3h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4L27 14.1c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4zM36 16.7c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path class="st0" d="M36.3 47c.1-.4.3-.4.4 0l4.1 12.8c.1.4.5.7.9.7h13.4c.4 0 .4.2.1.4l-10.9 7.8c-.3.3-.4.7-.3 1.1l4.1 12.8c.1.4 0 .5-.3.2l-10.9-7.9c-.3-.2-.8-.2-1.1 0l-10.9 7.9c-.3.2-.5.1-.3-.2l4.1-12.8c.1-.4 0-.8-.3-1.1l-10.9-7.9c-.3-.2-.2-.4.1-.4H31c.4 0 .8-.3.9-.7L36.3 47z"/><path d="M36.3 47c.1-.4.3-.4.4 0l4.1 12.8c.1.4.5.7.9.7h13.4c.4 0 .4.2.1.4l-10.9 7.8c-.3.3-.4.7-.3 1.1l4.1 12.8c.1.4 0 .5-.3.2l-10.9-7.9c-.3-.2-.8-.2-1.1 0l-10.9 7.9c-.3.2-.5.1-.3-.2l4.1-12.8c.1-.4 0-.8-.3-1.1l-10.9-7.9c-.3-.2-.2-.4.1-.4H31c.4 0 .8-.3.9-.7L36.3 47z" fill="none"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M33.383.531c.176-.707.527-.707.699 0l7.176 22.582c.176.707.875 1.235 1.574 1.235h23.45c.698 0 .698.351.175.707L47.383 38.816c-.524.528-.7 1.235-.524 1.942l7.172 22.582c.176.707 0 .883-.523.351L34.434 49.754c-.524-.352-1.399-.352-1.926 0L13.438 63.69c-.528.356-.876.176-.528-.351l7.176-22.582c.176-.707 0-1.414-.527-1.942L.489 24.88c-.528-.356-.352-.707.175-.707H24.11c.7 0 1.399-.531 1.575-1.235zm0 0" fill="#8ed200"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ico.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#8ed200}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v14.3H6.6V6.4zm12.8-.3c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4zm11.4 0c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5S25 17.7 25 13.5s2.1-7.4 5.8-7.4zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2c.1 2.5.8 4.3 2.5 4.3z" fill="#fff"/><path class="st0" d="M36.3 47c.1-.4.3-.4.4 0l4.1 12.8c.1.4.5.7.9.7h13.4c.4 0 .4.2.1.4l-10.9 7.8c-.3.3-.4.7-.3 1.1l4.1 12.8c.1.4 0 .5-.3.2l-10.9-7.9c-.3-.2-.8-.2-1.1 0l-10.9 7.9c-.3.2-.5.1-.3-.2l4.1-12.8c.1-.4 0-.8-.3-1.1l-10.9-7.9c-.3-.2-.2-.4.1-.4H31c.4 0 .8-.3.9-.7L36.3 47z"/><path d="M36.3 47c.1-.4.3-.4.4 0l4.1 12.8c.1.4.5.7.9.7h13.4c.4 0 .4.2.1.4l-10.9 7.8c-.3.3-.4.7-.3 1.1l4.1 12.8c.1.4 0 .5-.3.2l-10.9-7.9c-.3-.2-.8-.2-1.1 0l-10.9 7.9c-.3.2-.5.1-.3-.2l4.1-12.8c.1-.4 0-.8-.3-1.1l-10.9-7.9c-.3-.2-.2-.4.1-.4H31c.4 0 .8-.3.9-.7L36.3 47z" fill="none"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M33.383.531c.176-.707.527-.707.699 0l7.176 22.582c.176.707.875 1.235 1.574 1.235h23.45c.698 0 .698.351.175.707L47.383 38.816c-.524.528-.7 1.235-.524 1.942l7.172 22.582c.176.707 0 .883-.523.351L34.434 49.754c-.524-.352-1.399-.352-1.926 0L13.438 63.69c-.528.356-.876.176-.528-.351l7.176-22.582c.176-.707 0-1.414-.527-1.942L.489 24.88c-.528-.356-.352-.707.175-.707H24.11c.7 0 1.399-.531 1.575-1.235zm0 0" fill="#8ed200"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ics.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#c11e07}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v14.3H6.6V6.4zm12.8-.3c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4zm7.3 10.6c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path id="path1156" d="M20 80.5v-5.7h6.6v5.7H20zm8 0v-5.7h7.3v5.7H28zm-8-7v-6.4h6.6v6.4H20zm8 0v-6.4h7.3v6.4H28zm-8-7.7v-5.7h6.6v5.7H20zm16.8 14.7v-5.7h7.3v5.7h-7.3zM28 65.8v-5.7h7.3v5.7H28zm17.6 14.7v-5.7h6.6v5.7h-6.6zm-8.8-7v-6.4h7.3v6.4h-7.3zm-8-17.2c0 .3-.3.6-.7.6h-1.5c-.4 0-.7-.3-.7-.6v-5.7c0-.3.3-.6.7-.6H28c.4 0 .7.3.7.6v5.7zm16.8 17.2v-6.4h6.6v6.4h-6.6zm-8.8-7.7v-5.7h7.3v5.7h-7.3zm8.8 0v-5.7h6.6v5.7h-6.6zm.8-9.5c0 .3-.3.6-.7.6h-1.5c-.4 0-.7-.3-.7-.6v-5.7c0-.3.3-.6.7-.6h1.5c.4 0 .7.3.7.6v5.7zm8.8-1.3c0-1.4-1.3-2.5-2.9-2.5h-2.9v-1.9c0-1.7-1.6-3.2-3.7-3.2h-1.5c-2 0-3.7 1.4-3.7 3.2v1.9h-8.8v-1.9c0-1.7-1.6-3.2-3.7-3.2h-1.5c-2 0-3.7 1.4-3.7 3.2v1.9H20c-1.6 0-2.9 1.2-2.9 2.5v25.4c0 1.4 1.3 2.5 2.9 2.5h32.2c1.6 0 2.9-1.2 2.9-2.5V55z" fill="#111"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M5.102 59.219v-10.11h11.605v10.11zm14.066 0v-10.11h12.836v10.11zM5.102 46.805V35.457h11.605v11.348zm14.066 0V35.457h12.836v11.348zM5.102 33.152V23.047h11.605v10.105zM34.645 59.22v-10.11H47.48v10.11zM19.168 33.152V23.047h12.836v10.105zm30.95 26.067v-10.11h11.605v10.11zM34.644 46.805V35.457H47.48v11.348zm-14.07-30.496c0 .53-.528 1.062-1.231 1.062h-2.637c-.703 0-1.23-.531-1.23-1.062V6.203c0-.535.527-1.066 1.23-1.066h2.461c.703 0 1.23.531 1.23 1.066V16.31zm29.542 30.496V35.457h11.606v11.348zM34.645 33.152V23.047H47.48v10.105zm15.472 0V23.047h11.606v10.105zm1.406-16.843c0 .53-.527 1.062-1.23 1.062h-2.637c-.703 0-1.23-.531-1.23-1.062V6.203c0-.535.527-1.066 1.23-1.066h2.637c.703 0 1.23.531 1.23 1.066zM67 14.004c0-2.484-2.285-4.434-5.102-4.434h-5.097V6.203c0-3.016-2.813-5.676-6.508-5.676h-2.637c-3.515 0-6.508 2.48-6.508 5.676V9.57H25.676V6.203c0-3.016-2.817-5.676-6.508-5.676h-2.637c-3.52 0-6.508 2.48-6.508 5.676V9.57H5.102C2.285 9.57 0 11.7 0 14.004v45.035c0 2.484 2.285 4.434 5.102 4.434h56.62c2.817 0 5.102-2.13 5.102-4.434V14.004zm0 0" fill="#111"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/idx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v14.3H6.6V6.4zm7 0h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm11.2-4.2l-3.4-7.2h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.5-.9-.7-1.7-.7-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.3-7.1z" fill="#fff"/><path class="st0" d="M49.7 70c0 2.3-1.7 10.1-1.7 10.1-.4 1.9-2.1 3.9-4.3 3.9H33.3c-1.5 0-2.9-.9-3.5-2.3 0 0-5.1-9.4-7.1-12.8-1.4-2.4-1.4-2.4.4-3.4.3-.2.6-.3 1-.3.7 0 1.2.4 1.7 1l3.1 3.6.9 1.2V49.3c0-1.1 1-2 2.2-2 1.1 0 2 .9 2 2l.4 14h.9l.2-2.4c0-1.1.9-2 2-2s2 .9 2 2l.2 2.9h.9l.2-1.9c0-1.1.9-2 2-2s2 .9 2 2l.2 1.9v.5h.7l.2-1c0-1.1.9-2 2-2s2 .9 2 2c-.2 0-.2 4.4-.2 6.7z"/></svg>
1
<svg height="63" width="48" xmlns="http://www.w3.org/2000/svg"><path d="M47.66 38.852c0 3.89-2.894 17.074-2.894 17.074-.68 3.21-3.575 6.594-7.317 6.594H19.75c-2.555 0-4.938-1.524-5.957-3.891 0 0-8.68-15.887-12.082-21.637-2.383-4.054-2.383-4.054.68-5.746a2.905 2.905 0 0 1 1.703-.508c1.191 0 2.039.676 2.89 1.692l5.278 6.086 1.531 2.027V3.863c0-1.86 1.703-3.383 3.742-3.383 1.875 0 3.406 1.524 3.406 3.383l.68 23.664h1.531l.34-4.054c0-1.86 1.531-3.383 3.406-3.383 1.872 0 3.403 1.523 3.403 3.383l.34 4.898h1.53l.34-3.21c0-1.86 1.532-3.38 3.407-3.38 1.871 0 3.402 1.52 3.402 3.38l.34 3.21v.848h1.192l.34-1.692c0-1.859 1.53-3.379 3.406-3.379 1.87 0 3.402 1.52 3.402 3.38-.34 0-.34 7.437-.34 11.324zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/iff.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v14.3H6.6V6.4zm7 0h7.1v2.9h-3.8v3.1H20v2.9h-3.1v5.4h-3.3V6.4zm10 0h7.1v2.9h-3.8v3.1H30v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ifo.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h3.3v14.3H6.6V6.4zm7 0h7.1v2.9h-3.8v3.1H20v2.9h-3.1v5.4h-3.3V6.4zm15.3-.3c3.8 0 5.9 3.1 5.9 7.3s-2.1 7.5-5.9 7.5-5.8-3.2-5.8-7.5c0-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3z" fill="#fff"/><path d="M33.7 65.5c0 .6.2 1.2.7 1.6.9.9 2.4.9 3.3 0 .4-.4.7-1 .7-1.6s-.2-1.2-.7-1.6c-.4-.4-1-.7-1.6-.7s-1.2.2-1.6.7c-.6.4-.8 1-.8 1.6z" fill="#bababa"/><path class="st0" d="M22.9 52.4c-7.2 7.2-7.2 18.9 0 26.2 7.2 7.2 18.9 7.2 26.2 0 7.2-7.2 7.2-18.9 0-26.2-7.2-7.2-19-7.2-26.2 0zm27.4 20.9c-.7 1.2-1.6 2.4-2.6 3.4s-2.2 1.9-3.4 2.6L40 71.1s.4-.1 1.2-.9 1-1.2 1-1.2l8.1 4.3zm-11-11.1c.9.9 1.4 2.1 1.4 3.3 0 1.2-.5 2.4-1.4 3.3-1.8 1.8-4.7 1.8-6.5 0-.9-.9-1.4-2.1-1.4-3.3 0-1.2.4-2.4 1.4-3.3 1.7-1.8 4.7-1.8 6.5 0zM33 59s-.9.5-1.6 1.3c-.7.8-.7.9-1 1.3l-8.2-4.4c.7-1.2 1.6-2.4 2.6-3.4 1.1-1 2.2-1.9 3.4-2.6L33 59z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M28.023 32c0 1.04.344 2.074 1.211 2.766 1.555 1.558 4.149 1.558 5.707 0 .692-.692 1.211-1.727 1.211-2.766s-.347-2.074-1.21-2.766c-.692-.695-1.731-1.21-2.77-1.21-1.035 0-2.074.343-2.766 1.21-1.039.692-1.383 1.727-1.383 2.766zm0 0" fill="#bababa"/><path d="M9.34 9.34c-12.453 12.453-12.453 32.691 0 45.32 12.453 12.453 32.691 12.453 45.32 0 12.453-12.453 12.453-32.691 0-45.32-12.453-12.453-32.867-12.453-45.32 0zm47.394 36.152c-1.21 2.074-2.765 4.153-4.496 5.88-1.73 1.73-3.804 3.288-5.883 4.5l-7.437-14.184s.691-.176 2.078-1.56c1.383-1.382 1.727-2.073 1.727-2.073zM37.707 26.293c1.559 1.555 2.422 3.633 2.422 5.707s-.863 4.152-2.422 5.707a7.933 7.933 0 0 1-11.242 0c-1.559-1.555-2.422-3.633-2.422-5.707s.691-4.152 2.422-5.707c2.941-3.113 8.129-3.113 11.242 0zm-10.895-5.535s-1.558.863-2.769 2.246c-1.211 1.387-1.211 1.558-1.73 2.25l-14.184-7.61c1.21-2.078 2.77-4.152 4.5-5.882 1.902-1.73 3.805-3.285 5.879-4.496zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/image.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M9.8 74V37h52.8v35.4l-14.9-20c-.1-.1-.2-.2-.3-.2s-.3.1-.3.2L34.4 67.9l-9.8-8.7c-.2-.1-.4-.1-.6 0L9.8 74z" fill="#fff"/><path class="st0" d="M30.4 46.9c0-2.8-2.3-5.1-5.1-5.1s-5.1 2.3-5.1 5.1 2.3 5.1 5.1 5.1c2.8-.1 5.1-2.3 5.1-5.1z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M64 32C64 14.43 49.57 0 32 0S0 14.43 0 32s14.43 32 32 32c17.57-.629 32-14.43 32-32zm0 0" fill="#3c3"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/img.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#eab41b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v14.3H6.6V6.4zm7.5 0h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1.2-14.3zm20.8-.3c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7H35v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.6-7.6 6.5-7.6z" fill="#fff"/><path class="st0" d="M33.7 65.5c0 .6.2 1.2.7 1.6.9.9 2.4.9 3.3 0 .4-.4.7-1 .7-1.6 0-.6-.2-1.2-.7-1.6-.4-.4-1-.7-1.6-.7s-1.2.2-1.6.7c-.6.4-.8 1-.8 1.6z"/><path class="st0" d="M22.9 52.4c-7.2 7.2-7.2 18.9 0 26.2 7.2 7.2 18.9 7.2 26.2 0 7.2-7.2 7.2-18.9 0-26.2-7.2-7.2-19-7.2-26.2 0zm27.4 20.9c-.7 1.2-1.6 2.4-2.6 3.4s-2.2 1.9-3.4 2.6L40 71.1s.4-.1 1.2-.9c.8-.8 1-1.2 1-1.2l8.1 4.3zm-11-11.1c.9.9 1.4 2.1 1.4 3.3 0 1.2-.5 2.4-1.4 3.3-1.8 1.8-4.7 1.8-6.5 0-.9-.9-1.4-2.1-1.4-3.3 0-1.2.4-2.4 1.4-3.3 1.7-1.8 4.7-1.8 6.5 0zM33 59s-.9.5-1.6 1.3c-.7.8-.7.9-1 1.3l-8.2-4.4c.7-1.2 1.6-2.4 2.6-3.4 1.1-1 2.2-1.9 3.4-2.6L33 59z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#eab41b"><path d="M28.023 32c0 1.04.344 2.074 1.211 2.766 1.555 1.558 4.149 1.558 5.707 0 .692-.692 1.211-1.727 1.211-2.766s-.347-2.074-1.21-2.766c-.692-.695-1.731-1.21-2.77-1.21-1.035 0-2.074.343-2.766 1.21-1.039.692-1.383 1.727-1.383 2.766zm0 0"/><path d="M9.34 9.34c-12.453 12.453-12.453 32.691 0 45.32 12.453 12.453 32.691 12.453 45.32 0 12.453-12.453 12.453-32.691 0-45.32-12.453-12.453-32.867-12.453-45.32 0zm47.394 36.152c-1.21 2.074-2.765 4.153-4.496 5.88-1.73 1.73-3.804 3.288-5.883 4.5l-7.437-14.184s.691-.176 2.078-1.56c1.383-1.382 1.727-2.073 1.727-2.073zM37.707 26.293c1.559 1.555 2.422 3.633 2.422 5.707s-.863 4.152-2.422 5.707a7.933 7.933 0 0 1-11.242 0c-1.559-1.555-2.422-3.633-2.422-5.707s.691-4.152 2.422-5.707c2.941-3.113 8.129-3.113 11.242 0zm-10.895-5.535s-1.558.863-2.769 2.246c-1.211 1.387-1.211 1.558-1.73 2.25l-14.184-7.61c1.21-2.078 2.77-4.152 4.5-5.882 1.902-1.73 3.805-3.285 5.879-4.496zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/iml.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2{fill:#999}.st2{stroke:#999;stroke-width:.5;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v14.3H6.6V6.4zm7.5 0h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1.2-14.3zm15 0h3.3v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><path class="st2" d="M44.2 75.3c7.2-3.7 3.9-7.3 1.5-6.8-.6.1-.8.2-.8.2s.2-.3.6-.5c4.6-1.6 8.1 4.8-1.5 7.3l.2-.2m-6.4-10.5c1.8 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.1 0 .1-13.1 3.4-6.8 10.6"/><path class="st2" d="M39.8 46.5s4 4-3.8 10.1c-6.2 4.9-1.4 7.7 0 10.9-3.6-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.2M31 76.8s-1.5.9 1 1.1c3 .3 4.6.3 7.9-.3 0 0 .9.6 2.1 1-7.4 3.3-16.9-.1-11-1.8m-.9-4.2s-1.6 1.2.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.6 1-9.1 2.6-19.2.2-12.7-2"/><path class="st2" d="M47.7 79.9s1.1.9-1.2 1.6c-4.3 1.3-18 1.7-21.8.1-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.2 23.9-3m-16-11.6s-7 1.7-2.5 2.3c1.9.3 5.7.2 9.2-.1 2.9-.2 5.8-.8 5.8-.8s-1 .4-1.8.9c-7.1 1.9-20.7 1-16.8-.9 3.4-1.6 6.1-1.4 6.1-1.4"/><path class="st2" d="M32.4 85.4c6.9.4 17.5-.2 17.7-3.5 0 0-.5 1.2-5.7 2.2-5.9 1.1-13.1 1-17.5.3.1 0 1 .7 5.5 1"/></svg>
1
<svg height="64" width="48" xmlns="http://www.w3.org/2000/svg"><g fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".5"><path d="M44.2 75.3c7.2-3.701 3.9-7.3 1.5-6.799-.6.099-.801.2-.801.2s.2-.3.601-.5C50.1 66.6 53.6 73 44 75.5zm-6.4-10.5c1.801 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.101 0 .101-13.1 3.401-6.8 10.6" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M39.8 46.499s3.999 4-3.8 10.102c-6.2 4.898-1.4 7.7 0 10.899-3.601-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.201M31 76.8s-1.5.9 1 1.1c3 .299 4.6.299 7.9-.3 0 0 .9.599 2.1 1-7.4 3.3-16.901-.1-11-1.8m-.9-4.2s-1.6 1.199.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.599 1-9.1 2.6-19.199.2-12.698-2" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M47.7 79.9s1.1.9-1.2 1.599c-4.3 1.302-18 1.702-21.8.101-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.199 23.9-3M31.7 68.3s-7 1.702-2.499 2.301c1.9.301 5.699.2 9.2-.101 2.9-.2 5.799-.8 5.799-.8s-1 .4-1.8.901c-7.1 1.9-20.7.999-16.8-.9 3.4-1.6 6.1-1.401 6.1-1.401" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M32.399 85.4c6.901.4 17.502-.2 17.7-3.5 0 0-.499 1.2-5.699 2.2-5.899 1.1-13.101 1-17.5.3.1 0 1 .7 5.499 1" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/></g></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/in.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M26.2 70.4h3.3v14.3h-3.3V70.4zm7 0h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4v-6.6h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V70.4z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/inc.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v14.3H6.6V6.4zm7 0H17l2.4 6.6c.4 1 .7 2.4.7 2.4h.1S20 13.9 20 13V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4zm19.1-.3c1.3 0 2.6.4 3.6 1.2L35 10.2c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4-.1-4.3 2.3-7.5 6.3-7.5z" fill="#fff"/><path d="M28.4 65l-7.7 7.6c-.9 1-1.4 2.2-1.4 3.5 0 1.2.5 2.5 1.4 3.4l.1.1c.9.9 2.2 1.4 3.4 1.4 1.3 0 2.5-.5 3.5-1.4l8.6-8.6 9.3-9.3c.4-.4.6-1 .6-1.5s-.2-1.1-.6-1.5c-.4-.4-1-.6-1.5-.6s-1.1.2-1.5.6L29.2 72c-.6.6-1.5.6-2.2 0-.6-.6-.6-1.6 0-2.2l13.3-13.3c1-1 2.3-1.5 3.7-1.5 1.3 0 2.7.5 3.7 1.5s1.5 2.3 1.5 3.7c0 1.3-.5 2.7-1.5 3.7l-9.3 9.3-8.6 8.6c-1.5 1.5-3.6 2.3-5.6 2.3-2 0-4-.7-5.5-2.2l-.1-.1c-1.5-1.5-2.3-3.5-2.3-5.6 0-2 .8-4.1 2.3-5.6l8.6-8.6 10.9-11c2-2 4.6-3 7.3-3s5.3 1 7.3 3 3 4.6 3 7.3c0 2.6-1 5.3-3 7.3L37.8 80.5c-.6.6-1.6.6-2.2 0-.6-.6-.6-1.6 0-2.2l14.9-14.9c1.4-1.4 2.1-3.3 2.1-5.1 0-1.8-.7-3.7-2.1-5.1-1.4-1.4-3.3-2.1-5.2-2.1-1.9 0-3.7.7-5.1 2.1L28.4 65z" fill="#999" stroke="#999" stroke-width=".25" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="71" xmlns="http://www.w3.org/2000/svg"><path d="m12.225 17.126-7.7 7.598c-.9 1.001-1.4 2.201-1.4 3.501 0 1.2.5 2.5 1.4 3.4l.1.1c.9.9 2.2 1.4 3.4 1.4 1.3 0 2.5-.5 3.5-1.4l8.6-8.6 9.3-9.3c.4-.4.6-1 .6-1.5s-.2-1.101-.6-1.5-1-.6-1.5-.6-1.1.2-1.5.6l-13.4 13.3c-.6.6-1.5.6-2.2 0-.6-.6-.6-1.6 0-2.2l13.3-13.299c1-1 2.3-1.502 3.7-1.502 1.3 0 2.7.501 3.7 1.502 1 .998 1.5 2.299 1.5 3.698 0 1.3-.5 2.7-1.5 3.701l-9.3 9.3-8.6 8.6c-1.5 1.5-3.6 2.3-5.6 2.3-2 0-4-.7-5.499-2.2l-.1-.1c-1.5-1.5-2.3-3.501-2.3-5.6 0-2.001.8-4.1 2.3-5.6l8.6-8.599 10.899-11c2-2.001 4.6-3.002 7.3-3.002s5.3 1 7.3 3.002c1.999 1.999 2.999 4.6 2.999 7.3 0 2.6-1 5.3-3 7.299l-14.9 14.9c-.6.599-1.599.599-2.199 0-.6-.6-.6-1.6 0-2.201l14.9-14.898c1.4-1.4 2.1-3.301 2.1-5.1s-.7-3.701-2.1-5.101-3.3-2.1-5.2-2.1c-1.9 0-3.7.7-5.1 2.1zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".25" transform="matrix(1.7579 0 0 1.76066 .65 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/indd.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#db007b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.5-34.6h2.9v14.3H6.5V6.4zm5.2 0h3l2.1 6.6c.4 1 .6 2.4.6 2.4h.1s-.2-1.5-.2-2.4V6.4H20v14.3h-3l-2-6.6c-.3-1-.6-2.4-.6-2.4h-.1s.2 1.5.2 2.4v6.6h-2.7V6.4zm10.8 0h3.7c3.2 0 5.2 2.6 5.2 7.1s-2 7.2-5.2 7.2h-3.7V6.4zm3.6 11.4c1.5 0 2.3-1.5 2.3-4.3s-.8-4.2-2.3-4.2h-.7v8.5h.7zm7.2-11.4H37c3.2 0 5.2 2.6 5.2 7.1s-2 7.2-5.2 7.2h-3.7V6.4zm3.6 11.4c1.5 0 2.3-1.5 2.3-4.3s-.8-4.2-2.3-4.2h-.7v8.5h.7z" fill="#fff"/><path d="M22.3 79.3V50.4h3.9v28.9h-3.9zm19.3.4c-6.5 0-9.9-4-9.9-9.9s3.4-10.6 9.9-10.6c1.1 0 2.3.1 3.5.4v-9.3h3.7v28c-1.6.8-4.2 1.4-7.2 1.4zm3.5-18.2c-.9-.2-1.9-.4-2.9-.4-5.1 0-6.8 4-6.8 8.3 0 4.7 1.8 8.1 6.4 8.1 1.5 0 2.5-.2 3.3-.6V61.5z" fill="#db007b" stroke="#db007b" stroke-width="1.25" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="58" xmlns="http://www.w3.org/2000/svg"><path d="M.624 29.625V.725h3.9v28.9zm19.3.4c-6.5 0-9.899-4-9.899-9.9s3.4-10.6 9.9-10.6c1.1 0 2.3.1 3.5.4v-9.3h3.7v28c-1.6.8-4.2 1.4-7.2 1.4zm3.501-18.2c-.9-.2-1.9-.4-2.9-.4-5.1 0-6.8 4-6.8 8.3 0 4.7 1.8 8.1 6.4 8.1 1.5 0 2.5-.2 3.3-.6zm0 0" fill="#db007b" stroke="#db007b" stroke-miterlimit="10" stroke-width="1.25" transform="matrix(2.09009 0 0 2.08311 0 .076)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/inf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h3.3v14.3H6.6V6.4zm7 0H17l2.4 6.6c.4 1 .7 2.4.7 2.4h.1S20 13.9 20 13V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4h.1zm13.3 0H34v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M41.4 60.3c0-2.3-1.4-4.1-3.3-4.9v-6.6c0-1.1-.8-1.9-1.9-1.9-1.1 0-1.9.8-1.9 1.9v6.6c-2 .7-3.3 2.6-3.3 4.9 0 2.3 1.4 4.1 3.3 4.9 0 .1-.1.3-.1.4v16.6c0 1.1.8 1.9 1.9 1.9 1.1 0 1.9-.8 1.9-1.9V65.5c0-.2 0-.3-.1-.4 2.1-.6 3.5-2.5 3.5-4.8zm-5.3 1.5c-.8 0-1.4-.6-1.4-1.4 0-.8.6-1.4 1.4-1.4.8 0 1.4.6 1.4 1.4.1.7-.6 1.4-1.4 1.4zM51.3 49c0-1.1-.8-1.9-1.9-1.9-1.1 0-1.9.8-1.9 1.9v15.5c-2 .7-3.3 2.6-3.3 4.9s1.4 4.1 3.3 4.9c0 .1-.1.3-.1.4v7.6c0 1.1.8 1.9 1.9 1.9 1.1 0 1.9-.8 1.9-1.9v-7.6c0-.2 0-.3-.1-.4 2-.7 3.3-2.6 3.3-4.9s-1.4-4.1-3.3-4.9V49h.2zm-1.9 21.8c-.8 0-1.4-.6-1.4-1.4s.6-1.4 1.4-1.4c.8 0 1.4.6 1.4 1.4s-.6 1.4-1.4 1.4zM21 82.1c0 1.1.8 1.9 1.9 1.9s1.9-.8 1.9-1.9v-7.6c0-.2 0-.3-.1-.4 2-.7 3.3-2.6 3.3-4.9s-1.4-4.1-3.3-4.9V49c0-1.1-.8-1.9-1.9-1.9s-1.9.8-1.9 1.9v15.5c-2 .7-3.3 2.6-3.3 4.9s1.4 4.1 3.3 4.9c0 .1-.1.3-.1.4v7.6c0-.2.2-.2.2-.2zm1.9-14.2c.8 0 1.4.6 1.4 1.4s-.6 1.4-1.4 1.4-1.4-.6-1.4-1.4.6-1.4 1.4-1.4z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M41.266 22.992c0-3.945-2.403-7.035-5.664-8.406V3.262C35.602 1.372 34.23 0 32.344 0s-3.262 1.371-3.262 3.262v11.324c-3.43 1.2-5.66 4.46-5.66 8.406 0 3.945 2.402 7.035 5.66 8.406 0 .172-.172.516-.172.688V60.57c0 1.887 1.375 3.258 3.262 3.258s3.258-1.371 3.258-3.258V31.914c0-.344 0-.516-.168-.687 3.601-1.028 6.004-4.29 6.004-8.235zm-9.094 2.574c-1.371 0-2.402-1.03-2.402-2.402 0-1.375 1.03-2.402 2.402-2.402s2.402 1.027 2.402 2.402c.172 1.2-1.031 2.402-2.402 2.402zM58.254 3.602c0-1.887-1.375-3.258-3.262-3.258s-3.262 1.37-3.262 3.258v26.597c-3.43 1.2-5.66 4.461-5.66 8.406 0 3.946 2.403 7.036 5.66 8.407 0 .172-.171.515-.171.687v13.04c0 1.89 1.375 3.261 3.261 3.261 1.887 0 3.262-1.371 3.262-3.262V47.7c0-.344 0-.515-.172-.687 3.43-1.2 5.66-4.461 5.66-8.407 0-3.945-2.402-7.035-5.66-8.406V3.602zm-3.262 37.406c-1.37 0-2.402-1.028-2.402-2.403 0-1.37 1.031-2.402 2.402-2.402 1.371 0 2.403 1.031 2.403 2.402 0 1.375-1.032 2.403-2.403 2.403zm-48.73 19.39c0 1.887 1.375 3.258 3.261 3.258 1.887 0 3.258-1.37 3.258-3.258V47.355c0-.343 0-.511-.172-.683 3.434-1.203 5.664-4.461 5.664-8.41 0-3.946-2.402-7.035-5.664-8.407V3.602c0-1.887-1.37-3.258-3.257-3.258S6.09 1.714 6.09 3.602v26.597C2.66 31.4.43 34.66.43 38.605c0 3.946 2.402 7.036 5.66 8.407 0 .172-.172.515-.172.687v13.04c0-.34.344-.34.344-.34zm3.261-24.367c1.372 0 2.403 1.032 2.403 2.403 0 1.375-1.031 2.402-2.403 2.402-1.375 0-2.402-1.027-2.402-2.402 0-1.371 1.027-2.403 2.402-2.403zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/info.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.8-34.5h2.4v14.2H6.8V6.5zm5 0h2.6l3.7 8c.4.9.7 2.2.7 2.2h.1s-.1-1.3-.1-2.2v-8H21v14.2h-2.5l-3.7-8.1c-.4-.9-.7-2.2-.7-2.2H14s.1 1.3.1 2.2v8h-2.3V6.5zm11.7 0h6.6v2.2H26v4.1h3.5V15H26v5.8h-2.4V6.5zm13.4-.3c3.5 0 5.7 3 5.7 7.3s-2.2 7.4-5.7 7.4-5.7-3.1-5.7-7.4c0-4.2 2.2-7.3 5.7-7.3zm0 12.4c2 0 3.2-2 3.2-5.1 0-3-1.2-4.9-3.2-4.9s-3.2 1.9-3.2 4.9c0 3.1 1.2 5.1 3.2 5.1z" fill="#fff"/><path class="st0" d="M37.8 55c-.6 0-1.1.2-1.5.6-.4.4-.6.9-.6 1.5s.2 1.1.6 1.5c.4.4.9.6 1.5.6s1.1-.2 1.5-.6c.4-.4.6-.9.6-1.5s-.2-1.1-.6-1.5c-.3-.4-.8-.6-1.5-.6zm1 6.8l-.1.2h.1v-.2zm-.1.2c-2 .3-3.9.4-5.9.7l-.2.9h.5c.3 0 .6.1.8.3.2.2.3.4.3.6 0 .3-.1.5-.3 1.2l-2.1 7.1c-.2.6-.3 1-.3 1.4 0 .6.2 1 .6 1.4.4.4 1.6.5 2.2.5 1.7 0 4.5-.9 6-3.5l-1.2-.7c-.6 1-1.7 1.7-2.3 2-.6.3-.9.2-1 .2-.1 0-.2 0-.3-.1-.1-.1-.1-.2-.1-.3 0-.2.1-.6.3-1.2l3-10.5z"/><path d="M36 48.5c-9.4 0-17 7.6-17 17s7.6 17 17 17 17-7.6 17-17-7.6-17-17-17zm0 1.9c8.4 0 15.1 6.8 15.1 15.1 0 8.4-6.8 15.1-15.1 15.1s-15.1-6.8-15.1-15.1c0-8.4 6.7-15.1 15.1-15.1z" fill="#999" stroke="#999" stroke-width="2" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M35.2 13.332c-1.067 0-1.954.355-2.665 1.066-.715.711-1.07 1.602-1.07 2.668s.355 1.957 1.07 2.668c.711.711 1.598 1.067 2.664 1.067 1.067 0 1.957-.356 2.668-1.067.711-.71 1.067-1.601 1.067-2.668s-.356-1.957-1.067-2.668c-.535-.71-1.422-1.066-2.668-1.066zm1.777 12.09-.176.355h.176zm-.176.355c-3.555.535-6.934.711-10.489 1.246l-.355 1.598h.887c.535 0 1.066.18 1.422.535s.535.711.535 1.067c0 .53-.18.886-.535 2.132l-3.73 12.622C24.18 46.043 24 46.754 24 47.465c0 1.07.355 1.781 1.066 2.492.711.711 2.844.887 3.91.887 3.024 0 8-1.598 10.669-6.223l-2.133-1.242c-1.067 1.777-3.024 3.02-4.09 3.555-1.067.53-1.602.355-1.777.355-.18 0-.356 0-.536-.18-.175-.175-.175-.355-.175-.53 0-.356.175-1.067.53-2.134zm0 0"/><path d="M32 1.777C15.29 1.777 1.777 15.29 1.777 32S15.29 62.223 32 62.223 62.223 48.71 62.223 32 48.71 1.777 32 1.777zm0 3.38c14.934 0 26.844 12.09 26.844 26.843 0 14.934-12.09 26.844-26.844 26.844S5.156 46.754 5.156 32C5.156 17.066 17.066 5.156 32 5.156zm0 0" stroke="#999" stroke-miterlimit="10" stroke-width="3.55556"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ini.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h3.3v14.3H6.6V6.4zm7 0H17l2.4 6.6c.4 1 .7 2.4.7 2.4h.1S20 13.9 20 13V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4h.1zm13.3 0h3.3v14.3h-3.3V6.4z" fill="#fff"/><path class="st0" d="M41.4 60.3c0-2.3-1.4-4.1-3.3-4.9v-6.6c0-1.1-.8-1.9-1.9-1.9-1.1 0-1.9.8-1.9 1.9v6.6c-2 .7-3.3 2.6-3.3 4.9 0 2.3 1.4 4.1 3.3 4.9 0 .1-.1.3-.1.4v16.6c0 1.1.8 1.9 1.9 1.9 1.1 0 1.9-.8 1.9-1.9V65.5c0-.2 0-.3-.1-.4 2.1-.6 3.5-2.5 3.5-4.8zm-5.3 1.5c-.8 0-1.4-.6-1.4-1.4 0-.8.6-1.4 1.4-1.4.8 0 1.4.6 1.4 1.4.1.7-.6 1.4-1.4 1.4zM51.3 49c0-1.1-.8-1.9-1.9-1.9-1.1 0-1.9.8-1.9 1.9v15.5c-2 .7-3.3 2.6-3.3 4.9s1.4 4.1 3.3 4.9c0 .1-.1.3-.1.4v7.6c0 1.1.8 1.9 1.9 1.9 1.1 0 1.9-.8 1.9-1.9v-7.6c0-.2 0-.3-.1-.4 2-.7 3.3-2.6 3.3-4.9s-1.4-4.1-3.3-4.9V49h.2zm-1.9 21.8c-.8 0-1.4-.6-1.4-1.4s.6-1.4 1.4-1.4c.8 0 1.4.6 1.4 1.4s-.6 1.4-1.4 1.4zM21 82.1c0 1.1.8 1.9 1.9 1.9s1.9-.8 1.9-1.9v-7.6c0-.2 0-.3-.1-.4 2-.7 3.3-2.6 3.3-4.9s-1.4-4.1-3.3-4.9V49c0-1.1-.8-1.9-1.9-1.9s-1.9.8-1.9 1.9v15.5c-2 .7-3.3 2.6-3.3 4.9s1.4 4.1 3.3 4.9c0 .1-.1.3-.1.4v7.6c0-.2.2-.2.2-.2zm1.9-14.2c.8 0 1.4.6 1.4 1.4s-.6 1.4-1.4 1.4-1.4-.6-1.4-1.4.6-1.4 1.4-1.4z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M41.266 22.992c0-3.945-2.403-7.035-5.664-8.406V3.262C35.602 1.372 34.23 0 32.344 0s-3.262 1.371-3.262 3.262v11.324c-3.43 1.2-5.66 4.46-5.66 8.406 0 3.945 2.402 7.035 5.66 8.406 0 .172-.172.516-.172.688V60.57c0 1.887 1.375 3.258 3.262 3.258s3.258-1.371 3.258-3.258V31.914c0-.344 0-.516-.168-.687 3.601-1.028 6.004-4.29 6.004-8.235zm-9.094 2.574c-1.371 0-2.402-1.03-2.402-2.402 0-1.375 1.03-2.402 2.402-2.402s2.402 1.027 2.402 2.402c.172 1.2-1.031 2.402-2.402 2.402zM58.254 3.602c0-1.887-1.375-3.258-3.262-3.258s-3.262 1.37-3.262 3.258v26.597c-3.43 1.2-5.66 4.461-5.66 8.406 0 3.946 2.403 7.036 5.66 8.407 0 .172-.171.515-.171.687v13.04c0 1.89 1.375 3.261 3.261 3.261 1.887 0 3.262-1.371 3.262-3.262V47.7c0-.344 0-.515-.172-.687 3.43-1.2 5.66-4.461 5.66-8.407 0-3.945-2.402-7.035-5.66-8.406V3.602zm-3.262 37.406c-1.37 0-2.402-1.028-2.402-2.403 0-1.37 1.031-2.402 2.402-2.402 1.371 0 2.403 1.031 2.403 2.402 0 1.375-1.032 2.403-2.403 2.403zm-48.73 19.39c0 1.887 1.375 3.258 3.261 3.258 1.887 0 3.258-1.37 3.258-3.258V47.355c0-.343 0-.511-.172-.683 3.434-1.203 5.664-4.461 5.664-8.41 0-3.946-2.402-7.035-5.664-8.407V3.602c0-1.887-1.37-3.258-3.257-3.258S6.09 1.714 6.09 3.602v26.597C2.66 31.4.43 34.66.43 38.605c0 3.946 2.402 7.036 5.66 8.407 0 .172-.172.515-.172.687v13.04c0-.34.344-.34.344-.34zm3.261-24.367c1.372 0 2.403 1.032 2.403 2.403 0 1.375-1.031 2.402-2.403 2.402-1.375 0-2.402-1.027-2.402-2.402 0-1.371 1.027-2.403 2.402-2.403zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/inv.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#938886}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h3.3v14.3H6.6V6.4zm7 0H17l2.4 6.6c.4 1 .7 2.4.7 2.4h.1S20 13.9 20 13V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4h.1zm12 0h3.6l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3l1.7-8.1h3.5l-3.9 14.3h-3.3L25.6 6.4z" fill="#fff"/><path class="st0" d="M45.2 62.5v-9.9L35.9 47l-9.2 5.5v10l-9.2 5v11.1L27 84l9-5.2 9 5.2 9.5-5.4v-11l-9.3-5.1zm-1.7 0l-6.7 3.7v-7.6l6.7-3.9v7.8zm-7.6-13.4l6.6 4-6.6 3.9-6.4-4 6.4-3.9zM20.3 68l7.4-3.9 6.5 3.7L27 72l-6.7-4zm7.5 5.5l7.3-4.2v7.8l-7.3 4.3v-7.9zm10.1-5.7l6.5-3.7 7.4 4L45 72l-7.1-4.2zm14.8 9.7l-6.8 3.9v-7.9l6.8-3.9v7.9z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M47.914 26.813V9.688L31.828 0 15.914 9.512v17.3L0 35.462v19.2L16.434 64 32 55.004 47.566 64 64 54.66V35.633zm-2.941 0-11.59 6.398V20.066l11.59-6.746zM31.828 3.633l11.414 6.918-11.414 6.746-11.07-6.918zM4.844 36.324l12.8-6.746 11.243 6.399-12.453 7.265zm12.972 9.512 12.625-7.262v13.492l-12.625 7.438zm17.47-9.86 11.245-6.398 12.797 6.918-11.762 6.746zm25.6 16.782-11.761 6.746V45.836l11.762-6.742zm0 0" fill="#938886"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/iso.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#eab41b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v14.3H6.6V6.4zm7.7 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zM29.5 6.1c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2.1-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2S27 11 27 13.5c.1 2.5.8 4.3 2.5 4.3z" fill="#fff"/><path class="st0" d="M33.7 65.5c0 .6.2 1.2.7 1.6.9.9 2.4.9 3.3 0 .4-.4.7-1 .7-1.6 0-.6-.2-1.2-.7-1.6-.4-.4-1-.7-1.6-.7s-1.2.2-1.6.7c-.6.4-.8 1-.8 1.6z"/><path class="st0" d="M22.9 52.4c-7.2 7.2-7.2 18.9 0 26.2 7.2 7.2 18.9 7.2 26.2 0 7.2-7.2 7.2-18.9 0-26.2-7.2-7.2-19-7.2-26.2 0zm27.4 20.9c-.7 1.2-1.6 2.4-2.6 3.4s-2.2 1.9-3.4 2.6L40 71.1s.4-.1 1.2-.9c.8-.8 1-1.2 1-1.2l8.1 4.3zm-11-11.1c.9.9 1.4 2.1 1.4 3.3 0 1.2-.5 2.4-1.4 3.3-1.8 1.8-4.7 1.8-6.5 0-.9-.9-1.4-2.1-1.4-3.3 0-1.2.4-2.4 1.4-3.3 1.7-1.8 4.7-1.8 6.5 0zM33 59s-.9.5-1.6 1.3c-.7.8-.7.9-1 1.3l-8.2-4.4c.7-1.2 1.6-2.4 2.6-3.4 1.1-1 2.2-1.9 3.4-2.6L33 59z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#eab41b"><path d="M28.023 32c0 1.04.344 2.074 1.211 2.766 1.555 1.558 4.149 1.558 5.707 0 .692-.692 1.211-1.727 1.211-2.766s-.347-2.074-1.21-2.766c-.692-.695-1.731-1.21-2.77-1.21-1.035 0-2.074.343-2.766 1.21-1.039.692-1.383 1.727-1.383 2.766zm0 0"/><path d="M9.34 9.34c-12.453 12.453-12.453 32.691 0 45.32 12.453 12.453 32.691 12.453 45.32 0 12.453-12.453 12.453-32.691 0-45.32-12.453-12.453-32.867-12.453-45.32 0zm47.394 36.152c-1.21 2.074-2.765 4.153-4.496 5.88-1.73 1.73-3.804 3.288-5.883 4.5l-7.437-14.184s.691-.176 2.078-1.56c1.383-1.382 1.727-2.073 1.727-2.073zM37.707 26.293c1.559 1.555 2.422 3.633 2.422 5.707s-.863 4.152-2.422 5.707a7.933 7.933 0 0 1-11.242 0c-1.559-1.555-2.422-3.633-2.422-5.707s.691-4.152 2.422-5.707c2.941-3.113 8.129-3.113 11.242 0zm-10.895-5.535s-1.558.863-2.769 2.246c-1.211 1.387-1.211 1.558-1.73 2.25l-14.184-7.61c1.21-2.078 2.77-4.152 4.5-5.882 1.902-1.73 3.805-3.285 5.879-4.496zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/j2.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#b41717}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm-.3-25.7H9v1.1c0 1.5.4 1.6.7 1.6.5 0 .7-.3.7-1.6v-7H7.7v-3h6v9.9c0 3.3-2 4.6-4 4.6-2.1 0-4-1.4-4-4.6v-1zm11.4 3.8c0-5 4.5-5.5 4.5-8.4 0-1-.5-1.4-1.2-1.4-.6 0-1.1.3-1.4.8l-2.2-1.8c.8-1.1 2.3-2.1 4.1-2.1 2.1 0 4.2 1.3 4.2 4.2 0 4.1-4.2 5.4-4.4 7.5h4.6v2.9h-7.9c-.3-.7-.3-1.1-.3-1.7z" fill="#fff"/><path d="M55.8 47s-7.6 3.6-13.7 4.4c-6.1.8-17.9 1.6-20.2 1s-4-1.2-4-1.2l.5 1.6-1.5 1.3.3.5h.6l1.9.2.3.8 1.1.1.5 1.8s2.2.2 2.9.2c.7 0 2-.1 2-.1v.7l.5.1v.8l-1.1.9h.3v.3s-2.4.2-3.3 0c-1-.1-1.1-.1-1.1-.1l-.1.1v.4h.2l.1 1.8 4.9-.2-.5 6.6v.8l-4.1-.2v-1.7h.9l.1-.7.8-.2.1-.2-3.2-.7-2.4.7.4.3h.4v.6h.8v1.6l-.9.2.2.4.2.1v1.3h.6v5.9l-.9.1.1 1.7.6.1-.1 4h2.5l-.5-3.8 3.8-.1-.3 2.1-.4 1.5h3.8v-3.7l2.6-.2-.1 2.4-.1 1.4h2.2l-.1-3.8h.3L34 77h-.4l-.1-.8-.2-2.2.1-2.5h.5V70h-.6l.1-1.8.7-.1v-.6l.4-.1.4-.3-2.5-.5-2.5.6.2.4h.6l.1.7h.7v1.6l-3-.1.1-1.7.1-1.5v-2l.1-2.1 6-.3 7.1-.4.1 1.3-.3 3.2-.1 3H39v-2.1h1v-.6l.4-.1v-.1h.4l.2-.3-3-.7-2.9.6.2.4h.3v.2h.4v.7h.9v1.9H36v.4h.3v1.6h.6l-.1 6.4-.8.2v.3h.3v1.6h.5l-.2 2.3-.2 1.9 3.1.1-.1-1.7-.2-1.4v-1.2h2.6l-.1 1.9v2l1.5.1 2-.1.6-.2-.4-1.1-.1-1.7-.2-1.2 2.5-.1-.1 1.5v2.3l1 .1h1l.5-.2-.3-2.2-.1-1.6h.4v-1.5h.1v-.3h-.5l-.1-1.1v-4.7h.4V70h.2v-.3h-.6v-1.8l.9-.1-.1-.6h.4v-.1l.5-.3-2.7-.6-2.5.6.2.3h.4v.1h.4v.7h.9l.1 1.7h-3.2l-.4-2.6-.3-1.4-.2-2.5.1-1.4 6.3-.5v-2.1l.3-.1v-.3l-.2-.1s-3.5.5-4.6.6c-.3 0-.3 0-.5.1v-.4l-1.3-.7v-.8h.5v-1.1s2.7-.2 3.7-.4 2.4-.5 2.4-.5l.7-1.8 1.3-.4.1-.3 3-.8.3-.3-1.1-2.5.1-.6.6-.3.4-1.3-.2-.1zm-14.4 9.5v.9h.7v.9l-1.3.9-.1.3h.5v.2l-4.2.2v-.6l.2-.3v-.6l.1-.3v-.4l.2-.7 3.9-.5zm-8.5.8l-.1.6.3.4v.7l.3.5-.1.5.2.3-4.2.2v-.1l.5-.1v-.2l-1.1-.6-.1-.9h.5v-1l3.8-.3zM39 71.4l2.5.2-.1 3.4.3 2.8-2.7-.1v-6.3zm-16.9.1l4 .2-.3 2.3v2l.3 1.1-4 .2v-5.8zm25.9 0v5.8l-2.6.2-.1-3.1-.3-2.8 3-.1zm-19.5.1h3V77h-2.8l-.1-1.7v-1.7l-.1-2z" fill="#b41717" stroke="#b41717" stroke-width=".25" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M39.06.14s-7.599 3.599-13.7 4.4c-6.1.798-17.9 1.6-20.2 1-2.3-.601-4-1.201-4-1.201l.501 1.6-1.5 1.3.3.5h.6l1.9.201.3.799 1.1.1.501 1.8s2.2.2 2.9.2c.698 0 1.999-.101 1.999-.101v.7l.501.101v.801l-1.1.9h.3v.298s-2.4.201-3.302 0c-1-.098-1.098-.098-1.098-.098l-.101.098v.402h.2l.101 1.798 4.899-.198-.499 6.6v.798l-4.101-.198v-1.7h.9l.1-.701.801-.2.099-.2-3.2-.7-2.4.7.4.3h.4v.6h.8v1.6l-.899.2.2.4.2.1v1.301h.6v5.9l-.901.1.101 1.7.6.098-.101 4h2.5l-.499-3.8 3.798-.1-.299 2.1-.4 1.502h3.801v-3.702l2.599-.198-.099 2.398-.1 1.401h2.198l-.099-3.8h.301l.299-1.9h-.4l-.1-.8-.2-2.2.1-2.5h.501v-1.5h-.602l.101-1.8.701-.1v-.601l.4-.098.4-.301-2.5-.5-2.5.6.2.4h.6l.098.7h.701v1.6l-3-.1.1-1.7.101-1.5v-2l.1-2.099 5.999-.301 7.1-.4.101 1.299-.301 3.202-.099 2.999h-2.6v-2.1h.999v-.6l.4-.1v-.101h.4l.2-.299-3-.7-2.9.6.2.399h.3v.2h.4v.701h.9v1.9h-.9v.4h.3v1.6h.6l-.099 6.4-.802.2v.3h.301v1.6h.501l-.2 2.3-.2 1.9 3.1.101-.101-1.7-.2-1.401v-1.2h2.601l-.101 1.9v2l1.5.1 2-.1.6-.2-.4-1.1-.1-1.7-.2-1.2 2.5-.1-.1 1.5v2.3l1 .1h1.001l.499-.2-.3-2.2-.1-1.6h.4v-1.5h.1v-.299h-.5l-.099-1.1V24.74h.4v-1.6h.2v-.301h-.6V21.04l.898-.1-.098-.601h.4v-.1l.498-.3-2.7-.6-2.5.6.2.3h.402v.1h.4v.7h.898l.102 1.7H28.06l-.4-2.6-.299-1.4-.2-2.501.1-1.399 6.3-.5v-2.1l.298-.1v-.301l-.2-.098s-3.5.5-4.6.6c-.298 0-.298 0-.498.098v-.4l-1.3-.7v-.799h.5v-1.1s2.7-.2 3.7-.399c.999-.2 2.398-.502 2.398-.502l.701-1.798 1.3-.402.1-.299 3-.801.3-.299-1.1-2.499.1-.6.6-.301.4-1.299zM24.662 9.638v.901h.699v.9l-1.3.901-.1.299h.501v.2l-4.2.2v-.6l.2-.3v-.6l.099-.299v-.402l.2-.698zm-8.502.801-.098.6.298.4v.7l.301.5-.1.5.2.301-4.199.199v-.1l.499-.099v-.2l-1.099-.601-.1-.9h.5v-1.001zm6.101 14.1 2.5.2-.099 3.4.299 2.8-2.7-.1zm-16.9.1 4 .2-.3 2.3v2l.3 1.1-4 .2zm25.9 0v5.8l-2.6.2-.1-3.1-.3-2.8zm-19.5.1h3v5.4h-2.799l-.1-1.7v-1.7zm0 0" fill="#b41717" stroke="#b41717" stroke-miterlimit="10" stroke-width=".25" transform="matrix(1.7 0 0 1.71166 0 .105)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/jar.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}.st2,.st3{fill:#265db4;stroke:#265db4;stroke-width:.5;stroke-miterlimit:10}.st3{fill:#c00;stroke:#c00}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm-.3-25.7H9v1.1c0 1.5.4 1.6.7 1.6.5 0 .7-.3.7-1.6v-7H7.7v-3h6v9.9c0 3.3-2 4.6-4 4.6-2.1 0-4-1.4-4-4.6v-1zm14-8.9h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.5-2.9c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.6 2.9h2zm6.9-8.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.8v4.8h-3.3V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6z" fill="#fff"/><path class="st2" d="M44.2 75.3c7.2-3.7 3.9-7.3 1.5-6.8-.6.1-.8.2-.8.2s.2-.3.6-.5c4.6-1.6 8.1 4.8-1.5 7.3l.2-.2"/><path class="st3" d="M37.8 64.8c1.8 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.1 0 .1-13.1 3.4-6.8 10.6"/><path class="st3" d="M39.8 46.5s4 4-3.8 10.1c-6.2 4.9-1.4 7.7 0 10.9-3.6-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.2"/><path class="st2" d="M31 76.8s-1.5.9 1 1.1c3 .3 4.6.3 7.9-.3 0 0 .9.6 2.1 1-7.4 3.3-16.9-.1-11-1.8m-.9-4.2s-1.6 1.2.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.6 1-9.1 2.6-19.2.2-12.7-2"/><path class="st2" d="M47.7 79.9s1.1.9-1.2 1.6c-4.3 1.3-18 1.7-21.8.1-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.2 23.9-3m-16-11.6s-7 1.7-2.5 2.3c1.9.3 5.7.2 9.2-.1 2.9-.2 5.8-.8 5.8-.8s-1 .4-1.8.9c-7.1 1.9-20.7 1-16.8-.9 3.4-1.6 6.1-1.4 6.1-1.4"/><path class="st2" d="M32.4 85.4c6.9.4 17.5-.2 17.7-3.5 0 0-.5 1.2-5.7 2.2-5.9 1.1-13.1 1-17.5.3.1 0 1 .7 5.5 1"/></svg>
1
<svg height="64" width="48" xmlns="http://www.w3.org/2000/svg"><g stroke-miterlimit="10" stroke-width=".5"><path d="M44.2 75.3c7.2-3.701 3.9-7.3 1.5-6.799-.6.099-.801.2-.801.2s.2-.3.601-.5C50.1 66.6 53.6 73 44 75.5zm0 0" fill="#265db4" stroke="#265db4" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M37.8 64.8c1.801 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.101 0 .101-13.1 3.401-6.8 10.6" fill="#c00" stroke="#c00" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M39.8 46.499s3.999 4-3.8 10.102c-6.2 4.898-1.4 7.7 0 10.899-3.601-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.201" fill="#c00" stroke="#c00" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><g fill="#265db4" stroke="#265db4"><path d="M31 76.8s-1.5.9 1 1.1c3 .299 4.6.299 7.9-.3 0 0 .9.599 2.1 1-7.4 3.3-16.901-.1-11-1.8m-.9-4.2s-1.6 1.199.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.599 1-9.1 2.6-19.199.2-12.698-2" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M47.7 79.9s1.1.9-1.2 1.599c-4.3 1.302-18 1.702-21.8.101-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.199 23.9-3M31.7 68.3s-7 1.702-2.499 2.301c1.9.301 5.699.2 9.2-.101 2.9-.2 5.799-.8 5.799-.8s-1 .4-1.8.901c-7.1 1.9-20.7.999-16.8-.9 3.4-1.6 6.1-1.401 6.1-1.401" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M32.399 85.4c6.901.4 17.502-.2 17.7-3.5 0 0-.499 1.2-5.699 2.2-5.899 1.1-13.101 1-17.5.3.1 0 1 .7 5.499 1" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/></g></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/java.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}.st2,.st3{fill:#265db4;stroke:#265db4;stroke-width:.5;stroke-miterlimit:10}.st3{fill:#c00;stroke:#c00}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm-.3-25.7h2.7v1.1c0 1.5.3 1.6.6 1.6.4 0 .6-.3.6-1.6v-7H7.3v-3h4.9v9.9c0 3.3-1.6 4.6-3.3 4.6-1.7 0-3.3-1.4-3.3-4.6v-1zm11.5-8.9h2.9l3 14.3h-2.7l-.5-3h-2.5l-.5 3h-2.7l3-14.3zm2.3 8.6l-.5-2.9c-.2-.9-.3-2.5-.3-2.5h-.1s-.2 1.5-.3 2.5l-.5 2.9h1.7zm4.1-8.6h2.9l1.3 8.1c.1.9.3 2.3.3 2.3h.1s.1-1.4.3-2.3l1.4-8.1h2.9l-3.2 14.3h-2.7L23.6 6.4zm12.6 0h2.9l3 14.3h-2.7l-.5-3h-2.5l-.5 3h-2.7l3-14.3zm2.3 8.6l-.5-2.8c-.2-.9-.3-2.5-.3-2.5h-.1s-.2 1.5-.3 2.5l-.4 2.8h1.6z" fill="#fff"/><path class="st2" d="M44.2 75.3c7.2-3.7 3.9-7.3 1.5-6.8-.6.1-.8.2-.8.2s.2-.3.6-.5c4.6-1.6 8.1 4.8-1.5 7.3l.2-.2"/><path class="st3" d="M37.8 64.8c1.8 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.1 0 .1-13.1 3.4-6.8 10.6"/><path class="st3" d="M39.8 46.5s4 4-3.8 10.1c-6.2 4.9-1.4 7.7 0 10.9-3.6-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.2"/><path class="st2" d="M31 76.8s-1.5.9 1 1.1c3 .3 4.6.3 7.9-.3 0 0 .9.6 2.1 1-7.4 3.3-16.9-.1-11-1.8m-.9-4.2s-1.6 1.2.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.6 1-9.1 2.6-19.2.2-12.7-2"/><path class="st2" d="M47.7 79.9s1.1.9-1.2 1.6c-4.3 1.3-18 1.7-21.8.1-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.2 23.9-3m-16-11.6s-7 1.7-2.5 2.3c1.9.3 5.7.2 9.2-.1 2.9-.2 5.8-.8 5.8-.8s-1 .4-1.8.9c-7.1 1.9-20.7 1-16.8-.9 3.4-1.6 6.1-1.4 6.1-1.4"/><path class="st2" d="M32.4 85.4c6.9.4 17.5-.2 17.7-3.5 0 0-.5 1.2-5.7 2.2-5.9 1.1-13.1 1-17.5.3.1 0 1 .7 5.5 1"/></svg>
1
<svg height="64" width="48" xmlns="http://www.w3.org/2000/svg"><g stroke-miterlimit="10" stroke-width=".5"><path d="M44.2 75.3c7.2-3.701 3.9-7.3 1.5-6.799-.6.099-.801.2-.801.2s.2-.3.601-.5C50.1 66.6 53.6 73 44 75.5zm0 0" fill="#265db4" stroke="#265db4" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M37.8 64.8c1.801 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.101 0 .101-13.1 3.401-6.8 10.6" fill="#c00" stroke="#c00" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M39.8 46.499s3.999 4-3.8 10.102c-6.2 4.898-1.4 7.7 0 10.899-3.601-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.201" fill="#c00" stroke="#c00" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><g fill="#265db4" stroke="#265db4"><path d="M31 76.8s-1.5.9 1 1.1c3 .299 4.6.299 7.9-.3 0 0 .9.599 2.1 1-7.4 3.3-16.901-.1-11-1.8m-.9-4.2s-1.6 1.199.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.599 1-9.1 2.6-19.199.2-12.698-2" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M47.7 79.9s1.1.9-1.2 1.599c-4.3 1.302-18 1.702-21.8.101-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.199 23.9-3M31.7 68.3s-7 1.702-2.499 2.301c1.9.301 5.699.2 9.2-.101 2.9-.2 5.799-.8 5.799-.8s-1 .4-1.8.901c-7.1 1.9-20.7.999-16.8-.9 3.4-1.6 6.1-1.401 6.1-1.401" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M32.399 85.4c6.901.4 17.502-.2 17.7-3.5 0 0-.499 1.2-5.699 2.2-5.899 1.1-13.101 1-17.5.3.1 0 1 .7 5.499 1" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/></g></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/jpg.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm-.3-25.7H9v1.1c0 1.5.4 1.6.7 1.6.5 0 .7-.3.7-1.6v-7H7.7v-3h6v9.9c0 3.3-2 4.6-4 4.6-2.1 0-4-1.4-4-4.6v-1zm11.6-8.9h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm13.6-7.3c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7H35v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.1-4.5 2.5-7.6 6.4-7.6z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/js.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#307ac6}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm-.3-25.7H9v1.1c0 1.5.4 1.6.7 1.6.5 0 .7-.3.7-1.6v-7H7.7v-3h6v9.9c0 3.3-2 4.6-4 4.6-2.1 0-4-1.4-4-4.6v-1zM18 16.7c.6.6 1.4 1.2 2.3 1.2s1.3-.6 1.3-1.2c0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path d="M16.4 67.5v-4.1c.9-.1 1.6-.2 2-.4s.8-.6 1.2-1c.4-.5.5-1.1.7-1.9.1-.6.2-1.5.2-2.8 0-2.2.1-3.7.4-4.6.2-.8.6-1.6 1.2-2 .5-.5 1.4-.9 2.5-1.2.7-.2 1.9-.4 3.5-.4h.9V53c-1.3 0-2.2.1-2.6.3s-.6.4-.9.6c-.2.3-.3.7-.3 1.5s-.1 2-.2 4.1c-.1 1.2-.2 2-.4 2.8-.3.6-.6 1.2-1 1.8-.4.4-1 .9-1.8 1.4.7.4 1.3.8 1.8 1.3s.8 1.2 1.1 1.9c.3.7.4 1.8.4 3 .1 1.9.1 3.1.1 3.6 0 .7.1 1.2.3 1.6.2.4.5.5.9.6.4.2 1.2.3 2.6.3v4.1h-1c-1.6 0-2.9-.1-3.7-.4-.9-.3-1.6-.6-2.2-1.2s-1-1.2-1.2-2-.3-2.1-.3-4c0-2-.1-3.5-.3-4.1-.3-.9-.7-1.6-1.2-2-.7-.5-1.5-.7-2.7-.7zm39.1 0c-.9.1-1.6.2-2 .4-.4.2-.8.6-1.2 1-.4.5-.5 1.1-.7 1.9-.1.6-.2 1.5-.2 2.8 0 2.2-.1 3.7-.4 4.6-.2.9-.6 1.6-1.2 2-.5.5-1.4.9-2.5 1.2-.7.2-1.9.4-3.5.4h-1v-4.1c1.3 0 2.1-.1 2.6-.3s.7-.4.9-.6c.2-.3.3-.7.3-1.5 0-.6.1-2 .2-4 .1-1.2.3-2.1.5-2.8.3-.7.6-1.3 1.1-1.9.4-.5 1-.9 1.7-1.3-.9-.6-1.6-1.1-2-1.6-.5-.7-1-1.8-1.2-2.8-.2-.8-.3-2.6-.3-5.2 0-.8-.1-1.4-.3-1.8-.2-.3-.4-.5-.8-.6-.2-.3-1-.3-2.5-.3v-4h1c1.6 0 2.9.1 3.7.4.9.3 1.6.6 2.2 1.2s1 1.2 1.2 2 .4 2.1.4 4c0 2 .1 3.4.3 4.1.3.9.7 1.6 1.2 1.9.5.4 1.4.6 2.5.6.1.1 0 4.3 0 4.3z" fill="#307ac6" stroke="#307ac6" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="75" xmlns="http://www.w3.org/2000/svg"><path d="M.5 19v-4.1c.9-.1 1.6-.2 2-.4.4-.2.8-.6 1.2-1.001.4-.5.5-1.1.7-1.9.1-.6.2-1.499.2-2.799 0-2.201.1-3.7.4-4.6.2-.8.6-1.6 1.2-2 .5-.5 1.4-.9 2.5-1.2.7-.2 1.9-.4 3.5-.4h.9v3.9c-1.3 0-2.2.1-2.6.3-.4.2-.6.4-.9.6-.2.3-.3.7-.3 1.501 0 .8-.1 2-.2 4.099-.101 1.2-.2 2-.4 2.801-.301.6-.6 1.2-1 1.8-.4.4-1 .9-1.8 1.399.7.4 1.3.8 1.8 1.3s.8 1.2 1.1 1.899c.3.702.4 1.802.4 3.001.1 1.9.1 3.1.1 3.599 0 .702.1 1.202.3 1.602.2.4.5.5.9.6.4.2 1.2.3 2.6.3v4.098h-1c-1.6 0-2.9-.1-3.701-.4-.9-.3-1.6-.6-2.2-1.2-.6-.6-.999-1.2-1.2-1.999-.198-.8-.299-2.1-.299-4 0-2-.1-3.5-.3-4.1-.3-.9-.7-1.601-1.201-2-.698-.5-1.5-.7-2.7-.7zm39.1 0c-.9.1-1.6.2-2 .4s-.8.6-1.2 1.001c-.4.5-.5 1.1-.7 1.9-.099.6-.2 1.499-.2 2.799 0 2.201-.1 3.7-.4 4.6-.2.9-.6 1.6-1.2 2-.5.5-1.4.9-2.5 1.2-.7.2-1.9.4-3.5.4h-.999v-4.1c1.298 0 2.1-.1 2.599-.3s.7-.4.899-.6c.2-.3.301-.7.301-1.501 0-.6.1-2 .2-3.999.099-1.2.3-2.1.5-2.8.3-.7.6-1.3 1.1-1.9.4-.5 1-.9 1.7-1.3-.901-.6-1.6-1.1-2-1.6-.5-.7-1-1.801-1.201-2.8-.199-.8-.299-2.6-.299-5.2 0-.8-.1-1.4-.301-1.8-.199-.3-.4-.5-.799-.6-.2-.3-1-.3-2.5-.3v-4h.999c1.602 0 2.9.1 3.7.4.902.3 1.6.6 2.2 1.2.6.6 1.002 1.2 1.2 2 .201.8.402 2.1.402 4 0 2 .098 3.4.299 4.1.299.9.7 1.601 1.2 1.9.5.4 1.401.6 2.5.6.1.1 0 4.3 0 4.3zm0 0" fill="#307ac6" stroke="#307ac6" stroke-miterlimit="10" transform="matrix(1.86825 0 0 1.87558 0 .209)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/json.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}.st1{fill:#fff}.st2{fill:#999;stroke:#999;stroke-width:.5;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6V41z"/><path class="st2" d="M16.4 67.5v-4.1c.9-.1 1.6-.2 2-.4.4-.2.8-.6 1.2-1 .4-.5.5-1.1.7-1.9.1-.6.2-1.5.2-2.8 0-2.2.1-3.7.4-4.6.2-.8.6-1.6 1.2-2 .5-.5 1.4-.9 2.5-1.2.7-.2 1.9-.4 3.5-.4h.9V53c-1.3 0-2.2.1-2.6.3s-.6.4-.9.6c-.2.3-.3.7-.3 1.5s-.1 2-.2 4.1c-.1 1.2-.2 2-.4 2.8-.3.6-.6 1.2-1 1.8-.4.4-1 .9-1.8 1.4.7.4 1.3.8 1.8 1.3s.8 1.2 1.1 1.9c.3.7.4 1.8.4 3 .1 1.9.1 3.1.1 3.6 0 .7.1 1.2.3 1.6.2.4.5.5.9.6.4.2 1.2.3 2.6.3v4.1h-1c-1.6 0-2.9-.1-3.7-.4-.9-.3-1.6-.6-2.2-1.2-.6-.6-1-1.2-1.2-2-.2-.8-.3-2.1-.3-4 0-2-.1-3.5-.3-4.1-.3-.9-.7-1.6-1.2-2-.7-.5-1.5-.7-2.7-.7zm39.1 0c-.9.1-1.6.2-2 .4-.4.2-.8.6-1.2 1-.4.5-.5 1.1-.7 1.9-.1.6-.2 1.5-.2 2.8 0 2.2-.1 3.7-.4 4.6-.2.9-.6 1.6-1.2 2-.5.5-1.4.9-2.5 1.2-.7.2-1.9.4-3.5.4h-1v-4.1c1.3 0 2.1-.1 2.6-.3s.7-.4.9-.6c.2-.3.3-.7.3-1.5 0-.6.1-2 .2-4 .1-1.2.3-2.1.5-2.8.3-.7.6-1.3 1.1-1.9.4-.5 1-.9 1.7-1.3-.9-.6-1.6-1.1-2-1.6-.5-.7-1-1.8-1.2-2.8-.2-.8-.3-2.6-.3-5.2 0-.8-.1-1.4-.3-1.8-.2-.3-.4-.5-.8-.6-.2-.3-1-.3-2.5-.3v-4h1c1.6 0 2.9.1 3.7.4.9.3 1.6.6 2.2 1.2s1 1.2 1.2 2c.2.8.4 2.1.4 4 0 2 .1 3.4.3 4.1.3.9.7 1.6 1.2 1.9.5.4 1.4.6 2.5.6.1.1 0 4.3 0 4.3z"/><path class="st1" d="M5.8 15.7H8v.9c0 1.9.6 2.1 1.1 2.1.6 0 1.1-.4 1.1-2.1V8.7H7.8V6.5h4.6v10c0 3.2-1.6 4.4-3.3 4.4s-3.3-1.2-3.3-4.4v-.8zm9 1.8c.6.7 1.4 1.2 2.2 1.2 1 0 1.6-.7 1.6-1.8 0-2.6-4.5-2.5-4.5-6.6 0-2.3 1.4-4 3.8-4 1 0 2 .3 2.8.9L20 9.4c-.5-.4-1.3-.8-2-.8-1.1 0-1.6.8-1.6 1.7 0 2.6 4.5 2.4 4.5 6.5 0 2.2-1.3 4.1-3.7 4.1-1.2 0-2.4-.5-3.3-1.4l.9-2zM27.1 6.2c3.2 0 5.1 3 5.1 7.3s-2 7.4-5.1 7.4c-3.2 0-5.1-3.1-5.1-7.4 0-4.2 2-7.3 5.1-7.3zm0 12.4c1.8 0 2.9-2 2.9-5.1 0-3-1.1-4.9-2.9-4.9s-2.9 1.9-2.9 4.9c0 3.1 1.1 5.1 2.9 5.1zM34 6.5h2.3l3.3 8c.3.9.6 2.2.6 2.2h.1s-.1-1.3-.1-2.2v-8h2.1v14.2H40l-3.3-8.1c-.3-.9-.6-2.2-.6-2.2H36s.1 1.3.1 2.2v8H34V6.5z"/><path class="st2" d="M44.1 67.1c-.7-.3-1.2-.9-1.2-1.6s.5-1.4 1.2-1.6c.3-.1.4-.3.3-.5-.3-.8-.5-1.6-1-2.2-.1-.3-.4-.3-.6-.2s-.5.3-.8.3c-1 0-1.7-.8-1.7-1.7 0-.3.1-.6.3-.8.1-.3 0-.4-.2-.6-.7-.4-1.5-.7-2.2-1-.3-.1-.4.1-.5.3-.3.7-.9 1.2-1.6 1.2s-1.4-.5-1.6-1.2c-.1-.3-.3-.4-.5-.3-.8.3-1.6.5-2.2 1-.3.1-.3.4-.2.6.2.3.3.5.3.8 0 1-.8 1.7-1.7 1.7-.3 0-.6-.1-.8-.3-.3-.1-.4 0-.6.2-.4.7-.7 1.5-1 2.2-.1.3.1.4.3.5.7.3 1.2.9 1.2 1.6s-.5 1.4-1.2 1.6c-.3.1-.4.3-.3.5.3.8.5 1.6 1 2.2.1.3.4.3.6.2.3-.2.5-.3.8-.3 1 0 1.7.8 1.7 1.7 0 .3-.1.6-.3.8-.1.3 0 .4.2.6.7.4 1.5.7 2.2 1 .2 0 .4-.1.4-.3.3-.7.9-1.2 1.6-1.2s1.4.5 1.6 1.2c.1.3.3.4.5.3.8-.3 1.6-.5 2.2-1 .3-.1.3-.4.2-.6-.1-.3-.3-.5-.3-.8 0-1 .8-1.7 1.7-1.7.3 0 .6.1.8.3.3.1.4 0 .6-.2.4-.7.7-1.5 1-2.2.2-.1.1-.4-.2-.5zm-8.3 1c-1.5 0-2.7-1.2-2.7-2.7 0-1.5 1.2-2.7 2.7-2.7s2.7 1.2 2.7 2.7c.1 1.5-1.2 2.7-2.7 2.7z"/></svg>
1
<svg height="64" width="77" xmlns="http://www.w3.org/2000/svg"><g fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".5"><path d="M16.4 67.5v-4.1c.901-.1 1.6-.2 2-.4.4-.2.8-.6 1.2-1 .4-.5.5-1.1.7-1.9.1-.6.2-1.5.2-2.8 0-2.2.1-3.7.4-4.6.2-.8.599-1.6 1.2-2 .5-.5 1.4-.9 2.5-1.2.7-.2 1.9-.4 3.5-.4h.9V53c-1.3 0-2.2.1-2.6.3-.4.2-.6.4-.9.6-.2.3-.3.7-.3 1.5 0 .801-.1 2-.2 4.1-.1 1.2-.2 2-.4 2.8-.3.6-.6 1.2-1 1.8-.4.4-1 .9-1.8 1.401.7.4 1.301.8 1.8 1.299.5.499.801 1.2 1.1 1.9.3.7.4 1.8.4 3 .1 1.9.1 3.1.1 3.6 0 .7.1 1.2.3 1.6.199.4.5.5.9.6.4.2 1.2.3 2.6.3v4.1h-1c-1.6 0-2.9-.1-3.7-.4-.9-.3-1.6-.6-2.2-1.199-.601-.601-1-1.2-1.2-2.002-.2-.799-.3-2.1-.3-4 0-2-.1-3.5-.3-4.1-.3-.898-.7-1.6-1.2-1.999-.7-.5-1.5-.7-2.7-.7zm39.1 0c-.9.1-1.6.2-2 .4-.401.2-.8.6-1.2 1-.4.5-.499 1.1-.7 1.9-.1.6-.2 1.5-.2 2.8 0 2.2-.1 3.7-.4 4.6-.2.9-.6 1.6-1.2 2-.5.5-1.4.9-2.501 1.2-.698.2-1.9.4-3.5.4h-1v-4.1c1.3 0 2.101-.1 2.6-.3.501-.2.7-.4.902-.6.2-.3.3-.7.3-1.5 0-.601.098-2 .199-4 .1-1.2.3-2.099.499-2.8.302-.7.602-1.3 1.1-1.9.401-.5 1.001-.9 1.701-1.3-.9-.6-1.6-1.1-2-1.6-.5-.7-1-1.8-1.2-2.8-.2-.8-.3-2.6-.3-5.2 0-.8-.1-1.401-.3-1.8-.2-.3-.4-.5-.8-.6-.2-.3-1-.3-2.5-.3v-4h1c1.6 0 2.9.1 3.7.4.9.3 1.6.6 2.2 1.199.6.601 1 1.2 1.2 2.002.2.799.4 2.1.4 4 0 2 .1 3.4.301 4.1.3.898.698 1.6 1.2 1.9.499.399 1.398.598 2.499.598.1.1 0 4.302 0 4.302zm0 0" transform="matrix(1.90195 0 0 1.91617 -29.917 -93.413)"/><path d="M44.1 67.1c-.7-.3-1.2-.9-1.2-1.599 0-.701.5-1.4 1.2-1.6.299-.1.4-.3.299-.502-.3-.799-.499-1.598-.998-2.2-.1-.3-.4-.3-.602-.2-.2.1-.499.3-.799.3-1 0-1.7-.799-1.7-1.7 0-.3.1-.599.3-.799.1-.3 0-.4-.2-.6-.7-.4-1.499-.7-2.2-1-.3-.1-.4.1-.5.3-.3.7-.9 1.2-1.6 1.2s-1.4-.5-1.6-1.2c-.101-.3-.3-.4-.5-.3-.8.3-1.6.5-2.2 1-.301.1-.301.4-.2.6.2.3.3.5.3.8 0 1-.8 1.7-1.699 1.7-.302 0-.602-.1-.801-.3-.3-.1-.4 0-.6.2-.4.7-.7 1.5-1 2.2-.1.3.1.4.3.5.7.3 1.2.9 1.2 1.601 0 .7-.5 1.398-1.2 1.598-.3.1-.4.302-.3.502.3.799.5 1.6 1 2.2.1.299.4.299.6.2.3-.2.5-.3.801-.3.998 0 1.699.799 1.699 1.7 0 .3-.1.599-.3.799-.101.3 0 .4.2.6.7.4 1.5.7 2.2 1 .2 0 .399-.1.399-.3.302-.7.902-1.2 1.602-1.2.698 0 1.399.5 1.6 1.2.098.3.3.4.499.3.801-.3 1.6-.5 2.2-1 .3-.1.3-.4.2-.6-.1-.3-.301-.5-.301-.8 0-1 .801-1.7 1.7-1.7.3 0 .6.1.802.3.3.1.4 0 .6-.2.4-.701.7-1.5 1-2.2.199-.1.098-.4-.202-.5zm-8.3 1c-1.5 0-2.699-1.2-2.699-2.701 0-1.498 1.2-2.699 2.699-2.699 1.499 0 2.7 1.2 2.7 2.699.1 1.5-1.201 2.701-2.7 2.701zm0 0" transform="matrix(1.90195 0 0 1.91617 -29.917 -93.413)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/jsp.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm-.3-25.7H9v1.1c0 1.5.4 1.6.7 1.6.5 0 .7-.3.7-1.6v-7H7.7v-3h6v9.9c0 3.3-2 4.6-4 4.6-2.1 0-4-1.4-4-4.6v-1zM18 16.7c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zM28 6.4h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4H28V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path d="M45 67.1c2.2-.7 4.4.7 4.2 2.8-.2 2.4-3.3 3.6-5.1 4.2l.1-.1-.1-.1c1.3-1 3.9-2.2 3.7-4.6-.1-1.2-1-2.1-2.7-2v-.2H45zm-16.1.4l.1-.1c-1 0-1.9.4-2.7.7-.8.3-1.8.4-2.2 1.3.4.7 1.4.7 2.4.8 3.4.5 8.3.4 11.7 0 1.8-.2 3.4-.4 4.2-1.2l-.1-.1.1-.1c-3.4.4-7.8 1-11.9.8-1.3-.1-3-.1-3.7-.8.4-.7 1.4-.9 2.1-1.3zm19.9 14.1v-.1c-5.1 2.5-13.2 2.8-20.5 2.2l.1.1-.1.2c3 .5 6.9.7 10.7.4 3.7-.2 8.2-.7 9.9-2.7l-.1-.1zM34.4 66.2h.1c-.8-1.8-2.3-2.6-2.5-4.7-.2-1.9.7-3.1 1.6-4 1.1-1.2 2.7-2.2 3.9-3.5 1.6-1.8 3.4-4.5 1.9-7.1l-.1.1-.3-.1c.4 2.5-.6 4.1-1.9 5.4-1 1.2-2.6 2.2-4 3.3-1.6 1.3-3.7 2.9-3.1 5.3.5 2.3 2.8 3.9 4.1 5.4l.3-.1zm8-11.6l-.1-.1c-2.7 1-6.7 2.6-7.1 5.7-.1 1.5.4 2.6.9 3.4.4.6 1.1 1 1.3 1.9.2.8 0 1.6-.2 2.2h.1l.1.1c1.1-.8 2.2-1.9 1.9-3.4-.2-1.5-1.9-2.5-2.1-3.9-.1-.8.1-1.5.4-1.9 1.1-1.7 3.5-2.9 4.8-4zM28.6 72l-.1-.1c-.5.3-1.5.4-1.4 1.2s1.5 1 2.2 1.2c3.7.8 9.2.3 11.9-.6l-.1-.1.1-.1c-.3-.1-.7-.7-1.3-.7-.5-.1-1.6.3-2.6.4-1.6.2-3.3.3-4.8.2-1.1-.1-4.5-.1-3.9-1.4zm.9 4.1l.1-.1c-.6.2-1.3.4-1.3 1.1 0 .6 1.2 1 1.9 1.3 3.3 1 8.5.4 10.9-.7-.2-.3-.6-.4-.9-.6-.4-.1-.7-.3-1.1-.5-2 .5-5.1.7-7.5.4-.7-.1-1.7-.1-1.9-.8l-.2-.1zm17.7 3.2l-.1-.1c-.1 1-1.3 1.1-2.1 1.3-.9.2-1.9.4-3 .5-4.9.6-11.5.9-16.3 0-.9-.1-2.2-.4-2.5-1.1.4-.7 1.5-.8 2.4-1.2l-.1-.1.1-.1c-1.2.1-2.1.4-3 .7-.7.3-1.7.7-1.9 1.5.6.8 1.8.8 2.8 1 6.6 1 15.7 1.2 21.4-.7 1-.4 3.1-1 2.1-1.9l.2.2zm-3.7-5.1c.2 0 .4-.1.7-.2m.9-6.8c-.2 0-.4.1-.7.1M42.2 69c.1 0 .2-.1.4-.1m-12.5-1.6c-.4.1-.8.1-1.3.2m-2.2 15.9c.5.2 1.1.2 1.7.4m20.5-2.2c.1-.1.2-.2.3-.4m-9.9-34.3c0-.1-.1-.3-.1-.4m-4.7 19.7c.1.1.3.4.4.5m2.3 1.2c.1-.1.2-.2.3-.4m5.7-13.2c-.3.1-.5.2-.7.4m-1.2 18.8h.2m-12.6-1.8c0 .1-.2.1-.2.2m.9 4.2l.1-.1m-2.8 2.7c-.4 0-.7.1-1 .1m21.4.5c0-.1-.1-.1-.1-.1H47" fill="#666" stroke="#666" stroke-miterlimit="10"/></svg>
1
<svg height="63" width="49" xmlns="http://www.w3.org/2000/svg"><path d="M24.842 21.014c2.2-.7 4.4.7 4.202 2.8-.2 2.4-3.302 3.601-5.1 4.2l.1-.099-.1-.101c1.3-1 3.898-2.199 3.7-4.6-.1-1.2-1.001-2.098-2.702-2v-.2zm-16.099.401.1-.101c-1 0-1.901.4-2.701.7-.798.3-1.8.401-2.198 1.3.399.7 1.4.7 2.398.802 3.4.5 8.302.398 11.701 0 1.799-.201 3.4-.401 4.2-1.201l-.1-.101.1-.1c-3.4.402-7.8 1-11.9.8-1.301-.099-3-.099-3.7-.8.4-.7 1.4-.9 2.1-1.299zm19.9 14.099v-.1c-5.1 2.5-13.201 2.8-20.5 2.201l.1.1-.1.2c2.999.5 6.9.7 10.7.398 3.7-.198 8.199-.698 9.9-2.698zm-14.4-15.398h.1c-.8-1.802-2.3-2.602-2.499-4.7-.2-1.902.7-3.102 1.598-4 1.101-1.201 2.702-2.201 3.901-3.5 1.6-1.803 3.4-4.5 1.9-7.102l-.101.101-.299-.101c.4 2.5-.6 4.101-1.901 5.4-.999 1.201-2.6 2.201-4 3.3-1.6 1.3-3.7 2.901-3.1 5.3.502 2.302 2.8 3.9 4.102 5.4zm8-11.602-.1-.099c-2.7 1-6.701 2.6-7.1 5.698-.1 1.503.399 2.602.9 3.401.4.602 1.1 1 1.3 1.901.2.8 0 1.6-.2 2.2h.1l.1.1c1.099-.8 2.2-1.901 1.899-3.401-.198-1.5-1.9-2.5-2.1-3.899-.1-.802.1-1.5.401-1.9 1.1-1.701 3.5-2.902 4.8-4zm-13.8 17.401-.101-.101c-.5.301-1.5.4-1.4 1.2.1.8 1.5 1 2.2 1.2 3.7.8 9.2.3 11.902-.599l-.1-.101.1-.099c-.301-.101-.7-.7-1.3-.7-.502-.1-1.6.299-2.602.4-1.6.199-3.299.3-4.799.199-1.101-.1-4.5-.1-3.9-1.399zm.9 4.099.1-.1c-.6.201-1.3.4-1.3 1.1 0 .601 1.2 1 1.9 1.3 3.299 1 8.5.4 10.9-.699-.2-.302-.6-.4-.9-.601-.4-.1-.7-.3-1.1-.5-2.001.5-5.1.7-7.5.4-.7-.1-1.701-.1-1.9-.799zm17.699 3.2-.1-.099c-.098 1-1.3 1.1-2.1 1.3-.898.2-1.9.398-2.998.5-4.902.599-11.5.898-16.302 0-.898-.102-2.2-.401-2.499-1.102.4-.698 1.5-.8 2.399-1.198l-.098-.101.098-.1c-1.2.1-2.1.4-2.998.701-.7.3-1.701.698-1.902 1.5.6.8 1.801.8 2.8 1 6.6 1 15.7 1.198 21.402-.7.998-.401 3.098-1 2.1-1.901zm-3.7-5.099c.2 0 .4-.101.702-.2m.898-6.8c-.198 0-.399.1-.7.1m-2.2 1.7c.1 0 .2-.101.401-.101m-12.5-1.6c-.4.1-.8.1-1.3.201m-2.2 15.898c.499.2 1.099.2 1.7.401m20.5-2.2c.1-.1.2-.2.3-.399M19.043.814c0-.099-.098-.3-.098-.399m-4.702 19.7c.1.1.301.4.402.5m2.298 1.199c.1-.1.2-.198.3-.399m5.7-13.2c-.3.099-.499.2-.7.398m-1.198 18.802h.198m-12.6-1.8c0 .1-.2.1-.2.199m.9 4.2.101-.1m-2.8 2.701c-.4 0-.7.1-1 .1m21.399.5c0-.1-.1-.1-.1-.1h-.098" fill="#666" stroke="#666" stroke-miterlimit="10" transform="matrix(1.63519 0 0 1.61722 .336 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/jsx.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2{fill:#72bed3}.st2{stroke:#72bed3;stroke-width:.75;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm-.3-25.7H9v1.1c0 1.5.4 1.6.7 1.6.5 0 .7-.3.7-1.6v-7H7.7v-3h6v9.9c0 3.3-2 4.6-4 4.6-2.1 0-4-1.4-4-4.6v-1zM18 16.7c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm12.3-3.1l-3.4-7.2h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8L34 6.4h3.6l-3.4 7.2 3.3 7.1H34l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H27l3.3-7.1z" fill="#fff"/><path class="st2" d="M56.4 65.6c0-2.7-3.4-5.3-8.5-6.9 1.2-5.3.7-9.5-1.7-10.9-.6-.3-1.2-.4-1.9-.4v1.9c.4 0 .7.1.9.2 1.1.7 1.7 3.1 1.2 6.3-.1.8-.2 1.6-.4 2.4-1.7-.4-3.4-.7-5.3-.9-1.1-1.6-2.3-2.9-3.4-4.2 2.8-2.5 5.3-3.9 7-3.9v-1.9C42 47.3 39 49 36 51.8c-3.1-2.8-6.1-4.4-8.3-4.4v1.9c1.8 0 4.2 1.3 7 3.9-1.2 1.2-2.3 2.6-3.4 4.2-1.9.2-3.7.4-5.3.9-.1-.9-.3-1.7-.4-2.4-.4-3.1.1-5.7 1.2-6.3.2-.1.6-.2.9-.2v-1.9c-.7 0-1.3.1-1.9.4-2.3 1.3-2.8 5.5-1.7 10.9-5.3 1.6-8.7 4.2-8.7 6.9s3.4 5.3 8.5 6.9c-1.2 5.3-.7 9.5 1.7 10.9.6.3 1.2.4 1.9.4 2.3 0 5.3-1.7 8.3-4.5 3.1 2.8 6.1 4.4 8.3 4.4.7 0 1.3-.1 1.9-.4 2.3-1.3 2.8-5.5 1.7-10.9 5.4-1.7 8.7-4.2 8.7-6.9zM45.6 60c-.3 1.1-.7 2.2-1.1 3.3-.3-.7-.7-1.3-1.1-2-.4-.7-.8-1.3-1.2-2 1.2.2 2.3.4 3.4.7zm-3.8 8.9c-.7 1.1-1.3 2.2-2 3.1-1.2.1-2.4.2-3.7.2s-2.5-.1-3.8-.1c-.7-1-1.3-2-2-3.1s-1.2-2.2-1.8-3.3c.6-1.1 1.1-2.2 1.8-3.3.7-1.1 1.3-2.2 2-3.1 1.2-.1 2.5-.1 3.8-.1s2.5.1 3.8.1c.7 1 1.3 2 2 3.1s1.2 2.2 1.8 3.3c-.7 1-1.3 2.1-1.9 3.2zm2.7-1.1c.4 1.1.9 2.2 1.2 3.3-1.1.2-2.3.4-3.4.7.4-.7.8-1.3 1.2-2 .3-.6.6-1.3 1-2zM36 76.7c-.8-.8-1.6-1.8-2.3-2.7.8 0 1.5.1 2.3.1s1.6 0 2.3-.1c-.7 1-1.5 1.9-2.3 2.7zm-6.2-4.9c-1.2-.1-2.3-.4-3.4-.7.3-1.1.7-2.2 1.1-3.3.3.7.7 1.3 1.1 2 .4.7.8 1.3 1.2 2zM36 54.5c.8.8 1.6 1.8 2.3 2.7-.8 0-1.5-.1-2.3-.1s-1.6 0-2.3.1c.7-1 1.5-1.9 2.3-2.7zm-6.2 4.9c-.4.7-.8 1.3-1.2 2s-.7 1.3-1.1 2c-.4-1.1-.9-2.2-1.2-3.3 1.2-.4 2.3-.6 3.5-.7zm-7.5 10.4c-3-1.2-4.9-2.9-4.9-4.2 0-1.3 1.9-3 4.9-4.2.7-.3 1.5-.6 2.3-.9.4 1.7 1.1 3.3 1.9 5.1-.8 1.8-1.4 3.4-1.9 5-.8-.2-1.6-.4-2.3-.8zm4.4 11.9c-1.1-.7-1.7-3.1-1.2-6.3.1-.8.2-1.6.4-2.4 1.7.4 3.4.7 5.3.9 1.1 1.6 2.3 2.9 3.4 4.2-2.8 2.5-5.3 3.9-7 3.9-.2-.1-.6-.1-.9-.3zm19.8-6.3c.4 3.1-.1 5.7-1.2 6.3-.2.1-.6.2-.9.2-1.8 0-4.2-1.3-7-3.9 1.2-1.2 2.3-2.6 3.4-4.2 1.9-.2 3.7-.4 5.3-.9.2.8.3 1.7.4 2.5zm3.2-5.6c-.7.3-1.5.6-2.3.9-.4-1.7-1.1-3.3-1.9-5.1.8-1.8 1.4-3.4 1.9-5 .8.2 1.6.6 2.3.9 3 1.2 4.9 2.9 4.9 4.2-.1 1.2-2 2.9-4.9 4.1z"/><circle class="st2" cx="36" cy="65.6" r="3.8"/></svg>
1
<svg height="64" width="72" xmlns="http://www.w3.org/2000/svg"><g fill="#72bed3" stroke="#72bed3" stroke-miterlimit="10" stroke-width=".75"><path d="M56.4 65.6c0-2.7-3.4-5.3-8.5-6.9 1.2-5.3.7-9.5-1.7-10.9-.6-.3-1.2-.4-1.9-.4v1.9c.4 0 .7.1.9.201 1.1.7 1.7 3.098 1.2 6.299-.1.8-.2 1.6-.4 2.4-1.7-.401-3.4-.7-5.3-.9-1.099-1.6-2.3-2.9-3.4-4.2 2.8-2.5 5.3-3.9 7-3.9V47.3c-2.3 0-5.3 1.7-8.301 4.5-3.098-2.8-6.098-4.4-8.3-4.4V49.3c1.802 0 4.201 1.3 7 3.9-1.198 1.2-2.3 2.6-3.4 4.2-1.9.2-3.698.399-5.3.9-.098-.9-.298-1.7-.4-2.4-.4-3.1.102-5.7 1.201-6.301.2-.098.6-.198.9-.198v-1.902c-.7 0-1.3.1-1.9.402-2.3 1.3-2.8 5.498-1.7 10.899-5.3 1.6-8.7 4.199-8.7 6.9 0 2.7 3.4 5.3 8.5 6.9-1.2 5.301-.7 9.5 1.7 10.9.6.3 1.2.401 1.9.401 2.3 0 5.3-1.7 8.301-4.5 3.098 2.8 6.098 4.4 8.3 4.4.698 0 1.299-.1 1.9-.401C48.3 82.1 48.8 77.9 47.7 72.5c5.4-1.7 8.7-4.2 8.7-6.9zm-10.8-5.601c-.3 1.1-.7 2.202-1.1 3.3-.3-.699-.701-1.299-1.099-1.998-.4-.7-.8-1.302-1.2-2.002 1.2.2 2.3.401 3.399.7zM41.8 68.9c-.7 1.099-1.3 2.2-1.999 3.098-1.2.1-2.401.2-3.7.2s-2.501-.1-3.8-.1c-.7-.998-1.3-1.999-2.002-3.1-.7-1.099-1.198-2.2-1.799-3.299.6-1.1 1.1-2.2 1.799-3.3.702-1.1 1.302-2.2 2.001-3.101 1.2-.098 2.5-.098 3.8-.098s2.5.098 3.8.098c.7 1 1.3 2.002 1.999 3.1.701 1.101 1.2 2.2 1.801 3.301-.7 1.001-1.3 2.1-1.9 3.2zm2.7-1.101c.4 1.1.9 2.2 1.199 3.3-1.1.2-2.298.4-3.4.7.4-.7.8-1.301 1.2-2 .3-.6.601-1.3 1.001-2zM36 76.7C35.2 75.9 34.4 74.9 33.7 74c.798 0 1.5.1 2.298.1.8 0 1.6 0 2.3-.1-.7.999-1.5 1.9-2.3 2.7zm-6.2-4.9c-1.2-.1-2.3-.4-3.399-.7.3-1.1.7-2.199 1.1-3.3.301.7.699 1.3 1.1 2 .4.699.8 1.3 1.2 2zM36 54.5c.8.8 1.6 1.799 2.3 2.7-.798 0-1.5-.1-2.3-.1-.798 0-1.599 0-2.298.1.7-1 1.5-1.9 2.298-2.7zm-6.2 4.9c-.4.7-.8 1.301-1.2 2-.4.7-.7 1.3-1.1 2-.4-1.101-.899-2.2-1.2-3.3 1.2-.4 2.3-.6 3.5-.7zm-7.5 10.4c-3-1.2-4.9-2.9-4.9-4.2 0-1.3 1.9-3 4.9-4.2.701-.3 1.502-.601 2.3-.9.4 1.701 1.102 3.3 1.9 5.1a46.22 46.22 0 0 0-1.9 5c-.798-.199-1.599-.4-2.3-.8zm4.4 11.899c-1.1-.7-1.7-3.098-1.198-6.299.099-.8.2-1.6.4-2.4 1.7.401 3.4.7 5.3.9 1.1 1.6 2.3 2.9 3.4 4.2-2.8 2.5-5.3 3.9-7 3.9-.2-.1-.6-.1-.902-.301zM46.5 75.4c.4 3.1-.099 5.7-1.198 6.299-.2.1-.6.2-.902.2-1.799 0-4.2-1.299-7-3.9 1.201-1.199 2.3-2.599 3.4-4.2 1.9-.2 3.701-.398 5.3-.9.2.8.301 1.701.4 2.501zm3.2-5.6c-.7.3-1.5.601-2.298.9-.4-1.701-1.102-3.3-1.9-5.1a46.22 46.22 0 0 0 1.9-5c.798.199 1.599.6 2.298.899C52.7 62.7 54.6 64.4 54.6 65.7c-.102 1.2-2.002 2.9-4.902 4.1zm0 0" transform="matrix(1.69822 0 0 1.71352 -24.966 -80.407)"/><path d="M39.801 65.6a3.8 3.8 0 1 1-7.601 0 3.8 3.8 0 0 1 7.601 0zm0 0" transform="matrix(1.69822 0 0 1.71352 -24.966 -80.407)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/key.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#696}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v5.5h.6l2.3-5.5h3.5l-2.9 6.8 3 7.4h-3.7l-2.3-5.8h-.5v5.8H6.6V6.4zm12.5 0h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4zm12.8 8.4l-3.6-8.4h3.6L33 9.8c.3 1 .5 2.1.5 2.1h.1s.2-1.1.5-2.1l1.1-3.4h3.6l-3.6 8.4v5.9h-3.3v-5.9z" fill="#fff"/><path class="st0" d="M35.9 1003.6c2.8 2.8 3.6 6.7 2.6 10.2l14.8 14.8.3 6.6-8.3-.7v-4.2h-4.2v-4.2H37l-5.4-5.4c-3.5 1-7.5.2-10.2-2.6-4-4-4-10.6 0-14.6s10.5-4 14.5.1zm-7.6 2.8c-1.2-1.2-3-1.2-4.2 0-1.2 1.2-1.2 3 0 4.2 1.2 1.2 3 1.2 4.2 0 1.2-1.2 1.2-3.1 0-4.2z" transform="translate(0 -952.362)"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M31.816 6.078c5.094 5.094 6.547 12.184 4.73 18.547l26.907 26.91.547 12-15.09-1.273v-7.637h-7.637v-7.637h-7.457L24 37.172c-6.363 1.816-13.637.363-18.547-4.73-7.27-7.27-7.27-19.27 0-26.544a18.494 18.494 0 0 1 26.363.18zM18 11.172c-2.184-2.184-5.453-2.184-7.637 0-2.18 2.18-2.18 5.453 0 7.637 2.184 2.18 5.453 2.18 7.637 0 2.184-2.184 2.184-5.637 0-7.637zm0 0" fill="#696"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/kf8.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#963}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v5.5h.6l2.3-5.5h3.5l-2.9 6.8 3 7.4h-3.7l-2.3-5.8h-.5v5.8H6.6V6.4zm12.5 0h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4zm11.4 6.9c-.8-.8-1.4-1.8-1.4-3.3 0-2.1 1.2-3.9 4-3.9 2.7 0 4 1.6 4 3.6 0 1.5-1 3-1.4 3.6.9.7 1.7 1.8 1.7 3.4 0 2.2-1.4 4.2-4.4 4.2-3.1 0-4.3-2-4.3-4 0-1.9 1.4-3.2 1.8-3.6zm2.1 1.4c-.3.4-.6 1-.6 1.8s.2 1.5 1.1 1.5c.7 0 1-.4 1-1.2.1-1.2-.8-1.7-1.5-2.1zm.9-2.6c.2-.3.4-.9.4-1.7 0-.9-.3-1.2-.9-1.2s-.7.4-.7 1c0 1 .6 1.5 1.2 1.9z" fill="#fff"/><path id="path1236" class="st0" d="M56.6 61.3c-.2-.5-.6-.9-1-1.3-.1.4-.2.8-.5 1.2L42.6 80.5c-.5.7-1.5.9-2.3.7l-20-5.6c-1.2-.3-2.6-1-2.7-2.4 0-.5 0-.7.3-.9.3-.2.6-.2.9-.1l18.8 5.2c2.7.8 3.5.2 5.5-2.8L54.5 57c.6-.9.7-2 .4-2.9-.3-.9-1.1-1.6-2.1-1.9l-16.5-4.6c-.4-.1-.8-.1-1.2-.1v-.1c-2.5-1.5-3.5 1.3-4.8 2.4-.5.4-1.1.7-1.3 1.1-.2.4-.1.8-.2 1.1-.5 1.1-1.9 2.9-2.6 3.4-.4.3-1 .4-1.3.9-.2.3-.2.9-.3 1.3-.4 1-1.7 2.7-2.6 3.5-.3.3-.8.5-1 .9-.2.3-.1.9-.4 1.2-.6 1-1.8 2.6-2.7 3.5-.5.5-1.1.7-1.3 1.2-.1.2 0 .6-.1.9-.2.5-.4.9-.5 1.3-.5.7-.8 1.7-.7 2.7.2 2.4 2 4.8 4.2 5.4l20 5.6c1.9.5 4.2-.4 5.2-2l11.5-17.7c.6-.8.7-1.9.4-2.8zm-23.1-6.4l.8-1.2c.2-.3.7-.5 1.1-.4L48.6 57c.4.1.5.5.3.8l-.8 1.2c-.2.3-.7.5-1.1.4l-13.2-3.7c-.4-.1-.5-.4-.3-.8zm-3.3 5l.8-1.2c.2-.3.7-.5 1.1-.4L45.3 62c.4.1.5.5.3.8l-.8 1.2c-.2.3-.7.5-1.1.4l-13.2-3.7c-.4-.1-.6-.5-.3-.8z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><path d="M69.723 24.898c-.336-.851-1.012-1.535-1.688-2.222-.168.687-.336 1.37-.844 2.054L46.098 57.723c-.844 1.199-2.532 1.539-3.88 1.199l-33.75-9.574c-2.023-.512-4.386-1.711-4.554-4.106 0-.851 0-1.195.504-1.535.508-.344 1.016-.344 1.52-.172l31.726 8.89c4.555 1.368 5.902.34 9.277-4.788l19.239-30.09a5.83 5.83 0 0 0 .675-4.957c-.507-1.54-1.855-2.735-3.543-3.246L35.47 1.48c-.676-.171-1.352-.171-2.024-.171v-.172c-4.218-2.563-5.906 2.222-8.101 4.101-.844.684-1.856 1.2-2.196 1.883-.336.684-.168 1.367-.336 1.879-.843 1.883-3.207 4.957-4.386 5.813-.676.515-1.688.683-2.196 1.539-.335.511-.335 1.539-.503 2.222-.676 1.711-2.872 4.617-4.387 5.985-.508.511-1.352.855-1.688 1.539-.34.511-.172 1.539-.675 2.05-1.012 1.711-3.04 4.446-4.559 5.985-.844.855-1.856 1.195-2.191 2.05-.168.34 0 1.028-.168 1.54-.34.855-.676 1.539-.844 2.222C.37 41.141-.137 42.852.03 44.56c.34 4.105 3.375 8.207 7.09 9.234l33.746 9.574c3.207.852 7.09-.683 8.778-3.422l19.402-30.258c1.016-1.367 1.183-3.25.676-4.789zm-38.98-10.941 1.35-2.05c.337-.512 1.18-.856 1.856-.684l22.274 6.324c.675.172.843.855.507 1.371l-1.351 2.05c-.336.512-1.18.856-1.856.684L31.25 15.328c-.676-.172-.844-.687-.508-1.371zm-5.567 8.55 1.347-2.054c.34-.512 1.184-.851 1.86-.683l22.273 6.328c.676.172.844.855.504 1.367l-1.347 2.05c-.34.512-1.184.856-1.856.684L25.68 23.875c-.672-.172-1.012-.855-.504-1.367zm0 0" fill="#963"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/kmk.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1f385e}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v5.5h.6l2.3-5.5h3.5l-2.9 6.8 3 7.4h-3.7l-2.3-5.8h-.5v5.8H6.6V6.4zm12 0h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h.1s.1 1.3 0 2.4l-.4 6.4h-3l1-14.3zm14 0h3.3v5.5h.6l2.3-5.5h3.5l-2.9 6.8 3 7.4h-3.7l-2.3-5.8h-.6v5.8h-3.3V6.4h.1z" fill="#fff"/><path class="st0" d="M56.5 76.6c0-1.6-1.3-2.9-2.9-2.9H17.7c-1.6 0-2.9 1.3-2.9 2.9v4.1c0 1.6 1.3 2.9 2.9 2.9h35.9c1.6 0 2.9-1.3 2.9-2.9v-4.1zM41 80.4c-.9 0-1.7-.7-1.7-1.7S40.1 77 41 77s1.7.7 1.7 1.7-.7 1.7-1.7 1.7zm5.1 0c-.9 0-1.7-.7-1.7-1.7s.7-1.7 1.7-1.7c.9 0 1.7.7 1.7 1.7s-.8 1.7-1.7 1.7zm5 0c-.9 0-1.7-.7-1.7-1.7s.7-1.7 1.7-1.7c.9 0 1.7.7 1.7 1.7s-.8 1.7-1.7 1.7zM17.7 72h35.9c.8 0 1.6.2 2.2.6l-3.5-7.3c-1-2.1-2.6-2.9-4.2-2.9h-3.9l-5.6 5.8c-.4.4-.9.7-1.4.9-.5.2-1.1.3-1.6.3-.6 0-1.1-.1-1.6-.3h-.2c-.4-.2-.8-.5-1.2-.8l-5.6-6h-3.9c-1.6 0-3.1.9-4.2 2.9l-3.5 7.3c.7-.3 1.4-.5 2.3-.5z"/><path class="st0" d="M44 59.6c.2-.2.3-.4.5-.7.1-.3.2-.5.2-.9 0-.3-.1-.6-.2-.8-.1-.3-.3-.5-.5-.7s-.5-.4-.7-.5-.5-.2-.8-.2-.6.1-.8.2c-.3.1-.5.3-.7.5l-3.2 3.2v-10c0-.3-.1-.6-.2-.8-.1-.3-.3-.5-.5-.7s-.4-.4-.7-.5c-.2-.1-.5-.1-.8-.1s-.6 0-.8.1c-.3.1-.5.3-.7.5s-.4.4-.5.7-.2.5-.2.8v10.1l-3.2-3.2c-.2-.2-.4-.4-.7-.5-.2-.1-.5-.2-.8-.2s-.6.1-.8.2c-.2.1-.5.3-.7.5s-.4.4-.5.7-.2.5-.2.8.1.6.2.9c.1.3.3.5.5.7l6.9 7c.2.2.4.4.7.5.2.1.5.2.8.2s.6-.1.8-.2c.3-.1.5-.3.7-.5l6.9-7.1z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#1f385e"><path d="M73.734 51.555c0-2.844-2.289-5.157-5.109-5.157H5.375c-2.82 0-5.11 2.313-5.11 5.157v7.289c0 2.843 2.29 5.156 5.11 5.156h63.25c2.82 0 5.11-2.313 5.11-5.156zm-27.308 6.757a2.985 2.985 0 0 1-2.996-3.023 2.985 2.985 0 0 1 2.996-3.023 2.985 2.985 0 0 1 2.996 3.023c0 1.777-1.234 3.023-2.996 3.023zm8.984 0a2.984 2.984 0 0 1-2.992-3.023c0-1.777 1.23-3.023 2.992-3.023a2.985 2.985 0 0 1 2.996 3.023 2.985 2.985 0 0 1-2.996 3.023zm8.813 0a2.985 2.985 0 0 1-2.996-3.023c0-1.777 1.234-3.023 2.996-3.023a2.981 2.981 0 0 1 2.992 3.023 2.981 2.981 0 0 1-2.992 3.023zM5.375 43.38h63.25c1.41 0 2.82.355 3.879 1.066l-6.168-12.98c-1.762-3.73-4.582-5.153-7.398-5.153h-6.876L42.2 36.623c-.707.71-1.586 1.245-2.469 1.6-.878.356-1.937.532-2.82.532-1.055 0-1.937-.176-2.816-.531h-.352c-.707-.356-1.41-.891-2.117-1.422l-9.867-10.668h-6.871c-2.817 0-5.461 1.601-7.399 5.156L1.32 44.266c1.235-.532 2.47-.887 4.055-.887zm0 0"/><path d="M51.71 21.332c.352-.355.532-.71.884-1.242.176-.535.351-.89.351-1.602 0-.531-.175-1.066-.351-1.422-.176-.53-.532-.886-.883-1.246a5.273 5.273 0 0 0-1.23-.886c-.356-.18-.883-.356-1.41-.356-.532 0-1.06.176-1.41.356-.528.175-.884.53-1.235.886l-5.637 5.692V3.734c0-.535-.176-1.066-.352-1.421-.18-.536-.53-.891-.882-1.247-.352-.355-.703-.71-1.235-.886C37.97 0 37.441 0 36.91 0c-.527 0-1.055 0-1.406.18-.531.175-.883.53-1.234.886-.352.356-.708.711-.883 1.246-.176.532-.352.887-.352 1.422v17.953L27.398 16c-.351-.355-.707-.71-1.234-.89-.352-.176-.879-.356-1.41-.356-.527 0-1.055.18-1.41.355-.352.18-.88.536-1.23.891-.356.355-.708.71-.884 1.246-.175.531-.351.887-.351 1.422 0 .531.176 1.066.351 1.598.176.535.528.89.883 1.246L34.27 33.957c.351.355.703.711 1.234.887.351.18.879.355 1.406.355.531 0 1.059-.176 1.41-.355.532-.176.883-.532 1.235-.887zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ksh.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v5.5h.6l2.3-5.5h3.5l-2.9 6.8 3 7.4h-3.7l-2.3-5.8h-.5v5.8H6.6V6.4zm13.2 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10-10.3H33v5.8h3.2V6.4h3.3v14.3h-3.3V15H33v5.7h-3.3V6.4z" fill="#fff"/><path d="M30.8 61.4h10.9v2.7H30.8v-2.7zm0 5.4h10.9v2.7H30.8v-2.7zm0 5.5h10.9V75H30.8v-2.7zm19-24.4H28.1c-3 0-5.4 2.4-5.4 5.4v24.4h-5.4c0 3 2.4 5.4 5.4 5.4h21.7c3 0 5.4-2.4 5.4-5.4V56h5.4v-2.7c0-3-2.4-5.4-5.4-5.4zm-2.7 29.3c0 1.8-1.4 3.2-3.2 3.2H24c1.3-.9 1.3-2.7 1.3-2.7V53.3c0-1.5 1.2-2.7 2.7-2.7s2.7 1.2 2.7 2.7V56H47l.1 21.2zM33.5 53.3v-2.7h16.3c2.5 0 2.7 1.6 2.7 2.7h-19z" fill="#999" stroke="#999" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/kt.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#5171a5}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v5.5h.6l2.3-5.5h3.5l-2.9 6.8 3 7.4h-3.7l-2.3-5.8h-.5v5.8H6.6V6.4zm14.7 2.9h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path d="M20.3 74.4v-10c0-.6.2-1 .8-1.3 7.5-4.1 15-8.3 22.5-12.5 1.1-.5 2.1-1.2 3.4-1.2 2.1.1 3.9 1.3 4.5 3.3.6 2 0 4.3-1.7 5.4-1.9 1.2-4 2.3-6 3.5-7.5 4.1-15 8.3-22.6 12.5-.3.1-.5.2-.9.3z" fill="#e88e3d"/><path class="st0" d="M32.2 70.7c.3-.2.5-.3.6-.5 2.5-1.4 5-2.7 7.3-4 .5-.3.9-.3 1.4.1 2.8 2.6 5.7 5 8.4 7.6 1.6 1.4 2 3.2 1.4 5.1-.5 1.9-1.9 3-3.9 3.3-1.3.2-2.6-.2-3.6-1-3.8-3.5-7.6-7-11.6-10.6.1.2.1.1 0 0zm-11.9-9.8c0-2.5-.2-4.9.1-7.2.3-2.7 2.9-4.3 5.8-4 2.4.3 4.4 2.8 4.2 5.2 0 .3-.2.6-.5.7-3.1 1.7-6.2 3.5-9.4 5.2.1.1 0 0-.2.1zm10.1 10.8c0 2.3.1 4.3 0 6.4-.2 2.5-2.5 4.4-4.9 4.4-2.4 0-4.7-1.8-5.1-4.2-.1-.7 0-1.2.7-1.6 2.8-1.6 5.7-3.1 8.5-4.7.2 0 .4-.1.8-.3z"/></svg>
1
<svg height="63" width="60" xmlns="http://www.w3.org/2000/svg"><path d="M.125 47.379V28.586c0-1.125.379-1.879 1.523-2.441 14.29-7.707 28.579-15.598 42.868-23.493 2.097-.937 4.004-2.254 6.48-2.254 4 .188 7.43 2.442 8.57 6.204 1.145 3.757 0 8.078-3.238 10.144-3.617 2.258-7.621 4.324-11.43 6.578C30.61 31.031 16.32 38.922 1.84 46.816c-.574.188-.953.375-1.715.563zm0 0" fill="#e88e3d"/><path d="M22.797 40.426c.57-.375.953-.563 1.144-.938 4.762-2.633 9.524-5.074 13.907-7.52.953-.562 1.715-.562 2.668.188 5.336 4.887 10.859 9.399 16.004 14.285 3.046 2.63 3.812 6.012 2.667 9.582-.953 3.57-3.62 5.641-7.43 6.204-2.476.375-4.952-.375-6.859-1.88-7.242-6.577-14.48-13.156-22.101-19.921.191.375.191.187 0 0zM.125 22.008c0-4.695-.383-9.207.191-13.528C.886 3.406 5.84.398 11.367.96c4.57.567 8.383 5.263 8 9.774 0 .563-.379 1.13-.953 1.317-5.906 3.195-11.812 6.578-17.91 9.77.191.187 0 0-.379.187zm19.242 20.297c0 4.324.192 8.082 0 12.027-.379 4.7-4.762 8.27-9.336 8.27-4.57 0-8.953-3.383-9.715-7.891-.191-1.316 0-2.258 1.332-3.008 5.336-3.008 10.86-5.828 16.196-8.832.379 0 .761-.187 1.523-.566zm0 0" fill="#5171a5"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/kts.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#5171a5}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v5.5h.6l2.3-5.5h3.5l-2.9 6.8 3 7.4h-3.7l-2.3-5.8h-.5v5.8H6.6V6.4zm14.7 2.9h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3zm9.9 7.4c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path d="M20.3 74.4v-10c0-.6.2-1 .8-1.3 7.5-4.1 15-8.3 22.5-12.5 1.1-.5 2.1-1.2 3.4-1.2 2.1.1 3.9 1.3 4.5 3.3.6 2 0 4.3-1.7 5.4-1.9 1.2-4 2.3-6 3.5-7.5 4.1-15 8.3-22.6 12.5-.3.1-.5.2-.9.3z" fill="#e88e3d"/><path class="st0" d="M32.2 70.7c.3-.2.5-.3.6-.5 2.5-1.4 5-2.7 7.3-4 .5-.3.9-.3 1.4.1 2.8 2.6 5.7 5 8.4 7.6 1.6 1.4 2 3.2 1.4 5.1-.5 1.9-1.9 3-3.9 3.3-1.3.2-2.6-.2-3.6-1-3.8-3.5-7.6-7-11.6-10.6.1.2.1.1 0 0zm-11.9-9.8c0-2.5-.2-4.9.1-7.2.3-2.7 2.9-4.3 5.8-4 2.4.3 4.4 2.8 4.2 5.2 0 .3-.2.6-.5.7-3.1 1.7-6.2 3.5-9.4 5.2.1.1 0 0-.2.1zm10.1 10.8c0 2.3.1 4.3 0 6.4-.2 2.5-2.5 4.4-4.9 4.4-2.4 0-4.7-1.8-5.1-4.2-.1-.7 0-1.2.7-1.6 2.8-1.6 5.7-3.1 8.5-4.7.2 0 .4-.1.8-.3z"/></svg>
1
<svg height="63" width="60" xmlns="http://www.w3.org/2000/svg"><path d="M.125 47.379V28.586c0-1.125.379-1.879 1.523-2.441 14.29-7.707 28.579-15.598 42.868-23.493 2.097-.937 4.004-2.254 6.48-2.254 4 .188 7.43 2.442 8.57 6.204 1.145 3.757 0 8.078-3.238 10.144-3.617 2.258-7.621 4.324-11.43 6.578C30.61 31.031 16.32 38.922 1.84 46.816c-.574.188-.953.375-1.715.563zm0 0" fill="#e88e3d"/><path d="M22.797 40.426c.57-.375.953-.563 1.144-.938 4.762-2.633 9.524-5.074 13.907-7.52.953-.562 1.715-.562 2.668.188 5.336 4.887 10.859 9.399 16.004 14.285 3.046 2.63 3.812 6.012 2.667 9.582-.953 3.57-3.62 5.641-7.43 6.204-2.476.375-4.952-.375-6.859-1.88-7.242-6.577-14.48-13.156-22.101-19.921.191.375.191.187 0 0zM.125 22.008c0-4.695-.383-9.207.191-13.528C.886 3.406 5.84.398 11.367.96c4.57.567 8.383 5.263 8 9.774 0 .563-.379 1.13-.953 1.317-5.906 3.195-11.812 6.578-17.91 9.77.191.187 0 0-.379.187zm19.242 20.297c0 4.324.192 8.082 0 12.027-.379 4.7-4.762 8.27-9.336 8.27-4.57 0-8.953-3.383-9.715-7.891-.191-1.316 0-2.258 1.332-3.008 5.336-3.008 10.86-5.828 16.196-8.832.379 0 .761-.187 1.523-.566zm0 0" fill="#5171a5"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/kup.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v5.5h.6l2.3-5.5h3.5l-2.9 6.8 3 7.4h-3.7l-2.3-5.8h-.5v5.8H6.6V6.4zm12.4 0h3.3V16c0 1.4.6 1.9 1.5 1.9s1.5-.5 1.5-1.9V6.4h3.3V16c0 3-1.9 4.9-4.7 4.9-3.1 0-4.9-1.9-4.9-4.9V6.4zm13.1 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path class="st0" d="M40.3 76.5c-2.4-2.4-5.4.2-8 2.5-3.3 3-5.6 4.7-7.7 2.7-1.5-1.5-1.4-3.3 0-5.2l1.4 1.3c.4.3.9.3 1.3 0L43 63.3l-6.5-6.5L22 72.6c-.3.4-.3.9 0 1.3l1.4 1.4c-2.6 3.1-1.7 6.1 0 7.8 3.4 3.4 7.2.1 10.2-2.6 2.7-2.4 4.4-3.7 5.5-2.6.4.3 1 .3 1.3-.1.2-.4.2-.9-.1-1.3zm-4.6-11.1c-.4.4-.9.4-1.3 0s-.4-.9 0-1.3l1.3-1.3c.4-.4.9-.4 1.3 0s.4.9 0 1.3l-1.3 1.3zm8.5-3.4c.2.2.4.3.6.3 1.3 0 2.7-.3 3.8-1L38.5 51.2c-.7 1.2-1 2.5-1 3.8 0 .2.1.5.3.6l6.4 6.4zm5.9-12.3c-2.9-2.9-7.6-2.9-10.5 0l10.5 10.5c2.9-2.9 2.9-7.6 0-10.5z"/></svg>
1
<svg height="64" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M32.707 50.086c-4.18-4.148-9.402.348-13.93 4.324-5.742 5.184-9.746 8.125-13.402 4.668-2.613-2.594-2.438-5.707 0-8.992l2.438 2.25a1.847 1.847 0 0 0 2.261 0L37.406 27.27 26.09 16.03.848 43.344c-.524.691-.524 1.558 0 2.25l2.437 2.418c-4.527 5.36-2.96 10.547 0 13.484 5.918 5.879 12.535.172 17.758-4.496 4.7-4.148 7.66-6.395 9.574-4.492.695.52 1.738.52 2.262-.172.348-.691.348-1.559-.172-2.25zm-8.008-19.188c-.699.692-1.57.692-2.265 0-.696-.691-.696-1.554 0-2.246l2.265-2.246c.696-.691 1.567-.691 2.262 0 .695.692.695 1.555 0 2.246zm14.797-5.875c.348.344.695.516 1.043.516 2.262 0 4.7-.516 6.617-1.727L29.57 6.352c-1.218 2.074-1.738 4.324-1.738 6.57 0 .344.172.863.52 1.035zm10.27-21.261c-5.047-5.016-13.23-5.016-18.278 0L49.766 21.91a12.77 12.77 0 0 0 0-18.148zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/less.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#7058c6}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6V41z"/><path d="M16.4 67.5v-4.1c.9-.1 1.6-.2 2-.4.4-.2.8-.6 1.2-1 .4-.5.5-1.1.7-1.9.1-.6.2-1.5.2-2.8 0-2.2.1-3.7.4-4.6.2-.8.6-1.6 1.2-2 .5-.5 1.4-.9 2.5-1.2.7-.2 1.9-.4 3.5-.4h.9V53c-1.3 0-2.2.1-2.6.3s-.6.4-.9.6c-.2.3-.3.7-.3 1.5s-.1 2-.2 4.1c-.1 1.2-.2 2-.4 2.8-.3.6-.6 1.2-1 1.8-.4.4-1 .9-1.8 1.4.7.4 1.3.8 1.8 1.3s.8 1.2 1.1 1.9c.3.7.4 1.8.4 3 .1 1.9.1 3.1.1 3.6 0 .7.1 1.2.3 1.6.2.4.5.5.9.6.4.2 1.2.3 2.6.3v4.1h-1c-1.6 0-2.9-.1-3.7-.4-.9-.3-1.6-.6-2.2-1.2-.6-.6-1-1.2-1.2-2-.2-.8-.3-2.1-.3-4 0-2-.1-3.5-.3-4.1-.3-.9-.7-1.6-1.2-2-.7-.5-1.5-.7-2.7-.7zm39.1 0c-.9.1-1.6.2-2 .4-.4.2-.8.6-1.2 1-.4.5-.5 1.1-.7 1.9-.1.6-.2 1.5-.2 2.8 0 2.2-.1 3.7-.4 4.6-.2.9-.6 1.6-1.2 2-.5.5-1.4.9-2.5 1.2-.7.2-1.9.4-3.5.4h-1v-4.1c1.3 0 2.1-.1 2.6-.3s.7-.4.9-.6c.2-.3.3-.7.3-1.5 0-.6.1-2 .2-4 .1-1.2.3-2.1.5-2.8.3-.7.6-1.3 1.1-1.9.4-.5 1-.9 1.7-1.3-.9-.6-1.6-1.1-2-1.6-.5-.7-1-1.8-1.2-2.8-.2-.8-.3-2.6-.3-5.2 0-.8-.1-1.4-.3-1.8-.2-.3-.4-.5-.8-.6-.2-.3-1-.3-2.5-.3v-4h1c1.6 0 2.9.1 3.7.4.9.3 1.6.6 2.2 1.2s1 1.2 1.2 2c.2.8.4 2.1.4 4 0 2 .1 3.4.3 4.1.3.9.7 1.6 1.2 1.9.5.4 1.4.6 2.5.6.1.1 0 4.3 0 4.3z" fill="#7058c6" stroke="#7058c6" stroke-miterlimit="10"/><path class="st1" d="M6.5 6.4h3v11.4h3.9v2.9H6.5V6.4zm9.3 0h6.5v2.9h-3.5V12h2.8v2.9h-2.8v2.9h3.7v2.9h-6.6l-.1-14.3zm10.1 10.3c.5.6 1.3 1.2 2.1 1.2s1.2-.6 1.2-1.2c0-2-4.3-2.1-4.3-6.2 0-2.4 1.5-4.3 4.1-4.3 1.1 0 2.2.3 3.1 1L31 10.1c-.4-.4-1.3-.9-1.9-.9-.8 0-1.2.6-1.2 1.2 0 2.1 4.3 2 4.3 6.1 0 2.3-1.3 4.4-4 4.4-1.3 0-2.6-.5-3.6-1.4l1.3-2.8zm9.6 0c.5.6 1.3 1.2 2.1 1.2s1.2-.6 1.2-1.2c0-2-4.3-2.1-4.3-6.2 0-2.4 1.5-4.3 4.1-4.3 1.1 0 2.2.3 3.1 1l-1.1 2.9c-.4-.4-1.3-.9-1.9-.9-.8 0-1.2.6-1.2 1.2 0 2.1 4.3 2 4.3 6.1 0 2.3-1.3 4.4-4 4.4-1.3 0-2.6-.5-3.6-1.4l1.3-2.8z"/></svg>
1
<svg height="64" width="75" xmlns="http://www.w3.org/2000/svg"><path d="M.5 19v-4.1c.9-.1 1.6-.2 2-.4.4-.2.8-.6 1.2-1.001.4-.5.5-1.1.7-1.9.1-.6.2-1.499.2-2.799 0-2.201.1-3.7.4-4.6.2-.8.6-1.6 1.2-2 .5-.5 1.4-.9 2.5-1.2.7-.2 1.9-.4 3.5-.4h.9v3.9c-1.3 0-2.2.1-2.6.3-.4.2-.6.4-.9.6-.2.3-.3.7-.3 1.501 0 .8-.1 2-.2 4.099-.101 1.2-.2 2-.4 2.801-.301.6-.6 1.2-1 1.8-.4.4-1 .9-1.8 1.399.7.4 1.3.8 1.8 1.3s.8 1.2 1.1 1.899c.3.702.4 1.802.4 3.001.1 1.9.1 3.1.1 3.599 0 .702.1 1.202.3 1.602.2.4.5.5.9.6.4.2 1.2.3 2.6.3v4.098h-1c-1.6 0-2.9-.1-3.701-.4-.9-.3-1.6-.6-2.2-1.2-.6-.6-.999-1.2-1.2-1.999-.198-.8-.299-2.1-.299-4 0-2-.1-3.5-.3-4.1-.3-.9-.7-1.601-1.201-2-.698-.5-1.5-.7-2.7-.7zm39.1 0c-.9.1-1.6.2-2 .4s-.8.6-1.2 1.001c-.4.5-.5 1.1-.7 1.9-.099.6-.2 1.499-.2 2.799 0 2.201-.1 3.7-.4 4.6-.2.9-.6 1.6-1.2 2-.5.5-1.4.9-2.5 1.2-.7.2-1.9.4-3.5.4h-.999v-4.1c1.298 0 2.1-.1 2.599-.3s.7-.4.899-.6c.2-.3.301-.7.301-1.501 0-.6.1-2 .2-3.999.099-1.2.3-2.1.5-2.8.3-.7.6-1.3 1.1-1.9.4-.5 1-.9 1.7-1.3-.901-.6-1.6-1.1-2-1.6-.5-.7-1-1.801-1.201-2.8-.199-.8-.299-2.6-.299-5.2 0-.8-.1-1.4-.301-1.8-.199-.3-.4-.5-.799-.6-.2-.3-1-.3-2.5-.3v-4h.999c1.602 0 2.9.1 3.7.4.902.3 1.6.6 2.2 1.2.6.6 1.002 1.2 1.2 2 .201.8.402 2.1.402 4 0 2 .098 3.4.299 4.1.299.9.7 1.601 1.2 1.9.5.4 1.401.6 2.5.6.1.1 0 4.3 0 4.3zm0 0" fill="#7058c6" stroke="#7058c6" stroke-miterlimit="10" transform="matrix(1.86825 0 0 1.87558 0 .209)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/lex.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#c93}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v11.4h4.3v2.9H6.6V6.4zm10.3 0h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4zm12.9 7.2l-3.4-7.2H30l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9H37l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.3-7.1z" fill="#fff"/><path d="M34.9 68.2c-2.5-2.4-4.7-4.6-6-9.6h8.8V55H29v-4.9h-3.8v5h-8.8v3.7h9s-.1.7-.2 1.3c-1.3 4.9-2.7 8-8.8 11l1.3 3.7c5.7-3 8.7-6.9 10-11.1 1.3 3.2 3.4 5.8 5.8 8.2l1.4-3.7zm11.6-12h-5l-8.8 24.7h3.8l2.5-7.4h10l2.5 7.4h3.8l-8.8-24.7zm-6.2 13.6l3.8-9.8 3.8 9.9-7.6-.1z" fill="#c93" stroke="#c93" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><path d="M38.027 37.414c-5.011-4.812-9.425-9.223-12.03-19.25H43.64v-7.219H26.195V1.121h-7.617v10.024H.93v7.421h18.047s-.2 1.403-.399 2.606C15.968 30.996 13.164 37.215.93 43.23l2.61 7.418c11.429-6.015 17.444-13.835 20.05-22.257 2.605 6.418 6.816 11.629 11.629 16.441zM61.29 13.352H51.262L33.617 62.879h7.617l5.016-14.836H66.3l5.013 14.836h7.62zm-12.434 27.27 7.622-19.65 7.617 19.852zm0 0" fill="#c93" stroke="#c93" stroke-miterlimit="10" stroke-width="1.5039150000000001"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/licx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.5-34.6h2.8v11.4H13v2.9H6.5V6.4zm8.7 0H18v14.3h-2.8V6.4zm10.9-.3c1.1 0 2.2.4 3.1 1.2L28 10.2c-.3-.5-1.1-.9-1.8-.9-1.8 0-2.7 1.9-2.7 4.2s1 4.4 2.7 4.4c.8 0 1.4-.5 2-1l1.2 2.8c-.8.7-1.7 1.3-3.3 1.3-3.4 0-5.3-3.1-5.3-7.4-.2-4.3 1.9-7.5 5.3-7.5zm7.6 7.5l-2.9-7.2h3.1l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9H40l-2.9 7.2 2.8 7.1h-3l-.9-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3h-3l2.7-7.1z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/lisp.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#066}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v11.4h4.3v2.9H6.6V6.4zm9.8 0h3.3v14.3h-3.3V6.4zm7.2 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm9.5-10.3h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path id="path10" d="M47.4 75h.8c0 2.4-.4 4.2-1.2 5.3-.8 1.1-1.8 1.7-3 1.7-1 0-1.9-.4-2.8-1.1-.9-.7-1.7-2.7-2.4-5.9l-2-8.9-6.9 15.6h-4.4l9.9-21.2c-.5-2.7-1.2-4.8-1.9-6.1s-1.7-2-2.7-2c-.9 0-1.6.3-2.3 1-.6.7-1 1.7-1.1 3.1h-.8c0-2.3.5-4.1 1.4-5.4s1.9-2 3.2-2c.8 0 1.6.3 2.3 1 .7.7 1.4 1.8 1.9 3.5.6 1.7 1.4 5.1 2.6 10.3l1.6 7.3c.7 3 1.4 5 2.1 6.1.7 1 1.6 1.5 2.6 1.5 1.9-.1 2.9-1.3 3.1-3.8z" fill="#066" stroke="#066" stroke-miterlimit="10"/></svg>
1
<svg height="63" width="45" xmlns="http://www.w3.org/2000/svg"><path d="M22.686 26.4h.8c0 2.401-.4 4.2-1.2 5.3-.801 1.1-1.8 1.7-3 1.7-1.001 0-1.9-.4-2.8-1.1-.9-.699-1.701-2.7-2.4-5.9l-2-8.9-6.902 15.599h-4.4l9.901-21.2c-.5-2.698-1.2-4.799-1.899-6.098-.701-1.3-1.7-2.002-2.7-2.002-.902 0-1.601.301-2.3 1-.6.7-1 1.701-1.1 3.1h-.8c0-2.299.5-4.1 1.4-5.4.899-1.3 1.898-2 3.2-2 .8 0 1.599.302 2.3 1.002.7.699 1.4 1.799 1.9 3.499.599 1.7 1.4 5.1 2.6 10.3l1.599 7.3c.701 3 1.4 5 2.1 6.1.7 1 1.6 1.5 2.6 1.5 1.9-.1 2.901-1.3 3.101-3.8zm0 0" fill="#066" stroke="#066" stroke-miterlimit="10" transform="matrix(1.87615 0 0 1.85407 0 .073)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/lit.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#963}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v11.4h4.3v2.9H6.6V6.4zm10.3 0h3.3v14.3h-3.3V6.4zm9.2 2.9H23V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path id="path1236" class="st0" d="M56.6 61.3c-.2-.5-.6-.9-1-1.3-.1.4-.2.8-.5 1.2L42.6 80.5c-.5.7-1.5.9-2.3.7l-20-5.6c-1.2-.3-2.6-1-2.7-2.4 0-.5 0-.7.3-.9.3-.2.6-.2.9-.1l18.8 5.2c2.7.8 3.5.2 5.5-2.8L54.5 57c.6-.9.7-2 .4-2.9-.3-.9-1.1-1.6-2.1-1.9l-16.5-4.6c-.4-.1-.8-.1-1.2-.1v-.1c-2.5-1.5-3.5 1.3-4.8 2.4-.5.4-1.1.7-1.3 1.1-.2.4-.1.8-.2 1.1-.5 1.1-1.9 2.9-2.6 3.4-.4.3-1 .4-1.3.9-.2.3-.2.9-.3 1.3-.4 1-1.7 2.7-2.6 3.5-.3.3-.8.5-1 .9-.2.3-.1.9-.4 1.2-.6 1-1.8 2.6-2.7 3.5-.5.5-1.1.7-1.3 1.2-.1.2 0 .6-.1.9-.2.5-.4.9-.5 1.3-.5.7-.8 1.7-.7 2.7.2 2.4 2 4.8 4.2 5.4l20 5.6c1.9.5 4.2-.4 5.2-2l11.5-17.7c.6-.8.7-1.9.4-2.8zm-23.1-6.4l.8-1.2c.2-.3.7-.5 1.1-.4L48.6 57c.4.1.5.5.3.8l-.8 1.2c-.2.3-.7.5-1.1.4l-13.2-3.7c-.4-.1-.5-.4-.3-.8zm-3.3 5l.8-1.2c.2-.3.7-.5 1.1-.4L45.3 62c.4.1.5.5.3.8l-.8 1.2c-.2.3-.7.5-1.1.4l-13.2-3.7c-.4-.1-.6-.5-.3-.8z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><path d="M69.723 24.898c-.336-.851-1.012-1.535-1.688-2.222-.168.687-.336 1.37-.844 2.054L46.098 57.723c-.844 1.199-2.532 1.539-3.88 1.199l-33.75-9.574c-2.023-.512-4.386-1.711-4.554-4.106 0-.851 0-1.195.504-1.535.508-.344 1.016-.344 1.52-.172l31.726 8.89c4.555 1.368 5.902.34 9.277-4.788l19.239-30.09a5.83 5.83 0 0 0 .675-4.957c-.507-1.54-1.855-2.735-3.543-3.246L35.47 1.48c-.676-.171-1.352-.171-2.024-.171v-.172c-4.218-2.563-5.906 2.222-8.101 4.101-.844.684-1.856 1.2-2.196 1.883-.336.684-.168 1.367-.336 1.879-.843 1.883-3.207 4.957-4.386 5.813-.676.515-1.688.683-2.196 1.539-.335.511-.335 1.539-.503 2.222-.676 1.711-2.872 4.617-4.387 5.985-.508.511-1.352.855-1.688 1.539-.34.511-.172 1.539-.675 2.05-1.012 1.711-3.04 4.446-4.559 5.985-.844.855-1.856 1.195-2.191 2.05-.168.34 0 1.028-.168 1.54-.34.855-.676 1.539-.844 2.222C.37 41.141-.137 42.852.03 44.56c.34 4.105 3.375 8.207 7.09 9.234l33.746 9.574c3.207.852 7.09-.683 8.778-3.422l19.402-30.258c1.016-1.367 1.183-3.25.676-4.789zm-38.98-10.941 1.35-2.05c.337-.512 1.18-.856 1.856-.684l22.274 6.324c.675.172.843.855.507 1.371l-1.351 2.05c-.336.512-1.18.856-1.856.684L31.25 15.328c-.676-.172-.844-.687-.508-1.371zm-5.567 8.55 1.347-2.054c.34-.512 1.184-.851 1.86-.683l22.273 6.328c.676.172.844.855.504 1.367l-1.347 2.05c-.34.512-1.184.856-1.856.684L25.68 23.875c-.672-.172-1.012-.855-.504-1.367zm0 0" fill="#963"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/lnk.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v11.4h4.3v2.9H6.6V6.4zm10.3 0h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4zm13.3 0h3.3v5.5h.6l2.3-5.5h3.5L37 13.2l3 7.4h-3.7L34 14.8h-.6v5.8h-3.3V6.4z" fill="#fff"/><path class="st0" d="M37.6 51.2l-6.1 6.1c1.8-.5 3.8-.5 5.6 0 .3.1.5.2.7.2l3.1-3.1c1.8-1.8 4.8-1.8 6.6 0 1.8 1.8 1.8 4.8 0 6.6l-4.1 4.1-2.4 2.4c-.6.6-1.3 1-2.1 1.2-1.5.4-3.3 0-4.5-1.2-.8-.8-1.3-1.9-1.3-2.9-.4.2-.7.4-1 .6l-2.9 2.9c.4 1 1.1 1.9 1.9 2.7 1.2 1.2 2.6 2 4.2 2.4 2.4.6 5 .3 7.1-1 .7-.4 1.3-.9 1.8-1.4l6.6-6.6c3.6-3.6 3.6-9.5 0-13.1-3.7-3.5-9.5-3.5-13.2.1z"/><path class="st0" d="M40.5 74.6c-2.1.6-4.3.5-6.4-.2l-3 3c-1.8 1.8-4.8 1.8-6.6 0-1.8-1.8-1.8-4.8 0-6.6l6.6-6.6c.6-.6 1.3-1 2.1-1.2 1.5-.4 3.3 0 4.5 1.2.8.8 1.3 1.9 1.3 3 .3-.2.7-.4 1-.6l2.9-2.9c-.4-1-1.1-1.9-1.9-2.7-1.2-1.2-2.6-2-4.2-2.4-2.4-.6-5-.3-7.1 1-.7.4-1.3.9-1.8 1.4l-6.6 6.6c-3.6 3.6-3.6 9.5 0 13.1 3.6 3.6 9.5 3.6 13.1 0l6.1-6.1z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M34.84 4.973 23.66 16.156a19.478 19.478 0 0 1 10.266 0c.55.184.914.364 1.281.364l5.684-5.68c3.3-3.3 8.8-3.3 12.097 0 3.301 3.297 3.301 8.797 0 12.098L41.074 34.852c-1.101 1.101-2.383 1.836-3.851 2.199-2.746.734-6.047 0-8.246-2.2-1.47-1.464-2.383-3.48-2.383-5.316-.735.367-1.285.735-1.836 1.102l-5.317 5.316c.735 1.832 2.02 3.484 3.485 4.95 2.199 2.199 4.765 3.667 7.699 4.398 4.398 1.101 9.164.55 13.016-1.832 1.28-.735 2.382-1.649 3.3-2.567L59.04 28.805c6.598-6.602 6.598-17.418 0-24.016a17.443 17.443 0 0 0-24.2.184zm0 0"/><path d="M40.156 47.867c-3.847 1.102-7.883.918-11.73-.367l-5.5 5.5c-3.301 3.3-8.801 3.3-12.098 0-3.3-3.297-3.3-8.797 0-12.098l12.098-12.097c1.101-1.102 2.383-1.836 3.851-2.2 2.746-.734 6.047 0 8.246 2.2 1.47 1.465 2.383 3.48 2.383 5.5.551-.368 1.285-.735 1.836-1.102l5.317-5.316c-.735-1.832-2.02-3.485-3.485-4.95-2.199-2.199-4.765-3.667-7.699-4.398-4.398-1.102-9.164-.55-13.016 1.832-1.28.734-2.382 1.649-3.3 2.567L4.96 35.035c-6.598 6.602-6.598 17.414 0 24.016 6.598 6.597 17.414 6.597 24.016 0zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/lock.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.4-34.6H9v11.4h3.4v2.9h-6V6.4zM18 6.1c2.9 0 4.6 3.1 4.6 7.3 0 4.2-1.6 7.5-4.6 7.5s-4.6-3.2-4.6-7.5c.1-4.1 1.7-7.3 4.6-7.3zm0 11.7c1.3 0 1.9-1.8 1.9-4.3s-.6-4.2-1.9-4.2-1.9 1.7-1.9 4.2.6 4.3 1.9 4.3zM29.6 6.1c1 0 2.1.4 2.8 1.2l-1.1 2.8c-.3-.5-1-.9-1.6-.9-1.7 0-2.5 1.9-2.5 4.2 0 2.3.9 4.4 2.5 4.4.8 0 1.3-.5 1.8-1l1.1 2.8c-.7.7-1.5 1.3-3.1 1.3-3.1 0-4.9-3.1-4.9-7.4 0-4.2 1.9-7.4 5-7.4zm5.1.3h2.6v5.5h.5l1.8-5.5h2.8L40 13.2l2.4 7.4h-2.9l-1.8-5.8h-.5v5.8h-2.6V6.4z" fill="#fff"/><path class="st0" d="M49.2 62.2h-2.6v-5C46.6 51.5 42 47 36.4 47s-10.2 4.6-10.2 10.2v5h-2.6c-1 0-1.8.8-1.8 1.8v17.4c0 1 .8 1.8 1.8 1.8h25.6c1 0 1.8-.8 1.8-1.8V63.9c0-.9-.8-1.7-1.8-1.7zM38.6 76.6c.2.6-.3 1.1-.9 1.1H35c-.6 0-1-.6-.9-1.1l.8-3.2c-1-.5-1.7-1.5-1.7-2.8 0-1.7 1.4-3.1 3.1-3.1 1.7 0 3.1 1.4 3.1 3.1 0 1.2-.7 2.3-1.7 2.8l.9 3.2zm2.9-14.4H31.3v-5c0-2.8 2.3-5.1 5.1-5.1s5.1 2.3 5.1 5.1v5z"/></svg>
1
<svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/log.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.3v11.4h4.3v2.9H6.6V6.4zm15-.3c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c-.1-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zM36.3 6.1c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.6-7.6 6.5-7.6z" fill="#fff"/><path class="st0" d="M14.6 77.2h42.8v6.2H14.6zm0-14.8h42.8v6.2H14.6zm0-15h42.8v6.2H14.6z"/></svg>
1
<svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><path d="M.176 52.977h75.648V64H.176zm0-26.309h75.648v11.02H.176zM.176 0h75.648v11.023H.176zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/lua.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:navy}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h3.3v11.4h4.3v2.9H6.6V6.4zm9.8 0h3.3V16c0 1.4.6 1.9 1.5 1.9s1.5-.5 1.5-1.9V6.4H26V16c0 3-1.9 4.9-4.7 4.9-2.9 0-4.8-1.9-4.8-4.9V6.4h-.1zm15.4 0h3.6L39 20.7h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.9c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.9h2z" fill="#fff"/><path class="st0" d="M33.7 84C25 84 18 77 18 68.3s7-15.8 16-15.7c8.5.2 15.3 7 15.3 15.7S42.3 84 33.7 84zm6.4-26.8c-2.5 0-4.7 2.2-4.7 4.7s2 4.7 4.7 4.7c2.5 0 4.7-2 4.7-4.7 0-2.6-2-4.7-4.7-4.7zm9.2 0c-2.5 0-4.7-2-4.5-4.7 0-2.5 2-4.5 4.7-4.5 2.5 0 4.5 2.2 4.5 4.7s-2.2 4.5-4.7 4.5z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M27.91 64A27.846 27.846 0 0 1 0 36.09C0 20.62 12.445 8 28.445 8.18c15.11.355 27.2 12.441 27.2 27.91C55.645 51.555 43.199 64 27.91 64zm11.38-47.645c-4.446 0-8.356 3.91-8.356 8.356 0 4.445 3.554 8.355 8.355 8.355 4.445 0 8.356-3.554 8.356-8.355 0-4.621-3.555-8.356-8.356-8.356zm16.355 0c-4.446 0-8.356-3.554-8-8.355 0-4.445 3.554-8 8.355-8 4.445 0 8 3.91 8 8.355 0 4.446-3.91 8-8.355 8zm0 0" fill="navy"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/m.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3z" fill="#fff"/><path class="st0" d="M14 48.9h37v4.3H14zm7 9.6h37v4.3H21zm-7 9.6h37v4.3H14zm7 9.6h37V82H21z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/m2v.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm14.3 12.7c0-5 4.5-5.5 4.5-8.4 0-1-.5-1.4-1.2-1.4-.6 0-1.1.3-1.4.8l-2.2-1.8c.8-1.1 2.3-2.1 4.1-2.1 2.1 0 4.2 1.3 4.2 4.2 0 4.1-4.2 5.4-4.4 7.5h4.6v2.9h-7.9c-.2-.7-.3-1.1-.3-1.7zm9.7-12.7h3.6l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3l1.7-8.1h3.5l-3.9 14.3H35L31.1 6.4z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/m3u.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zM22.5 17c.4.4 1.1.7 1.7.7.9 0 1.6-.4 1.6-1.6 0-1-.7-1.5-2.3-1.5h-.9l-.6-1.8 2-2.5c.5-.6.9-1 .9-1s-.4.1-1.1.1h-2.3v-3h7.2V9l-2.6 3.1c2 .5 3.1 2.1 3.1 4.1 0 2.4-1.4 4.8-4.7 4.8-1.3 0-2.5-.4-3.5-1.3l1.5-2.7zm9.3-10.6h3.3V16c0 1.4.6 1.9 1.5 1.9s1.5-.5 1.5-1.9V6.4h3.3V16c0 3-1.9 4.9-4.7 4.9-2.9 0-4.8-1.9-4.8-4.9V6.4z" fill="#fff"/><path class="st0" d="M14.6 54.3h22.9c1.2 0 2.1-.9 2.1-2.1s-.9-2.1-2.1-2.1H14.6c-1.2 0-2.1.9-2.1 2.1s.9 2.1 2.1 2.1zm0 11.1h22.9c1.2 0 2.1-.9 2.1-2.1s-.9-2.1-2.1-2.1H14.6c-1.2 0-2.1.9-2.1 2.1s.9 2.1 2.1 2.1zm11 5.9h-11c-1.2 0-2.1.9-2.1 2.1s.9 2.1 2.1 2.1h11c1.2 0 2.1-.9 2.1-2.1s-.9-2.1-2.1-2.1z"/><path class="st0" d="M52.5 53.8c-1.6-.8-3.7-2-4.5-3.7 0-.9-.7-1.6-1.6-1.6-.9 0-1.6.7-1.6 1.6v21.5c-1.7-.9-4.9-.6-7.3.8-3.8 2.1-5.4 6.1-3.8 8.8s6.1 3.3 9.9 1.2c2.6-1.5 4.4-3.9 4.5-6.3V57.6c5.4 0 8.7 2.2 7.5 7.5-.2 1-.6 1.9-1 2.9-.2.3-.2.7.1 1 .3.3.8.2 1.2-.2 2-2 3.3-4.6 3.4-7.5-.1-3.8-3.7-6-6.8-7.5z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#039;fill-opacity:1" d="M4.059 10.39h40.254c2.109 0 3.69-1.613 3.69-3.761 0-2.149-1.581-3.758-3.69-3.758H4.059c-2.11 0-3.692 1.61-3.692 3.758 0 2.152 1.582 3.762 3.692 3.762zm0 19.891h40.254c2.109 0 3.69-1.613 3.69-3.765 0-2.149-1.581-3.762-3.69-3.762H4.059c-2.11 0-3.692 1.613-3.692 3.762 0 2.148 1.582 3.765 3.692 3.765zm19.336 10.57H4.059c-2.11 0-3.692 1.614-3.692 3.762 0 2.149 1.582 3.766 3.692 3.766h19.336c2.109 0 3.69-1.617 3.69-3.766 0-2.148-1.581-3.761-3.69-3.761zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#039;fill-opacity:1" d="M70.68 9.496c-2.813-1.434-6.504-3.582-7.91-6.629C62.77 1.254 61.54 0 59.957 0c-1.582 0-2.812 1.254-2.812 2.867v38.52c-2.989-1.614-8.614-1.075-12.833 1.433-6.68 3.766-9.492 10.93-6.68 15.766 2.813 4.84 10.723 5.914 17.4 2.152 4.573-2.687 7.738-6.988 7.913-11.289V16.305c9.492 0 15.29 3.941 13.18 13.437-.352 1.793-1.05 3.403-1.754 5.195-.355.54-.355 1.254.176 1.793.527.536 1.402.356 2.11-.359 3.515-3.582 5.796-8.242 5.976-13.437-.18-6.805-6.508-10.75-11.953-13.438zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/m3u8.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zM7 6.5h2.3l1.6 6.9c.2.9.4 2.2.4 2.2h.1s.2-1.3.4-2.2l1.6-6.9h2.3l.8 14.2h-1.9l-.4-7.9c-.1-.9 0-2.2 0-2.2h-.1s-.2 1.4-.4 2.3l-1.3 5.4h-2L9 12.9c-.2-.8-.4-2.3-.4-2.3s.1 1.3 0 2.2l-.4 7.9h-2L7 6.5zm11.6 11.2c.4.5 1 .9 1.7.9 1 0 1.8-.7 1.8-2.3 0-1.4-.8-2.1-2.3-2.1H19l-.4-1.4 2.2-3.3c.4-.5.7-.8.7-.8H18V6.5h5.8v1.9l-2.6 3.8c1.8.3 3 1.7 3 4.1 0 2.4-1.3 4.6-3.7 4.6-1 0-2.1-.4-2.9-1.3l1-1.9zm7.3-11.2H28v9.6c0 1.8.7 2.6 1.8 2.6s1.8-.8 1.8-2.6V6.5h2.1v9.6c0 3-1.5 4.8-3.8 4.8S26 19.1 26 16.1V6.5zM37 13.1c-.8-.8-1.4-1.7-1.4-3.2 0-1.9 1-3.7 3.2-3.7S42 7.9 42 9.8c0 1.8-1 3.2-1.3 3.7.8.7 1.5 1.8 1.5 3.4 0 2.2-1.2 4-3.6 4-2.3 0-3.5-1.8-3.5-3.9.1-2.1 1.5-3.5 1.9-3.9zm1.3 1.1c-.3.3-1 1.1-1 2.5 0 1.1.5 2 1.4 2 .9 0 1.4-.8 1.4-1.8.1-1.5-.9-2.1-1.8-2.7zm1-1.7c.2-.3.7-1.1.7-2.3 0-1-.4-1.7-1.3-1.7s-1.1.6-1.1 1.4c0 1.4.9 2.1 1.7 2.6z" fill="#fff"/><path class="st0" d="M14.6 54.3h22.9c1.2 0 2.1-.9 2.1-2.1s-.9-2.1-2.1-2.1H14.6c-1.2 0-2.1.9-2.1 2.1s.9 2.1 2.1 2.1zm0 11.1h22.9c1.2 0 2.1-.9 2.1-2.1s-.9-2.1-2.1-2.1H14.6c-1.2 0-2.1.9-2.1 2.1s.9 2.1 2.1 2.1zm11 5.9h-11c-1.2 0-2.1.9-2.1 2.1s.9 2.1 2.1 2.1h11c1.2 0 2.1-.9 2.1-2.1s-.9-2.1-2.1-2.1z"/><path class="st0" d="M52.5 53.8c-1.6-.8-3.7-2-4.5-3.7 0-.9-.7-1.6-1.6-1.6-.9 0-1.6.7-1.6 1.6v21.5c-1.7-.9-4.9-.6-7.3.8-3.8 2.1-5.4 6.1-3.8 8.8s6.1 3.3 9.9 1.2c2.6-1.5 4.4-3.9 4.5-6.3V57.6c5.4 0 8.7 2.2 7.5 7.5-.2 1-.6 1.9-1 2.9-.2.3-.2.7.1 1s.8.2 1.2-.2c2-2 3.3-4.6 3.4-7.5-.1-3.8-3.7-6-6.8-7.5z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#039;fill-opacity:1" d="M4.059 10.39h40.254c2.109 0 3.69-1.613 3.69-3.761 0-2.149-1.581-3.758-3.69-3.758H4.059c-2.11 0-3.692 1.61-3.692 3.758 0 2.152 1.582 3.762 3.692 3.762zm0 19.891h40.254c2.109 0 3.69-1.613 3.69-3.765 0-2.149-1.581-3.762-3.69-3.762H4.059c-2.11 0-3.692 1.613-3.692 3.762 0 2.148 1.582 3.765 3.692 3.765zm19.336 10.57H4.059c-2.11 0-3.692 1.614-3.692 3.762 0 2.149 1.582 3.766 3.692 3.766h19.336c2.109 0 3.69-1.617 3.69-3.766 0-2.148-1.581-3.761-3.69-3.761zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#039;fill-opacity:1" d="M70.68 9.496c-2.813-1.434-6.504-3.582-7.91-6.629C62.77 1.254 61.54 0 59.957 0c-1.582 0-2.812 1.254-2.812 2.867v38.52c-2.989-1.614-8.614-1.075-12.833 1.433-6.68 3.766-9.492 10.93-6.68 15.766 2.813 4.84 10.723 5.914 17.4 2.152 4.573-2.687 7.738-6.988 7.913-11.289V16.305c9.492 0 15.29 3.941 13.18 13.437-.352 1.793-1.05 3.403-1.754 5.195-.355.54-.355 1.254.176 1.793.527.536 1.402.356 2.11-.359 3.515-3.582 5.796-8.242 5.976-13.437-.18-6.805-6.508-10.75-11.953-13.438zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/m4.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm14.4 8.8l3.7-8.8h4.2v8.1h1.2v3h-1.2v3.2h-3.2v-3.2h-4.7v-2.3zm4.7-.7v-3.4c0-.8.1-1.3.1-1.3s-.1.6-.3 1.2l-1.4 3.5h1.6z" fill="#fff"/><path d="M51.7 70.3l-.1-.2-.2-.2c0-3-1.8-5.6-4.3-6.9-.3-1.1-.1-1.5-.1-1.5.1-.1.1-.3.2-.4h2.6c.6 0 1.2-.2 1.6-.7 1.4-1.4 2.1-3.2 2.1-5.2 0-3.7-2.6-6.7-6.2-7.2-.2 0-.4-.1-.6-.1H25.8c-4 0-7.3 3.3-7.3 7.3 0 .3 0 .6.1 1 .2 6.8 5.3 12.3 8 14.8h-5.2c-.8 0-1.6.4-1.9 1.2-.6 1.1-1 2.3-1 3.5 0 4 3.3 7.3 7.3 7.3h21.1c3.8-.4 6.7-3.6 6.7-7.3-.1-1.9-.8-4-1.9-5.4m-5-20.1c2.6.3 4.7 2.4 4.7 5.2 0 1.5-.6 2.7-1.6 3.7h-19c.8-1.1 1.3-2.3 1.3-3.7 0-2.1-1.1-4-2.6-5.2h17.2zM20.6 75.7c0-.9.3-1.8.7-2.4h8.8c.4.8.7 1.6.7 2.4 0 2.8-2.3 5.1-5.2 5.1s-5-2.4-5-5.1m26.1 5.1H29.3c1.7-1.2 2.7-3 2.7-5.2 0-2.1-1.1-4-2.6-5.2h.1s-8.6-6.4-8.7-14.5c0-.3-.1-.5-.1-.8 0-2.8 2.3-5.2 5.2-5.2s5.2 2.3 5.2 5.2v.3c0 .5-.1 1-.3 1.4-.2.6-.5 1.1-.9 1.6l-1.3 1.8h16.7c0 .1-.1.2-.2.3-.3.6-.4 1.2-.4 1.8-.3 0-.7-.1-1.1-.1-4.2 0-7.7 3.4-7.7 7.7s3.4 7.7 7.7 7.7c3.1 0 5.8-1.8 7-4.6.4.9.7 1.8.7 2.7.1 2.6-2 4.9-4.6 5.1m.3-10.9l-5.1 3.8V66l5.1 3.9z" fill="#999" stroke="#999" stroke-width=".5" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="m60.137 40.719-.184-.36-.36-.359c0-5.395-3.234-10.066-7.73-12.406-.539-1.977-.18-2.696-.18-2.696.18-.18.18-.539.364-.718h4.672c1.078 0 2.156-.36 2.875-1.258 2.52-2.516 3.777-5.754 3.777-9.348 0-6.652-4.676-12.047-11.144-12.945-.364 0-.723-.18-1.082-.18h-37.57C6.382.45.448 6.383.448 13.574c0 .54 0 1.078.18 1.797.36 12.223 9.527 22.113 14.383 26.606H5.664c-1.437 0-2.879.718-3.418 2.16C1.168 46.113.45 48.27.45 50.426c0 7.191 5.934 13.125 13.125 13.125h37.93c6.832-.719 12.047-6.473 12.047-13.125-.18-3.414-1.438-7.192-3.414-9.707M51.145 4.586c4.675.539 8.449 4.312 8.449 9.348 0 2.695-1.078 4.851-2.875 6.652H22.563c1.437-1.98 2.335-4.137 2.335-6.652 0-3.778-1.976-7.192-4.671-9.348zM4.227 50.426c0-1.617.539-3.235 1.257-4.313h15.82c.72 1.438 1.259 2.875 1.259 4.313 0 5.035-4.137 9.168-9.348 9.168-5.215 0-8.988-4.313-8.988-9.168m46.918 9.168H19.863c3.059-2.156 4.856-5.39 4.856-9.348 0-3.773-1.977-7.191-4.672-9.348h.18S4.766 29.395 4.586 14.832c0-.539-.18-.898-.18-1.437 0-5.036 4.133-9.348 9.348-9.348 5.21 0 9.348 4.133 9.348 9.348v.539c0 .898-.18 1.796-.54 2.515-.359 1.078-.898 1.977-1.617 2.875l-2.34 3.239H48.63c0 .18-.18.359-.36.539-.539 1.078-.718 2.156-.718 3.234-.54 0-1.258-.18-1.977-.18-7.55 0-13.844 6.114-13.844 13.844s6.114 13.844 13.844 13.844c5.57 0 10.426-3.239 12.582-8.27.719 1.617 1.258 3.235 1.258 4.852.18 4.676-3.594 8.808-8.27 9.168M51.685 40l-9.168 6.832V32.988zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".898875"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/m4a.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zM21 15.2l3.7-8.8h4.2v8.1h1.2v3h-1.2v3.2h-3.2v-3.2H21v-2.3zm4.7-.7v-3.4c0-.8.1-1.3.1-1.3s-.1.6-.3 1.2L24 14.5h1.7zm9.5-8.1h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zM38 15l-.6-2.8c-.2-1-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5L36 15h2z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/m4r.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zM21 15.2l3.7-8.8h4.2v8.1h1.2v3h-1.2v3.2h-3.2v-3.2H21v-2.3zm4.7-.7v-3.4c0-.8.1-1.3.1-1.3s-.1.6-.3 1.2L24 14.5h1.7zm7.1-8.1h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8H36v4.8h-3.3V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3H36V13h.7z" fill="#fff"/><path class="st0" d="M18.2 55c-.6 1.5.6 6 .6 6 2.3 6.4 7.7 11.9 7.7 11.9 5.3 5.5 10.6 8.9 15.3 10 4.7 1.1 5.6-.8 5.6-.8s3.9-3.8 5-5.1c1.1-1.4-.3-2.2-.3-2.2s-6.8-4.1-7.9-4.5c-1.1-.5-1.7.3-2.4.9s-2.1 1.9-2.1 1.9c-.8.1-2.3-.5-4.7-2.4s-5.3-5.5-6.1-6.8c-.8-1.2-.8-2.5-.8-2.5s1-.8 2-1.9c1-1.1.7-2.1.7-2.1l-3.1-5.7c-1.9-4-2.4-3.2-2.4-3.2-1.3.5-2.4 1.5-3.1 2.2-.5.5-3.2 2.8-4 4.3zm27 8.5c.8 0 1.5-.6 1.5-1.5 0-4.4-3.6-8.2-8.2-8.2-.8 0-1.5.6-1.5 1.5 0 .8.6 1.5 1.5 1.5 2.8 0 5.1 2.3 5.1 5.1 0 .9.8 1.6 1.6 1.6z"/><path class="st0" d="M39.2 49.1c-.8 0-1.5.6-1.5 1.5 0 .8.6 1.5 1.5 1.5 5.1 0 9.2 4.1 9.2 9.2 0 .8.6 1.5 1.5 1.5s1.5-.6 1.5-1.5c0-6.7-5.5-12.2-12.2-12.2zm-2 8.9c-.8 0-1.5.6-1.5 1.5s.6 1.5 1.5 1.5c1.3 0 2.4 1.1 2.4 2.4 0 .8.6 1.5 1.5 1.5.8 0 1.5-.6 1.5-1.5-.1-3-2.5-5.4-5.4-5.4z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#039"><path d="M.324 12.07C-.777 14.828 1.43 23.102 1.43 23.102c4.226 11.77 14.156 21.882 14.156 21.882 9.746 10.114 19.492 16.364 28.133 18.387 8.64 2.02 10.297-1.473 10.297-1.473s7.168-6.988 9.191-9.375c2.023-2.574-.55-4.046-.55-4.046s-12.505-7.54-14.524-8.274c-2.024-.918-3.13.55-4.414 1.656-1.29 1.102-3.864 3.493-3.864 3.493-1.468.183-4.226-.918-8.64-4.414C26.8 37.444 21.469 30.823 20 28.434c-1.473-2.204-1.473-4.594-1.473-4.594s1.84-1.473 3.68-3.496c1.836-2.02 1.285-3.86 1.285-3.86l-5.699-10.48C14.301-1.352 13.379.12 13.379.12c-2.39.918-4.41 2.758-5.7 4.043-.917.922-5.882 5.149-7.355 7.906zM49.97 27.7c1.472 0 2.758-1.102 2.758-2.759 0-8.09-6.618-15.078-15.075-15.078-1.472 0-2.761 1.106-2.761 2.758 0 1.473 1.105 2.762 2.761 2.762 5.145 0 9.375 4.226 9.375 9.375 0 1.656 1.473 2.941 2.942 2.941zm0 0"/><path d="M38.938 1.223c-1.473 0-2.758 1.105-2.758 2.757 0 1.473 1.101 2.758 2.757 2.758a16.87 16.87 0 0 1 16.915 16.918c0 1.469 1.105 2.758 2.757 2.758 1.657 0 2.762-1.105 2.762-2.758 0-12.32-10.113-22.433-22.434-22.433zm-3.676 16.363c-1.473 0-2.758 1.105-2.758 2.758 0 1.656 1.101 2.758 2.758 2.758 2.39 0 4.41 2.023 4.41 4.414 0 1.472 1.105 2.757 2.758 2.757 1.472 0 2.757-1.101 2.757-2.757-.183-5.516-4.593-9.93-9.925-9.93zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/m4v.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm14.4 8.8l3.7-8.8h4.2v8.1h1.2v3h-1.2v3.2h-3.2v-3.2h-4.7v-2.3zm4.7-.7v-3.4c0-.8.1-1.3.1-1.3s-.1.6-.3 1.2l-1.4 3.5h1.6zm6-8.1h3.6l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3l1.7-8.1h3.5l-3.9 14.3h-3.3L32.2 6.4z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/map.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm17.5 0h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3H21l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2zm6.9-8.6h4.5c2.6 0 4.4 2 4.4 4.9s-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path class="st0" d="M52 72.5c-.2-.3-.4-.4-.7-.4h-9.4c-.3.7-.7 1.3-1 2-.8 1.6-1.7 3.3-2.5 4.7v.1c-.5.8-1.3 1.4-2.3 1.4s-1.8-.5-2.3-1.4c-.3-.5-1.3-2.4-2.5-4.8-.4-.7-.7-1.4-1-2.1h-5.1c-.3 0-.6.2-.8.5L20 81.8c-.1.3-.1.6 0 .8.2.3.4.4.7.4h26.1c.3 0 .6-.2.8-.5l4.4-9.2c.2-.2.1-.6 0-.8z"/><path class="st0" d="M36 47c-5.3 0-9.7 4.3-9.7 9.7 0 3.2 3.5 10.8 6.4 16.7 1.4 2.7 2.5 4.7 2.5 4.8.2.3.4.5.8.5s.6-.2.8-.5c0 0 1.1-2 2.5-4.8 2.9-5.8 6.4-13.4 6.4-16.7 0-5.4-4.4-9.7-9.7-9.7zm0 15.6c-2.4 0-4.5-1.9-4.7-4.3v-.5c0-2.6 2.1-4.7 4.7-4.7 2.4 0 4.5 1.9 4.7 4.2v.5c0 2.6-2.1 4.8-4.7 4.8z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M56.797 45.254c-.356-.531-.711-.707-1.242-.707H38.91c-.531 1.238-1.238 2.297-1.77 3.535-1.417 2.828-3.011 5.832-4.425 8.305v.18c-.887 1.413-2.305 2.472-4.074 2.472s-3.188-.883-4.07-2.473c-.532-.886-2.305-4.242-4.43-8.484-.707-1.238-1.239-2.473-1.77-3.71H9.34c-.531 0-1.063.35-1.414.882L.133 61.69c-.176.528-.176 1.059 0 1.414.355.528.707.708 1.238.708h46.215c.531 0 1.062-.356 1.418-.887l7.793-16.258c.351-.352.176-1.059 0-1.414zm0 0"/><path d="M28.465.188c-9.387 0-17.176 7.601-17.176 17.144 0 5.656 6.195 19.086 11.332 29.512 2.48 4.773 4.426 8.308 4.426 8.484.355.531.71.883 1.418.883.707 0 1.062-.352 1.414-.883 0 0 1.95-3.535 4.43-8.484 5.132-10.25 11.332-23.68 11.332-29.512C45.64 7.789 37.848.187 28.465.187zm0 27.57c-4.25 0-7.969-3.356-8.324-7.598v-.883c0-4.597 3.718-8.308 8.324-8.308 4.25 0 7.969 3.36 8.32 7.422v.886c0 4.594-3.719 8.48-8.32 8.48zm0 0"/></g></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/master.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2,.st4{fill:#bababa}.st4{stroke:#bababa;stroke-width:.5;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M7.6 70.4h3.3l1.2 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.2-6h3.3l.8 14.3h-2.7l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.8 4.1h-2.9l-.8-4.1c-.2-.9-.4-2.4-.4-2.4s.1 1.3 0 2.4l-.4 6.4H6.8l.8-14.3zm14.9 0h3.2l3.2 14.3h-3l-.5-3h-2.7l-.5 3h-3l3.3-14.3zM25 79l-.5-2.8c-.2-.9-.4-2.5-.4-2.5H24s-.2 1.5-.4 2.5l-.4 2.8H25zm5.9 1.7c.5.6 1.3 1.2 2.1 1.2s1.2-.6 1.2-1.2c0-2-4.3-2.1-4.3-6.2 0-2.4 1.5-4.3 4.1-4.3 1.1 0 2.2.3 3.1 1L36 74.1c-.4-.4-1.3-.9-1.9-.9-.8 0-1.2.6-1.2 1.2 0 2.1 4.3 2 4.3 6.1 0 2.3-1.3 4.4-4 4.4-1.3 0-2.6-.5-3.6-1.4l1.3-2.8zM41 73.3h-2.8v-2.9h8.6v2.9H44v11.4h-3V73.3zm7.4-2.9h6.5v2.9h-3.5V76h2.8v2.9h-2.8v2.9H55v2.9h-6.6V70.4zm8.5 0H61c.5 0 1.2.1 1.7.4 1.3.6 2.2 2.1 2.2 4 0 1.7-.7 3.3-1.8 4 0 0 .2.2.4.9l2.1 5h-3.2l-1.8-4.8h-.7v4.8h-3V70.4zm3.6 6.6c.8 0 1.4-.7 1.4-1.9 0-.7-.2-1.2-.5-1.5-.2-.2-.5-.3-.8-.3h-.7V77h.6z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/><g opacity=".9"><path class="st4" d="M52.9 39.8c-.5-.3-1.1-.3-1.6.1l-7.8 6-7.1-9.5c-.3-.3-.7-.6-1.1-.6-.4 0-.8.2-1.1.5l-7.6 9.5-7.4-6c-.5-.4-1.1-.4-1.6-.1-.5.3-.8.9-.7 1.5L19.3 54c.1.7.7 1.1 1.4 1.1h29.1c.7 0 1.3-.5 1.4-1.1l2.4-12.7c.1-.6-.2-1.2-.7-1.5zm-4.3 12.5H21.9l-1.5-7.8 5.5 4.4c.3.2.7.3 1 .3.4 0 .7-.2.9-.5l7.4-9.2 6.9 9.2c.2.3.6.5.9.5.4.1.7 0 1-.3l6-4.6-1.4 8z"/><path class="st4" d="M48.3 53.7v3.6H22.1v-3.6h-2.8v5c0 .8.6 1.4 1.4 1.4h29.1c.8 0 1.4-.6 1.4-1.4v-5h-2.9zM35.2 29.2c-2.6 0-4.7 2.1-4.7 4.7s2.1 4.7 4.7 4.7 4.7-2.1 4.7-4.7-2.1-4.7-4.7-4.7zm0 6.5c-1 0-1.9-.8-1.9-1.9s.8-1.9 1.9-1.9c1 0 1.9.8 1.9 1.9s-.9 1.9-1.9 1.9zm17.3-2.8c-2.6 0-4.7 2.1-4.7 4.7s2.1 4.7 4.7 4.7 4.7-2.1 4.7-4.7-2.1-4.7-4.7-4.7zm0 6.5c-1 0-1.9-.8-1.9-1.9 0-1 .8-1.9 1.9-1.9 1 0 1.9.8 1.9 1.9 0 1.1-.8 1.9-1.9 1.9zm-34.6-6.5c-2.6 0-4.7 2.1-4.7 4.7s2.1 4.7 4.7 4.7 4.7-2.1 4.7-4.7-2.1-4.7-4.7-4.7zm0 6.5c-1 0-1.9-.8-1.9-1.9 0-1 .8-1.9 1.9-1.9 1 0 1.9.8 1.9 1.9 0 1.1-.9 1.9-1.9 1.9z"/></g></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/mc.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zM28 6.1c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4z"/><path class="st0" d="M54.5 65.5C54.5 75.7 46.2 84 36 84s-18.5-8.3-18.5-18.5S25.8 47 36 47s18.5 8.3 18.5 18.5"/><path class="st1" d="M48.9 66.9c-.6-3.9-4.7-6.5-7.8-8.4-1.3-.8-3.5-1.9-3.8-3.7-.1-.7-.1-1.5-.1-2.2v-.9c0-.4-.4.1-.6-.2-.5-.8-.3.2-.3.7.1 1 .3 2 .3 3 0 1.9-.3 3.8-.8 5.6-1.1 4.3-2 8.8-.9 13.2.2.9.5 1.8.9 2.7.1.3.3 1 .7 1.1 1.2.3 2.1.4 3 1.3.6.5 1 .2 1.7 0 2.1-.8 3.9-1.9 5.4-3.6 1.9-2.6 2.8-5.5 2.3-8.6m-2.2 3.9c-.2 1.6-1.2 3.1-2.2 4.3-.8.9-1.8 2-2.9 2.4-.4.1.1-.7.1-.7.3-.5.8-1 1.2-1.5.6-.7 1.1-1.5 1.4-2.3 1.1-2.9.9-6.3-.8-8.9-.9-1.4-2.2-2.6-3.4-3.7-.6-.5-1.2-1-1.7-1.6-.1-.1-1.2-1.5-.8-1.7.1-.1 2.4 2.3 2.6 2.5.9.7 1.9 1.4 2.8 2.2 1.2 1.1 2.4 2.3 3.1 3.8.7 1.6.8 3.5.6 5.2"/><path class="st1" d="M35.3 47.5c.3.2.4 1.6.4 2.8 0 1.2.1 6.5-.3 7.9-.4 1.4-1.3 3-2.2 4.4-1 1.4-2.1 4.3-2 6.1 0 1.8 1.1 4.7 1.9 6 .8 1.2 2.2 2.9 1.9 3.3-.5.7-2.7-1.7-3.9-3.1-1.1-1.4-2.3-4.2-2.3-6.4s1.2-4.2 2.1-5.4c.9-1.2 2.6-3.3 3.1-4.3s1-2 1.1-3.3c.2-1.3 0-6.1 0-6.1s-.1-2.1.2-1.9"/><path class="st1" d="M34.4 49.8c.3.2.4.6.4 1s-.1 2.1-.2 3.8c-.1 1.7-1.5 3.1-2.4 4.1-1 1-3.9 4.1-4.9 5.6-1.1 1.5-1.6 3.5-1.5 5.2.1 1.7.5 3.4 2.1 5.2 1.6 1.8 2.7 2.6 3.6 3.1.8.4 1.7.7 1.5 1.1-.2.4-1 .1-1.9-.2-.9-.3-3.9-1.5-5.6-3.5-1.7-2-2.6-4.6-2.5-7 .1-2.5.8-3.5 1.9-5.1 1.1-1.6 4.3-4 5.3-4.6 1-.6 2.3-1.6 3-2.5.7-.8 1-1.5 1-2.7 0-1.1.1-2.2 0-2.6-.1-.3-.1-1.1.2-.9m.1 30c.2 0 .1.7-.2 1-.3.3-.7.5-.8.4-.1-.1.3-.2.6-.5.3-.4.2-.9.4-.9m3.1-.1c-.2 0-.1.7.2 1 .3.3.7.5.8.4.1-.1-.3-.2-.6-.5s-.2-.9-.4-.9m-1.4.8c0 .6 0 1.1-.1 1.1-.2 0-.1-.5-.1-1.1 0-.6-.1-1.1.1-1.1s.1.5.1 1.1"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M64 32c0 17.645-14.355 32-32 32S0 49.645 0 32 14.355 0 32 0s32 14.355 32 32" fill="#999"/><g fill="#fff"><path d="M54.313 34.422c-1.036-6.746-8.13-11.242-13.493-14.531-2.246-1.383-6.054-3.286-6.57-6.399-.176-1.21-.176-2.594-.176-3.805V8.13c0-.692-.691.172-1.035-.344-.867-1.387-.52.344-.52 1.211.172 1.727.52 3.457.52 5.188 0 3.285-.52 6.574-1.387 9.687-1.902 7.438-3.457 15.223-1.554 22.832a24.518 24.518 0 0 0 1.554 4.668c.176.52.52 1.73 1.211 1.906 2.078.516 3.633.692 5.192 2.246 1.039.868 1.73.348 2.941 0 3.633-1.382 6.746-3.285 9.34-6.226 3.285-4.496 4.844-9.512 3.977-14.875m-3.805 6.746c-.344 2.766-2.074 5.363-3.805 7.437-1.383 1.56-3.113 3.461-5.016 4.153-.69.172.172-1.211.172-1.211.52-.867 1.383-1.73 2.075-2.594 1.039-1.21 1.902-2.598 2.421-3.98 1.903-5.016 1.56-10.899-1.382-15.395-1.555-2.422-3.805-4.496-5.88-6.398-1.038-.868-2.077-1.73-2.94-2.77-.176-.172-2.079-2.594-1.387-2.941.175-.172 4.152 3.98 4.5 4.324 1.554 1.21 3.285 2.422 4.843 3.809 2.075 1.902 4.149 3.976 5.36 6.57 1.21 2.77 1.386 6.055 1.039 8.996"/><path d="M30.79.863c.519.348.69 2.77.69 4.844 0 2.078.172 11.246-.52 13.664-.69 2.422-2.245 5.192-3.804 7.613-1.73 2.422-3.633 7.438-3.457 10.551 0 3.113 1.903 8.13 3.285 10.38 1.383 2.073 3.805 5.015 3.286 5.706-.864 1.211-4.668-2.941-6.747-5.363-1.902-2.422-3.976-7.262-3.976-11.07 0-3.805 2.074-7.262 3.633-9.34 1.554-2.075 4.496-5.707 5.36-7.438.866-1.73 1.73-3.457 1.901-5.707.348-2.25 0-10.55 0-10.55S30.27.52 30.79.862"/><path d="M29.234 4.844c.516.343.692 1.039.692 1.73 0 .692-.176 3.633-.348 6.57-.172 2.942-2.594 5.364-4.152 7.094-1.727 1.73-6.746 7.09-8.473 9.688-1.906 2.594-2.77 6.05-2.598 8.992.176 2.941.868 5.883 3.633 8.996 2.77 3.113 4.672 4.496 6.227 5.363 1.387.692 2.941 1.211 2.597 1.903-.347.691-1.73.172-3.289-.348-1.554-.52-6.746-2.594-9.687-6.055-2.938-3.457-4.496-7.957-4.324-12.105.175-4.324 1.386-6.055 3.289-8.824 1.902-2.766 7.437-6.918 9.168-7.957 1.73-1.036 3.976-2.766 5.187-4.325 1.211-1.382 1.73-2.593 1.73-4.668 0-1.902.173-3.804 0-4.5-.171-.515-.171-1.902.348-1.554m.172 51.89c.344 0 .172 1.211-.347 1.73-.52.52-1.211.864-1.383.692s.52-.343 1.039-.863c.52-.691.344-1.559.691-1.559m5.36-.172c-.344 0-.172 1.211.347 1.731s1.211.863 1.383.691c.176-.172-.52-.347-1.035-.867-.52-.515-.348-1.554-.695-1.554m-2.418 1.382c0 1.04 0 1.903-.176 1.903-.344 0-.172-.864-.172-1.903 0-1.039-.172-1.902.172-1.902.348 0 .176.863.176 1.902"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/md.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm14.6 0h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2H25v8.5h.8z" fill="#fff"/><path class="st0" d="M13.5 76.4V54.6h6.4l6.4 8 6.4-8h6.4v21.8h-6.4V63.9l-6.4 8-6.4-8v12.5h-6.4zm38.4 0l-9.6-10.6h6.4V54.6h6.4v11.2h6.4l-9.6 10.6z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="39"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M0 38.824V.176h11.2l11.198 14.183L33.602.176H44.8v38.648H33.6v-22.16l-11.203 14.18-11.195-14.18v22.16zm67.2 0L50.397 20.031h11.204V.176h11.195V20.03H84zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mdb.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#a03537}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm14 0h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm8-11.4h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1z" fill="#fff"/><path class="st0" d="M54.6 70.3c-.1.9-1.2 1.6-3.4 2.1s-5 .8-8.3.8h-2.8v5.2c.9.1 1.9.1 2.8.1 3.3 0 6.1-.3 8.3-.9 2.2-.6 3.4-1.3 3.5-2.1-.1-.2-.1-5.2-.1-5.2zm-11.8-3.8c-1 0-1.9 0-2.8-.1v5.3h2.8c3.3 0 6.1-.3 8.3-.9 2.2-.6 3.4-1.3 3.4-2.1v-5.1c-.1.9-1.2 1.6-3.5 2.1-2.1.6-4.9.9-8.2.8zm0-6.5c-1 0-1.9 0-2.8-.1v5.3c.9.1 1.9.1 2.8.1 3.3 0 6.1-.3 8.4-.9 2.2-.6 3.4-1.3 3.5-2.1v-5.1c-.1.9-1.2 1.6-3.5 2.1-2.3.4-5.1.7-8.4.7zm0-7.4c-1 0-1.9 0-2.8.1v5.9c.9.1 1.9.1 2.8.1 3.3 0 6.1-.3 8.4-.9 2.2-.6 3.4-1.3 3.5-2.1-.1-.9-1.2-1.6-3.5-2.2-2.3-.6-5.1-.8-8.4-.9zm-16.1 8.3c-.1.3-.3 1.3-.7 3l-.7 2.9h2.9l-.7-2.9c-.4-1.7-.7-2.7-.7-3h-.1zm-10.3-9.5v28.3L38 83.4V47.6l-21.6 3.8zm13.2 21.1l-.8-3.2-4-.1-.8 3-2.5-.2 3.8-13.5 2.9-.2 4.2 14.3-2.8-.1z"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M66.824 40.465c-.176 1.59-2.097 2.824-5.945 3.707-3.852.879-8.75 1.41-14.52 1.41h-4.898v9.172c1.574.176 3.324.176 4.898.176 5.77 0 10.668-.528 14.52-1.586 3.848-1.059 5.945-2.293 6.121-3.707-.176-.352-.176-9.172-.176-9.172zm-20.64-6.7c-1.75 0-3.325 0-4.899-.18v9.352h4.899c5.773 0 10.671-.53 14.52-1.59s5.944-2.292 5.944-3.702v-8.997c-.171 1.586-2.097 2.825-6.12 3.704-3.673 1.058-8.571 1.59-14.344 1.414zm0-11.468c-1.75 0-3.325 0-4.899-.176v9.352c1.574.175 3.324.175 4.899.175 5.773 0 10.671-.53 14.695-1.59C64.727 29 66.824 27.767 67 26.356V17.36c-.176 1.59-2.098 2.825-6.121 3.704-4.024.707-8.922 1.234-14.695 1.234zm0-13.05c-1.75 0-3.325 0-4.899.175v10.406c1.574.176 3.324.176 4.899.176 5.773 0 10.671-.527 14.695-1.586 3.848-1.059 5.945-2.293 6.121-3.703-.176-1.59-2.098-2.824-6.121-3.883-4.024-1.055-8.922-1.41-14.695-1.586zM18.02 23.886c-.176.527-.528 2.293-1.227 5.293l-1.223 5.113h5.07l-1.222-5.113c-.7-3-1.227-4.766-1.227-5.293zM0 7.129v49.918l37.785 6.527V.426zm23.09 37.219-1.399-5.645-6.996-.176-1.398 5.29-4.375-.352 6.648-23.813 5.07-.351 7.348 25.222zm0 0" fill="#a03537"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mdf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d5006e}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.1 0h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.1-11.4h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#d5006e"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/me.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.1 0h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4z" fill="#fff"/><path class="st0" d="M14.6 77.2h42.8v6.2H14.6zm0-14.8h42.8v6.2H14.6zm0-15h42.8v6.2H14.6z"/></svg>
1
<svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><path d="M.176 52.977h75.648V64H.176zm0-26.309h75.648v11.02H.176zM.176 0h75.648v11.023H.176zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mi.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.1 0h3.3v14.3h-3.3V6.4z"/><path class="st0" d="M54.5 65.5C54.5 75.7 46.2 84 36 84s-18.5-8.3-18.5-18.5S25.8 47 36 47s18.5 8.3 18.5 18.5"/><path class="st1" d="M48.9 66.9c-.6-3.9-4.7-6.5-7.8-8.4-1.3-.8-3.5-1.9-3.8-3.7-.1-.7-.1-1.5-.1-2.2v-.9c0-.4-.4.1-.6-.2-.5-.8-.3.2-.3.7.1 1 .3 2 .3 3 0 1.9-.3 3.8-.8 5.6-1.1 4.3-2 8.8-.9 13.2.2.9.5 1.8.9 2.7.1.3.3 1 .7 1.1 1.2.3 2.1.4 3 1.3.6.5 1 .2 1.7 0 2.1-.8 3.9-1.9 5.4-3.6 1.9-2.6 2.8-5.5 2.3-8.6m-2.2 3.9c-.2 1.6-1.2 3.1-2.2 4.3-.8.9-1.8 2-2.9 2.4-.4.1.1-.7.1-.7.3-.5.8-1 1.2-1.5.6-.7 1.1-1.5 1.4-2.3 1.1-2.9.9-6.3-.8-8.9-.9-1.4-2.2-2.6-3.4-3.7-.6-.5-1.2-1-1.7-1.6-.1-.1-1.2-1.5-.8-1.7.1-.1 2.4 2.3 2.6 2.5.9.7 1.9 1.4 2.8 2.2 1.2 1.1 2.4 2.3 3.1 3.8.7 1.6.8 3.5.6 5.2"/><path class="st1" d="M35.3 47.5c.3.2.4 1.6.4 2.8 0 1.2.1 6.5-.3 7.9-.4 1.4-1.3 3-2.2 4.4-1 1.4-2.1 4.3-2 6.1 0 1.8 1.1 4.7 1.9 6 .8 1.2 2.2 2.9 1.9 3.3-.5.7-2.7-1.7-3.9-3.1-1.1-1.4-2.3-4.2-2.3-6.4s1.2-4.2 2.1-5.4c.9-1.2 2.6-3.3 3.1-4.3s1-2 1.1-3.3c.2-1.3 0-6.1 0-6.1s-.1-2.1.2-1.9"/><path class="st1" d="M34.4 49.8c.3.2.4.6.4 1s-.1 2.1-.2 3.8c-.1 1.7-1.5 3.1-2.4 4.1-1 1-3.9 4.1-4.9 5.6-1.1 1.5-1.6 3.5-1.5 5.2.1 1.7.5 3.4 2.1 5.2 1.6 1.8 2.7 2.6 3.6 3.1.8.4 1.7.7 1.5 1.1-.2.4-1 .1-1.9-.2-.9-.3-3.9-1.5-5.6-3.5-1.7-2-2.6-4.6-2.5-7 .1-2.5.8-3.5 1.9-5.1 1.1-1.6 4.3-4 5.3-4.6 1-.6 2.3-1.6 3-2.5.7-.8 1-1.5 1-2.7 0-1.1.1-2.2 0-2.6-.1-.3-.1-1.1.2-.9m.1 30c.2 0 .1.7-.2 1-.3.3-.7.5-.8.4-.1-.1.3-.2.6-.5.3-.4.2-.9.4-.9m3.1-.1c-.2 0-.1.7.2 1 .3.3.7.5.8.4.1-.1-.3-.2-.6-.5s-.2-.9-.4-.9m-1.4.8c0 .6 0 1.1-.1 1.1-.2 0-.1-.5-.1-1.1 0-.6-.1-1.1.1-1.1s.1.5.1 1.1"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M64 32c0 17.645-14.355 32-32 32S0 49.645 0 32 14.355 0 32 0s32 14.355 32 32" fill="#999"/><g fill="#fff"><path d="M54.313 34.422c-1.036-6.746-8.13-11.242-13.493-14.531-2.246-1.383-6.054-3.286-6.57-6.399-.176-1.21-.176-2.594-.176-3.805V8.13c0-.692-.691.172-1.035-.344-.867-1.387-.52.344-.52 1.211.172 1.727.52 3.457.52 5.188 0 3.285-.52 6.574-1.387 9.687-1.902 7.438-3.457 15.223-1.554 22.832a24.518 24.518 0 0 0 1.554 4.668c.176.52.52 1.73 1.211 1.906 2.078.516 3.633.692 5.192 2.246 1.039.868 1.73.348 2.941 0 3.633-1.382 6.746-3.285 9.34-6.226 3.285-4.496 4.844-9.512 3.977-14.875m-3.805 6.746c-.344 2.766-2.074 5.363-3.805 7.437-1.383 1.56-3.113 3.461-5.016 4.153-.69.172.172-1.211.172-1.211.52-.867 1.383-1.73 2.075-2.594 1.039-1.21 1.902-2.598 2.421-3.98 1.903-5.016 1.56-10.899-1.382-15.395-1.555-2.422-3.805-4.496-5.88-6.398-1.038-.868-2.077-1.73-2.94-2.77-.176-.172-2.079-2.594-1.387-2.941.175-.172 4.152 3.98 4.5 4.324 1.554 1.21 3.285 2.422 4.843 3.809 2.075 1.902 4.149 3.976 5.36 6.57 1.21 2.77 1.386 6.055 1.039 8.996"/><path d="M30.79.863c.519.348.69 2.77.69 4.844 0 2.078.172 11.246-.52 13.664-.69 2.422-2.245 5.192-3.804 7.613-1.73 2.422-3.633 7.438-3.457 10.551 0 3.113 1.903 8.13 3.285 10.38 1.383 2.073 3.805 5.015 3.286 5.706-.864 1.211-4.668-2.941-6.747-5.363-1.902-2.422-3.976-7.262-3.976-11.07 0-3.805 2.074-7.262 3.633-9.34 1.554-2.075 4.496-5.707 5.36-7.438.866-1.73 1.73-3.457 1.901-5.707.348-2.25 0-10.55 0-10.55S30.27.52 30.79.862"/><path d="M29.234 4.844c.516.343.692 1.039.692 1.73 0 .692-.176 3.633-.348 6.57-.172 2.942-2.594 5.364-4.152 7.094-1.727 1.73-6.746 7.09-8.473 9.688-1.906 2.594-2.77 6.05-2.598 8.992.176 2.941.868 5.883 3.633 8.996 2.77 3.113 4.672 4.496 6.227 5.363 1.387.692 2.941 1.211 2.597 1.903-.347.691-1.73.172-3.289-.348-1.554-.52-6.746-2.594-9.687-6.055-2.938-3.457-4.496-7.957-4.324-12.105.175-4.324 1.386-6.055 3.289-8.824 1.902-2.766 7.437-6.918 9.168-7.957 1.73-1.036 3.976-2.766 5.187-4.325 1.211-1.382 1.73-2.593 1.73-4.668 0-1.902.173-3.804 0-4.5-.171-.515-.171-1.902.348-1.554m.172 51.89c.344 0 .172 1.211-.347 1.73-.52.52-1.211.864-1.383.692s.52-.343 1.039-.863c.52-.691.344-1.559.691-1.559m5.36-.172c-.344 0-.172 1.211.347 1.731s1.211.863 1.383.691c.176-.172-.52-.347-1.035-.867-.52-.515-.348-1.554-.695-1.554m-2.418 1.382c0 1.04 0 1.903-.176 1.903-.344 0-.172-.864-.172-1.903 0-1.039-.172-1.902.172-1.902.348 0 .176.863.176 1.902"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mid.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.1 0h3.3v14.3h-3.3V6.4zm6.9 0h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/midi.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm13.6 0H24v14.3h-3.3V6.4zm5.4 0h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm7.7-11.4h3.3v14.3h-3.3V6.4z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mk.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.1 0h3.3v5.5h.5l2.3-5.5h3.5L29 13.2l3 7.4h-3.7L26 14.9h-.6v5.8h-3.3V6.4z" fill="#fff"/><path class="st0" d="M38 68.1l2.8.8 1.7-6.2-2.8-.8c0-1-.1-2-.4-3l2.5-1.5-3.2-5.6-2.6 1.5c-.7-.7-1.5-1.3-2.4-1.8l.8-2.8-6.2-1.7-.8 2.8c-1 0-2 .1-3 .4l-1.5-2.5-5.6 3.2 1.5 2.5c-.7.7-1.3 1.5-1.8 2.4l-2.8-.8-1.7 6.2 2.8.8c0 1 .1 2 .4 3l-2.5 1.5 3.2 5.6 2.5-1.5c.7.7 1.5 1.3 2.4 1.8l-.8 2.8 6.2 1.7.8-2.8c1 0 2-.1 3-.4l1.5 2.5 5.6-3.2-1.5-2.5c.7-.7 1.4-1.5 1.9-2.4zm-15.5-3.3c-1.6-2.7-.6-6.2 2.1-7.8 2.7-1.6 6.2-.6 7.8 2.1 1.6 2.7.6 6.2-2.1 7.8-2.7 1.6-6.2.7-7.8-2.1zm30.2 19.8l3.6-2.1-1-1.7c.5-.5.9-1 1.2-1.6l1.9.5 1.1-4.1-1.9-.5c0-.7-.1-1.3-.3-2l1.7-1-2.1-3.6-1.7 1c-.5-.5-1-.9-1.6-1.2l.5-1.9-4.1-1.1-.5 1.9c-.7 0-1.3.1-2 .3l-1-1.7-3.4 2.2 1 1.7c-.5.5-.9 1-1.2 1.6l-1.9-.6-1.1 4.1 1.9.5c0 .7.1 1.3.3 2l-1.7 1 2.1 3.6 1.7-1c.5.5 1 .9 1.6 1.2l-.5 1.9 4.1 1.1.5-1.9c.7 0 1.3-.1 2-.3-.2 0 .8 1.7.8 1.7zm-6.2-7.5c-1-1.8-.4-4.1 1.4-5.1 1.8-1 4.1-.4 5.1 1.4 1 1.8.4 4.1-1.4 5.1-1.8 1-4.1.4-5.1-1.4z"/></svg>
1
<svg height="64" width="79" xmlns="http://www.w3.org/2000/svg"><path d="m42.852 35.445 4.695 1.344 2.851-10.418-4.695-1.344c0-1.68-.168-3.359-.672-5.039l4.192-2.52-5.364-9.405-4.359 2.519a18.036 18.036 0 0 0-4.023-3.023l1.34-4.704L26.421 0l-1.34 4.703c-1.676 0-3.352.168-5.027.672l-2.516-4.2-9.387 5.376 2.512 4.199a18.053 18.053 0 0 0-3.016 4.031l-4.695-1.343L.105 23.852l4.692 1.343c0 1.68.168 3.36.672 5.04l-4.192 2.523 5.364 9.406 4.191-2.52a18.126 18.126 0 0 0 4.023 3.024l-1.34 4.703 10.395 2.856 1.34-4.704c1.676 0 3.352-.168 5.031-.671l2.512 4.199 9.39-5.375-2.515-4.2c1.172-1.175 2.348-2.519 3.184-4.03zm-25.985-5.547c-2.68-4.535-1.004-10.414 3.52-13.101 4.527-2.688 10.394-1.008 13.078 3.527 2.683 4.535 1.004 10.414-3.52 13.106-4.527 2.687-10.394 1.175-13.078-3.532zm50.63 33.262 6.034-3.527-1.676-2.856c.84-.84 1.508-1.68 2.012-2.687l3.184.84 1.844-6.887-3.184-.84c0-1.176-.168-2.183-.504-3.36l2.852-1.679-3.52-6.047-2.852 1.68c-.84-.84-1.675-1.512-2.683-2.016l.84-3.191-6.875-1.852-.836 3.196c-1.176 0-2.18.168-3.356.504l-1.675-2.86-5.7 3.7 1.676 2.855c-.836.84-1.508 1.68-2.012 2.687l-3.183-1.007-1.844 6.886 3.184.84c0 1.176.168 2.184.504 3.36l-2.852 1.68 3.523 6.046 2.848-1.68c.84.84 1.676 1.512 2.684 2.016l-.84 3.191L61.965 64l.836-3.191c1.176 0 2.18-.168 3.355-.504-.336 0 1.34 2.855 1.34 2.855zM57.101 50.563c-1.676-3.024-.668-6.887 2.347-8.567 3.02-1.68 6.875-.672 8.551 2.352 1.676 3.023.672 6.886-2.348 8.566-3.015 1.68-6.875.672-8.55-2.352zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mkv.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm14.6 0H25v5.5h.6l2.3-5.5h3.5l-2.9 6.8 3 7.4h-3.7l-2.3-5.8H25v5.8h-3.3V6.4zm10.7 0H36l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L40 6.4h3.5l-3.9 14.3h-3.3L32.4 6.4z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mm.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.6 0h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.3-6.4c-.1-1.1 0-2.4 0-2.4s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1-14.3z" fill="#fff"/><path class="st0" d="M14 48.9h37v4.3H14zm7 9.6h37v4.3H21zm-7 9.6h37v4.3H14zm7 9.6h37V82H21z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mng.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm13.8 0h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h3.1v14.3H27l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4zm17.7-.3c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9H43v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.6-7.6 6.5-7.6z" fill="#fff"/><path d="M52.6 83H19.4c-.5 0-.9-.4-.9-.9V48.9c0-.5.4-.9.9-.9h33.2c.5 0 .9.4.9.9v33.2c0 .5-.4.9-.9.9zm-32.4-2.2c0 .3.2.4.4.4h30.6c.3 0 .4-.2.4-.4v-7.9c0-.3-.2-.4-.4-.4H20.7c-.3 0-.4.2-.4.4v7.9zm31.1-31H20.7c-.3 0-.4.2-.4.4v20.1c0 .1 0 .2.1.2l6.5-8.1 6.6 3.9 7.4-8.8L51.8 66V50.2c0-.3-.2-.4-.5-.4zM24.6 74.2c1.4 0 2.6 1.2 2.6 2.6s-1.2 2.6-2.6 2.6-2.6-1.1-2.6-2.5 1.2-2.7 2.6-2.7zm4.8 1.8h20.1c.3 0 .4.2.4.4v.9c0 .3-.2.4-.4.4H29.4c-.3 0-.4-.2-.4-.4v-.9c0-.2.2-.4.4-.4z" fill="#3c3" stroke="#3c3" stroke-width=".25" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M62.14 63.773H1.86a1.627 1.627 0 0 1-1.633-1.632V1.859C.227.953.953.227 1.859.227h60.282c.906 0 1.632.726 1.632 1.632v60.282c0 .906-.726 1.632-1.632 1.632zM3.314 59.777c0 .547.363.727.726.727h55.559c.543 0 .726-.363.726-.727V45.434c0-.543-.363-.723-.726-.723H4.223c-.547 0-.727.363-.727.723v14.343zm56.464-56.28H4.223c-.547 0-.727.362-.727.726v36.492c0 .18 0 .363.18.363l11.8-14.707 11.985 7.082 13.434-15.976 19.793 15.43V4.222c0-.547-.364-.727-.91-.727zm-48.476 44.3c2.543 0 4.722 2.176 4.722 4.719s-2.18 4.722-4.722 4.722c-2.54 0-4.719-2-4.719-4.539 0-2.543 2.18-4.902 4.719-4.902zm8.715 3.266h36.496c.543 0 .726.363.726.726v1.637c0 .543-.363.722-.726.722H20.016c-.543 0-.727-.359-.727-.722v-1.637c0-.363.363-.726.727-.726zm0 0" fill="#3c3" stroke="#3c3" stroke-miterlimit="10" stroke-width=".4539"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mo.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#a87c2d}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm20.4-.3c3.8 0 5.9 3.1 5.9 7.3s-2.1 7.5-5.9 7.5-5.8-3.2-5.8-7.5c-.1-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2S25 11 25 13.5s.8 4.3 2.5 4.3z" fill="#fff"/><path d="M34.9 68.2c-2.5-2.4-4.7-4.6-6-9.6h8.8V55H29v-4.9h-3.8v5h-8.8v3.7h9s-.1.7-.2 1.3c-1.3 4.9-2.7 8-8.8 11l1.3 3.7c5.7-3 8.7-6.9 10-11.1 1.3 3.2 3.4 5.8 5.8 8.2l1.4-3.7zm11.6-12h-5l-8.8 24.7h3.8l2.5-7.4h10l2.5 7.4h3.8l-8.8-24.7zm-6.2 13.6l3.8-9.8 3.8 9.9-7.6-.1z" fill="#a87c2d" stroke="#a87c2d" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><path d="M38.027 37.414c-5.011-4.812-9.425-9.223-12.03-19.25H43.64v-7.219H26.195V1.121h-7.617v10.024H.93v7.421h18.047s-.2 1.403-.399 2.606C15.968 30.996 13.164 37.215.93 43.23l2.61 7.418c11.429-6.015 17.444-13.835 20.05-22.257 2.605 6.418 6.816 11.629 11.629 16.441zM61.29 13.352H51.262L33.617 62.879h7.617l5.016-14.836H66.3l5.013 14.836h7.62zm-12.434 27.27 7.622-19.65 7.617 19.852zm0 0" fill="#a87c2d" stroke="#a87c2d" stroke-miterlimit="10" stroke-width="1.5039150000000001"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mobi.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#963}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7 6.4h3.3l1.2 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.2-6h3.3l.8 14.3H15l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.8 4.1h-2.9l-.8-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4H6.1L7 6.4zm16.9-.3c3.4 0 5.3 3.1 5.3 7.3 0 4.2-1.9 7.5-5.3 7.5s-5.3-3.2-5.3-7.5c.1-4.1 1.9-7.3 5.3-7.3zm0 11.7c1.5 0 2.2-1.8 2.2-4.3s-.7-4.2-2.2-4.2c-1.5 0-2.2 1.7-2.2 4.2s.7 4.3 2.2 4.3zm6.7-11.4h3.8c2.2 0 3.8 1.3 3.8 3.7 0 1.2-.5 2.4-1.5 3 1.5.5 1.9 1.9 1.9 3.2 0 3.1-1.8 4.3-4 4.3h-4V6.4zm3.8 5.6c.6 0 .8-.6.8-1.4s-.3-1.3-.9-1.3h-.7V12h.8zm.2 5.8c.7 0 1-.7 1-1.6 0-.9-.3-1.5-1-1.5h-1.1v3.1h1.1zM40 6.4h3v14.3h-3V6.4z" fill="#fff"/><path id="path1236" class="st0" d="M56.6 61.3c-.2-.5-.6-.9-1-1.3-.1.4-.2.8-.5 1.2L42.6 80.5c-.5.7-1.5.9-2.3.7l-20-5.6c-1.2-.3-2.6-1-2.7-2.4 0-.5 0-.7.3-.9.3-.2.6-.2.9-.1l18.8 5.2c2.7.8 3.5.2 5.5-2.8L54.5 57c.6-.9.7-2 .4-2.9-.3-.9-1.1-1.6-2.1-1.9l-16.5-4.6c-.4-.1-.8-.1-1.2-.1v-.1c-2.5-1.5-3.5 1.3-4.8 2.4-.5.4-1.1.7-1.3 1.1-.2.4-.1.8-.2 1.1-.5 1.1-1.9 2.9-2.6 3.4-.4.3-1 .4-1.3.9-.2.3-.2.9-.3 1.3-.4 1-1.7 2.7-2.6 3.5-.3.3-.8.5-1 .9-.2.3-.1.9-.4 1.2-.6 1-1.8 2.6-2.7 3.5-.5.5-1.1.7-1.3 1.2-.1.2 0 .6-.1.9-.2.5-.4.9-.5 1.3-.5.7-.8 1.7-.7 2.7.2 2.4 2 4.8 4.2 5.4l20 5.6c1.9.5 4.2-.4 5.2-2l11.5-17.7c.6-.8.7-1.9.4-2.8zm-23.1-6.4l.8-1.2c.2-.3.7-.5 1.1-.4L48.6 57c.4.1.5.5.3.8l-.8 1.2c-.2.3-.7.5-1.1.4l-13.2-3.7c-.4-.1-.5-.4-.3-.8zm-3.3 5l.8-1.2c.2-.3.7-.5 1.1-.4L45.3 62c.4.1.5.5.3.8l-.8 1.2c-.2.3-.7.5-1.1.4l-13.2-3.7c-.4-.1-.6-.5-.3-.8z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><path d="M69.723 24.898c-.336-.851-1.012-1.535-1.688-2.222-.168.687-.336 1.37-.844 2.054L46.098 57.723c-.844 1.199-2.532 1.539-3.88 1.199l-33.75-9.574c-2.023-.512-4.386-1.711-4.554-4.106 0-.851 0-1.195.504-1.535.508-.344 1.016-.344 1.52-.172l31.726 8.89c4.555 1.368 5.902.34 9.277-4.788l19.239-30.09a5.83 5.83 0 0 0 .675-4.957c-.507-1.54-1.855-2.735-3.543-3.246L35.47 1.48c-.676-.171-1.352-.171-2.024-.171v-.172c-4.218-2.563-5.906 2.222-8.101 4.101-.844.684-1.856 1.2-2.196 1.883-.336.684-.168 1.367-.336 1.879-.843 1.883-3.207 4.957-4.386 5.813-.676.515-1.688.683-2.196 1.539-.335.511-.335 1.539-.503 2.222-.676 1.711-2.872 4.617-4.387 5.985-.508.511-1.352.855-1.688 1.539-.34.511-.172 1.539-.675 2.05-1.012 1.711-3.04 4.446-4.559 5.985-.844.855-1.856 1.195-2.191 2.05-.168.34 0 1.028-.168 1.54-.34.855-.676 1.539-.844 2.222C.37 41.141-.137 42.852.03 44.56c.34 4.105 3.375 8.207 7.09 9.234l33.746 9.574c3.207.852 7.09-.683 8.778-3.422l19.402-30.258c1.016-1.367 1.183-3.25.676-4.789zm-38.98-10.941 1.35-2.05c.337-.512 1.18-.856 1.856-.684l22.274 6.324c.675.172.843.855.507 1.371l-1.351 2.05c-.336.512-1.18.856-1.856.684L31.25 15.328c-.676-.172-.844-.687-.508-1.371zm-5.567 8.55 1.347-2.054c.34-.512 1.184-.851 1.86-.683l22.273 6.328c.676.172.844.855.504 1.367l-1.347 2.05c-.34.512-1.184.856-1.856.684L25.68 23.875c-.672-.172-1.012-.855-.504-1.367zm0 0" fill="#963"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mod.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.3 6.5H10l1.9 6.9c.2.9.4 2.2.4 2.2h.1s.2-1.3.4-2.2l1.9-6.9h2.7l.9 14.2H16l-.5-7.9c-.1-.9 0-2.2 0-2.2h-.1s-.3 1.4-.5 2.3l-1.5 5.4H11l-1.5-5.4c-.2-.8-.5-2.3-.5-2.3h.1s.1 1.3 0 2.2l-.5 7.9H6.4l.9-14.2zm18.2-.3c3.5 0 5.7 3 5.7 7.3s-2.2 7.4-5.7 7.4-5.7-3.1-5.7-7.4c0-4.2 2.2-7.3 5.7-7.3zm0 12.4c2 0 3.2-2 3.2-5.1 0-3-1.2-4.9-3.2-4.9s-3.2 1.9-3.2 4.9c0 3.1 1.2 5.1 3.2 5.1zm7.6-12.1H37c3.5 0 5.7 2.6 5.7 7.1s-2.2 7.1-5.7 7.1h-3.9V6.5zm3.8 12c2.1 0 3.3-1.7 3.3-4.9s-1.3-4.9-3.3-4.9h-1.4v9.8h1.4z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mov.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7 6.4h3.3l1.2 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.2-6h3.3l.8 14.3H15l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.8 4.1h-2.9l-.8-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4H6.1L7 6.4zm18.3-.3c3.4 0 5.3 3.1 5.3 7.3 0 4.2-1.9 7.5-5.3 7.5S20 17.7 20 13.4c0-4.1 1.9-7.3 5.3-7.3zm0 11.7c1.5 0 2.2-1.8 2.2-4.3s-.7-4.2-2.2-4.2S23 11 23 13.5s.7 4.3 2.3 4.3zM32 6.4h3.2l1.5 8.1c.2.9.3 2.3.3 2.3s.1-1.4.3-2.3l1.5-8.1H42l-3.5 14.3h-3L32 6.4z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mp2.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.1 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm7.6 5.7c0-5 4.5-5.5 4.5-8.4 0-1-.5-1.4-1.2-1.4-.6 0-1.1.3-1.4.8l-2.2-1.8c.8-1.1 2.3-2.1 4.1-2.1 2.1 0 4.2 1.3 4.2 4.2 0 4.1-4.2 5.4-4.4 7.5h4.6v2.9H34c-.3-.7-.3-1.1-.3-1.7z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mp3.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.1 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm8.7 3.6c.4.4 1.1.7 1.7.7.9 0 1.6-.4 1.6-1.6 0-1-.7-1.5-2.3-1.5h-.9l-.7-1.8 2-2.5c.5-.6.9-1 .9-1s-.4.1-1.1.1h-2.3v-3h7.2V9l-2.6 3.1c2 .5 3.1 2.1 3.1 4.1 0 2.4-1.4 4.8-4.7 4.8-1.3 0-2.5-.4-3.5-1.3l1.6-2.7z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mp4.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.1 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm6.8 1.8l3.7-8.8h4.2v8.1H42v3h-1.2v3.2h-3.2v-3.2h-4.7v-2.3zm4.7-.7v-3.4c0-.8.1-1.3.1-1.3s-.1.6-.3 1.2L36 14.5h1.6z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mpa.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm14.6 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H25v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2H25v4.1h.6zm9.1-7h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.6 2.8h2.1z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mpd.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm14.1 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm6.8-7h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zM36 17.8c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z"/><path class="st0" d="M17.1 51.3l21.3-4.1V83l-21.3-3.9z"/><path class="st0" d="M53.3 79.5H35.2c-.9 0-1.6-.7-1.6-1.6V52.4c0-.9.7-1.6 1.6-1.6h18.1c.9 0 1.6.7 1.6 1.6v25.5c0 .9-.7 1.6-1.6 1.6zM35.2 52.3c-.1 0-.2.1-.2.2V78c0 .1.1.2.2.2h18.1c.1 0 .2-.1.2-.2V52.4c0-.1-.1-.2-.2-.2 0 .1-18.1.1-18.1.1z"/><path class="st0" d="M50.7 66.4h-2.4V58H37.2v-2.4h13.5z"/><path class="st0" d="M49.4 68.5l-4.3-4.7h8.5z"/><path transform="rotate(-45.001 42.925 71.003)" class="st0" d="M39.7 67.8h6.5v6.5h-6.5z"/><path class="st1" d="M30.4 59.7c-.4-.4-.8-.6-1.4-.8-.5-.2-1.2-.1-1.8-.1-1.2 0-3.3.2-3.3.2l-.1 11.6 2.2.2v-4.1s1.3.2 2.4-.1c.6-.2 1.2-.5 1.5-.8.4-.4.7-.8.9-1.2.3-.6.4-1.2.4-2.1.2-1.1-.1-2.1-.8-2.8zm-1.7 4c-.4.9-1.5.9-1.5.9H26v-3.7s.8-.1 1.4 0c.3.1.6.2.8.3.6.5.9 1.7.5 2.5z"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M0 7.336 37.754.008v63.984L0 57.02zm0 0"/><path d="M64.164 57.734H32.082c-1.594 0-2.836-1.25-2.836-2.859V9.305c0-1.61 1.242-2.864 2.836-2.864h32.082C65.758 6.441 67 7.695 67 9.305v45.57c0 1.61-1.242 2.86-2.836 2.86zM32.082 9.125c-.176 0-.355.18-.355.355v45.575c0 .18.18.36.355.36h32.082c.176 0 .356-.18.356-.36V9.305c0-.18-.18-.36-.356-.36 0 .18-32.082.18-32.082.18zm0 0"/><path d="M59.555 34.324H55.3V19.313H35.629v-4.29h23.926zm0 0"/><path d="m57.25 38.078-7.621-8.402h15.066zM37.719 42.578l8.144-8.215 8.149 8.215-8.149 8.215zm0 0"/></g><path d="M23.574 22.348c-.71-.715-1.418-1.07-2.48-1.43-.887-.355-2.13-.176-3.192-.176-2.129 0-5.847.356-5.847.356l-.18 20.73 3.898.36v-7.329s2.305.36 4.254-.18c1.067-.355 2.13-.89 2.66-1.429.711-.715 1.243-1.43 1.594-2.145.535-1.07.711-2.144.711-3.753.356-1.965-.176-3.75-1.418-5.004zm-3.012 7.148c-.71 1.61-2.66 1.61-2.66 1.61h-2.129v-6.614s1.418-.176 2.485 0c.531.18 1.062.36 1.418.54 1.062.89 1.594 3.034.886 4.464zm0 0" fill="#fff"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mpe.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.1 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm7.8-7h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mpeg.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.8-34.6h2.9l1.1 6c.2.9.3 2.4.3 2.4s.2-1.5.3-2.4l1.1-6h2.9l.7 14.3h-2.4l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.7 4.1H9.9l-.7-4.1c-.2-.9-.4-2.4-.4-2.4s.1 1.3 0 2.4l-.3 6.4H6l.8-14.3zm11.2 0h3.6c2.1 0 3.5 2 3.5 4.9 0 2.9-1.4 5-3.5 5h-1v4.4H18V6.4zm3.2 7c.8 0 1.3-.9 1.3-2.1s-.5-2-1.2-2h-.5v4.1h.4zm5.4-7h5.7v2.9h-3.1V12h2.5v2.9h-2.5v2.9h3.3v2.9h-5.9V6.4zm12-.3c1.1 0 2.3.4 3.2 1.3l-1.1 2.8c-.4-.6-1.1-.9-1.9-.9-1.8 0-2.5 1.9-2.5 4.2 0 2.6 1 4.3 2.3 4.3.5 0 1-.2 1.4-.6v-1.7h-1.2v-2.9h3.5v8.1h-2v-.9c-.4.7-1.3 1.2-2.2 1.2-2.2 0-4.5-2.7-4.5-7.3 0-4.5 1.9-7.6 5-7.6z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mpg.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7 6.4h3.5l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.5l.9 14.3h-2.9l-.5-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.8 4.1h-3l-.8-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4L9 20.7H6.1L7 6.4zm14.3 0h4.3c2.5 0 4.1 2 4.1 4.9 0 2.9-1.7 5-4.1 5h-1.2v4.4h-3.1V6.4zm3.7 7c1 0 1.5-.9 1.5-2.1s-.6-2-1.5-2h-.6v4.1h.6zm12.9-7.3c1.3 0 2.8.4 3.7 1.3l-1.3 2.8c-.5-.6-1.3-.9-2.2-.9-2.1 0-3 1.9-3 4.2 0 2.6 1.1 4.3 2.7 4.3.6 0 1.2-.2 1.6-.6v-1.7H38v-2.9h4.1v8.1h-2.4v-.9c-.5.7-1.5 1.2-2.6 1.2-2.6 0-5.3-2.7-5.3-7.3.1-4.5 2.5-7.6 6.1-7.6z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mpga.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7 6.5h2.2l1.6 6.9c.2.9.4 2.2.4 2.2s.2-1.3.4-2.2l1.6-6.9h2.2l.7 14.2h-1.9l-.4-7.9v-2.2s-.2 1.4-.4 2.3l-1.3 5.4h-2L9 12.9c-.2-.8-.4-2.3-.4-2.3h-.1s.1 1.3 0 2.2l-.4 7.9H6.2L7 6.5zm11 0h3.4c2.1 0 3.5 1.9 3.5 4.6s-1.4 4.7-3.5 4.7H20v4.9h-2V6.5zm3 7.1c1.1 0 1.8-1 1.8-2.5s-.7-2.5-1.7-2.5h-1v5h.9zm9.8-7.4c1.1 0 2.3.4 3.1 1.2L33 9.6c-.5-.6-1.3-1-2.2-1-2 0-3.1 2.1-3.1 5 0 3.1 1.3 5 2.9 5 .7 0 1.4-.3 1.9-1v-2.2h-1.3v-2.2h3.1v7.5h-1.6v-1c-.5.8-1.4 1.3-2.5 1.3-2.4 0-4.6-2.7-4.6-7.3.1-4.5 2.1-7.5 5.2-7.5zm7.4.3h2.2l3.1 14.2h-2l-.7-3.7h-2.9l-.7 3.7h-2l3-14.2zm2.2 8.5l-.7-3.8c-.2-.8-.4-2.2-.4-2.2s-.2 1.4-.3 2.2l-.8 3.8h2.2z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mpp.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#2d7136}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.1 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm7.8-7h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z"/><path class="st0" d="M17.1 52.3l21.3-4.1V84l-21.3-3.9z"/><path class="st0" d="M53.3 80.5H35.2c-.9 0-1.6-.7-1.6-1.6V53.4c0-.9.7-1.6 1.6-1.6h18.1c.9 0 1.6.7 1.6 1.6v25.5c0 .9-.7 1.6-1.6 1.6zM35.2 53.3c-.1 0-.2.1-.2.2V79c0 .1.1.2.2.2h18.1c.1 0 .2-.1.2-.2V53.4c0-.1-.1-.2-.2-.2 0 .1-18.1.1-18.1.1z"/><path class="st0" d="M50.7 67.4h-2.4V59H37.2v-2.4h13.5z"/><path class="st0" d="M49.4 69.5l-4.3-4.7h8.5z"/><path transform="rotate(-45.001 42.925 72.003)" class="st0" d="M39.7 68.8h6.5v6.5h-6.5z"/><path class="st1" d="M30.4 60.7c-.4-.4-.8-.6-1.4-.8-.5-.2-1.2-.1-1.8-.1-1.2 0-3.3.2-3.3.2l-.1 11.6 2.2.2v-4.1s1.3.2 2.4-.1c.6-.2 1.2-.5 1.5-.8.4-.4.7-.8.9-1.2.3-.6.4-1.2.4-2.1.2-1.1-.1-2.1-.8-2.8zm-1.7 4c-.4.9-1.5.9-1.5.9H26v-3.7s.8-.1 1.4 0c.3.1.6.2.8.3.6.5.9 1.7.5 2.5z"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><g fill="#2d7136"><path d="M0 7.336 37.754.008v63.984L0 57.02zm0 0"/><path d="M64.164 57.734H32.082c-1.594 0-2.836-1.25-2.836-2.859V9.305c0-1.61 1.242-2.864 2.836-2.864h32.082C65.758 6.441 67 7.695 67 9.305v45.57c0 1.61-1.242 2.86-2.836 2.86zM32.082 9.125c-.176 0-.355.18-.355.355v45.575c0 .18.18.36.355.36h32.082c.176 0 .356-.18.356-.36V9.305c0-.18-.18-.36-.356-.36 0 .18-32.082.18-32.082.18zm0 0"/><path d="M59.555 34.324H55.3V19.313H35.629v-4.29h23.926zm0 0"/><path d="m57.25 38.078-7.621-8.402h15.066zM37.719 42.578l8.144-8.215 8.149 8.215-8.149 8.215zm0 0"/></g><path d="M23.574 22.348c-.71-.715-1.418-1.07-2.48-1.43-.887-.355-2.13-.176-3.192-.176-2.129 0-5.847.356-5.847.356l-.18 20.73 3.898.36v-7.329s2.305.36 4.254-.18c1.067-.355 2.13-.89 2.66-1.429.711-.715 1.243-1.43 1.594-2.145.535-1.07.711-2.144.711-3.753.356-1.965-.176-3.75-1.418-5.004zm-3.012 7.148c-.71 1.61-2.66 1.61-2.66 1.61h-2.129v-6.614s1.418-.176 2.485 0c.531.18 1.062.36 1.418.54 1.062.89 1.594 3.034.886 4.464zm0 0" fill="#fff"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/mpt.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#2d7136}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.1 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm10.1-4.1H33V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z"/><path class="st0" d="M17.1 52.3l21.3-4.1V84l-21.3-3.9z"/><path class="st0" d="M53.3 80.5H35.2c-.9 0-1.6-.7-1.6-1.6V53.4c0-.9.7-1.6 1.6-1.6h18.1c.9 0 1.6.7 1.6 1.6v25.5c0 .9-.7 1.6-1.6 1.6zM35.2 53.3c-.1 0-.2.1-.2.2V79c0 .1.1.2.2.2h18.1c.1 0 .2-.1.2-.2V53.4c0-.1-.1-.2-.2-.2 0 .1-18.1.1-18.1.1z"/><path class="st0" d="M50.7 67.4h-2.4V59H37.2v-2.4h13.5z"/><path class="st0" d="M49.4 69.5l-4.3-4.7h8.5z"/><path transform="rotate(-45.001 42.925 72.003)" class="st0" d="M39.7 68.8h6.5v6.5h-6.5z"/><path class="st1" d="M30.4 60.7c-.4-.4-.8-.6-1.4-.8-.5-.2-1.2-.1-1.8-.1-1.2 0-3.3.2-3.3.2l-.1 11.6 2.2.2v-4.1s1.3.2 2.4-.1c.6-.2 1.2-.5 1.5-.8.4-.4.7-.8.9-1.2.3-.6.4-1.2.4-2.1.2-1.1-.1-2.1-.8-2.8zm-1.7 4c-.4.9-1.5.9-1.5.9H26v-3.7s.8-.1 1.4 0c.3.1.6.2.8.3.6.5.9 1.7.5 2.5z"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><g fill="#2d7136"><path d="M0 7.336 37.754.008v63.984L0 57.02zm0 0"/><path d="M64.164 57.734H32.082c-1.594 0-2.836-1.25-2.836-2.859V9.305c0-1.61 1.242-2.864 2.836-2.864h32.082C65.758 6.441 67 7.695 67 9.305v45.57c0 1.61-1.242 2.86-2.836 2.86zM32.082 9.125c-.176 0-.355.18-.355.355v45.575c0 .18.18.36.355.36h32.082c.176 0 .356-.18.356-.36V9.305c0-.18-.18-.36-.356-.36 0 .18-32.082.18-32.082.18zm0 0"/><path d="M59.555 34.324H55.3V19.313H35.629v-4.29h23.926zm0 0"/><path d="m57.25 38.078-7.621-8.402h15.066zM37.719 42.578l8.144-8.215 8.149 8.215-8.149 8.215zm0 0"/></g><path d="M23.574 22.348c-.71-.715-1.418-1.07-2.48-1.43-.887-.355-2.13-.176-3.192-.176-2.129 0-5.847.356-5.847.356l-.18 20.73 3.898.36v-7.329s2.305.36 4.254-.18c1.067-.355 2.13-.89 2.66-1.429.711-.715 1.243-1.43 1.594-2.145.535-1.07.711-2.144.711-3.753.356-1.965-.176-3.75-1.418-5.004zm-3.012 7.148c-.71 1.61-2.66 1.61-2.66 1.61h-2.129v-6.614s1.418-.176 2.485 0c.531.18 1.062.36 1.418.54 1.062.89 1.594 3.034.886 4.464zm0 0" fill="#fff"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/msg.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1d6fb5}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.3 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L28 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.5-2.8zM37.6 6.1c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9H42v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.6-7.6 6.5-7.6z" fill="#fff"/><path d="M21.9 77.2h28.3l-9.7-9.3-4.5 3.8-4.5-3.8-9.6 9.3zM56 52v28H16V52h40zM42.6 66.2l10.7 10.3V57.2l-10.7 9zM18.4 76.5l10.7-10.3-10.7-9v19.3zm1.4-21.7l15.9 13.4 15.9-13.4H19.8z" fill="#1d6fb5" stroke="#1d6fb5" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="fill-rule:nonzero;fill:#1d6fb5;fill-opacity:1;stroke-width:.75;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1d6fb5;stroke-opacity:1;stroke-miterlimit:10" d="M6.274 25.574h28.3l-9.698-9.3-4.501 3.802-4.5-3.802zm34.1-25.2v28.002H.376V.374zM26.976 14.576l10.7 10.298v-19.3zm-24.2 10.298 10.7-10.298-10.7-9.002zm1.4-21.7 15.9 13.4 15.9-13.4zm0 0" transform="matrix(2.06135 0 0 2.08166 0 .076)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/msi.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#4d1b9b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.8 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10-10.3h3.3v14.3h-3.3V6.4z" fill="#fff"/><path class="st0" d="M43.6 68.3l-7.3-3.4L51 58l7.3 3.4-7.3 3.5-7.4 3.4zM51 51.2l-7.3-3.4-7.3 3.4L51 58.1l7.3-3.4-7.3-3.5zM28.9 61.4L21.6 58l-7.3 3.4L29 68.3l7.3-3.4-7.4-3.5zm0-6.8l7.3-3.4-7.3-3.4-14.7 6.9 7.3 3.4 7.4-3.5zM51 66.9l-6.6 3-.8.4-.8-.4-6.6-3-6.6 3-.8.4-.8-.4-6.6-3v10.7l14.7 7.7L51 77.6V66.9z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#4d1b9b"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/msu.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#55486d}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM7.1 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H18l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H11l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3zm15.3 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L28 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.5-2.8zm9.4-10.3H35V16c0 1.4.6 1.9 1.5 1.9S38 17.4 38 16V6.4h3.3V16c0 3-1.9 4.9-4.7 4.9-2.9 0-4.8-1.9-4.8-4.9V6.4z" fill="#fff"/><path class="st0" d="M43.6 68.3l-7.3-3.4L51 58l7.3 3.4-7.3 3.5-7.4 3.4zM51 51.2l-7.3-3.4-7.3 3.4L51 58.1l7.3-3.4-7.3-3.5zM28.9 61.4L21.6 58l-7.3 3.4L29 68.3l7.3-3.4-7.4-3.5zm0-6.8l7.3-3.4-7.3-3.4-14.7 6.9 7.3 3.4 7.4-3.5zM51 66.9l-6.6 3-.8.4-.8-.4-6.6-3-6.6 3-.8.4-.8-.4-6.6-3v10.7l14.7 7.7L51 77.6V66.9z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#55486d"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/nef.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6H6.6V6.4zm13.3 0h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4zm10.5 0h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/nes.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#ff141f}.st2{fill:#ff0021}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6H6.6V6.4zm13.3 0h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4zm11.2 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path class="st2" d="M45.3 48.8h-7.7v34h7.7c4.2 0 7.7-3.4 7.7-7.7V56.4c0-4.2-3.4-7.6-7.7-7.6zm0 22c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4zm-9.6 12h-9c-4.2 0-7.7-3.4-7.7-7.7V56.4c0-4.3 3.4-7.7 7.7-7.7h9v34.1zm-9-32c-3.1 0-5.7 2.5-5.7 5.7v18.7c0 3.1 2.5 5.7 5.7 5.7h7.1V50.8h-7.1z"/><path class="st2" d="M27.3 62.8c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#ff0021"><path d="M49.453.188h-14.45V64h14.45c7.883 0 14.453-6.383 14.453-14.453V14.453C63.906 6.57 57.523.188 49.453.188zm0 41.289c-4.129 0-7.508-3.375-7.508-7.508 0-4.13 3.38-7.504 7.508-7.504s7.508 3.375 7.508 7.504c0 4.133-3.379 7.508-7.508 7.508zM31.437 64h-16.89C6.664 64 .094 57.617.094 49.547V14.453C.094 6.383 6.477 0 14.547 0h16.89zM14.547 3.941c-5.82 0-10.7 4.692-10.7 10.7v35.093c0 5.82 4.692 10.7 10.7 10.7H27.87V3.94zm0 0"/><path d="M15.672 26.465c-4.129 0-7.508-3.38-7.508-7.508 0-4.129 3.379-7.508 7.508-7.508s7.508 3.38 7.508 7.508c0 4.129-3.38 7.508-7.508 7.508zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/nfo.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6H6.6V6.4zm13.3 0H27v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4zm15.3-.3c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2.1-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3z" fill="#fff"/><path d="M58 47.3v4.2H14.4v-4.2m43.2 10.1v4.2H14v-4.2M57.6 68v4.1H14V68m43.6 10.5v4.2H14v-4.2" fill="#bababa" stroke="#bababa" stroke-miterlimit="10"/><path d="M29.8 60.9v-1.8c.5-.2 1.2-.4 2.2-.7.9-.3 1.8-.4 2.8-.6 1-.2 2-.3 2.9-.4.9-.1 1.8-.2 2.6-.2l.9.6-4.8 22.8h3.7v1.9c-.4.3-1 .6-1.6.9-.6.3-1.3.5-2 .8-.7.3-1.4.4-2.1.5-.7.1-1.4.2-2 .2-1.4 0-2.2-.3-2.8-.8-.4-.5-.6-1.1-.6-1.7 0-.7.1-1.4.2-2.1.1-.7.3-1.4.4-2.2l3.6-16.4-3.4-.8zm4.5-12c0-1.2.4-2.2 1.2-2.8.8-.7 1.8-1 3.1-1 1.4 0 2.4.3 3.2 1 .8.7 1.2 1.6 1.2 2.8 0 1.1-.4 2.1-1.2 2.7-.8.7-1.9 1-3.2 1-1.2 0-2.2-.3-3.1-1-.7-.6-1.2-1.5-1.2-2.7z" fill="#bababa" stroke="#fff" stroke-width="3" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="66" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa" stroke-miterlimit="10"><path d="M58 47.3v4.2H14.4v-4.2m43.2 10.1V61.6H14V57.4M57.6 68v4.1H14V68M57.6 78.5v4.2H14v-4.2" stroke="#bababa" transform="matrix(1.46667 0 0 1.48837 -19.8 -64.744)"/><path d="M29.8 60.9v-1.8c.5-.2 1.2-.399 2.2-.7.9-.3 1.8-.4 2.799-.599 1.001-.202 2-.302 2.9-.402.9-.1 1.8-.2 2.602-.2l.898.602-4.8 22.8h3.7v1.9c-.4.298-.999.6-1.598.9-.602.299-1.3.498-2 .8-.7.3-1.401.399-2.102.499-.7.1-1.398.199-2 .199-1.398 0-2.2-.3-2.799-.798-.4-.501-.6-1.102-.6-1.7 0-.701.1-1.402.2-2.1.099-.7.299-1.402.4-2.202L33.2 61.7zm4.5-11.999c0-1.202.4-2.202 1.2-2.8.801-.7 1.8-1 3.1-1 1.4 0 2.4.3 3.2 1 .8.698 1.2 1.598 1.2 2.8 0 1.1-.4 2.1-1.2 2.698-.8.701-1.9 1-3.2 1-1.2 0-2.2-.299-3.1-1-.701-.598-1.2-1.498-1.2-2.698zm0 0" stroke="#fff" stroke-width="3" transform="matrix(1.46667 0 0 1.48837 -19.8 -64.744)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/nix.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6H6.6V6.4zm13.3 0h3.3v14.3h-3.3V6.4zm9.3 7.2l-3.4-7.2h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6L33 13.6l3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.3-7.1z" fill="#fff"/><path class="st0" d="M14 48.9h37v4.3H14zm7 9.6h37v4.3H21zm-7 9.6h37v4.3H14zm7 9.6h37V82H21z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#666;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/npmignore.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm2.5 10c-8-8-21-8-29 0s-8 21 0 29 21 8 29 0 8-21 0-29zM23.3 58.7c-3.8-5.9-3.1-13.8 2-18.9s13-5.8 18.9-2L23.3 58.7zm4.5 4.5l20.9-20.9c3.8 5.9 3.1 13.8-2 18.9s-13 5.8-18.9 2z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M54.633 9.367C42.145-3.12 21.855-3.12 9.367 9.367s-12.488 32.778 0 45.266 32.778 12.488 45.266 0 12.488-32.778 0-45.266zM12.176 44.801c-5.934-9.211-4.84-21.543 3.12-29.504s20.294-9.055 29.505-3.121zm7.023 7.023L51.824 19.2c5.934 9.211 4.84 21.543-3.12 29.504s-20.294 9.055-29.505 3.121zm0 0" fill="#bababa"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ocx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.9-34.9c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zM26.2 6.1c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4zm8.4 7.5l-3.4-7.2h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.2-7.1z" fill="#fff"/><path class="st0" d="M52.4 58.4c1.7-4.2 1.9-7.6-.2-9.7-2.3-2.3-7.9-1.6-13.8 1.2h-.7c-4.2 0-8.2 1.5-11.2 4.2-2.5 2.3-4.4 5.3-5.2 8.7.6-.7 3.8-4.5 7.5-6.6.1 0 1-.6 1-.6-.1 0-1.9 1.7-2.2 2.1-8.1 8.3-12.8 20.9-9.1 24.6 2.4 2.4 6.8 1.9 11.9-.9 2.2 1 4.6 1.5 7.3 1.5 3.5 0 6.7-.9 9.5-2.8 2.9-1.9 5-4.7 6.2-8.1h-9c-1.2 2.2-3.8 3.7-6.6 3.7-3.9 0-7.2-3.2-7.3-6.9v-.3h23.6V68c0-.6.1-1.3.1-1.7 0-2.8-.6-5.5-1.8-7.9zM21.1 81.5c-1.9-1.9-1.3-5.4.9-9.7 1 2.9 2.8 5.4 5 7.3.7.6 1.5 1.2 2.3 1.6-3.7 2-6.7 2.3-8.2.8zm23.7-17.6H30.7v-.1c.2-3.6 3.6-6.7 7.5-6.7 3.7 0 6.7 2.9 6.9 6.7v.1h-.3zm7-6.4c-.7-1.2-1.6-2.3-2.7-3.2-1.6-1.5-3.5-2.7-5.6-3.5 3.7-1.7 6.8-2 8.4-.3 1.4 1.4 1.3 3.9-.1 7 0 .1 0 .1 0 0 0 .1 0 .1 0 0z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M60.887 19.578c2.941-7.27 3.285-13.152-.348-16.789C56.56-1.19 46.867.02 36.656 4.867h-1.21c-7.27 0-14.192 2.598-19.383 7.27-4.325 3.98-7.614 9.172-9 15.054 1.039-1.21 6.578-7.789 12.98-11.421.172 0 1.73-1.04 1.73-1.04-.171 0-3.289 2.942-3.808 3.637C3.949 32.73-4.184 54.535 2.219 60.937c4.152 4.153 11.765 3.29 20.593-1.558 3.81 1.73 7.961 2.598 12.633 2.598 6.059 0 11.594-1.559 16.442-4.848 5.02-3.285 8.652-8.133 10.73-14.016H47.04c-2.074 3.809-6.574 6.403-11.422 6.403-6.746 0-12.457-5.54-12.633-11.942v-.52h40.844v-.863c0-1.039.172-2.25.172-2.941 0-4.848-1.04-9.52-3.113-13.672zM6.719 59.555c-3.29-3.29-2.25-9.348 1.554-16.79 1.735 5.02 4.848 9.348 8.657 12.633 1.21 1.04 2.593 2.079 3.98 2.77-6.406 3.46-11.598 3.98-14.191 1.387zm41.015-30.461H23.332v-.172c.344-6.23 6.23-11.594 12.98-11.594 6.403 0 11.594 5.02 11.938 11.594v.172zM59.848 18.02c-1.211-2.079-2.77-3.98-4.672-5.54a29.6 29.6 0 0 0-9.692-6.054c6.403-2.942 11.766-3.461 14.536-.52 2.421 2.422 2.25 6.75-.172 12.114 0 .171 0 .171 0 0zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/odb.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#a03537}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.9-34.9c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm8.5-11.4h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm8.6-11.4h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1z" fill="#fff"/><path class="st0" d="M-4938.1 722.8c-4.8-.2-9.1-1.7-11.4-4-.7-.6-1.4-1.5-1.7-2.1l-.2-.4v-4.5c0-4.5 0-4.5.1-4.1.2 1 .8 2 1.7 2.8.6.5 1.8 1.4 2.8 1.9 1.7.9 3.9 1.5 6.2 1.8 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.5-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.2.4c-.7 1.4-1.9 2.6-3.5 3.6-3.1 1.8-7.8 2.8-12.4 2.6zm0-11.2c-4.2-.2-8.1-1.4-10.6-3.2-.6-.4-1.4-1.2-1.7-1.6-.3-.4-.6-.9-.8-1.4l-.2-.4v-4.4c0-4.4 0-4.4.1-4.1.2.7.5 1.5 1.1 2.1.3.4.8.9 1.1 1.1.1.1.4.2.6.4 2 1.4 4.8 2.4 8 2.9 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.4-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.3.6c-.5.9-.8 1.4-1.4 2-.6.6-1.2 1.1-2 1.5-3.2 1.8-7.9 2.8-12.5 2.5zm-.3-11.1c-2.8-.2-5-.7-7.1-1.5-2.5-1-4.3-2.3-5.2-3.9-.2-.3-.4-.7-.5-1.2-.1-.4-.2-1.4-.1-2 .6-3.2 4.9-5.8 10.7-6.7 1.4-.2 1.9-.2 3.9-.2s2.5 0 3.9.2c2.3.3 4.4 1 6.2 1.8 2.6 1.3 4.2 3 4.5 4.8.1.5.1 1.6-.1 2-.3 1-.7 1.6-1.5 2.4-2.1 2.2-5.8 3.6-10.4 4.1-.6.2-3.7.2-4.3.2z" transform="translate(4973.037 -638.07)"/><path d="M38.5 55.7h1.7c2.5.2 4.5.8 6.5 1.6 3.7-1.7 9.1-.4 12.4.9-4.3-.4-9.3 0-12.2 1.7-2.9-2.4-8.5-3-13.7-2.4 1.4-1 3.1-1.5 5.3-1.8zm-1.3 6.6c-3 .2-5.5 1.2-7.2 2.6-5-2.3-13.7-1.3-17 1.8-.3.2-.6.4-.5.7 2.8-.9 6.3-1.6 9.9-1.3 3.5.3 6.2 1.5 8.2 3.1 3.6-3.3 9-5.1 15.9-5-2.4-1.4-5.8-2.3-9.3-1.9z" fill="#a03537" stroke="#fff" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><g fill="#a03537"><path d="M38.684 63.957c-8.098-.34-15.356-2.875-19.239-6.77-1.183-1.011-2.363-2.535-2.87-3.55l-.337-.676v-7.617c0-7.614 0-7.614.168-6.934.34 1.692 1.352 3.383 2.871 4.735 1.012.847 3.035 2.37 4.723 3.214 2.871 1.524 6.586 2.54 10.465 3.047 2.363.34 3.207.34 6.582.34s4.223 0 6.582-.34c3.883-.508 7.43-1.691 10.465-3.047 1.687-.843 3.715-2.199 4.726-3.214 1.352-1.352 2.532-3.043 2.871-4.735.168-.508.168-.508.168 6.934v7.445l-.34.68c-1.18 2.367-3.207 4.398-5.906 6.09-5.23 3.046-13.164 4.738-20.93 4.398zm0-18.95c-7.086-.339-13.668-2.37-17.887-5.413-1.016-.68-2.363-2.032-2.871-2.707a10.877 10.877 0 0 1-1.352-2.371l-.336-.676v-7.445c0-7.446 0-7.446.168-6.938.34 1.184.844 2.54 1.856 3.555.508.675 1.351 1.523 1.86 1.86.167.171.675.339 1.01.679 3.376 2.367 8.102 4.058 13.5 4.906 2.364.336 3.208.336 6.587.336 3.375 0 4.218 0 6.582-.336 3.879-.508 7.426-1.691 10.46-3.047 1.692-.847 3.716-2.2 4.727-3.215 1.352-1.351 2.364-3.047 2.871-4.738.168-.508.168-.508.168 6.938v7.445l-.507 1.015c-.844 1.524-1.348 2.368-2.364 3.383-1.011 1.016-2.023 1.864-3.375 2.54-5.398 3.046-13.332 4.738-21.097 4.23zm-.504-18.78c-4.727-.34-8.438-1.184-11.985-2.54-4.218-1.69-7.257-3.89-8.777-6.597a5.733 5.733 0 0 1-.844-2.031c-.168-.676-.336-2.368-.168-3.383C17.418 6.262 24.676 1.859 34.465.34 36.828 0 37.672 0 41.047 0s4.223 0 6.582.34c3.883.508 7.43 1.691 10.465 3.043 4.39 2.199 7.09 5.078 7.597 8.12.168.849.168 2.708-.171 3.388-.504 1.691-1.18 2.707-2.532 4.058-3.543 3.723-9.789 6.094-17.55 6.938-1.016.34-6.247.34-7.258.34zm0 0"/><path d="M38.5 55.7h1.7c2.501.2 4.5.8 6.5 1.6 3.699-1.7 9.1-.399 12.399.9-4.298-.4-9.3 0-12.2 1.7-2.9-2.4-8.498-2.999-13.699-2.4 1.4-1 3.1-1.5 5.3-1.8zm-1.3 6.601c-3 .199-5.5 1.198-7.2 2.6-5-2.302-13.7-1.3-17 1.798-.299.201-.6.402-.5.702 2.8-.9 6.3-1.6 9.901-1.302 3.5.3 6.198 1.5 8.2 3.1 3.6-3.299 8.999-5.1 15.898-5-2.4-1.4-5.8-2.3-9.3-1.898zm0 0" stroke="#fff" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.68776 0 0 1.692 -20.28 -79.405)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ods.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1f7244}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.9-34.9c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm8-11.4h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zM24 17.8c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm8.8-1.1c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.3-.5-1.3-.9-2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8z" fill="#fff"/><path class="st0" d="M46 53.1h11.4v7.6H46v-7.6zm0 11.7h11.4v7.6H46v-7.6zm0 11.6h11.4V84H46v-7.6zm-15.5 0H42V84H30.5v-7.6zm-15.4 0h11.4V84H15.1v-7.6zM35 48h1.6c2.4.2 4.3.8 6.2 1.5 3.6-1.6 8.6-.4 11.8.8-4-.4-8.8 0-11.6 1.6-2.8-2.3-8.1-2.9-13-2.3 1.4-.8 3.1-1.4 5-1.6zm-1.1 6.1c-2.9.2-5.3 1.1-6.8 2.4-4.8-2.2-13-1.2-16.1 1.7-.3.2-.6.4-.5.7 2.7-.8 6-1.5 9.4-1.2s5.9 1.4 7.8 2.9c3.5-3.1 8.6-4.9 15.1-4.8-2.3-1-5.6-1.9-8.9-1.7zm-3.3 10.8H42v7.6H30.6v-7.6zm-15.4 0h11.4v7.6H15.2v-7.6z"/></svg>
1
<svg height="64" width="83" xmlns="http://www.w3.org/2000/svg"><path d="M62.797 9.066H82.93v13.512H62.797zm0 20.801H82.93V43.38H62.797zm0 20.621H82.93V64H62.797zm-27.371 0h20.308V64H35.426zm-27.196 0h20.13V64H8.23zM43.371 0h2.824c4.239.355 7.594 1.422 10.95 2.668 6.359-2.848 15.187-.711 20.84 1.422-7.063-.711-15.54 0-20.485 2.844-4.945-4.09-14.305-5.157-22.957-4.09A22.506 22.506 0 0 1 43.371 0zM41.43 10.844c-5.121.355-9.36 1.957-12.008 4.265C20.945 11.2 6.465 12.977.988 18.133c-.531.355-1.058.71-.883 1.246 4.77-1.422 10.598-2.668 16.602-2.133 6.004.531 10.418 2.488 13.773 5.152 6.18-5.507 15.188-8.71 26.665-8.53-4.06-1.778-9.887-3.38-15.715-3.024zm-5.828 19.199h20.132v13.512H35.602zm-27.196 0H28.54v13.512H8.406zm0 0" fill="#1f7244"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/odt.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2{fill:#1a75ce}.st2{stroke:#1a75ce;stroke-width:.5;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.9-34.9c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm9-11.4h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zM25 17.8c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm10.6-8.5h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path class="st2" d="M43.4 59.6h15.8v2.5H43.4zm-30.9 6.9h46.7v2.8H12.5zm0 6.8h46.7v2.8H12.5z"/><path class="st0" d="M38.7 48.2h1.7c2.6.2 4.6.8 6.6 1.6 3.8-1.7 9.2-.4 12.6.9-4.3-.4-9.4 0-12.4 1.7-3-2.4-8.6-3.1-13.9-2.4 1.5-1 3.3-1.6 5.4-1.8zm-1.2 6.5c-3.1.2-5.6 1.2-7.3 2.6C25.1 55 16.3 56 13 59.1c-.3.2-.6.4-.5.7 2.9-.9 6.4-1.6 10-1.3 3.6.3 6.3 1.5 8.3 3.1 3.7-3.3 9.2-5.2 16.1-5.1-2.4-1.1-5.9-2-9.4-1.8z"/><path class="st2" d="M12.5 80h46.7v2.8H12.5z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M43.399 59.6h15.802v2.498H43.399zm-30.9 6.902h46.702V69.3H12.499zm0 6.799h46.702v2.798H12.499zm0 0" transform="matrix(1.7529 0 0 1.7867 -21.473 -85.752)"/><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="M46.363.363h2.985c4.554.36 8.058 1.434 11.566 2.864C67.574.187 77.043 2.512 83 4.832c-7.54-.715-16.477 0-21.738 3.04-5.258-4.286-15.075-5.54-24.364-4.286 2.63-1.79 5.786-2.863 9.465-3.223zM44.262 11.98c-5.434.36-9.82 2.145-12.797 4.649-8.942-4.113-24.367-2.324-30.149 3.21-.527.36-1.054.72-.879 1.25 5.086-1.605 11.22-2.855 17.528-2.32 6.312.536 11.047 2.68 14.55 5.54 6.485-5.899 16.13-9.29 28.223-9.114-4.207-1.965-10.343-3.57-16.476-3.215zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M12.5 80h46.7v2.8H12.5zm0 0" transform="matrix(1.7529 0 0 1.7867 -21.473 -85.752)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ogg.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.9-34.9c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zM25.5 6.1c1.4 0 2.9.4 3.9 1.3L28 10.2c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.7-7.6 6.5-7.6zm12.5 0c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1H40v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3 0-4.5 2.4-7.6 6.3-7.6z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ogv.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.9-34.9c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zM26.1 6.1c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.7-7.6 6.5-7.6zm5.9.3h3.6l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3l1.7-8.1h3.5l-3.9 14.3h-3.3L32 6.4z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ost.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1d6fb5}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.9-34.9c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm9.7-1.1c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm12.2-7.4h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path class="st0" d="M26.9 62.1c-1.5.2-2.7 1.8-2.7 3.5s1.2 3.4 2.7 3.5c1.5.2 2.7-1.4 2.7-3.5s-1.2-3.7-2.7-3.5z"/><path class="st0" d="M16.4 51.9v27.7L38 83.5V47.7l-21.6 4.2zm10.5 19.4c-2.4-.3-4.3-2.9-4.3-5.7 0-2.9 1.9-5.4 4.3-5.7s4.3 2.3 4.3 5.7c0 3.5-1.9 6-4.3 5.7zm28.2-15.2L43.2 66 40 63.4v-8.2h15.1z"/><path class="st0" d="M55.1 58l-11.9 9.9-3.2-2.6v11.1h15.1z"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><g fill="#1d6fb5"><path d="M18.754 25.742c-2.668.36-4.8 3.219-4.8 6.258s2.132 6.078 4.8 6.258c2.668.355 4.805-2.504 4.805-6.258s-2.137-6.613-4.805-6.258zm0 0"/><path d="M.074 7.508v49.52L38.504 64V0zm18.68 34.683c-4.27-.539-7.649-5.187-7.649-10.191 0-5.184 3.38-9.652 7.649-10.191 4.27-.536 7.652 4.113 7.652 10.191 0 6.258-3.383 10.727-7.652 10.191zm50.172-27.175L47.754 32.715l-5.691-4.649v-14.66h26.863zm0 0"/><path d="m68.926 18.414-21.172 17.7-5.691-4.65V51.31h26.863zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/otf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#36454d}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.9-34.9c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm10.5-8.5h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3zm9.2-2.9h7.1v2.9h-3.8v3.1H38v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path d="M28.1 68.3h-8.9l-1.1 2.4c-.3.8-.5 1.4-.5 2 0 .7.3 1.2.9 1.5.3.2 1.2.3 2.5.4v.7h-8.4v-.7c.9-.1 1.6-.5 2.2-1.1.6-.6 1.3-1.8 2.1-3.7l9-19.4h.4l9.1 19.9c.9 1.9 1.6 3.1 2.1 3.6.4.4 1 .6 1.8.6v.7H27.2v-.7h.5c1 0 1.7-.1 2.1-.4.3-.2.4-.5.4-.8 0-.2 0-.4-.1-.7 0-.1-.2-.6-.6-1.3l-1.4-3zm-.6-1.3l-3.7-8.4-3.9 8.4h7.6z" fill="#7291a1"/><path class="st0" d="M58.2 59.2l-3.6 11.9-.4 1.5c0 .2-.1.3-.1.4 0 .1.1.3.2.4.1.1.2.2.3.2.3 0 .6-.2 1.1-.6.2-.2.6-.7 1.3-1.6l.6.3c-.9 1.6-1.8 2.7-2.8 3.4-1 .7-2.1 1.1-3.2 1.1-.7 0-1.2-.2-1.6-.5-.4-.4-.6-.8-.6-1.3s.2-1.3.6-2.6l.4-1.5c-1.4 2.4-2.8 4.1-4.1 5.1-.8.6-1.6.9-2.4.9-1.1 0-2-.5-2.5-1.4s-.8-1.9-.8-3.1c0-1.7.5-3.6 1.6-5.8 1.1-2.2 2.5-3.9 4.2-5.3 1.4-1.1 2.8-1.6 4-1.6.7 0 1.2.2 1.7.6.4.4.7 1.1.9 2.1l.7-2.2 4.5-.4zm-5.9 3.5c0-1-.2-1.7-.5-2.1-.2-.3-.5-.4-.9-.4s-.8.2-1.2.5c-.8.7-1.7 2.2-2.7 4.5-1 2.3-1.4 4.2-1.4 5.9 0 .6.1 1.1.3 1.4.2.3.5.4.7.4.6 0 1.1-.3 1.7-.9.8-.9 1.6-2 2.2-3.2 1.2-2.4 1.8-4.4 1.8-6.1z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="48"><path style="stroke:none;fill-rule:nonzero;fill:#7291a1;fill-opacity:1" d="M28.621 33.172h-16.32l-2.012 4.45c-.55 1.483-.918 2.593-.918 3.706 0 1.297.547 2.223 1.649 2.781.55.371 2.203.555 4.582.743v1.293H.203v-1.293c1.652-.188 2.934-.93 4.035-2.04 1.098-1.113 2.383-3.34 3.848-6.859L24.586 0h.73L42 36.879c1.648 3.52 2.934 5.746 3.852 6.672.73.742 1.832 1.113 3.296 1.113v1.297h-22.18v-1.297h.919c1.832 0 3.113-.184 3.847-.742.551-.371.735-.926.735-1.48 0-.372 0-.743-.184-1.301 0-.184-.367-1.11-1.101-2.407zm-1.101-2.406-6.786-15.57-7.148 15.57zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#36454d;fill-opacity:1" d="m83.797 16.309-6.602 22.054-.734 2.778c0 .375-.184.558-.184.742 0 .187.184.558.371.742.184.188.368.371.547.371.551 0 1.102-.371 2.016-1.113.371-.367 1.102-1.297 2.387-2.965l1.097.559c-1.648 2.964-3.3 5.003-5.132 6.3-1.833 1.297-3.852 2.04-5.864 2.04-1.285 0-2.203-.372-2.933-.93-.735-.742-1.102-1.485-1.102-2.407 0-.93.367-2.41 1.102-4.82l.73-2.781c-2.562 4.45-5.133 7.601-7.516 9.453C60.516 47.442 59.05 48 57.582 48c-2.016 0-3.668-.926-4.582-2.594-.918-1.668-1.465-3.523-1.465-5.746 0-3.152.914-6.672 2.934-10.75 2.011-4.074 4.582-7.226 7.695-9.82 2.566-2.04 5.133-2.965 7.332-2.965 1.285 0 2.203.367 3.121 1.11.73.742 1.281 2.038 1.649 3.89l1.28-4.074zM72.98 22.797c0-1.856-.367-3.152-.918-3.895-.367-.554-.914-.742-1.648-.742-.734 0-1.469.375-2.2.93-1.464 1.297-3.116 4.074-4.948 8.336-1.832 4.265-2.57 7.785-2.57 10.937 0 1.11.183 2.035.554 2.594.363.559.914.742 1.281.742 1.098 0 2.016-.558 3.117-1.668 1.465-1.668 2.934-3.707 4.032-5.93 2.199-4.449 3.3-8.156 3.3-11.304zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ott.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2{fill:#1a75ce}.st2{stroke:#1a75ce;stroke-width:.5;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.9-34.9c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm10.5-8.5h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3zm11.5 0h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path class="st2" d="M43.4 59.6h15.8v2.5H43.4zm-30.9 6.9h46.7v2.8H12.5zm0 6.8h46.7v2.8H12.5z"/><path class="st0" d="M38.7 48.2h1.7c2.6.2 4.6.8 6.6 1.6 3.8-1.7 9.2-.4 12.6.9-4.3-.4-9.4 0-12.4 1.7-3-2.4-8.6-3.1-13.9-2.4 1.5-1 3.3-1.6 5.4-1.8zm-1.2 6.5c-3.1.2-5.6 1.2-7.3 2.6C25.1 55 16.3 56 13 59.1c-.3.2-.6.4-.5.7 2.9-.9 6.4-1.6 10-1.3 3.6.3 6.3 1.5 8.3 3.1 3.7-3.3 9.2-5.2 16.1-5.1-2.4-1.1-5.9-2-9.4-1.8z"/><path class="st2" d="M12.5 80h46.7v2.8H12.5z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M43.399 59.6h15.802v2.498H43.399zm-30.9 6.902h46.702V69.3H12.499zm0 6.799h46.702v2.798H12.499zm0 0" transform="matrix(1.7529 0 0 1.7867 -21.473 -85.752)"/><path style="stroke:none;fill-rule:nonzero;fill:#1a75ce;fill-opacity:1" d="M46.363.363h2.985c4.554.36 8.058 1.434 11.566 2.864C67.574.187 77.043 2.512 83 4.832c-7.54-.715-16.477 0-21.738 3.04-5.258-4.286-15.075-5.54-24.364-4.286 2.63-1.79 5.786-2.863 9.465-3.223zM44.262 11.98c-5.434.36-9.82 2.145-12.797 4.649-8.942-4.113-24.367-2.324-30.149 3.21-.527.36-1.054.72-.879 1.25 5.086-1.605 11.22-2.855 17.528-2.32 6.312.536 11.047 2.68 14.55 5.54 6.485-5.899 16.13-9.29 28.223-9.114-4.207-1.965-10.343-3.57-16.476-3.215zm0 0"/><path style="fill-rule:nonzero;fill:#1a75ce;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1a75ce;stroke-opacity:1;stroke-miterlimit:10" d="M12.5 80h46.7v2.8H12.5zm0 0" transform="matrix(1.7529 0 0 1.7867 -21.473 -85.752)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ova.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#4d1b9b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.9-34.9c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm7.5-11.4H23l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L27 6.4h3.5l-3.9 14.3h-3.3L19.4 6.4zm15.4 0h3.6L42 20.7h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.9c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.6 2.9h2.1z" fill="#fff"/><path class="st0" d="M56.5 76.6c0-1.6-1.3-2.9-2.9-2.9H17.7c-1.6 0-2.9 1.3-2.9 2.9v4.1c0 1.6 1.3 2.9 2.9 2.9h35.9c1.6 0 2.9-1.3 2.9-2.9v-4.1zM41 80.4c-.9 0-1.7-.7-1.7-1.7S40.1 77 41 77s1.7.7 1.7 1.7-.7 1.7-1.7 1.7zm5.1 0c-.9 0-1.7-.7-1.7-1.7s.7-1.7 1.7-1.7c.9 0 1.7.7 1.7 1.7s-.8 1.7-1.7 1.7zm5 0c-.9 0-1.7-.7-1.7-1.7s.7-1.7 1.7-1.7c.9 0 1.7.7 1.7 1.7s-.8 1.7-1.7 1.7zM17.7 72h35.9c.8 0 1.6.2 2.2.6l-3.5-7.3c-1-2.1-2.6-2.9-4.2-2.9h-3.9l-5.6 5.8c-.4.4-.9.7-1.4.9-.5.2-1.1.3-1.6.3-.6 0-1.1-.1-1.6-.3h-.2c-.4-.2-.8-.5-1.2-.8l-5.6-6h-3.9c-1.6 0-3.1.9-4.2 2.9l-3.5 7.3c.7-.3 1.4-.5 2.3-.5z"/><path class="st0" d="M44 59.6c.2-.2.3-.4.5-.7.1-.3.2-.5.2-.9 0-.3-.1-.6-.2-.8-.1-.3-.3-.5-.5-.7-.2-.2-.5-.4-.7-.5-.2-.1-.5-.2-.8-.2s-.6.1-.8.2c-.3.1-.5.3-.7.5l-3.2 3.2v-10c0-.3-.1-.6-.2-.8-.1-.3-.3-.5-.5-.7-.2-.2-.4-.4-.7-.5-.2-.1-.5-.1-.8-.1-.3 0-.6 0-.8.1-.3.1-.5.3-.7.5-.2.2-.4.4-.5.7-.1.3-.2.5-.2.8v10.1l-3.2-3.2c-.2-.2-.4-.4-.7-.5-.2-.1-.5-.2-.8-.2-.3 0-.6.1-.8.2-.2.1-.5.3-.7.5-.2.2-.4.4-.5.7-.1.3-.2.5-.2.8 0 .3.1.6.2.9.1.3.3.5.5.7l6.9 7c.2.2.4.4.7.5.2.1.5.2.8.2.3 0 .6-.1.8-.2.3-.1.5-.3.7-.5l6.9-7.1z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#4d1b9b"><path d="M73.734 51.555c0-2.844-2.289-5.157-5.109-5.157H5.375c-2.82 0-5.11 2.313-5.11 5.157v7.289c0 2.843 2.29 5.156 5.11 5.156h63.25c2.82 0 5.11-2.313 5.11-5.156zm-27.308 6.757a2.985 2.985 0 0 1-2.996-3.023 2.985 2.985 0 0 1 2.996-3.023 2.985 2.985 0 0 1 2.996 3.023c0 1.777-1.234 3.023-2.996 3.023zm8.984 0a2.984 2.984 0 0 1-2.992-3.023c0-1.777 1.23-3.023 2.992-3.023a2.985 2.985 0 0 1 2.996 3.023 2.985 2.985 0 0 1-2.996 3.023zm8.813 0a2.985 2.985 0 0 1-2.996-3.023c0-1.777 1.234-3.023 2.996-3.023a2.981 2.981 0 0 1 2.992 3.023 2.981 2.981 0 0 1-2.992 3.023zM5.375 43.38h63.25c1.41 0 2.82.355 3.879 1.066l-6.168-12.98c-1.762-3.73-4.582-5.153-7.398-5.153h-6.876L42.2 36.623c-.707.71-1.586 1.245-2.469 1.6-.878.356-1.937.532-2.82.532-1.055 0-1.937-.176-2.816-.531h-.352c-.707-.356-1.41-.891-2.117-1.422l-9.867-10.668h-6.871c-2.817 0-5.461 1.601-7.399 5.156L1.32 44.266c1.235-.532 2.47-.887 4.055-.887zm0 0"/><path d="M51.71 21.332c.352-.355.532-.71.884-1.242.176-.535.351-.89.351-1.602 0-.531-.175-1.066-.351-1.422-.176-.53-.532-.886-.883-1.246a5.273 5.273 0 0 0-1.23-.886c-.356-.18-.883-.356-1.41-.356-.532 0-1.06.176-1.41.356-.528.175-.884.53-1.235.886l-5.637 5.692V3.734c0-.535-.176-1.066-.352-1.421-.18-.536-.53-.891-.882-1.247-.352-.355-.703-.71-1.235-.886C37.97 0 37.441 0 36.91 0c-.527 0-1.055 0-1.406.18-.531.175-.883.53-1.234.886-.352.356-.708.711-.883 1.246-.176.532-.352.887-.352 1.422v17.953L27.398 16c-.351-.355-.707-.71-1.234-.89-.352-.176-.879-.356-1.41-.356-.527 0-1.055.18-1.41.355-.352.18-.88.536-1.23.891-.356.355-.708.71-.884 1.246-.175.531-.351.887-.351 1.422 0 .531.176 1.066.351 1.598.176.535.528.89.883 1.246L34.27 33.957c.351.355.703.711 1.234.887.351.18.879.355 1.406.355.531 0 1.059-.176 1.41-.355.532-.176.883-.532 1.235-.887zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ovf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#4d1b9b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.9-34.9c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm7.5-11.4H23l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L27 6.4h3.5l-3.9 14.3h-3.3L19.4 6.4zm13.5 0H40v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M56.5 76.6c0-1.6-1.3-2.9-2.9-2.9H17.7c-1.6 0-2.9 1.3-2.9 2.9v4.1c0 1.6 1.3 2.9 2.9 2.9h35.9c1.6 0 2.9-1.3 2.9-2.9v-4.1zM41 80.4c-.9 0-1.7-.7-1.7-1.7S40.1 77 41 77s1.7.7 1.7 1.7-.7 1.7-1.7 1.7zm5.1 0c-.9 0-1.7-.7-1.7-1.7s.7-1.7 1.7-1.7c.9 0 1.7.7 1.7 1.7s-.8 1.7-1.7 1.7zm5 0c-.9 0-1.7-.7-1.7-1.7s.7-1.7 1.7-1.7c.9 0 1.7.7 1.7 1.7s-.8 1.7-1.7 1.7zM17.7 72h35.9c.8 0 1.6.2 2.2.6l-3.5-7.3c-1-2.1-2.6-2.9-4.2-2.9h-3.9l-5.6 5.8c-.4.4-.9.7-1.4.9-.5.2-1.1.3-1.6.3-.6 0-1.1-.1-1.6-.3h-.2c-.4-.2-.8-.5-1.2-.8l-5.6-6h-3.9c-1.6 0-3.1.9-4.2 2.9l-3.5 7.3c.7-.3 1.4-.5 2.3-.5z"/><path class="st0" d="M44 59.6c.2-.2.3-.4.5-.7.1-.3.2-.5.2-.9 0-.3-.1-.6-.2-.8-.1-.3-.3-.5-.5-.7-.2-.2-.5-.4-.7-.5-.2-.1-.5-.2-.8-.2s-.6.1-.8.2c-.3.1-.5.3-.7.5l-3.2 3.2v-10c0-.3-.1-.6-.2-.8-.1-.3-.3-.5-.5-.7-.2-.2-.4-.4-.7-.5-.2-.1-.5-.1-.8-.1-.3 0-.6 0-.8.1-.3.1-.5.3-.7.5-.2.2-.4.4-.5.7-.1.3-.2.5-.2.8v10.1l-3.2-3.2c-.2-.2-.4-.4-.7-.5-.2-.1-.5-.2-.8-.2-.3 0-.6.1-.8.2-.2.1-.5.3-.7.5-.2.2-.4.4-.5.7-.1.3-.2.5-.2.8 0 .3.1.6.2.9.1.3.3.5.5.7l6.9 7c.2.2.4.4.7.5.2.1.5.2.8.2.3 0 .6-.1.8-.2.3-.1.5-.3.7-.5l6.9-7.1z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#4d1b9b"><path d="M73.734 51.555c0-2.844-2.289-5.157-5.109-5.157H5.375c-2.82 0-5.11 2.313-5.11 5.157v7.289c0 2.843 2.29 5.156 5.11 5.156h63.25c2.82 0 5.11-2.313 5.11-5.156zm-27.308 6.757a2.985 2.985 0 0 1-2.996-3.023 2.985 2.985 0 0 1 2.996-3.023 2.985 2.985 0 0 1 2.996 3.023c0 1.777-1.234 3.023-2.996 3.023zm8.984 0a2.984 2.984 0 0 1-2.992-3.023c0-1.777 1.23-3.023 2.992-3.023a2.985 2.985 0 0 1 2.996 3.023 2.985 2.985 0 0 1-2.996 3.023zm8.813 0a2.985 2.985 0 0 1-2.996-3.023c0-1.777 1.234-3.023 2.996-3.023a2.981 2.981 0 0 1 2.992 3.023 2.981 2.981 0 0 1-2.992 3.023zM5.375 43.38h63.25c1.41 0 2.82.355 3.879 1.066l-6.168-12.98c-1.762-3.73-4.582-5.153-7.398-5.153h-6.876L42.2 36.623c-.707.71-1.586 1.245-2.469 1.6-.878.356-1.937.532-2.82.532-1.055 0-1.937-.176-2.816-.531h-.352c-.707-.356-1.41-.891-2.117-1.422l-9.867-10.668h-6.871c-2.817 0-5.461 1.601-7.399 5.156L1.32 44.266c1.235-.532 2.47-.887 4.055-.887zm0 0"/><path d="M51.71 21.332c.352-.355.532-.71.884-1.242.176-.535.351-.89.351-1.602 0-.531-.175-1.066-.351-1.422-.176-.53-.532-.886-.883-1.246a5.273 5.273 0 0 0-1.23-.886c-.356-.18-.883-.356-1.41-.356-.532 0-1.06.176-1.41.356-.528.175-.884.53-1.235.886l-5.637 5.692V3.734c0-.535-.176-1.066-.352-1.421-.18-.536-.53-.891-.882-1.247-.352-.355-.703-.71-1.235-.886C37.97 0 37.441 0 36.91 0c-.527 0-1.055 0-1.406.18-.531.175-.883.53-1.234.886-.352.356-.708.711-.883 1.246-.176.532-.352.887-.352 1.422v17.953L27.398 16c-.351-.355-.707-.71-1.234-.89-.352-.176-.879-.356-1.41-.356-.527 0-1.055.18-1.41.355-.352.18-.88.536-1.23.891-.356.355-.708.71-.884 1.246-.175.531-.351.887-.351 1.422 0 .531.176 1.066.351 1.598.176.535.528.89.883 1.246L34.27 33.957c.351.355.703.711 1.234.887.351.18.879.355 1.406.355.531 0 1.059-.176 1.41-.355.532-.176.883-.532 1.235-.887zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/p12.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#696}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.7 4.5h2.3v-6.2c0-.5.1-1 .1-1s-.1.3-.4.7l-.6.6-1.9-1.9 3.2-3.7h2.8v11.5H26v2.8h-7.9v-2.8zm10.5 1.2c0-5 4.5-5.5 4.5-8.4 0-1-.5-1.4-1.2-1.4-.6 0-1.1.3-1.4.8l-2.2-1.8c.8-1.1 2.3-2.1 4.1-2.1 2.1 0 4.2 1.3 4.2 4.2 0 4.1-4.2 5.4-4.4 7.5h4.6v2.9H29c-.2-.7-.3-1.1-.3-1.7z" fill="#fff"/><path class="st0" d="M35.9 1003.6c2.8 2.8 3.6 6.7 2.6 10.2l14.8 14.8.3 6.6-8.3-.7v-4.2h-4.2v-4.2H37l-5.4-5.4c-3.5 1-7.5.2-10.2-2.6-4-4-4-10.6 0-14.6s10.5-4 14.5.1zm-7.6 2.8c-1.2-1.2-3-1.2-4.2 0-1.2 1.2-1.2 3 0 4.2 1.2 1.2 3 1.2 4.2 0 1.2-1.2 1.2-3.1 0-4.2z" transform="translate(0 -952.362)"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M31.816 6.078c5.094 5.094 6.547 12.184 4.73 18.547l26.907 26.91.547 12-15.09-1.273v-7.637h-7.637v-7.637h-7.457L24 37.172c-6.363 1.816-13.637.363-18.547-4.73-7.27-7.27-7.27-19.27 0-26.544a18.494 18.494 0 0 1 26.363.18zM18 11.172c-2.184-2.184-5.453-2.184-7.637 0-2.18 2.18-2.18 5.453 0 7.637 2.184 2.18 5.453 2.18 7.637 0 2.184-2.184 2.184-5.637 0-7.637zm0 0" fill="#696"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/p7b.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#696}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zM22 10.7c.4-1 .6-1.4.6-1.4h-4.8V6.4H26v2.4l-4.6 11.9H18l4-10zm6.9-4.3h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.1 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1z" fill="#fff"/><path class="st0" d="M35.9 1003.6c2.8 2.8 3.6 6.7 2.6 10.2l14.8 14.8.3 6.6-8.3-.7v-4.2h-4.2v-4.2H37l-5.4-5.4c-3.5 1-7.5.2-10.2-2.6-4-4-4-10.6 0-14.6s10.5-4 14.5.1zm-7.6 2.8c-1.2-1.2-3-1.2-4.2 0-1.2 1.2-1.2 3 0 4.2 1.2 1.2 3 1.2 4.2 0 1.2-1.2 1.2-3.1 0-4.2z" transform="translate(0 -952.362)"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M31.816 6.078c5.094 5.094 6.547 12.184 4.73 18.547l26.907 26.91.547 12-15.09-1.273v-7.637h-7.637v-7.637h-7.457L24 37.172c-6.363 1.816-13.637.363-18.547-4.73-7.27-7.27-7.27-19.27 0-26.544a18.494 18.494 0 0 1 26.363.18zM18 11.172c-2.184-2.184-5.453-2.184-7.637 0-2.18 2.18-2.18 5.453 0 7.637 2.184 2.18 5.453 2.18 7.637 0 2.184-2.184 2.184-5.637 0-7.637zm0 0" fill="#696"/></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/pages.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2,.st3{fill:#1a75ce}.st2,.st3{stroke:#1a75ce;stroke-width:.25;stroke-miterlimit:10}.st3{fill-opacity:0;stroke-linejoin:round;stroke-miterlimit:1}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.3-34.6h3.3c1.9 0 3.2 2 3.2 4.9 0 2.9-1.3 5-3.2 5h-.8v4.4H6.3V6.4zm2.9 7c.8 0 1.2-.9 1.2-2.1s-.5-2-1.2-2h-.4v4.1h.4zm6-7h2.6l2.7 14.3h-2.4l-.4-3h-2.2l-.4 3h-2.4l2.5-14.3zm2.1 8.6l-.4-2.8c-.1-.9-.3-2.5-.3-2.5h-.1s-.1 1.5-.3 2.5l-.4 2.8h1.5zm8-8.9c1 0 2.1.4 2.9 1.3l-1 2.8c-.4-.6-1-.9-1.7-.9-1.6 0-2.3 1.9-2.3 4.2 0 2.6.9 4.3 2.1 4.3.5 0 .9-.2 1.3-.6v-1.7h-1.1v-2.9h3.2v8.1h-1.9v-.9c-.4.7-1.2 1.2-2 1.2-2.1 0-4.1-2.7-4.1-7.3-.1-4.5 1.7-7.6 4.6-7.6zm4.7.3h5.3v2.9h-2.9V12h2.3v2.9h-2.3v2.9h3v2.9H30V6.4zm7.1 10.3c.4.6 1 1.2 1.7 1.2s1-.6 1-1.2c0-2-3.5-2.1-3.5-6.2 0-2.4 1.2-4.3 3.4-4.3.9 0 1.8.3 2.5 1l-.9 2.9c-.4-.4-1.1-.9-1.6-.9-.7 0-1 .6-1 1.2 0 2.1 3.5 2 3.5 6.1 0 2.3-1.1 4.4-3.3 4.4-1 0-2.1-.5-3-1.4l1.2-2.8z" fill="#fff"/><path class="st2" d="M57.4 81.5l-.1.6-.1.8-41.3-.1-.5-.1-.2-.3-.1-.4.1-.3.4-.3h41.8z"/><path class="st3" d="M57.4 81.5l-.1.6-.1.8-41.3-.1-.5-.1-.2-.3-.1-.4.1-.3.4-.3h41.8z"/><path class="st2" d="M18.1 76.9l1.5 1.6-2 1.4-1 .6h-.4l-.2-.4.7-1 1.4-2.2z"/><path class="st3" d="M18.1 76.9l1.5 1.6-2 1.4-1 .6h-.4l-.2-.4.7-1 1.4-2.2z"/><path class="st2" d="M31.4 61.7l3.3 3.4-2.9 2.9-3.2 2.9-3.2 2.8-2.5 2.2-2.7 1.9-1.6-1.6 1.5-2.2 2.1-2.5 1.6-1.9 2.1-2.2 2.6-2.8 2.9-2.9z"/><path class="st3" d="M31.4 61.7l3.3 3.4-2.9 2.9-3.2 2.9-3.2 2.8-2.5 2.2-2.7 1.9-1.6-1.6 1.5-2.2 2.1-2.5 1.6-1.9 2.1-2.2 2.6-2.8 2.9-2.9z"/><path class="st2" d="M46.6 48l.8.1.5.4.4.7v.9l-.3.8-.4.6v.7l.3.4.1.5-.1.7-6.7 7.2-1.9 2-.7.9-.1.4.1.5-.4.5-.7-.3-.2-.7.1-.7.4-.6 4.7-5 4-4.4.1-.5-.5-.1-2.8 3.1-4.6 4.8-3.3 3.4-3.4-3.1 3.8-4 4.3-4.2 4-3.7 1-.7.7-.4h.8z"/><path class="st3" d="M46.6 48l.8.1.5.4.4.7v.9l-.3.8-.4.6v.7l.3.4.1.5-.1.7-6.7 7.2-1.9 2-.7.9-.1.4.1.5-.4.5-.7-.3-.2-.7.1-.7.4-.6 4.7-5 4-4.4.1-.5-.5-.1-2.8 3.1-4.6 4.8-3.3 3.4-3.4-3.1 3.8-4 4.3-4.2 4-3.7 1-.7.7-.4h.8z"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/part.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.7-34.5h3.8c2.4 0 4 1.9 4 4.6s-1.6 4.7-4 4.7H9.1v4.9H6.7V6.5zm3.5 7.1c1.3 0 2-1 2-2.5s-.8-2.5-2-2.5H9.1v5h1.1zm7.7-7.1h2.5L24 20.7h-2.3l-.9-3.7h-3.3l-.8 3.7h-2.3l3.5-14.2zm2.6 8.5l-.9-3.8c-.2-.8-.4-2.2-.4-2.2h-.1s-.2 1.4-.4 2.2l-.8 3.8h2.6zm4.8-8.5h3.9c.5 0 1.2.1 1.8.4 1.2.6 2 2 2 3.8 0 1.9-.9 3.3-2 3.9 0 0 .2.3.4.8l2.2 5.3h-2.5L29 15.4h-1.5v5.3h-2.3V6.5zm3.5 6.7c1 0 1.8-.9 1.8-2.3 0-.8-.3-1.5-.7-1.9-.3-.2-.7-.3-1-.3h-1.3v4.6h1.2zm8.4-4.5H34V6.5h8.8v2.2h-3.3v12h-2.3v-12z" fill="#fff"/><path class="st0" d="M55.1 58.1c-.5-.1-.9-.2-1.4-.1-1.1.1-2.3.7-3.4.9-.8.1-1.5-.5-1.6-1.4-.2-2.6-.2-5.3 0-7.9 0-.4-.3-.6-.6-.6-3-.1-5.9.2-9 .9-.8.2-1.4.9-1.4 1.6.1 1.6 1.2 3.4.7 5.1-.4 1.5-1.6 2.6-3.2 2.9-1.5.3-3.1-.4-3.9-1.6-1-1.4-.5-3.4-.9-5.1-.2-.8-1-1.2-1.8-1.1-3 .3-5.9 1-8.7 2.1-.4.1-.6.5-.4.8 1.1 2.4 1.9 4.9 2.6 7.5.2.8-.3 1.6-1.1 1.8-1.1.3-2.4.1-3.5.4-.5.1-.9.3-1.3.6-1.4.9-2 2.4-1.8 3.9.2 1.4 1.3 2.6 2.6 3.2 1.7.6 3.2-.5 4.9-.6.8-.1 1.5.5 1.6 1.4.2 2.6.2 5.3 0 7.9 0 .4.3.6.6.6 3 .2 6-.2 9-.9.8-.2 1.4-.9 1.4-1.6-.1-1.7-1.3-3.4-.8-5.2.4-1.4 1.8-2.6 3.2-2.8 1.4-.2 3.1.4 3.9 1.6 1.1 1.4.5 3.5.9 5.2.2.8 1 1.2 1.8 1.1 3-.3 6-.9 8.7-2.1.4-.1.6-.5.4-.8-1.1-2.4-1.9-4.9-2.6-7.5-.2-.8.3-1.6 1.1-1.8 1.6-.4 3.4.1 4.9-1 1.1-.9 1.8-2.4 1.5-3.8.1-1.9-1.1-3.2-2.4-3.6z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#bababa;fill-opacity:1" d="M78.953 17.746c-.969-.191-1.742-.387-2.707-.191-2.125.191-4.441 1.36-6.566 1.746-1.543.199-2.895-.973-3.09-2.719a102.076 102.076 0 0 1 0-15.379c0-.777-.578-1.168-1.156-1.168C59.64-.156 54.039.425 48.05 1.79c-1.547.387-2.7 1.754-2.7 3.113.188 3.118 2.313 6.618 1.348 9.926-.773 2.918-3.09 5.059-6.18 5.645-2.894.586-5.988-.778-7.53-3.114-1.93-2.726-.966-6.62-1.739-9.925-.383-1.559-1.93-2.34-3.473-2.145a62.499 62.499 0 0 0-16.804 4.09c-.77.195-1.157.973-.77 1.555 2.125 4.671 3.664 9.539 5.02 14.597.386 1.559-.578 3.117-2.125 3.504-2.125.586-4.637.195-6.758.777-.969.196-1.738.586-2.508 1.168-2.707 1.754-3.867 4.672-3.48 7.59.39 2.727 2.507 5.063 5.02 6.23 3.284 1.165 6.183-.972 9.464-1.167 1.543-.192 2.898.972 3.09 2.726.387 5.059.387 10.313 0 15.371 0 .782.578 1.168 1.16 1.168 5.789.391 11.586-.386 17.379-1.75 1.543-.39 2.703-1.75 2.703-3.113-.195-3.308-2.508-6.617-1.543-10.12.77-2.727 3.473-5.06 6.18-5.454 2.699-.387 5.988.781 7.53 3.117 2.122 2.727.966 6.813 1.74 10.121.382 1.555 1.929 2.336 3.472 2.14 5.797-.585 11.59-1.753 16.805-4.089.77-.195 1.156-.973.77-1.555-2.126-4.672-3.669-9.535-5.02-14.597-.387-1.559.578-3.114 2.125-3.5 3.09-.782 6.566.195 9.46-1.95 2.126-1.75 3.477-4.671 2.895-7.394.195-3.695-2.121-6.227-4.629-7.008zm0 0"/></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/pcd.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#bababa}</style><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path d="M17.7 70.4h4.5c2.6 0 4.4 2 4.4 4.9s-1.7 5-4.4 5H21v4.4h-3.3V70.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2H21v4.1h.6zm13.7-7.2c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.4 2.4-7.4 6.4-7.4zm6.5.2H46c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V70.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/pdb.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#a03537}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.9-7h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.1-11.4h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.1 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1z" fill="#fff"/><path class="st0" d="M-4938.1 722.8c-4.8-.2-9.1-1.7-11.4-4-.7-.6-1.4-1.5-1.7-2.1l-.2-.4v-4.5c0-4.5 0-4.5.1-4.1.2 1 .8 2 1.7 2.8.6.5 1.8 1.4 2.8 1.9 1.7.9 3.9 1.5 6.2 1.8 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.5-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.2.4c-.7 1.4-1.9 2.6-3.5 3.6-3.1 1.8-7.8 2.8-12.4 2.6zm0-11.2c-4.2-.2-8.1-1.4-10.6-3.2-.6-.4-1.4-1.2-1.7-1.6-.3-.4-.6-.9-.8-1.4l-.2-.4v-4.4c0-4.4 0-4.4.1-4.1.2.7.5 1.5 1.1 2.1.3.4.8.9 1.1 1.1.1.1.4.2.6.4 2 1.4 4.8 2.4 8 2.9 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.4-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.3.6c-.5.9-.8 1.4-1.4 2-.6.6-1.2 1.1-2 1.5-3.2 1.8-7.9 2.8-12.5 2.5zm-.3-11.1c-2.8-.2-5-.7-7.1-1.5-2.5-1-4.3-2.3-5.2-3.9-.2-.3-.4-.7-.5-1.2-.1-.4-.2-1.4-.1-2 .6-3.2 4.9-5.8 10.7-6.7 1.4-.2 1.9-.2 3.9-.2s2.5 0 3.9.2c2.3.3 4.4 1 6.2 1.8 2.6 1.3 4.2 3 4.5 4.8.1.5.1 1.6-.1 2-.3 1-.7 1.6-1.5 2.4-2.1 2.2-5.8 3.6-10.4 4.1-.6.2-3.7.2-4.3.2z" transform="translate(4973.037 -638.07)"/></svg>
1
<svg height="64" width="51" xmlns="http://www.w3.org/2000/svg"><path d="M23.023 63.957c-8.199-.34-15.543-2.875-19.468-6.77-1.196-1.011-2.39-2.535-2.903-3.55L.31 52.96v-7.617c0-7.614 0-7.614.171-6.934.34 1.692 1.368 3.383 2.903 4.735 1.023.847 3.074 2.37 4.781 3.214 2.906 1.524 6.66 2.54 10.59 3.047 2.39.34 3.246.34 6.66.34 3.418 0 4.27 0 6.66-.34 3.93-.508 7.516-1.691 10.59-3.047 1.707-.843 3.758-2.199 4.781-3.214 1.368-1.352 2.563-3.043 2.903-4.735.172-.508.172-.508.172 6.934v7.445l-.34.68c-1.196 2.367-3.246 4.398-5.98 6.09-5.294 3.046-13.321 4.738-21.177 4.398zm0-18.95c-7.171-.339-13.832-2.37-18.101-5.413-1.027-.68-2.39-2.032-2.906-2.707-.512-.68-1.024-1.524-1.364-2.371L.31 33.84v-7.445c0-7.446 0-7.446.171-6.938.34 1.184.852 2.54 1.88 3.555.511.675 1.367 1.523 1.878 1.86.168.171.684.339 1.024.679 3.414 2.367 8.199 4.058 13.664 4.906 2.39.336 3.242.336 6.66.336 3.414 0 4.27 0 6.66-.336 3.93-.508 7.516-1.691 10.59-3.047 1.707-.847 3.758-2.2 4.781-3.215 1.367-1.351 2.39-3.047 2.903-4.738.171-.508.171-.508.171 6.938v7.445l-.511 1.015c-.856 1.524-1.368 2.368-2.39 3.383-1.028 1.016-2.052 1.864-3.419 2.54-5.465 3.046-13.492 4.738-21.348 4.23zm-.511-18.78c-4.782-.34-8.54-1.184-12.125-2.54-4.27-1.69-7.344-3.89-8.883-6.597a5.594 5.594 0 0 1-.852-2.031C.48 14.383.31 12.69.48 11.676 1.504 6.262 8.848 1.859 18.754.34 21.144 0 22 0 25.414 0c3.418 0 4.27 0 6.66.34 3.93.508 7.516 1.691 10.59 3.043 4.441 2.199 7.172 5.078 7.684 8.12.172.849.172 2.708-.168 3.388-.512 1.691-1.196 2.707-2.563 4.058-3.586 3.723-9.906 6.094-17.762 6.938-1.023.34-6.32.34-7.343.34zm0 0" fill="#a03537"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pdf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#c11e07}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.9-7h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.1-11.4h7.1v2.9h-3.8v3.1H38v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path d="M33.5 46.538c-2.3 0-4.1 1.9-4.1 4.1 0 2.8 1.6 6.3 3.2 9.6-1.3 4-2.7 8.3-4.6 11.9-3.8 1.5-7.2 2.6-9.2 4.3l-.1.1c-.7.8-1.2 1.8-1.2 2.9 0 2.3 1.9 4.1 4.1 4.1 1.1 0 2.2-.4 2.9-1.2 0 0 .1 0 .1-.1 1.5-1.8 3.3-5.1 4.9-8 3.6-1.4 7.5-2.9 11.1-3.8 2.7 2.2 6.6 3.6 9.8 3.6 2.3 0 4.1-1.9 4.1-4.1 0-2.3-1.9-4.1-4.1-4.1-2.6 0-6.3.9-9.1 1.9-2.3-2.2-4.4-4.9-6-7.8 1.1-3.4 2.4-6.7 2.4-9.3-.1-2.3-1.9-4.1-4.2-4.1zm0 2.4c.9 0 1.6.7 1.6 1.6 0 1.2-.7 3.5-1.4 5.9-1-2.4-1.9-4.7-1.9-5.9.1-.8.8-1.6 1.7-1.6zm.7 14.1c1.2 2 2.7 3.8 4.3 5.4-2.4.7-4.8 1.5-7.2 2.4 1.2-2.5 2.1-5.2 2.9-7.8zm16.2 5.3c.9 0 1.6.7 1.6 1.6 0 .9-.7 1.6-1.6 1.6-1.9 0-4.5-.8-6.6-2 2.4-.6 5.1-1.2 6.6-1.2zm-24.5 7.3c-1.2 2.1-2.3 4-3.1 5-.3.3-.6.4-1.1.4-.9 0-1.6-.7-1.6-1.6 0-.4.2-.9.4-1.1.9-.8 3-1.7 5.4-2.7z" fill="#c11e07" stroke="#c11e07" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M27.762.637c-3.899 0-6.95 3.218-6.95 6.949 0 4.746 2.711 10.68 5.422 16.277-2.203 6.782-4.574 14.07-7.797 20.172-6.44 2.547-12.207 4.41-15.597 7.293l-.168.168C1.484 52.852.637 54.546.637 56.414c0 3.898 3.218 6.95 6.949 6.95 1.867 0 3.73-.677 4.918-2.036 0 0 .168 0 .168-.168 2.543-3.05 5.594-8.644 8.308-13.562 6.102-2.375 12.715-4.918 18.817-6.442 4.578 3.73 11.191 6.102 16.617 6.102 3.898 0 6.95-3.223 6.95-6.95 0-3.902-3.22-6.953-6.95-6.953-4.41 0-10.68 1.528-15.43 3.223a56.197 56.197 0 0 1-10.172-13.223c1.868-5.765 4.07-11.359 4.07-15.77-.171-3.898-3.222-6.948-7.12-6.948zm0 4.066c1.527 0 2.71 1.188 2.71 2.715 0 2.035-1.183 5.934-2.37 10-1.696-4.066-3.223-7.965-3.223-10 .172-1.356 1.355-2.715 2.883-2.715zm1.187 23.906c2.035 3.391 4.578 6.442 7.29 9.157a171.201 171.201 0 0 0-12.208 4.066c2.035-4.238 3.563-8.816 4.918-13.223zm27.465 8.985a2.679 2.679 0 0 1 2.711 2.715 2.678 2.678 0 0 1-2.71 2.71c-3.224 0-7.63-1.355-11.192-3.39 4.07-1.016 8.648-2.035 11.191-2.035zM14.875 49.973c-2.031 3.558-3.898 6.78-5.254 8.476-.508.508-1.016.676-1.863.676a2.679 2.679 0 0 1-2.715-2.71c0-.68.34-1.528.68-1.868 1.523-1.356 5.086-2.879 9.152-4.574zm0 0" fill="#c11e07" stroke="#c11e07" stroke-miterlimit="10" stroke-width="1.27152"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pem.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#696}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.9-7h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4zm10.9 0H33l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H33l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1.1-14.3z" fill="#fff"/><path class="st0" d="M49.2 62.2h-2.6v-5C46.6 51.5 42 47 36.4 47s-10.2 4.6-10.2 10.2v5h-2.6c-1 0-1.8.8-1.8 1.8v17.4c0 1 .8 1.8 1.8 1.8h25.6c1 0 1.8-.8 1.8-1.8V63.9c0-.9-.8-1.7-1.8-1.7zM38.6 76.6c.2.6-.3 1.1-.9 1.1H35c-.6 0-1-.6-.9-1.1l.8-3.2c-1-.5-1.7-1.5-1.7-2.8 0-1.7 1.4-3.1 3.1-3.1 1.7 0 3.1 1.4 3.1 3.1 0 1.2-.7 2.3-1.7 2.8l.9 3.2zm2.9-14.4H31.3v-5c0-2.8 2.3-5.1 5.1-5.1s5.1 2.3 5.1 5.1v5z"/></svg>
1
<svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#696"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pfx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#696}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.9-7h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4zm12.3 7.2l-3.4-7.2h3.6L32 9.3l.6 1.8s.2-.9.6-1.8l1.2-2.9H38l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.2-7.1z" fill="#fff"/><path class="st0" d="M35.9 1003.6c2.8 2.8 3.6 6.7 2.6 10.2l14.8 14.8.3 6.6-8.3-.7v-4.2h-4.2v-4.2H37l-5.4-5.4c-3.5 1-7.5.2-10.2-2.6-4-4-4-10.6 0-14.6s10.5-4 14.5.1zm-7.6 2.8c-1.2-1.2-3-1.2-4.2 0-1.2 1.2-1.2 3 0 4.2 1.2 1.2 3 1.2 4.2 0 1.2-1.2 1.2-3.1 0-4.2z" transform="translate(0 -952.362)"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M31.816 6.078c5.094 5.094 6.547 12.184 4.73 18.547l26.907 26.91.547 12-15.09-1.273v-7.637h-7.637v-7.637h-7.457L24 37.172c-6.363 1.816-13.637.363-18.547-4.73-7.27-7.27-7.27-19.27 0-26.544a18.494 18.494 0 0 1 26.363.18zM18 11.172c-2.184-2.184-5.453-2.184-7.637 0-2.18 2.18-2.18 5.453 0 7.637 2.184 2.18 5.453 2.18 7.637 0 2.184-2.184 2.184-5.637 0-7.637zm0 0" fill="#696"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pgp.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#696}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm13.6-7.3c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.6-7.6 6.5-7.6zm7.8.3h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path class="st0" d="M35.9 1003.6c2.8 2.8 3.6 6.7 2.6 10.2l14.8 14.8.3 6.6-8.3-.7v-4.2h-4.2v-4.2H37l-5.4-5.4c-3.5 1-7.5.2-10.2-2.6-4-4-4-10.6 0-14.6s10.5-4 14.5.1zm-7.6 2.8c-1.2-1.2-3-1.2-4.2 0-1.2 1.2-1.2 3 0 4.2 1.2 1.2 3 1.2 4.2 0 1.2-1.2 1.2-3.1 0-4.2z" transform="translate(0 -952.362)"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M31.816 6.078c5.094 5.094 6.547 12.184 4.73 18.547l26.907 26.91.547 12-15.09-1.273v-7.637h-7.637v-7.637h-7.457L24 37.172c-6.363 1.816-13.637.363-18.547-4.73-7.27-7.27-7.27-19.27 0-26.544a18.494 18.494 0 0 1 26.363.18zM18 11.172c-2.184-2.184-5.453-2.184-7.637 0-2.18 2.18-2.18 5.453 0 7.637 2.184 2.18 5.453 2.18 7.637 0 2.184-2.184 2.184-5.637 0-7.637zm0 0" fill="#696"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ph.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.9-7h3.3v5.8h3.2V6.4h3.3v14.3h-3.3V15h-3.2v5.7h-3.3V6.4z"/><path class="st0" d="M54.5 65.5C54.5 75.7 46.2 84 36 84s-18.5-8.3-18.5-18.5S25.8 47 36 47s18.5 8.3 18.5 18.5"/><path class="st1" d="M48.9 66.9c-.6-3.9-4.7-6.5-7.8-8.4-1.3-.8-3.5-1.9-3.8-3.7-.1-.7-.1-1.5-.1-2.2v-.9c0-.4-.4.1-.6-.2-.5-.8-.3.2-.3.7.1 1 .3 2 .3 3 0 1.9-.3 3.8-.8 5.6-1.1 4.3-2 8.8-.9 13.2.2.9.5 1.8.9 2.7.1.3.3 1 .7 1.1 1.2.3 2.1.4 3 1.3.6.5 1 .2 1.7 0 2.1-.8 3.9-1.9 5.4-3.6 1.9-2.6 2.8-5.5 2.3-8.6m-2.2 3.9c-.2 1.6-1.2 3.1-2.2 4.3-.8.9-1.8 2-2.9 2.4-.4.1.1-.7.1-.7.3-.5.8-1 1.2-1.5.6-.7 1.1-1.5 1.4-2.3 1.1-2.9.9-6.3-.8-8.9-.9-1.4-2.2-2.6-3.4-3.7-.6-.5-1.2-1-1.7-1.6-.1-.1-1.2-1.5-.8-1.7.1-.1 2.4 2.3 2.6 2.5.9.7 1.9 1.4 2.8 2.2 1.2 1.1 2.4 2.3 3.1 3.8.7 1.6.8 3.5.6 5.2"/><path class="st1" d="M35.3 47.5c.3.2.4 1.6.4 2.8 0 1.2.1 6.5-.3 7.9-.4 1.4-1.3 3-2.2 4.4-1 1.4-2.1 4.3-2 6.1 0 1.8 1.1 4.7 1.9 6 .8 1.2 2.2 2.9 1.9 3.3-.5.7-2.7-1.7-3.9-3.1-1.1-1.4-2.3-4.2-2.3-6.4s1.2-4.2 2.1-5.4c.9-1.2 2.6-3.3 3.1-4.3s1-2 1.1-3.3c.2-1.3 0-6.1 0-6.1s-.1-2.1.2-1.9"/><path class="st1" d="M34.4 49.8c.3.2.4.6.4 1s-.1 2.1-.2 3.8c-.1 1.7-1.5 3.1-2.4 4.1-1 1-3.9 4.1-4.9 5.6-1.1 1.5-1.6 3.5-1.5 5.2.1 1.7.5 3.4 2.1 5.2 1.6 1.8 2.7 2.6 3.6 3.1.8.4 1.7.7 1.5 1.1-.2.4-1 .1-1.9-.2-.9-.3-3.9-1.5-5.6-3.5-1.7-2-2.6-4.6-2.5-7 .1-2.5.8-3.5 1.9-5.1 1.1-1.6 4.3-4 5.3-4.6 1-.6 2.3-1.6 3-2.5.7-.8 1-1.5 1-2.7 0-1.1.1-2.2 0-2.6-.1-.3-.1-1.1.2-.9m.1 30c.2 0 .1.7-.2 1-.3.3-.7.5-.8.4-.1-.1.3-.2.6-.5.3-.4.2-.9.4-.9m3.1-.1c-.2 0-.1.7.2 1 .3.3.7.5.8.4.1-.1-.3-.2-.6-.5s-.2-.9-.4-.9m-1.4.8c0 .6 0 1.1-.1 1.1-.2 0-.1-.5-.1-1.1 0-.6-.1-1.1.1-1.1s.1.5.1 1.1"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M64 32c0 17.645-14.355 32-32 32S0 49.645 0 32 14.355 0 32 0s32 14.355 32 32" fill="#999"/><g fill="#fff"><path d="M54.313 34.422c-1.036-6.746-8.13-11.242-13.493-14.531-2.246-1.383-6.054-3.286-6.57-6.399-.176-1.21-.176-2.594-.176-3.805V8.13c0-.692-.691.172-1.035-.344-.867-1.387-.52.344-.52 1.211.172 1.727.52 3.457.52 5.188 0 3.285-.52 6.574-1.387 9.687-1.902 7.438-3.457 15.223-1.554 22.832a24.518 24.518 0 0 0 1.554 4.668c.176.52.52 1.73 1.211 1.906 2.078.516 3.633.692 5.192 2.246 1.039.868 1.73.348 2.941 0 3.633-1.382 6.746-3.285 9.34-6.226 3.285-4.496 4.844-9.512 3.977-14.875m-3.805 6.746c-.344 2.766-2.074 5.363-3.805 7.437-1.383 1.56-3.113 3.461-5.016 4.153-.69.172.172-1.211.172-1.211.52-.867 1.383-1.73 2.075-2.594 1.039-1.21 1.902-2.598 2.421-3.98 1.903-5.016 1.56-10.899-1.382-15.395-1.555-2.422-3.805-4.496-5.88-6.398-1.038-.868-2.077-1.73-2.94-2.77-.176-.172-2.079-2.594-1.387-2.941.175-.172 4.152 3.98 4.5 4.324 1.554 1.21 3.285 2.422 4.843 3.809 2.075 1.902 4.149 3.976 5.36 6.57 1.21 2.77 1.386 6.055 1.039 8.996"/><path d="M30.79.863c.519.348.69 2.77.69 4.844 0 2.078.172 11.246-.52 13.664-.69 2.422-2.245 5.192-3.804 7.613-1.73 2.422-3.633 7.438-3.457 10.551 0 3.113 1.903 8.13 3.285 10.38 1.383 2.073 3.805 5.015 3.286 5.706-.864 1.211-4.668-2.941-6.747-5.363-1.902-2.422-3.976-7.262-3.976-11.07 0-3.805 2.074-7.262 3.633-9.34 1.554-2.075 4.496-5.707 5.36-7.438.866-1.73 1.73-3.457 1.901-5.707.348-2.25 0-10.55 0-10.55S30.27.52 30.79.862"/><path d="M29.234 4.844c.516.343.692 1.039.692 1.73 0 .692-.176 3.633-.348 6.57-.172 2.942-2.594 5.364-4.152 7.094-1.727 1.73-6.746 7.09-8.473 9.688-1.906 2.594-2.77 6.05-2.598 8.992.176 2.941.868 5.883 3.633 8.996 2.77 3.113 4.672 4.496 6.227 5.363 1.387.692 2.941 1.211 2.597 1.903-.347.691-1.73.172-3.289-.348-1.554-.52-6.746-2.594-9.687-6.055-2.938-3.457-4.496-7.957-4.324-12.105.175-4.324 1.386-6.055 3.289-8.824 1.902-2.766 7.437-6.918 9.168-7.957 1.73-1.036 3.976-2.766 5.187-4.325 1.211-1.382 1.73-2.593 1.73-4.668 0-1.902.173-3.804 0-4.5-.171-.515-.171-1.902.348-1.554m.172 51.89c.344 0 .172 1.211-.347 1.73-.52.52-1.211.864-1.383.692s.52-.343 1.039-.863c.52-.691.344-1.559.691-1.559m5.36-.172c-.344 0-.172 1.211.347 1.731s1.211.863 1.383.691c.176-.172-.52-.347-1.035-.867-.52-.515-.348-1.554-.695-1.554m-2.418 1.382c0 1.04 0 1.903-.176 1.903-.344 0-.172-.864-.172-1.903 0-1.039-.172-1.902.172-1.902.348 0 .176.863.176 1.902"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/phar.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#6781b2}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zm.7-33.8h3.7c2.3 0 3.8 1.8 3.8 4.4S12.6 16 10.4 16H8.9v4.7H6.7V7.2zM10 14c1.2 0 2-.9 2-2.4 0-1.4-.8-2.4-1.9-2.4H8.9V14H10zm5.3-6.8h2.2v5.7h4V7.2h2.2v13.5h-2.2V15h-4v5.7h-2.2V7.2zm12.6 0h2.4l3.4 13.5h-2.2l-.8-3.5h-3.2l-.8 3.5h-2.2l3.4-13.5zm2.4 8.1l-.8-3.6c-.2-.8-.4-2.1-.4-2.1H29s-.2 1.3-.4 2.1l-.8 3.6h2.5zm4.2-8.1h3.8c.5 0 1.1.1 1.7.4 1.1.6 2 1.9 2 3.6 0 1.8-.9 3.1-1.9 3.7 0 0 .2.2.4.7l2.2 5h-2.4l-2-5h-1.4v5h-2.2V7.2zm3.4 6.4c.9 0 1.7-.8 1.7-2.2 0-.8-.3-1.5-.7-1.8-.3-.2-.7-.3-1-.3h-1.2v4.3h1.2z"/><path class="st0" d="M55.2 54.8L36 47.1l-7.6 3.1 19.2 7.6zm-31.6-2.7l-6.8 2.7L36 62.5l6.8-2.7zm-7.6 25l19.4 7.8V63.5L16 55.7zm32.4-18.3v6l-.8-.5-.8 1.1-.8-.4-.8 1.1-.8-.5-.8 1.1v-6l-7 2.8v21.4L56 77.1V55.7z"/><path class="st1" d="M20.4 68.5c.4.2.8.2 1 .1.2-.1.5-.3.7-.6.2-.3.3-.6.2-.7s-.3-.4-.7-.5l-.6-.4-1.1 1.8.5.3zM17.3 70s-.1 0 0 0c-.1-.1-.1-.1 0-.2l2.9-4.8.1-.1 2.1.8c.7.3 1.1.6 1.3 1.1.2.5.1 1-.3 1.6-.1.2-.3.5-.5.6-.2.2-.4.3-.7.4-.3.1-.6.2-.9.2-.3 0-.7-.1-1.1-.3l-.9-.3-.8 1.2-.1.1-1.1-.3zm8.5 1.7c-.1-.1-.1-.1 0-.2l1.3-2.1c.1-.2.2-.4.1-.4 0-.1-.1-.2-.4-.3l-.8-.3-1.6 2.6-.1.1-1.1-.4s-.1 0-.1-.1v-.1l2.9-4.8.1-.1 1.1.4s.1 0 .1.1v.1l-.7 1.2.8.3c.6.2 1 .5 1.2.9.2.3.1.8-.2 1.2L27 72l-.1.1-1.1-.4zm4.6.6c.4.2.8.2 1.1.1.3-.1.5-.3.7-.6.2-.3.3-.6.2-.7-.1-.2-.3-.4-.7-.5l-.7-.3-1.1 1.8.5.2zm-3.2 1.5c-.1-.1-.1-.1-.1-.2l3-4.8s.1-.1.2 0l2.2.8c.7.3 1.1.6 1.3 1.1.2.5.1 1-.3 1.6-.1.2-.3.5-.5.6-.2.2-.4.3-.7.4-.3.1-.7.2-1 .2-.3 0-.7-.1-1.2-.3l-.8-.2-.8 1.2s-.1.1-.2 0l-1.1-.4z"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M65.66 13.137 33.5.168 20.77 5.391l32.16 12.8zM12.73 8.59 1.34 13.137 33.5 26.105l11.39-4.546zM0 50.695l32.496 13.137V27.789L0 14.652zm54.27-30.82V29.98l-1.34-.843-1.34 1.851-1.34-.672-1.34 1.852-1.34-.84-1.34 1.852V23.074L34.504 27.79v36.043L67 50.695V14.652zm0 0" fill="#6781b2"/><path d="M7.371 36.21c.668.337 1.34.337 1.676.169.332-.168.836-.504 1.172-1.012.332-.504.5-1.008.332-1.176-.164-.171-.5-.675-1.172-.843l-1.004-.676-1.844 3.035zm-5.195 2.528c-.164-.168-.164-.168 0-.34l4.86-8.082.167-.168 3.516 1.348c1.172.504 1.844 1.008 2.18 1.852.335.843.167 1.683-.504 2.695-.168.336-.504.84-.836 1.008-.336.34-.672.508-1.172.676-.504.168-1.008.336-1.508.336-.504 0-1.176-.168-1.844-.504l-1.508-.508-1.34 2.023-.167.168zm14.238 2.864c-.168-.172-.168-.172 0-.34l2.18-3.535c.168-.336.332-.676.168-.676 0-.168-.168-.336-.672-.504l-1.34-.504-2.68 4.379-.168.168-1.843-.676s-.168 0-.168-.168v-.168l4.859-8.082.168-.168 1.844.672s.164 0 .164.168v.168l-1.172 2.023 1.34.504c1.008.336 1.676.844 2.011 1.516.336.504.168 1.348-.335 2.02l-2.344 3.706-.168.168zm7.707 1.007c.668.34 1.34.34 1.84.168.504-.168.84-.504 1.176-1.007.332-.508.5-1.012.332-1.18-.168-.336-.5-.676-1.172-.844l-1.172-.504-1.844 3.031zm-5.36 2.528c-.167-.168-.167-.168-.167-.336l5.023-8.086s.168-.168.336 0l3.684 1.347c1.172.508 1.843 1.012 2.18 1.852.331.844.167 1.688-.504 2.695-.168.34-.504.844-.836 1.012-.336.336-.672.504-1.176.672-.5.172-1.172.34-1.672.34-.504 0-1.176-.168-2.012-.508l-1.34-.336-1.34 2.02s-.167.171-.335 0zm0 0" fill="#fff"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/php.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#6781b2}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.9-7h3.3v5.8h3.2V6.4h3.3v14.3h-3.3V15h-3.2v5.7h-3.3V6.4zm13.4 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2H35v4.1h.7z" fill="#fff"/><path class="st0" d="M33.9 73c1.9.7 5 .6 7.2.3.4.9-.2 2.1.2 3.1.2.5.8.9 1.8 1.4.2.1.5.1.7.2l.2.2c.4.3 1.2.8 1.4.8.3.1.6.1.8.1h1c1.4-.1 2.8-.5 3.2-1 .7-.9.3-2.9.2-4.7-.1-1.5-.3-3.5 0-4.7.1-.4.5-.8.7-1.3.8-1.7 1.6-4.5 1.3-7.2-.2-1.2-.8-2.3-.9-3.2 1.9.2 3.7-.2 5.3 0 1 .1 1.8.8 2.7.7.2-.5.8-.8.8-1.4.1-.7-.2-1.5-.5-2-1.3-.2-2.3 1-3.6 1.1-.4 0-.9-.1-1.4-.2-1.5-.1-3.6.3-4.9 0-.9-.2-1.7-1.2-2.6-1.6-.2-.1-.6 0-.8-.2-.3-.1-.5-.3-.7-.3-1-.4-2.1-.8-3.1-.9-1.9-.5-4.5-.5-6.9-.3-.8.1-1.5.5-2.3.3-.6-.1-.7-.5-1.1-.7-1.7-.8-3.4.1-4.5.7-.8.4-1.8 1-2.6 1.1-.8.2-2 0-2.7 0-.9 0-2.1.2-3.1.3-.9.2-2.2.3-2.7.7-1.4.8-1.8 4.5-2.3 6.7-.2.8-.5 1.6-.7 2.4-.3 1.8-.5 3.7-.5 5.4-.1 3.5-.5 8.4 1.3 9.7.4.3 1.7.7 2.1.5.1 0 .6-.5.7-.7.1-.3-.2-.7-.2-1.1 0-.8-.2-1.8-.2-2.6 0-2.1.4-4.4.9-5.3 0-.1.3-.1.3-.2.1-.2 0-.4.2-.5.4-.4 1-.8 1.4-.9 1.2-.5 1.9.1 2.4.8 1 1.3 1.2 3.5 1.3 5.6v1.3c0 .5-.2 1-.2 1.3.3.8 1.7 1.2 2.3 1.6 0 .3.1.7.3.9.3.5.8.8 1.1 1 1.5.8 5.3.3 6-.7.1-.1.2-.2.2-.4.1-.3.3-.6.3-.8.6-1.8-.1-3.4.2-5.3zm-2.1-17.9c-.1.1-.1.1 0 0"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="52"><path style="stroke:none;fill-rule:nonzero;fill:#6781b2;fill-opacity:1" d="M36.18 38.57c3.308 1.235 8.703 1.063 12.535.528.7 1.593-.348 3.715.347 5.48.352.887 1.395 1.594 3.137 2.477.348.18.867.18 1.219.355l.348.352c.695.531 2.09 1.418 2.437 1.418.524.172 1.047.172 1.39.172h1.747c2.433-.172 4.87-.883 5.57-1.766 1.219-1.59.524-5.125.348-8.309-.176-2.652-.524-6.187 0-8.308.176-.707.87-1.418 1.215-2.301 1.394-3.004 2.789-7.957 2.27-12.73-.352-2.122-1.395-4.063-1.571-5.653 3.308.352 6.441-.355 9.226 0 1.747.172 3.137 1.41 4.704 1.235.351-.883 1.39-1.415 1.39-2.473.176-1.238-.344-2.656-.867-3.54-2.266-.35-4.004 1.77-6.266 1.95-.703 0-1.57-.18-2.441-.355-2.613-.18-6.266.527-8.531 0-1.567-.356-2.961-2.122-4.528-2.829-.347-.18-1.043 0-1.394-.355-.52-.176-.871-.531-1.215-.531-1.742-.703-3.66-1.414-5.402-1.59C48.543.91 44.016.91 39.836 1.266c-1.39.18-2.61.882-4.004.53C34.785 1.618 34.613.91 33.918.56c-2.965-1.414-5.922.175-7.84 1.238-1.39.707-3.129 1.766-4.527 1.945-1.39.352-3.48 0-4.7 0-1.566 0-3.656.352-5.398.531-1.566.352-3.828.528-4.7 1.235-2.437 1.414-3.132 7.957-4.007 11.847-.344 1.415-.867 2.829-1.215 4.243-.523 3.18-.875 6.543-.875 9.547-.172 6.187-.867 14.851 2.27 17.148.695.531 2.957 1.238 3.652.887.176 0 1.047-.887 1.219-1.239.176-.53-.344-1.238-.344-1.945 0-1.418-.351-3.184-.351-4.598 0-3.71.695-7.777 1.566-9.37 0-.176.523-.176.523-.352.176-.352 0-.707.352-.887.695-.703 1.738-1.414 2.434-1.59 2.09-.883 3.308.176 4.18 1.414 1.741 2.301 2.09 6.188 2.265 9.903v2.297c0 .882-.352 1.765-.352 2.296.524 1.414 2.961 2.125 4.008 2.832 0 .528.176 1.239.52 1.59.523.887 1.394 1.414 1.918 1.766 2.609 1.418 9.226.531 10.449-1.234.172-.18.344-.356.344-.708.171-.53.523-1.062.523-1.414 1.047-3.183-.172-6.011.348-9.37zM32.523 6.922c-.171.18-.171.18 0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pid.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.9-7h3.3v14.3h-3.3V6.4zm6.9 0h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z" fill="#fff"/><path class="st0" d="M53.8 69.2c-1.6-.5-2.7-2-2.7-3.7s1.1-3.2 2.7-3.7c.5-.2.8-.7.6-1.2-.5-1.8-1.1-3.4-2.1-5-.3-.5-.8-.6-1.3-.4-.6.3-1.2.5-1.9.5-2.2 0-3.9-1.8-3.9-3.9 0-.7.2-1.3.5-1.9.3-.5.1-1-.4-1.3-1.6-.9-3.3-1.6-5-2.1-.5-.1-1 .1-1.2.6-.5 1.6-2 2.7-3.7 2.7s-3.2-1.1-3.7-2.7c-.2-.5-.7-.8-1.2-.6-1.8.5-3.4 1.1-5 2.1-.5.3-.6.8-.4 1.3.3.6.5 1.2.5 1.9 0 2.2-1.8 3.9-3.9 3.9-.7 0-1.3-.2-1.9-.5-.5-.3-1-.1-1.3.4-.9 1.6-1.6 3.3-2.1 5-.1.5.1 1 .6 1.2 1.6.5 2.7 2 2.7 3.7 0 1.7-1.1 3.2-2.7 3.7-.5.2-.8.7-.6 1.2.5 1.8 1.1 3.4 2.1 5 .3.5.8.6 1.3.4.6-.3 1.2-.5 1.9-.5 2.2 0 3.9 1.8 3.9 3.9 0 .7-.2 1.3-.5 1.9-.3.5-.1 1 .4 1.3 1.6.9 3.3 1.6 5 2.1h.2c.4 0 .8-.3.9-.7.5-1.6 2-2.7 3.7-2.7 1.7 0 3.2 1.1 3.7 2.7.2.5.7.8 1.2.6 1.8-.5 3.4-1.1 5-2.1.5-.3.6-.8.4-1.3-.3-.6-.5-1.2-.5-1.9 0-2.2 1.8-3.9 3.9-3.9.7 0 1.3.2 1.9.5.5.3 1 .1 1.3-.4.9-1.6 1.6-3.3 2.1-5 .3-.4 0-.9-.5-1.1zm-18.3 2.2c-3.2 0-5.9-2.6-5.9-5.9 0-3.2 2.6-5.9 5.9-5.9 3.2 0 5.9 2.6 5.9 5.9 0 3.2-2.7 5.9-5.9 5.9z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M62.887 38.266c-2.684-.84-4.532-3.36-4.532-6.215 0-2.852 1.848-5.371 4.532-6.211.84-.336 1.343-1.172 1.008-2.012-.84-3.023-1.848-5.707-3.524-8.394-.504-.84-1.344-1.008-2.184-.672-1.007.504-2.015.84-3.19.84-3.692 0-6.548-3.024-6.548-6.547 0-1.176.336-2.184.84-3.188.504-.84.168-1.68-.672-2.183a40.47 40.47 0 0 0-8.39-3.528c-.84-.168-1.68.168-2.016 1.008C37.37 3.852 34.855 5.7 32 5.7s-5.371-1.847-6.21-4.535C25.452.324 24.612-.18 23.772.156c-3.02.84-5.707 1.848-8.39 3.528-.84.503-1.008 1.343-.672 2.183.504 1.004.84 2.012.84 3.188 0 3.691-3.024 6.547-6.547 6.547-1.176 0-2.184-.336-3.191-.84-.84-.504-1.68-.168-2.184.672a40.699 40.699 0 0 0-3.524 8.394c-.167.84.168 1.676 1.008 2.012 2.684.84 4.532 3.36 4.532 6.21 0 2.856-1.848 5.376-4.532 6.216-.84.332-1.343 1.172-1.008 2.011.84 3.024 1.848 5.707 3.524 8.395.504.84 1.344 1.008 2.184.672 1.007-.504 2.015-.84 3.19-.84 3.692 0 6.548 3.02 6.548 6.547 0 1.176-.336 2.183-.84 3.187-.504.84-.168 1.68.672 2.184a40.47 40.47 0 0 0 8.39 3.527h.336c.672 0 1.344-.504 1.512-1.176.84-2.687 3.356-4.535 6.211-4.535s5.371 1.848 6.211 4.535c.336.84 1.176 1.344 2.016 1.008 3.02-.84 5.707-1.847 8.39-3.527.84-.504 1.008-1.344.672-2.184-.504-1.004-.84-2.011-.84-3.187 0-3.692 3.024-6.547 6.547-6.547 1.176 0 2.184.336 3.192.84.84.504 1.68.168 2.183-.672a40.698 40.698 0 0 0 3.524-8.395c.503-.672 0-1.511-.84-1.843zm-30.719 3.691c-5.371 0-9.902-4.363-9.902-9.906 0-5.371 4.363-9.903 9.902-9.903 5.371 0 9.902 4.364 9.902 9.903 0 5.375-4.53 9.906-9.902 9.906zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pkg.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#4d1b9b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.9-7h3.3v5.5h.6l2.3-5.5H28l-2.9 6.8 3 7.4h-3.7l-2.3-5.8h-.6v5.8h-3.3V6.4zm17.9-.3c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.6-7.6 6.5-7.6z" fill="#fff"/><path class="st0" d="M43.6 68.3l-7.3-3.4L51 58l7.3 3.4-7.3 3.5-7.4 3.4zM51 51.2l-7.3-3.4-7.3 3.4L51 58.1l7.3-3.4-7.3-3.5zM28.9 61.4L21.6 58l-7.3 3.4L29 68.3l7.3-3.4-7.4-3.5zm0-6.8l7.3-3.4-7.3-3.4-14.7 6.9 7.3 3.4 7.4-3.5zM51 66.9l-6.6 3-.8.4-.8-.4-6.6-3-6.6 3-.8.4-.8-.4-6.6-3v10.7l14.7 7.7L51 77.6V66.9z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#4d1b9b"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pl.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3a3c5b}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.9-7h3.3v11.4H26v2.9h-7.6V6.4z"/><path class="st0" d="M54.5 65.5C54.5 75.7 46.2 84 36 84s-18.5-8.3-18.5-18.5S25.8 47 36 47s18.5 8.3 18.5 18.5"/><path class="st1" d="M48.9 66.9c-.6-3.9-4.7-6.5-7.8-8.4-1.3-.8-3.5-1.9-3.8-3.7-.1-.7-.1-1.5-.1-2.2v-.9c0-.4-.4.1-.6-.2-.5-.8-.3.2-.3.7.1 1 .3 2 .3 3 0 1.9-.3 3.8-.8 5.6-1.1 4.3-2 8.8-.9 13.2.2.9.5 1.8.9 2.7.1.3.3 1 .7 1.1 1.2.3 2.1.4 3 1.3.6.5 1 .2 1.7 0 2.1-.8 3.9-1.9 5.4-3.6 1.9-2.6 2.8-5.5 2.3-8.6m-2.2 3.9c-.2 1.6-1.2 3.1-2.2 4.3-.8.9-1.8 2-2.9 2.4-.4.1.1-.7.1-.7.3-.5.8-1 1.2-1.5.6-.7 1.1-1.5 1.4-2.3 1.1-2.9.9-6.3-.8-8.9-.9-1.4-2.2-2.6-3.4-3.7-.6-.5-1.2-1-1.7-1.6-.1-.1-1.2-1.5-.8-1.7.1-.1 2.4 2.3 2.6 2.5.9.7 1.9 1.4 2.8 2.2 1.2 1.1 2.4 2.3 3.1 3.8.7 1.6.8 3.5.6 5.2"/><path class="st1" d="M35.3 47.5c.3.2.4 1.6.4 2.8 0 1.2.1 6.5-.3 7.9-.4 1.4-1.3 3-2.2 4.4-1 1.4-2.1 4.3-2 6.1 0 1.8 1.1 4.7 1.9 6 .8 1.2 2.2 2.9 1.9 3.3-.5.7-2.7-1.7-3.9-3.1-1.1-1.4-2.3-4.2-2.3-6.4s1.2-4.2 2.1-5.4c.9-1.2 2.6-3.3 3.1-4.3s1-2 1.1-3.3c.2-1.3 0-6.1 0-6.1s-.1-2.1.2-1.9"/><path class="st1" d="M34.4 49.8c.3.2.4.6.4 1s-.1 2.1-.2 3.8c-.1 1.7-1.5 3.1-2.4 4.1-1 1-3.9 4.1-4.9 5.6-1.1 1.5-1.6 3.5-1.5 5.2.1 1.7.5 3.4 2.1 5.2 1.6 1.8 2.7 2.6 3.6 3.1.8.4 1.7.7 1.5 1.1-.2.4-1 .1-1.9-.2-.9-.3-3.9-1.5-5.6-3.5-1.7-2-2.6-4.6-2.5-7 .1-2.5.8-3.5 1.9-5.1 1.1-1.6 4.3-4 5.3-4.6 1-.6 2.3-1.6 3-2.5.7-.8 1-1.5 1-2.7 0-1.1.1-2.2 0-2.6-.1-.3-.1-1.1.2-.9m.1 30c.2 0 .1.7-.2 1-.3.3-.7.5-.8.4-.1-.1.3-.2.6-.5.3-.4.2-.9.4-.9m3.1-.1c-.2 0-.1.7.2 1 .3.3.7.5.8.4.1-.1-.3-.2-.6-.5s-.2-.9-.4-.9m-1.4.8c0 .6 0 1.1-.1 1.1-.2 0-.1-.5-.1-1.1 0-.6-.1-1.1.1-1.1s.1.5.1 1.1"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M64 32c0 17.645-14.355 32-32 32S0 49.645 0 32 14.355 0 32 0s32 14.355 32 32" fill="#3a3c5b"/><g fill="#fff"><path d="M54.313 34.422c-1.036-6.746-8.13-11.242-13.493-14.531-2.246-1.383-6.054-3.286-6.57-6.399-.176-1.21-.176-2.594-.176-3.805V8.13c0-.692-.691.172-1.035-.344-.867-1.387-.52.344-.52 1.211.172 1.727.52 3.457.52 5.188 0 3.285-.52 6.574-1.387 9.687-1.902 7.438-3.457 15.223-1.554 22.832a24.518 24.518 0 0 0 1.554 4.668c.176.52.52 1.73 1.211 1.906 2.078.516 3.633.692 5.192 2.246 1.039.868 1.73.348 2.941 0 3.633-1.382 6.746-3.285 9.34-6.226 3.285-4.496 4.844-9.512 3.977-14.875m-3.805 6.746c-.344 2.766-2.074 5.363-3.805 7.437-1.383 1.56-3.113 3.461-5.016 4.153-.69.172.172-1.211.172-1.211.52-.867 1.383-1.73 2.075-2.594 1.039-1.21 1.902-2.598 2.421-3.98 1.903-5.016 1.56-10.899-1.382-15.395-1.555-2.422-3.805-4.496-5.88-6.398-1.038-.868-2.077-1.73-2.94-2.77-.176-.172-2.079-2.594-1.387-2.941.175-.172 4.152 3.98 4.5 4.324 1.554 1.21 3.285 2.422 4.843 3.809 2.075 1.902 4.149 3.976 5.36 6.57 1.21 2.77 1.386 6.055 1.039 8.996"/><path d="M30.79.863c.519.348.69 2.77.69 4.844 0 2.078.172 11.246-.52 13.664-.69 2.422-2.245 5.192-3.804 7.613-1.73 2.422-3.633 7.438-3.457 10.551 0 3.113 1.903 8.13 3.285 10.38 1.383 2.073 3.805 5.015 3.286 5.706-.864 1.211-4.668-2.941-6.747-5.363-1.902-2.422-3.976-7.262-3.976-11.07 0-3.805 2.074-7.262 3.633-9.34 1.554-2.075 4.496-5.707 5.36-7.438.866-1.73 1.73-3.457 1.901-5.707.348-2.25 0-10.55 0-10.55S30.27.52 30.79.862"/><path d="M29.234 4.844c.516.343.692 1.039.692 1.73 0 .692-.176 3.633-.348 6.57-.172 2.942-2.594 5.364-4.152 7.094-1.727 1.73-6.746 7.09-8.473 9.688-1.906 2.594-2.77 6.05-2.598 8.992.176 2.941.868 5.883 3.633 8.996 2.77 3.113 4.672 4.496 6.227 5.363 1.387.692 2.941 1.211 2.597 1.903-.347.691-1.73.172-3.289-.348-1.554-.52-6.746-2.594-9.687-6.055-2.938-3.457-4.496-7.957-4.324-12.105.175-4.324 1.386-6.055 3.289-8.824 1.902-2.766 7.437-6.918 9.168-7.957 1.73-1.036 3.976-2.766 5.187-4.325 1.211-1.382 1.73-2.593 1.73-4.668 0-1.902.173-3.804 0-4.5-.171-.515-.171-1.902.348-1.554m.172 51.89c.344 0 .172 1.211-.347 1.73-.52.52-1.211.864-1.383.692s.52-.343 1.039-.863c.52-.691.344-1.559.691-1.559m5.36-.172c-.344 0-.172 1.211.347 1.731s1.211.863 1.383.691c.176-.172-.52-.347-1.035-.867-.52-.515-.348-1.554-.695-1.554m-2.418 1.382c0 1.04 0 1.903-.176 1.903-.344 0-.172-.864-.172-1.903 0-1.039-.172-1.902.172-1.902.348 0 .176.863.176 1.902"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/plist.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#b4bdcc}</style><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/><path d="M55.4 32.3H16.6c-1.5 0-2.6 1.2-2.6 2.6v26.9c0 1.5 1.2 2.6 2.6 2.6h38.7c1.5 0 2.6-1.2 2.6-2.6V35c.2-1.5-1-2.7-2.5-2.7z" fill="#ced2d8"/><path d="M16.6 38.8h38.8v23H16.6v-23z" fill="#f2f2f2"/><circle cx="23.7" cy="35.8" r=".9" fill="#54b845"/><circle cx="20.6" cy="35.8" r=".9" fill="#fbd303"/><circle cx="17.7" cy="35.8" r=".9" fill="#f0582f"/><path d="M30.4 70.1c-.5-.4-1-.8-1.4-1.3-.4-.5-.8-1.1-1.2-1.6-.9-1.3-1.5-2.7-2-4.1-.6-1.7-.8-3.3-.8-4.9 0-1.8.4-3.3 1.1-4.6.6-1 1.4-1.9 2.4-2.5 1-.6 2.1-.9 3.2-1 .4 0 .8.1 1.3.2.3.1.7.2 1.2.4.6.2 1 .4 1.1.4.4.1.7.2.9.2.2 0 .4-.1.7-.1.2-.1.5-.2.9-.4s.8-.3 1.1-.4l1.2-.3c.4-.1.9-.1 1.3-.1.8.1 1.5.2 2.2.5 1.2.5 2.1 1.2 2.8 2.2-.3.2-.6.4-.8.6-.6.5-1 1.1-1.4 1.7-.5.9-.7 1.9-.7 2.9 0 1.2.3 2.3 1 3.2.4.7 1 1.3 1.7 1.7.4.2.7.4 1 .5-.1.4-.3.8-.5 1.2-.4.9-.9 1.8-1.4 2.6-.5.7-.9 1.2-1.2 1.6-.5.5-.9 1-1.3 1.2-.5.3-1.1.5-1.6.5-.4 0-.8 0-1.2-.1-.3-.1-.7-.2-1-.4-.3-.2-.7-.3-1-.4-.4-.1-.9-.2-1.3-.2-.5 0-.9.1-1.3.2s-.7.2-1 .4c-.5.2-.8.3-1 .4-.4.1-.7.2-1.1.2-.8.1-1.4-.1-1.9-.4zm7.8-20.9c-.8.4-1.5.5-2.2.5-.1-.7 0-1.5.3-2.3.3-.7.6-1.3 1.1-1.9.5-.6 1.1-1.1 1.8-1.4.7-.4 1.5-.6 2.1-.6.1.8 0 1.5-.3 2.3-.3.7-.6 1.4-1.1 2-.5.5-1.1 1-1.7 1.4z" fill="#c6a8e5"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="M69.5 0H4.633C2.125 0 .285 2.008.285 4.352V49.39c0 2.511 2.004 4.351 4.348 4.351h64.699c2.508 0 4.348-2.008 4.348-4.351V4.52C74.016 2.008 72.008 0 69.5 0zm0 0" fill="#ced2d8"/><path d="M4.633 10.883H69.5V49.39H4.633zm0 0" fill="#f2f2f2"/><path d="M18.008 5.86c0 .831-.676 1.507-1.508 1.507a1.508 1.508 0 0 1 0-3.015c.832 0 1.508.675 1.508 1.507zm0 0" fill="#54b845"/><path d="M12.824 5.86c0 .831-.676 1.507-1.504 1.507a1.509 1.509 0 0 1 0-3.015c.828 0 1.504.675 1.504 1.507zm0 0" fill="#fbd303"/><path d="M7.977 5.86c0 .831-.676 1.507-1.508 1.507a1.508 1.508 0 0 1 0-3.015c.832 0 1.508.675 1.508 1.507zm0 0" fill="#f0582f"/><path d="M27.703 63.285c-.836-.668-1.672-1.336-2.34-2.176-.668-.836-1.34-1.84-2.008-2.68-1.503-2.175-2.507-4.519-3.343-6.863-1.004-2.843-1.336-5.523-1.336-8.203 0-3.015.668-5.523 1.84-7.703 1-1.672 2.34-3.18 4.011-4.183 1.672-1.004 3.512-1.508 5.348-1.676.672 0 1.34.168 2.176.336.5.168 1.168.336 2.004.668 1.004.336 1.672.672 1.84.672.667.168 1.171.335 1.503.335.336 0 .672-.167 1.172-.167.336-.168.836-.336 1.504-.672.668-.332 1.34-.5 1.84-.668l2.008-.504c.668-.168 1.504-.168 2.172-.168 1.336.168 2.508.336 3.68.84 2.003.836 3.507 2.007 4.68 3.683-.5.332-1.005.668-1.337 1.004-1.004.836-1.672 1.84-2.344 2.844-.836 1.508-1.168 3.184-1.168 4.855 0 2.012.5 3.852 1.672 5.36a7.757 7.757 0 0 0 2.84 2.847c.672.332 1.172.668 1.672.836-.164.668-.5 1.34-.836 2.008-.668 1.508-1.504 3.016-2.34 4.356-.836 1.172-1.504 2.007-2.004 2.675-.836.84-1.507 1.676-2.175 2.012-.836.5-1.84.836-2.676.836-.668 0-1.336 0-2.004-.168-.504-.168-1.172-.336-1.672-.668-.504-.336-1.172-.504-1.672-.672-.668-.168-1.504-.332-2.176-.332-.836 0-1.504.164-2.172.332s-1.171.336-1.671.672c-.836.332-1.336.5-1.672.668-.668.168-1.172.336-1.84.336-1.336.168-2.34-.168-3.176-.672zm13.04-34.992c-1.337.672-2.509.84-3.677.84-.168-1.172 0-2.512.5-3.852.504-1.172 1.004-2.176 1.84-3.18.836-1.007 1.84-1.843 3.008-2.343 1.172-.672 2.508-1.008 3.512-1.008.168 1.34 0 2.512-.5 3.852-.504 1.171-1.004 2.343-1.84 3.347-.836.84-1.84 1.676-2.844 2.344zm0 0" fill="#c6a8e5"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pm.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm8.4-7h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4H27s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.1 6.4h-3l.9-14.3z"/><path class="st0" d="M54.5 65.5C54.5 75.7 46.2 84 36 84s-18.5-8.3-18.5-18.5S25.8 47 36 47s18.5 8.3 18.5 18.5"/><path class="st1" d="M48.9 66.9c-.6-3.9-4.7-6.5-7.8-8.4-1.3-.8-3.5-1.9-3.8-3.7-.1-.7-.1-1.5-.1-2.2v-.9c0-.4-.4.1-.6-.2-.5-.8-.3.2-.3.7.1 1 .3 2 .3 3 0 1.9-.3 3.8-.8 5.6-1.1 4.3-2 8.8-.9 13.2.2.9.5 1.8.9 2.7.1.3.3 1 .7 1.1 1.2.3 2.1.4 3 1.3.6.5 1 .2 1.7 0 2.1-.8 3.9-1.9 5.4-3.6 1.9-2.6 2.8-5.5 2.3-8.6m-2.2 3.9c-.2 1.6-1.2 3.1-2.2 4.3-.8.9-1.8 2-2.9 2.4-.4.1.1-.7.1-.7.3-.5.8-1 1.2-1.5.6-.7 1.1-1.5 1.4-2.3 1.1-2.9.9-6.3-.8-8.9-.9-1.4-2.2-2.6-3.4-3.7-.6-.5-1.2-1-1.7-1.6-.1-.1-1.2-1.5-.8-1.7.1-.1 2.4 2.3 2.6 2.5.9.7 1.9 1.4 2.8 2.2 1.2 1.1 2.4 2.3 3.1 3.8.7 1.6.8 3.5.6 5.2"/><path class="st1" d="M35.3 47.5c.3.2.4 1.6.4 2.8 0 1.2.1 6.5-.3 7.9-.4 1.4-1.3 3-2.2 4.4-1 1.4-2.1 4.3-2 6.1 0 1.8 1.1 4.7 1.9 6 .8 1.2 2.2 2.9 1.9 3.3-.5.7-2.7-1.7-3.9-3.1-1.1-1.4-2.3-4.2-2.3-6.4s1.2-4.2 2.1-5.4c.9-1.2 2.6-3.3 3.1-4.3s1-2 1.1-3.3c.2-1.3 0-6.1 0-6.1s-.1-2.1.2-1.9"/><path class="st1" d="M34.4 49.8c.3.2.4.6.4 1s-.1 2.1-.2 3.8c-.1 1.7-1.5 3.1-2.4 4.1-1 1-3.9 4.1-4.9 5.6-1.1 1.5-1.6 3.5-1.5 5.2.1 1.7.5 3.4 2.1 5.2 1.6 1.8 2.7 2.6 3.6 3.1.8.4 1.7.7 1.5 1.1-.2.4-1 .1-1.9-.2-.9-.3-3.9-1.5-5.6-3.5-1.7-2-2.6-4.6-2.5-7 .1-2.5.8-3.5 1.9-5.1 1.1-1.6 4.3-4 5.3-4.6 1-.6 2.3-1.6 3-2.5.7-.8 1-1.5 1-2.7 0-1.1.1-2.2 0-2.6-.1-.3-.1-1.1.2-.9m.1 30c.2 0 .1.7-.2 1-.3.3-.7.5-.8.4-.1-.1.3-.2.6-.5.3-.4.2-.9.4-.9m3.1-.1c-.2 0-.1.7.2 1 .3.3.7.5.8.4.1-.1-.3-.2-.6-.5s-.2-.9-.4-.9m-1.4.8c0 .6 0 1.1-.1 1.1-.2 0-.1-.5-.1-1.1 0-.6-.1-1.1.1-1.1s.1.5.1 1.1"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M64 32c0 17.645-14.355 32-32 32S0 49.645 0 32 14.355 0 32 0s32 14.355 32 32" fill="#999"/><g fill="#fff"><path d="M54.313 34.422c-1.036-6.746-8.13-11.242-13.493-14.531-2.246-1.383-6.054-3.286-6.57-6.399-.176-1.21-.176-2.594-.176-3.805V8.13c0-.692-.691.172-1.035-.344-.867-1.387-.52.344-.52 1.211.172 1.727.52 3.457.52 5.188 0 3.285-.52 6.574-1.387 9.687-1.902 7.438-3.457 15.223-1.554 22.832a24.518 24.518 0 0 0 1.554 4.668c.176.52.52 1.73 1.211 1.906 2.078.516 3.633.692 5.192 2.246 1.039.868 1.73.348 2.941 0 3.633-1.382 6.746-3.285 9.34-6.226 3.285-4.496 4.844-9.512 3.977-14.875m-3.805 6.746c-.344 2.766-2.074 5.363-3.805 7.437-1.383 1.56-3.113 3.461-5.016 4.153-.69.172.172-1.211.172-1.211.52-.867 1.383-1.73 2.075-2.594 1.039-1.21 1.902-2.598 2.421-3.98 1.903-5.016 1.56-10.899-1.382-15.395-1.555-2.422-3.805-4.496-5.88-6.398-1.038-.868-2.077-1.73-2.94-2.77-.176-.172-2.079-2.594-1.387-2.941.175-.172 4.152 3.98 4.5 4.324 1.554 1.21 3.285 2.422 4.843 3.809 2.075 1.902 4.149 3.976 5.36 6.57 1.21 2.77 1.386 6.055 1.039 8.996"/><path d="M30.79.863c.519.348.69 2.77.69 4.844 0 2.078.172 11.246-.52 13.664-.69 2.422-2.245 5.192-3.804 7.613-1.73 2.422-3.633 7.438-3.457 10.551 0 3.113 1.903 8.13 3.285 10.38 1.383 2.073 3.805 5.015 3.286 5.706-.864 1.211-4.668-2.941-6.747-5.363-1.902-2.422-3.976-7.262-3.976-11.07 0-3.805 2.074-7.262 3.633-9.34 1.554-2.075 4.496-5.707 5.36-7.438.866-1.73 1.73-3.457 1.901-5.707.348-2.25 0-10.55 0-10.55S30.27.52 30.79.862"/><path d="M29.234 4.844c.516.343.692 1.039.692 1.73 0 .692-.176 3.633-.348 6.57-.172 2.942-2.594 5.364-4.152 7.094-1.727 1.73-6.746 7.09-8.473 9.688-1.906 2.594-2.77 6.05-2.598 8.992.176 2.941.868 5.883 3.633 8.996 2.77 3.113 4.672 4.496 6.227 5.363 1.387.692 2.941 1.211 2.597 1.903-.347.691-1.73.172-3.289-.348-1.554-.52-6.746-2.594-9.687-6.055-2.938-3.457-4.496-7.957-4.324-12.105.175-4.324 1.386-6.055 3.289-8.824 1.902-2.766 7.437-6.918 9.168-7.957 1.73-1.036 3.976-2.766 5.187-4.325 1.211-1.382 1.73-2.593 1.73-4.668 0-1.902.173-3.804 0-4.5-.171-.515-.171-1.902.348-1.554m.172 51.89c.344 0 .172 1.211-.347 1.73-.52.52-1.211.864-1.383.692s.52-.343 1.039-.863c.52-.691.344-1.559.691-1.559m5.36-.172c-.344 0-.172 1.211.347 1.731s1.211.863 1.383.691c.176-.172-.52-.347-1.035-.867-.52-.515-.348-1.554-.695-1.554m-2.418 1.382c0 1.04 0 1.903-.176 1.903-.344 0-.172-.864-.172-1.903 0-1.039-.172-1.902.172-1.902.348 0 .176.863.176 1.902"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/png.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.9-7h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4L22 14.1c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4zm19-.3c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.6-7.6 6.5-7.6z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/po.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#a87c2d}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9s-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm13.1-7.3c3.8 0 5.9 3.1 5.9 7.3s-2.1 7.5-5.9 7.5-5.8-3.2-5.8-7.5c0-4.1 2.1-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2c.1 2.5.8 4.3 2.5 4.3z" fill="#fff"/><path d="M34.9 68.2c-2.5-2.4-4.7-4.6-6-9.6h8.8V55H29v-4.9h-3.8v5h-8.8v3.7h9s-.1.7-.2 1.3c-1.3 4.9-2.7 8-8.8 11l1.3 3.7c5.7-3 8.7-6.9 10-11.1 1.3 3.2 3.4 5.8 5.8 8.2l1.4-3.7zm11.6-12h-5l-8.8 24.7h3.8l2.5-7.4h10l2.5 7.4h3.8l-8.8-24.7zm-6.2 13.6l3.8-9.8 3.8 9.9-7.6-.1z" fill="#a87c2d" stroke="#a87c2d" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><path d="M38.027 37.414c-5.011-4.812-9.425-9.223-12.03-19.25H43.64v-7.219H26.195V1.121h-7.617v10.024H.93v7.421h18.047s-.2 1.403-.399 2.606C15.968 30.996 13.164 37.215.93 43.23l2.61 7.418c11.429-6.015 17.444-13.835 20.05-22.257 2.605 6.418 6.816 11.629 11.629 16.441zM61.29 13.352H51.262L33.617 62.879h7.617l5.016-14.836H66.3l5.013 14.836h7.62zm-12.434 27.27 7.622-19.65 7.617 19.852zm0 0" fill="#a87c2d" stroke="#a87c2d" stroke-miterlimit="10" stroke-width="1.5039150000000001"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pom.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#ef712f}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9s-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm11.6-7.3c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2.1-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2c.1 2.5.8 4.3 2.5 4.3zm8-11.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6H41l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H34l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3z" fill="#fff"/><path class="st0" d="M52.5 47.1s-14.4.2-23.6 11.9c-.5.7-1 1.3-1.5 2-.3.4-.6 4.4-.6 4.4s-.4-.3-.6-.8c-.3-.6-.4-1.3-.4-1.3-5.2 8.5-3.7 12.9-3.7 12.9-.4 1-1.2 1.6-2.3 3.9-1.1 2.3-1 4.5-1 4.5 0 .4.1.5.3.1 0 0 1.2-2.3 2.1-3.8.6-1 2.4-3.3 2.4-3.3s3 .1 6.6-.8c-.3-.1-1.3-.4-2-.7-.7-.3-1.1-.8-1.1-.8l12.9-3c1.8-1.1 3.4-2.4 4.7-4 6.8-8.1 8.5-20.5 8.5-20.5.1-.4-.2-.7-.7-.7zM39.7 60s-6 5.3-9 8.1-7 9.5-7 9.5l-1.5-1.4s1.1-2.7 5.5-8.1c4.3-5.3 11.8-8.6 11.8-8.6.9-.4 1-.2.2.5z"/></svg>
1
<svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M55.809.504S31.965.832 16.73 19.992c-.828 1.145-1.656 2.13-2.484 3.274-.496.656-.996 7.207-.996 7.207s-.66-.493-.992-1.309c-.496-.984-.664-2.129-.664-2.129C2.984 40.953 5.469 48.16 5.469 48.16c-.664 1.637-1.989 2.617-3.809 6.387C-.16 58.313.004 61.914.004 61.914c0 .656.164.82.496.164 0 0 1.988-3.766 3.477-6.223.996-1.636 3.976-5.402 3.976-5.402s4.969.16 10.93-1.312c-.496-.164-2.153-.657-3.313-1.145-1.16-.492-1.82-1.312-1.82-1.312l21.36-4.91c2.98-1.801 5.628-3.93 7.785-6.551 11.257-13.266 14.074-33.57 14.074-33.57.164-.657-.332-1.15-1.16-1.15zM34.613 21.629s-9.937 8.68-14.902 13.266C14.742 39.48 8.117 50.453 8.117 50.453L5.633 48.16s1.824-4.422 9.11-13.265c7.12-8.68 19.538-14.083 19.538-14.083 1.492-.656 1.657-.328.332.817zm0 0" fill="#ef712f"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pot.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#c93}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm13.1-7.3c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2.1-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2c.1 2.5.8 4.3 2.5 4.3zm10.6-8.5H31V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path d="M34.9 68.2c-2.5-2.4-4.7-4.6-6-9.6h8.8V55H29v-4.9h-3.8v5h-8.8v3.7h9s-.1.7-.2 1.3c-1.3 4.9-2.7 8-8.8 11l1.3 3.7c5.7-3 8.7-6.9 10-11.1 1.3 3.2 3.4 5.8 5.8 8.2l1.4-3.7zm11.6-12h-5l-8.8 24.7h3.8l2.5-7.4h10l2.5 7.4h3.8l-8.8-24.7zm-6.2 13.6l3.8-9.8 3.8 9.9-7.6-.1z" fill="#c93" stroke="#c93" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><path d="M38.027 37.414c-5.011-4.812-9.425-9.223-12.03-19.25H43.64v-7.219H26.195V1.121h-7.617v10.024H.93v7.421h18.047s-.2 1.403-.399 2.606C15.968 30.996 13.164 37.215.93 43.23l2.61 7.418c11.429-6.015 17.444-13.835 20.05-22.257 2.605 6.418 6.816 11.629 11.629 16.441zM61.29 13.352H51.262L33.617 62.879h7.617l5.016-14.836H66.3l5.013 14.836h7.62zm-12.434 27.27 7.622-19.65 7.617 19.852zm0 0" fill="#c93" stroke="#c93" stroke-miterlimit="10" stroke-width="1.5039150000000001"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/potx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2{fill:#f57e00}.st2{stroke:#f57e00;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.4-34.6H10c2.1 0 3.5 2 3.5 4.9 0 2.9-1.4 5-3.5 5H9v4.4H6.4V6.4zm3.1 7c.8 0 1.3-.9 1.3-2.1s-.5-2-1.2-2H9v4.1h.5zm9.7-7.3c3 0 4.7 3.1 4.7 7.3 0 4.2-1.7 7.5-4.7 7.5s-4.7-3.2-4.7-7.5c0-4.1 1.7-7.3 4.7-7.3zm0 11.7c1.4 0 2-1.8 2-4.3s-.6-4.2-2-4.2-2 1.7-2 4.2.7 4.3 2 4.3zm7.6-8.5h-2.5V6.4H32v2.9h-2.5v11.4h-2.6V9.3zm8.5 4.3l-2.8-7.2h2.9l.9 2.9c.3.9.4 1.8.4 1.8s.2-.9.5-1.8l.9-2.9H41l-2.8 7.2 2.7 7.1h-2.8l-.9-3c-.2-.9-.4-1.7-.4-1.7s-.2.8-.4 1.7l-.9 3h-2.8l2.6-7.1z" fill="#fff"/><path class="st2" d="M53 47.7H19c-1.7 0-3.1 1.4-3.1 3.1v21.8c0 1.7 1.4 3.1 3.1 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.5-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.5 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.1-1.4 3.1-3.1V50.8c0-1.7-1.4-3.1-3.1-3.1zm.3 25.1H18.7V50.6h34.5l.1 22.2z"/><path class="st2" d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.8v7.4h-2.8zm4.6-1.9h2.8v9.3h-2.8zm4.6-1.8h2.8v11.1h-2.8zm-.2-4.1L36.4 57l-3.6-1.2-6.1 3.3.9 1 5.4-2.8 3.6 1.2 5.6-3.1.9 1 2.1-3.5-4.8.3z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#f57e00" stroke="#f57e00" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pps.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2{fill:#f57e00}.st2{stroke:#f57e00;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.9-7h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm8.5 3.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.3-.5-1.3-.9-2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8z" fill="#fff"/><path class="st2" d="M53 47.7H19c-1.7 0-3.1 1.4-3.1 3.1v21.8c0 1.7 1.4 3.1 3.1 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.5-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.5 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.1-1.4 3.1-3.1V50.8c0-1.7-1.4-3.1-3.1-3.1zm.3 25.1H18.7V50.6h34.5l.1 22.2z"/><path class="st2" d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.8v7.4h-2.8zm4.6-1.9h2.8v9.3h-2.8zm4.6-1.8h2.8v11.1h-2.8zm-.2-4.1L36.4 57l-3.6-1.2-6.1 3.3.9 1 5.4-2.8 3.6 1.2 5.6-3.1.9 1 2.1-3.5-4.8.3z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#f57e00" stroke="#f57e00" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ppsx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2{fill:#f57e00}.st2{stroke:#f57e00;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.5-34.6h4.1c2.4 0 3.9 2 3.9 4.9 0 2.9-1.6 5-3.9 5H9.5v4.4h-3V6.4zm3.5 7c.9 0 1.5-.9 1.5-2.1s-.6-2-1.4-2h-.6v4.1h.5zm5.7-7h4.1c2.4 0 3.9 2 3.9 4.9 0 2.9-1.6 5-3.9 5h-1.1v4.4h-3V6.4zm3.5 7c.9 0 1.5-.9 1.5-2.1s-.6-2-1.4-2h-.6v4.1h.5zm6.4 3.3c.5.6 1.3 1.2 2.1 1.2s1.2-.6 1.2-1.2c0-2-4.3-2.1-4.3-6.2 0-2.4 1.5-4.3 4.1-4.3 1.1 0 2.2.3 3.1 1l-1.1 2.9c-.4-.4-1.3-.9-1.9-.9-.8 0-1.2.6-1.2 1.2 0 2.1 4.3 2 4.3 6.1 0 2.3-1.3 4.4-4 4.4-1.3 0-2.6-.5-3.6-1.4l1.3-2.8zm9.7-3.1l-3.1-7.2h3.3l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3.2l-3.1 7.2 3 7.1h-3.2l-1-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3h-3.2l3.1-7.1z" fill="#fff"/><path class="st2" d="M53 47.7H19c-1.7 0-3.1 1.4-3.1 3.1v21.8c0 1.7 1.4 3.1 3.1 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.5-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.5 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.1-1.4 3.1-3.1V50.8c0-1.7-1.4-3.1-3.1-3.1zm.3 25.1H18.7V50.6h34.5l.1 22.2z"/><path class="st2" d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.8v7.4h-2.8zm4.6-1.9h2.8v9.3h-2.8zm4.6-1.8h2.8v11.1h-2.8zm-.2-4.1L36.4 57l-3.6-1.2-6.1 3.3.9 1 5.4-2.8 3.6 1.2 5.6-3.1.9 1 2.1-3.5-4.8.3z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#f57e00" stroke="#f57e00" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ppt.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2{fill:#f57e00}.st2{stroke:#f57e00;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.9-7h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm10-4.1h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path class="st2" d="M53 47.7H19c-1.7 0-3.1 1.4-3.1 3.1v21.8c0 1.7 1.4 3.1 3.1 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.5-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.5 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.1-1.4 3.1-3.1V50.8c0-1.7-1.4-3.1-3.1-3.1zm.3 25.1H18.7V50.6h34.5l.1 22.2z"/><path class="st2" d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.8v7.4h-2.8zm4.6-1.9h2.8v9.3h-2.8zm4.6-1.8h2.8v11.1h-2.8zm-.2-4.1L36.4 57l-3.6-1.2-6.1 3.3.9 1 5.4-2.8 3.6 1.2 5.6-3.1.9 1 2.1-3.5-4.8.3z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#f57e00" stroke="#f57e00" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pptm.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2{fill:#f57e00}.st2{stroke:#f57e00;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.4-34.6H10c2.1 0 3.5 2 3.5 4.9 0 2.9-1.4 5-3.5 5H9v4.4H6.4V6.4zm3.1 7c.8 0 1.3-.9 1.3-2.1s-.5-2-1.2-2H9v4.1h.5zm5.5-7h3.6c2.1 0 3.5 2 3.5 4.9 0 2.9-1.4 5-3.5 5h-1v4.4H15V6.4zm3.1 7c.8 0 1.3-.9 1.3-2.1s-.5-2-1.2-2h-.5v4.1h.4zm7.3-4.1h-2.5V6.4h7.7v2.9H28v11.4h-2.6V9.3zm6.9-2.9h2.9l1.1 6c.2.9.3 2.4.3 2.4s.2-1.5.3-2.4l1.1-6h3l.7 14.3h-2.4l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.7 4.1h-2.5l-.7-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.1 6.4h-2.4l.7-14.3z" fill="#fff"/><path class="st2" d="M53 47.7H19c-1.7 0-3.1 1.4-3.1 3.1v21.8c0 1.7 1.4 3.1 3.1 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.5-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.5 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.1-1.4 3.1-3.1V50.8c0-1.7-1.4-3.1-3.1-3.1zm.3 25.1H18.7V50.6h34.5l.1 22.2z"/><path class="st2" d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.8v7.4h-2.8zm4.6-1.9h2.8v9.3h-2.8zm4.6-1.8h2.8v11.1h-2.8zm-.2-4.1L36.4 57l-3.6-1.2-6.1 3.3.9 1 5.4-2.8 3.6 1.2 5.6-3.1.9 1 2.1-3.5-4.8.3z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#f57e00" stroke="#f57e00" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pptx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2{fill:#f57e00}.st2{stroke:#f57e00;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.5-34.6h4.1c2.4 0 3.9 2 3.9 4.9 0 2.9-1.6 5-3.9 5H9.5v4.4h-3V6.4zm3.5 7c.9 0 1.5-.9 1.5-2.1s-.6-2-1.4-2h-.6v4.1h.5zm5.7-7h4.1c2.4 0 3.9 2 3.9 4.9 0 2.9-1.6 5-3.9 5h-1.1v4.4h-3V6.4zm3.5 7c.9 0 1.5-.9 1.5-2.1s-.6-2-1.4-2h-.6v4.1h.5zM27 9.3h-2.8V6.4h8.6v2.9H30v11.4h-3V9.3zm9 4.3l-3.1-7.2h3.3l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3.2l-3.1 7.2 3 7.1h-3.2l-1-3c-.1-.9-.3-1.7-.3-1.7s-.2.8-.5 1.7l-1 3H33l3-7.1z" fill="#fff"/><path class="st2" d="M53 47.7H19c-1.7 0-3.1 1.4-3.1 3.1v21.8c0 1.7 1.4 3.1 3.1 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.5-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.5 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.1-1.4 3.1-3.1V50.8c0-1.7-1.4-3.1-3.1-3.1zm.3 25.1H18.7V50.6h34.5l.1 22.2z"/><path class="st2" d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.8v7.4h-2.8zm4.6-1.9h2.8v9.3h-2.8zm4.6-1.8h2.8v11.1h-2.8zm-.2-4.1L36.4 57l-3.6-1.2-6.1 3.3.9 1 5.4-2.8 3.6 1.2 5.6-3.1.9 1 2.1-3.5-4.8.3z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#f57e00" stroke="#f57e00" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/prop.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.5h3.5c2.2 0 3.7 1.9 3.7 4.6s-1.5 4.7-3.7 4.7H8.8v4.9H6.6V6.5zm3.2 7.1c1.1 0 1.9-1 1.9-2.5s-.8-2.5-1.8-2.5H8.8v5h1zm5.4-7.1h3.6c.5 0 1.1.1 1.6.4 1.1.6 1.9 2 1.9 3.8 0 1.9-.9 3.3-1.8 3.9 0 0 .2.3.4.8l2.1 5.3h-2.3l-1.9-5.3h-1.3v5.3h-2.1V6.5zm3.3 6.7c.9 0 1.7-.9 1.7-2.3 0-.8-.2-1.5-.7-1.9-.3-.2-.7-.3-1-.3h-1.2v4.6h1.2zm10.2-7c3 0 5 3 5 7.3s-1.9 7.4-5 7.4-5-3.1-5-7.4c0-4.2 1.9-7.3 5-7.3zm0 12.4c1.7 0 2.8-2 2.8-5.1 0-3-1-4.9-2.8-4.9-1.8 0-2.8 1.9-2.8 4.9 0 3.1 1 5.1 2.8 5.1zm6.7-12.1h3.5c2.2 0 3.7 1.9 3.7 4.6s-1.5 4.7-3.7 4.7h-1.4v4.9h-2.1V6.5zm3.1 7.1c1.1 0 1.9-1 1.9-2.5s-.8-2.5-1.8-2.5h-1.1v5h1z" fill="#fff"/><path class="st0" d="M26.7 75.1c0 .9.6 1.5 1.5 1.5h1.6V82c0 1.2 1.1 2.3 2.3 2.3 1.2 0 2.3-1.1 2.3-2.3v-5.4h3.1V82c0 1.2 1.1 2.3 2.3 2.3 1.2 0 2.3-1.1 2.3-2.3v-5.4h1.5c.9 0 1.5-.6 1.5-1.6V59.6H26.7v15.5zm-3.9-15.5c-1.2 0-2.3 1.1-2.3 2.3v10.8c0 1.2 1.1 2.3 2.3 2.3 1.2 0 2.3-1.1 2.3-2.3V61.9c0-1.2-1-2.3-2.3-2.3zm26.4 0c-1.2 0-2.3 1.1-2.3 2.3v10.8c0 1.2 1.1 2.3 2.3 2.3 1.2 0 2.3-1.1 2.3-2.3V61.9c0-1.2-1.1-2.3-2.3-2.3zm-7.8-9l2-2c.3-.3.3-.8 0-1.1-.3-.3-.8-.3-1.1 0L40 49.8c-1.1-.8-2.5-1.1-4-1.1-1.6 0-2.9.3-4.2.9l-2.2-2.3c-.3-.2-.9-.2-1.2 0-.2.3-.2.9 0 1.2l2 2c-2.2 1.7-3.7 4.3-3.7 7.4h18.6c0-3-1.5-5.7-3.9-7.3zm-8.5 4.3h-1.6v-1.5h1.6v1.5zm7.8 0h-1.6v-1.5h1.6v1.5z" id="android"/></svg>
1
<svg height="64" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M10.867 48.152c0 1.551 1.04 2.582 2.602 2.582h2.773v9.305c0 2.066 1.91 3.961 3.992 3.961s3.989-1.895 3.989-3.96v-9.306h5.379v9.305c0 2.066 1.91 3.961 3.992 3.961s3.988-1.895 3.988-3.96v-9.306h2.602c1.562 0 2.605-1.03 2.605-2.757V21.449H10.867zM4.097 21.45C2.017 21.45.11 23.344.11 25.41v18.606c0 2.066 1.907 3.96 3.989 3.96s3.992-1.894 3.992-3.96V25.41c0-2.066-1.735-3.96-3.992-3.96zm45.805 0c-2.082 0-3.992 1.895-3.992 3.961v18.606c0 2.066 1.91 3.96 3.992 3.96s3.989-1.894 3.989-3.96V25.41c0-2.066-1.907-3.96-3.989-3.96zM36.367 5.945l3.473-3.449c.52-.516.52-1.375 0-1.894a1.373 1.373 0 0 0-1.91 0L33.94 4.566c-1.91-1.379-4.34-1.894-6.941-1.894-2.777 0-5.031.515-7.285 1.55L15.898.259c-.523-.344-1.562-.344-2.082 0-.347.515-.347 1.55 0 2.066l3.47 3.446c-3.817 2.93-6.419 7.41-6.419 12.75h32.266c0-5.168-2.602-9.82-6.766-12.575zm-14.746 7.407h-2.773v-2.586h2.773zm13.531 0H32.38v-2.586h2.773zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ps.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fea500}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm8.6 3.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path class="st0" d="M27.1 60.2L18 79.4l1.7 1.7L31 69.8c-.4-.9-.3-2 .5-2.8 1-1 2.5-1 3.5 0s1 2.5 0 3.5c-.7.7-1.9.9-2.8.5L20.9 82.3l1.7 1.7 19.2-9.1L46 63.4 38.6 56l-11.5 4.2zm26.3-2.3L44 48.5c-.8-.8-2-.8-2.8 0L39 50.7c-.8.8-.8 2 0 2.8l9.4 9.4c.8.8 2 .8 2.8 0l2.2-2.2c.8-.8.8-2 0-2.8z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M16.223 21.805.09 55.844l3.012 3.015 20.035-20.035c-.711-1.594-.532-3.543.886-4.96 1.774-1.774 4.43-1.774 6.204 0 1.773 1.769 1.773 4.429 0 6.202-1.243 1.243-3.368 1.594-4.965.887L5.23 60.984 8.242 64l34.04-16.133L49.73 27.48 36.61 14.36zm46.625-4.075L46.184 1.062c-1.418-1.417-3.547-1.417-4.965 0L37.32 4.966c-1.422 1.418-1.422 3.543 0 4.965l16.664 16.664c1.418 1.418 3.543 1.418 4.965 0l3.899-3.903c1.418-1.418 1.418-3.543 0-4.96zm0 0" fill="#fea500"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ps1.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#6190aa}.st1{fill:#fff}.st2{fill:#737373}.st4{fill:#517889}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm8.6 3.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm9.8 1.2h2.3v-6.2c0-.5.1-1 .1-1s-.1.3-.4.7l-.6.6-1.9-1.9 3.2-3.7h2.8v11.5h2.3v2.8h-7.9v-2.8z"/><path class="st2" d="M37.7 45.8l-13.5 7.8v15.5l13.5 7.8 13.5-7.8V53.6z"/><path class="st2" d="M24.2 53.6l13.5 7.8 13.5-7.8-13.5-7.8z"/><path class="st2" d="M24.2 69.1l13.5 7.8 13.5-7.8-13.5-7.7z"/><path class="st1" d="M23.8 69.9l13.5 7.7c.1.1.3.1.4.1s.3-.1.4-.1l13.5-7.8c.3-.1.4-.4.4-.7V53.6c0-.3-.1-.5-.4-.7l-13.5-7.7c-.3-.1-.5-.1-.8 0L23.8 53c-.3.1-.4.4-.4.7v15.6c0 .1.1.4.4.6zm13.9-23.2l11.9 6.9-11.9 7-11.9-7 11.9-6.9m1.6 14.7L50.4 55v13.7l-11.9 6.9V61.9M25 67.7V55l11.1 6.4.8.5v13.7L25 68.7"/><path class="st1" d="M27.5 67.4l-7.1 4.1v8.1l7.1 4.1 7-4.1v-8.1z"/><path class="st1" d="M20.4 71.5l7.1 4 7-4-7-4.1zm0 8.1l7.1 4.1 7-4.1-7-4.1z"/><path d="M20.2 80l7.1 4.1c.1.1.1.1.2.1s.1 0 .2-.1l7.1-4.1c.1-.1.2-.2.2-.3v-8.2c0-.1-.1-.3-.2-.3l-7.1-4.1c-.1-.1-.3-.1-.4 0l-7.1 4.1c-.1.1-.2.2-.2.3v8.1c0 .1.1.3.2.4zm7.3-12.1l6.2 3.6-6.2 3.7-6.2-3.7 6.2-3.6m.8 7.6l5.8-3.3v7.2l-6.2 3.5v-7.2m-7 3.2v-6.7l5.8 3.3.4.3V83l-6.2-3.6" fill="#444"/><path class="st4" d="M35.3 74.1l-4.6 2.6V82l4.6 2.7 4.6-2.7v-5.3z"/><path class="st4" d="M30.7 76.7l4.6 2.6 4.6-2.6-4.6-2.6zm0 5.3l4.6 2.7 4.6-2.7-4.6-2.7z"/><path class="st1" d="M30.6 82.3l4.6 2.7c.1 0 .1.1.1.1s.1 0 .1-.1l4.6-2.7c.1-.1.1-.1.1-.3v-5.3c0-.1-.1-.2-.1-.3l-4.6-2.7c-.1-.1-.2-.1-.3 0l-4.6 2.7c-.1.1-.1.1-.1.3V82c.1.1.1.2.2.3zm4.7-7.9l4.1 2.3-4.1 2.3-4.1-2.4 4.1-2.2m.6 4.9l3.7-2.2v4.7l-4.1 2.3v-4.6m-4.5 2v-4.3l3.7 2.2.3.1v4.6l-4.1-2.3"/></svg>
1
<svg height="63" width="51" xmlns="http://www.w3.org/2000/svg"><g fill="#737373"><path d="M28.21 1.082 6.696 13.367v24.414l21.516 12.285 21.516-12.285V13.367zm0 0"/><path d="m6.695 13.367 21.516 12.285 21.516-12.285L28.21 1.082zM6.695 37.781l21.516 12.285 21.516-12.285L28.21 25.652zm0 0"/></g><path d="M6.055 39.04 27.57 51.167c.16.156.48.156.64.156.157 0 .477-.156.638-.156l21.515-12.285c.477-.156.637-.63.637-1.102V13.367c0-.472-.16-.785-.637-1.101L28.848.136c-.48-.156-.797-.156-1.278 0L6.055 12.423c-.477.16-.637.633-.637 1.101v24.57c0 .16.16.634.637.946zM28.21 2.5l18.965 10.867L28.21 24.395 9.242 13.367zm2.547 23.152 17.691-10.078v21.574L29.484 48.02V26.44M7.97 35.574v-20L25.66 25.652l1.274.79V48.02L7.969 37.148" fill="#fff"/><path d="M11.953 35.102.637 41.559v12.757l11.316 6.457 11.156-6.457V41.56zm0 0" fill="#fff"/><path d="m.637 41.559 11.316 6.3 11.156-6.3-11.156-6.457zm0 12.757 11.316 6.457 11.156-6.457-11.156-6.457zm0 0" fill="#fff"/><path d="m.32 54.95 11.313 6.456c.16.157.16.157.32.157s.16 0 .32-.157l11.313-6.457c.16-.16.32-.316.32-.472V41.559c0-.157-.16-.473-.32-.473l-11.313-6.457a.496.496 0 0 0-.64 0L.32 41.086c-.16.16-.32.316-.32.473v12.757c0 .16.16.473.32.633zm11.633-19.06 9.883 5.669-9.883 5.828-9.883-5.828zm1.274 11.97 9.246-5.196v11.34l-9.883 5.512v-11.34M1.434 53.215v-10.55l9.246 5.194.636.473v11.34l-9.882-5.668" fill="#444"/><path d="m24.383 45.656-7.328 4.094v8.348l7.328 4.254 7.332-4.254V49.75zm0 0" fill="#517889"/><path d="m17.055 49.75 7.328 4.094 7.332-4.094-7.332-4.094zm0 8.348 7.328 4.254 7.332-4.254-7.332-4.254zm0 0" fill="#517889"/><path d="m16.895 58.57 7.332 4.254c.156 0 .156.156.156.156s.16 0 .16-.156l7.332-4.254c.16-.156.16-.156.16-.472V49.75c0-.156-.16-.316-.16-.473l-7.332-4.254c-.16-.156-.316-.156-.477 0l-7.332 4.254c-.16.157-.16.157-.16.473v8.348c.16.156.16.316.32.472zm7.488-12.441 6.535 3.621-6.535 3.621-6.531-3.777zm.957 7.715 5.898-3.465v7.402l-6.535 3.625V54.16m-7.172 3.149v-6.77l5.899 3.465.476.156v7.246l-6.535-3.625" fill="#fff"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/psd.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#03c}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm8.6 3.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zM29 6.4h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2H29V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z" fill="#fff"/><path d="M25.9 68.5c-1 0-2-.1-2.8-.3v12.1h-3.8V52.6c1.9-.9 4.5-1.6 7.2-1.6 6.8 0 9.9 3.6 9.9 8.7 0 4.9-3.2 8.8-10.5 8.8zm.6-15.2c-1.3 0-2.5.3-3.4.6V66c.8.1 1.8.2 2.8.2 5 0 6.8-2.9 6.8-6.5 0-3.9-1.8-6.4-6.2-6.4zM46 80.8c-2.2 0-4.7-.6-6.1-1.6l1-2.4c1.3.8 3.1 1.3 4.7 1.3 2.6 0 4.4-1.7 4.4-3.9 0-5.5-9.6-3.3-9.6-10.8 0-3.5 2.8-6.2 7-6.2 2.2 0 4.2.5 5.7 1.6l-1 2.2c-1.2-.8-2.7-1.3-4.2-1.3-2.6 0-3.8 1.6-3.8 3.6 0 5.2 9.7 3.1 9.7 10.8-.1 3.6-3.2 6.7-7.8 6.7z" fill="#03c" stroke="#03c" stroke-width="1.25" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="M7.225 18.125c-1 0-2-.1-2.8-.3v12.1h-3.8v-27.7c1.9-.9 4.5-1.6 7.2-1.6 6.8 0 9.9 3.6 9.9 8.7 0 4.9-3.2 8.8-10.5 8.8zm.6-15.2c-1.3 0-2.5.3-3.4.6v12.1c.8.1 1.8.2 2.8.2 5 0 6.8-2.9 6.8-6.5 0-3.9-1.8-6.4-6.2-6.4zm19.5 27.5c-2.2 0-4.7-.6-6.1-1.6l1-2.4c1.3.8 3.1 1.3 4.7 1.3 2.6 0 4.4-1.7 4.4-3.9 0-5.5-9.6-3.3-9.6-10.8 0-3.5 2.8-6.2 7-6.2 2.2 0 4.2.5 5.7 1.6l-1 2.2c-1.2-.8-2.7-1.3-4.2-1.3-2.6 0-3.8 1.6-3.8 3.6 0 5.2 9.7 3.1 9.7 10.8-.1 3.6-3.2 6.7-7.8 6.7zm0 0" fill="#03c" stroke="#03c" stroke-miterlimit="10" stroke-width="1.25" transform="matrix(2.05225 0 0 2.0612 .316 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/psp.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm8.6 3.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zM29 6.4h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4H29V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pst.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1d6fb5}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm8.6 3.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm12.2-7.4h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path class="st0" d="M26.9 62.1c-1.5.2-2.7 1.8-2.7 3.5s1.2 3.4 2.7 3.5c1.5.2 2.7-1.4 2.7-3.5s-1.2-3.7-2.7-3.5z"/><path class="st0" d="M16.4 51.9v27.7L38 83.5V47.7l-21.6 4.2zm10.5 19.4c-2.4-.3-4.3-2.9-4.3-5.7 0-2.9 1.9-5.4 4.3-5.7s4.3 2.3 4.3 5.7c0 3.5-1.9 6-4.3 5.7zm28.2-15.2L43.2 66 40 63.4v-8.2h15.1z"/><path class="st0" d="M55.1 58l-11.9 9.9-3.2-2.6v11.1h15.1z"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><g fill="#1d6fb5"><path d="M18.754 25.742c-2.668.36-4.8 3.219-4.8 6.258s2.132 6.078 4.8 6.258c2.668.355 4.805-2.504 4.805-6.258s-2.137-6.613-4.805-6.258zm0 0"/><path d="M.074 7.508v49.52L38.504 64V0zm18.68 34.683c-4.27-.539-7.649-5.187-7.649-10.191 0-5.184 3.38-9.652 7.649-10.191 4.27-.536 7.652 4.113 7.652 10.191 0 6.258-3.383 10.727-7.652 10.191zm50.172-27.175L47.754 32.715l-5.691-4.649v-14.66h26.863zm0 0"/><path d="m68.926 18.414-21.172 17.7-5.691-4.65V51.31h26.863zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pub.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#077265}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm7.8-7h3.3V16c0 1.4.6 1.9 1.5 1.9s1.5-.5 1.5-1.9V6.4h3.3V16c0 3-1.9 4.9-4.7 4.9-2.9 0-4.8-1.9-4.8-4.9V6.4zm13.1 0h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1z" fill="#fff"/><path class="st0" d="M31.2 61.2c0-2.7-1.3-4-3.4-4-.8 0-1.4.1-1.8.3v8c.4.2.9.3 1.5.3 2.4-.2 3.7-1.7 3.7-4.6z"/><path class="st0" d="M17.6 77.3l22 5.6V47l-22 5.6v24.7zm6.6-21.9c.9-.3 2.1-.4 3.5-.4 1.9 0 3.2.6 4 1.7.8 1 1.3 2.4 1.3 4.3s-.4 3.4-1.1 4.4c-1 1.5-2.6 2.3-4.4 2.3-.6 0-1.1 0-1.5-.2v8.2h-1.9V55.4zm17.3-3.9v2.2h7.4v6.2h-7.4v2.3h7.4v2.7h-7.4v2.2h7.4v2.8h-7.4v2.4h7.4v2.8h-7.4v4.6H54V51.5z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#077265"><path d="M23.91 25.406c0-4.746-2.285-7.031-5.976-7.031-1.407 0-2.461.176-3.164.527V32.97c.703.351 1.582.527 2.636.527 4.219-.351 6.504-2.992 6.504-8.09zm0 0"/><path d="m0 53.715 38.68 9.844V.44L0 10.285zm11.605-38.508c1.582-.527 3.692-.703 6.153-.703 3.34 0 5.625 1.055 7.035 2.992 1.406 1.758 2.285 4.219 2.285 7.559s-.703 5.976-1.933 7.738c-1.762 2.637-4.575 4.043-7.739 4.043-1.054 0-1.933 0-2.636-.352v14.418h-3.34V15.207zm30.418-6.855v3.867h13.008V23.12H42.023v4.043h13.008v4.746H42.023v3.871h13.008v4.922H42.023v4.219h13.008v4.926H42.023v8.086H64V8.352zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/py.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9s-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm10 1.4l-3.6-8.4h3.6l1.1 3.4c.3 1 .5 2.1.5 2.1h.1s.2-1.1.5-2.1l1.1-3.4h3.6l-3.6 8.4v5.9h-3.3v-5.9z" fill="#fff"/><path d="M34.5 83.4c-4.4-.1-7.2-1.5-7.9-3.8l-.1-.3v-4.5c0-5.2 0-5.3.3-6.1.5-1.5 1.7-2.5 3.5-2.9l.4-.1h5.1c3.7 0 5.2 0 5.4-.1 1.1-.2 1.7-.4 2.3-.9.8-.6 1.4-1.6 1.6-2.6.2-.8.2-.7.2-3.5v-2.5h3.6l.4.1c1.9.6 3.3 2.3 3.9 5.1.2 1.1.2 1.1.2 3.8 0 2.6 0 2.6-.2 3.5-.2.8-.4 1.6-.8 2.3-.7 1.4-1.8 2.4-3.1 2.8-.8.3-.1.2-7.5.3h-6.7v1.2h8.8v4.6c-.1.3-.1.6-.4 1s-.8.9-1.1 1.2c-1.2.8-3 1.3-5.4 1.4h-2.5zm6.1-2.8c.8-.1 1.5-1 1.3-1.8-.1-.7-.6-1.2-1.3-1.3-1.1-.1-2 .8-1.8 1.8.1.8.8 1.3 1.6 1.3h.2zm-19-6.5c-1-.2-2-.8-2.7-1.7-1.3-1.6-2-4.4-1.9-7.8.1-2.1.4-3.7 1.1-5.1.8-1.8 2.1-2.7 3.8-3.1.4-.1.4-.1 6.9-.1h6.6c.1 0 .1-.1.1-.6v-.6h-8.8v-2.3c0-2.5 0-2.5.2-3 .8-1.6 3-2.6 6.5-2.9.3 0 .9-.1 1.6-.1 3.9-.1 6.8.6 8.3 2l.5.5c.2.3.5.8.6 1.3l.1.3v4.8c0 4.4 0 4.8-.1 5.1-.1.4-.3 1-.4 1.3-.6 1.1-1.6 1.8-2.9 2.2-.8.2-.5.2-6.1.3-5.6 0-5.3 0-6.1.2-1.6.4-2.7 1.6-3.1 3.3-.2.8-.2.7-.2 3.5v2.6h-1.7c-1.7 0-2.2 0-2.3-.1zM31 52.7c.6-.3 1.1-1.1.9-1.7s-.6-1.1-1.1-1.3c-.9-.3-1.9.3-2 1.3-.1.8.3 1.6 1.1 1.8.1.1.3.1.6.1.2-.1.2-.1.5-.2z" fill="#fed142"/><path d="M21.6 74.1c-1-.2-2-.8-2.7-1.7-1.3-1.6-2-4.4-1.9-7.8.1-2.1.4-3.7 1.1-5.1.8-1.8 2.1-2.7 3.8-3.1.4-.1.4-.1 6.9-.1h6.6c.1 0 .1-.1.1-.6v-.6h-8.8v-2.3c0-2.5 0-2.5.2-3 .8-1.6 3-2.6 6.5-2.9.3 0 .9-.1 1.6-.1 3.9-.1 6.8.6 8.3 2l.5.5c.2.3.5.8.6 1.3l.1.3v4.8c0 4.4 0 4.8-.1 5.1-.1.4-.3 1-.4 1.3-.6 1.1-1.6 1.8-2.9 2.2-.8.2-.5.2-6.1.3-5.6 0-5.3 0-6.1.2-1.6.4-2.7 1.6-3.1 3.3-.2.8-.2.7-.2 3.5v2.6h-1.7c-1.7 0-2.2 0-2.3-.1zM31 52.7c.6-.3 1.1-1.1.9-1.7s-.6-1.1-1.1-1.3c-.9-.3-1.9.3-2 1.3-.1.8.3 1.6 1.1 1.8.1.1.3.1.6.1.2-.1.2-.1.5-.2z" fill="#3571a3"/></svg>
1
<svg height="63" width="62" xmlns="http://www.w3.org/2000/svg"><path d="M29.816 62.316c-7.492-.168-12.261-2.523-13.453-6.398l-.172-.504V47.84c0-8.758 0-8.926.512-10.27.852-2.527 2.895-4.21 5.961-4.882l.68-.168h8.687c6.301 0 8.852 0 9.196-.168 1.87-.34 2.894-.676 3.914-1.516 1.363-1.012 2.386-2.695 2.726-4.379.34-1.348.34-1.18.34-5.89v-4.212h6.129l.684.168c3.234 1.012 5.617 3.872 6.64 8.586.34 1.852.34 1.852.34 6.399 0 4.379 0 4.379-.34 5.89-.34 1.348-.683 2.696-1.363 3.875-1.192 2.356-3.067 4.04-5.277 4.715-1.364.504-.172.336-12.774.504h-11.41v2.02h14.988v7.746c-.172.504-.172 1.008-.683 1.683-.508.672-1.36 1.512-1.871 2.02-2.043 1.348-5.11 2.187-9.196 2.355zm10.387-4.714c1.363-.168 2.555-1.684 2.215-3.028-.172-1.18-1.023-2.023-2.215-2.191-1.871-.168-3.406 1.347-3.066 3.031.172 1.348 1.363 2.188 2.726 2.188zM7.848 46.66c-1.703-.336-3.403-1.347-4.598-2.863C1.04 41.105-.152 36.39.016 30.668c.172-3.54.68-6.23 1.875-8.59 1.359-3.027 3.574-4.543 6.468-5.219.684-.168.684-.168 11.75-.168h11.239c.172 0 .172-.168.172-1.007v-1.012H16.535V10.8c0-4.211 0-4.211.34-5.051 1.363-2.695 5.11-4.379 11.066-4.883.512 0 1.536-.168 2.727-.168 6.64-.168 11.578 1.008 14.133 3.367l.851.84c.34.508.852 1.348 1.024 2.192l.168.504v8.082c0 7.406 0 8.078-.168 8.586-.172.671-.512 1.683-.684 2.187-1.02 1.852-2.722 3.031-4.937 3.703-1.364.336-.852.336-10.387.508-9.535 0-9.027 0-10.387.336-2.726.672-4.597 2.691-5.281 5.555-.34 1.347-.34 1.18-.34 5.89v4.38h-2.894c-2.895 0-3.746 0-3.918-.169zm16.007-36.027c1.024-.508 1.875-1.852 1.532-2.863-.34-1.012-1.02-1.852-1.871-2.188-1.532-.508-3.235.504-3.407 2.188-.168 1.347.512 2.695 1.875 3.03.168.169.508.169 1.02.169.34-.168.34-.168.851-.336zm0 0" fill="#fed142"/><path d="M7.848 46.66c-1.703-.336-3.403-1.347-4.598-2.863C1.04 41.105-.152 36.39.016 30.668c.171-3.54.68-6.23 1.875-8.59 1.359-3.027 3.574-4.543 6.468-5.219.684-.168.684-.168 11.75-.168h11.239c.172 0 .172-.168.172-1.007v-1.012H16.535V10.8c0-4.211 0-4.211.34-5.051 1.363-2.695 5.11-4.379 11.066-4.883.512 0 1.536-.168 2.727-.168 6.64-.168 11.578 1.008 14.133 3.367l.851.84c.34.508.852 1.348 1.024 2.192l.168.504v8.082c0 7.406 0 8.078-.168 8.586-.172.671-.512 1.683-.684 2.187-1.02 1.852-2.722 3.031-4.937 3.703-1.364.336-.852.336-10.387.508-9.535 0-9.027 0-10.387.336-2.726.672-4.597 2.691-5.281 5.555-.34 1.347-.34 1.18-.34 5.89v4.38h-2.894c-2.895 0-3.746 0-3.918-.169zm16.007-36.027c1.024-.508 1.875-1.852 1.532-2.863-.34-1.012-1.02-1.852-1.871-2.188-1.532-.508-3.235.504-3.407 2.188-.168 1.347.512 2.695 1.875 3.03.168.169.508.169 1.02.169.34-.168.34-.168.851-.336zm0 0" fill="#3571a3"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/pyc.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5H9.9v4.4H6.6V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.6v4.1h.6zm10 1.4l-3.6-8.4h3.6l1.1 3.4c.3 1 .5 2.1.5 2.1h.1s.2-1.1.5-2.1l1.1-3.4h3.6l-3.6 8.4v5.9h-3.3v-5.9zm14.6-8.7c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4z" fill="#fff"/><path class="st0" d="M34.5 83.4c-4.4-.1-7.2-1.5-7.9-3.8l-.1-.3v-4.5c0-5.2 0-5.3.3-6.1.5-1.5 1.7-2.5 3.5-2.9l.4-.1h5.1c3.7 0 5.2 0 5.4-.1 1.1-.2 1.7-.4 2.3-.9.8-.6 1.4-1.6 1.6-2.6.2-.8.2-.7.2-3.5v-2.5h3.6l.4.1c1.9.6 3.3 2.3 3.9 5.1.2 1.1.2 1.1.2 3.8 0 2.6 0 2.6-.2 3.5-.2.8-.4 1.6-.8 2.3-.7 1.4-1.8 2.4-3.1 2.8-.8.3-.1.2-7.5.3h-6.7v1.2h8.8v4.6c-.1.3-.1.6-.4 1s-.8.9-1.1 1.2c-1.2.8-3 1.3-5.4 1.4h-2.5zm6.1-2.8c.8-.1 1.5-1 1.3-1.8-.1-.7-.6-1.2-1.3-1.3-1.1-.1-2 .8-1.8 1.8.1.8.8 1.3 1.6 1.3h.2zm-19-6.5c-1-.2-2-.8-2.7-1.7-1.3-1.6-2-4.4-1.9-7.8.1-2.1.4-3.7 1.1-5.1.8-1.8 2.1-2.7 3.8-3.1.4-.1.4-.1 6.9-.1h6.6c.1 0 .1-.1.1-.6v-.6h-8.8v-2.3c0-2.5 0-2.5.2-3 .8-1.6 3-2.6 6.5-2.9.3 0 .9-.1 1.6-.1 3.9-.1 6.8.6 8.3 2l.5.5c.2.3.5.8.6 1.3l.1.3v4.8c0 4.4 0 4.8-.1 5.1-.1.4-.3 1-.4 1.3-.6 1.1-1.6 1.8-2.9 2.2-.8.2-.5.2-6.1.3-5.6 0-5.3 0-6.1.2-1.6.4-2.7 1.6-3.1 3.3-.2.8-.2.7-.2 3.5v2.6h-1.7c-1.7 0-2.2 0-2.3-.1zM31 52.7c.6-.3 1.1-1.1.9-1.7s-.6-1.1-1.1-1.3c-.9-.3-1.9.3-2 1.3-.1.8.3 1.6 1.1 1.8.1.1.3.1.6.1.2-.1.2-.1.5-.2z"/><path class="st0" d="M21.6 74.1c-1-.2-2-.8-2.7-1.7-1.3-1.6-2-4.4-1.9-7.8.1-2.1.4-3.7 1.1-5.1.8-1.8 2.1-2.7 3.8-3.1.4-.1.4-.1 6.9-.1h6.6c.1 0 .1-.1.1-.6v-.6h-8.8v-2.3c0-2.5 0-2.5.2-3 .8-1.6 3-2.6 6.5-2.9.3 0 .9-.1 1.6-.1 3.9-.1 6.8.6 8.3 2l.5.5c.2.3.5.8.6 1.3l.1.3v4.8c0 4.4 0 4.8-.1 5.1-.1.4-.3 1-.4 1.3-.6 1.1-1.6 1.8-2.9 2.2-.8.2-.5.2-6.1.3-5.6 0-5.3 0-6.1.2-1.6.4-2.7 1.6-3.1 3.3-.2.8-.2.7-.2 3.5v2.6h-1.7c-1.7 0-2.2 0-2.3-.1zM31 52.7c.6-.3 1.1-1.1.9-1.7s-.6-1.1-1.1-1.3c-.9-.3-1.9.3-2 1.3-.1.8.3 1.6 1.1 1.8.1.1.3.1.6.1.2-.1.2-.1.5-.2z"/></svg>
1
<svg height="63" width="62" xmlns="http://www.w3.org/2000/svg"><g fill="#666"><path d="M29.816 62.316c-7.492-.168-12.261-2.523-13.453-6.398l-.172-.504V47.84c0-8.758 0-8.926.512-10.27.852-2.527 2.895-4.21 5.961-4.882l.68-.168h8.687c6.301 0 8.852 0 9.196-.168 1.87-.34 2.894-.676 3.914-1.516 1.363-1.012 2.386-2.695 2.726-4.379.34-1.348.34-1.18.34-5.89v-4.212h6.129l.684.168c3.234 1.012 5.617 3.872 6.64 8.586.34 1.852.34 1.852.34 6.399 0 4.379 0 4.379-.34 5.89-.34 1.348-.683 2.696-1.363 3.875-1.192 2.356-3.067 4.04-5.277 4.715-1.364.504-.172.336-12.774.504h-11.41v2.02h14.988v7.746c-.172.504-.172 1.008-.683 1.683-.508.672-1.36 1.512-1.871 2.02-2.043 1.348-5.11 2.187-9.196 2.355zm10.387-4.714c1.363-.168 2.555-1.684 2.215-3.028-.172-1.18-1.023-2.023-2.215-2.191-1.871-.168-3.406 1.347-3.066 3.031.172 1.348 1.363 2.188 2.726 2.188zM7.848 46.66c-1.703-.336-3.403-1.347-4.598-2.863C1.04 41.105-.152 36.39.016 30.668c.172-3.54.68-6.23 1.875-8.59 1.359-3.027 3.574-4.543 6.468-5.219.684-.168.684-.168 11.75-.168h11.239c.172 0 .172-.168.172-1.007v-1.012H16.535V10.8c0-4.211 0-4.211.34-5.051 1.363-2.695 5.11-4.379 11.066-4.883.512 0 1.536-.168 2.727-.168 6.64-.168 11.578 1.008 14.133 3.367l.851.84c.34.508.852 1.348 1.024 2.192l.168.504v8.082c0 7.406 0 8.078-.168 8.586-.172.671-.512 1.683-.684 2.187-1.02 1.852-2.722 3.031-4.937 3.703-1.364.336-.852.336-10.387.508-9.535 0-9.027 0-10.387.336-2.726.672-4.597 2.691-5.281 5.555-.34 1.347-.34 1.18-.34 5.89v4.38h-2.894c-2.895 0-3.746 0-3.918-.169zm16.007-36.027c1.024-.508 1.875-1.852 1.532-2.863-.34-1.012-1.02-1.852-1.871-2.188-1.532-.508-3.235.504-3.407 2.188-.168 1.347.512 2.695 1.875 3.03.168.169.508.169 1.02.169.34-.168.34-.168.851-.336zm0 0"/><path d="M7.848 46.66c-1.703-.336-3.403-1.347-4.598-2.863C1.04 41.105-.152 36.39.016 30.668c.171-3.54.68-6.23 1.875-8.59 1.359-3.027 3.574-4.543 6.468-5.219.684-.168.684-.168 11.75-.168h11.239c.172 0 .172-.168.172-1.007v-1.012H16.535V10.8c0-4.211 0-4.211.34-5.051 1.363-2.695 5.11-4.379 11.066-4.883.512 0 1.536-.168 2.727-.168 6.64-.168 11.578 1.008 14.133 3.367l.851.84c.34.508.852 1.348 1.024 2.192l.168.504v8.082c0 7.406 0 8.078-.168 8.586-.172.671-.512 1.683-.684 2.187-1.02 1.852-2.722 3.031-4.937 3.703-1.364.336-.852.336-10.387.508-9.535 0-9.027 0-10.387.336-2.726.672-4.597 2.691-5.281 5.555-.34 1.347-.34 1.18-.34 5.89v4.38h-2.894c-2.895 0-3.746 0-3.918-.169zm16.007-36.027c1.024-.508 1.875-1.852 1.532-2.863-.34-1.012-1.02-1.852-1.871-2.188-1.532-.508-3.235.504-3.407 2.188-.168 1.347.512 2.695 1.875 3.03.168.169.508.169 1.02.169.34-.168.34-.168.851-.336zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/qt.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm5.9-34.9c3.7 0 5.9 3.1 5.9 7.3 0 1.8-.6 3.3-1.1 4.2l1.4 1.3-1.8 2.1-1.3-1.1c-.6.5-1.6 1.1-3.1 1.1C8.1 21 6 17.8 6 13.5c0-4.2 2.1-7.4 5.9-7.4zm0 11.8c.3 0 .5 0 .9-.3l-1.6-1.5L13 14l1.2 1.3c.2-.7.2-1.2.2-1.9 0-2.5-.7-4.2-2.5-4.2S9.4 11 9.4 13.5c0 2.6.8 4.4 2.5 4.4zm10.5-8.6h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/r.svg
1
<?xml version="1.0" encoding="UTF-8"?>
2
<svg version="1.1" viewBox="0 0 72 96" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
<defs>
4
<linearGradient id="b" x1=".74144" x2="590.86" y1="3.6658" y2="593.79" gradientTransform="scale(1.2219 .81837)" gradientUnits="userSpaceOnUse">
5
<stop stop-color="#cbced0" offset="0"/>
6
<stop stop-color="#84838b" offset="1"/>
7
</linearGradient>
8
<linearGradient id="a" x1="301.03" x2="703.07" y1="151.4" y2="553.44" gradientTransform="scale(.98995 1.0102)" gradientUnits="userSpaceOnUse">
9
<stop stop-color="#276dc3" offset="0"/>
10
<stop stop-color="#165caa" offset="1"/>
11
</linearGradient>
12
</defs>
13
<style>.st0{fill:#999}</style>
14
<path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/>
15
<path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/>
16
<path d="m6 41h60v49h-60z" fill="#fff"/>
17
<path d="m6.5 6.4h4.5c0.6 0 1.3 0.1 1.9 0.4 1.4 0.6 2.4 2.1 2.4 4 0 1.7-0.8 3.3-2 4 0 0 0.2 0.2 0.5 0.9l2.3 5h-3.6l-2-4.8h-0.7v4.8h-3.3zm3.9 6.6c0.9 0 1.6-0.7 1.6-1.9 0-0.7-0.2-1.2-0.6-1.5-0.3-0.2-0.6-0.3-0.9-0.3h-0.7v3.7z" fill="#fff"/>
18
<g transform="matrix(.066565 0 0 .066565 11.94 46.793)" fill-rule="evenodd">
19
<path d="m361.45 485.94c-199.12 0-360.55-108.11-360.55-241.47s161.42-241.47 360.55-241.47c199.12 0 360.55 108.11 360.55 241.47s-161.42 241.47-360.55 241.47zm55.188-388.53c-151.35 0-274.05 73.908-274.05 165.08s122.7 165.08 274.05 165.08 263.05-50.529 263.05-165.08c0-114.51-111.7-165.08-263.05-165.08z" fill="url(#b)"/>
20
<path d="m550 377s21.822 6.585 34.5 13c4.399 2.226 12.01 6.668 17.5 12.5 5.378 5.712 8 11.5 8 11.5l86 145-139 0.062-65-122.06s-13.31-22.869-21.5-29.5c-6.832-5.531-9.745-7.5-16.5-7.5h-33.026l0.026 158.97-123 0.052v-406.09h247s112.5 2.029 112.5 109.06-107.5 115-107.5 115zm-53.5-135.98-74.463-0.048-0.037 69.05 74.5-0.024s34.5-0.107 34.5-35.125c0-35.722-34.5-33.853-34.5-33.853z" fill="url(#a)"/>
21
</g>
22
</svg>
23
1
<svg height="64" width="83" xmlns="http://www.w3.org/2000/svg"><linearGradient id="a" gradientTransform="matrix(.14059 0 0 .09419 -.088 -.345)" gradientUnits="userSpaceOnUse" x1=".741" x2="590.86" y1="3.666" y2="593.79"><stop offset="0" stop-color="#cbced0"/><stop offset="1" stop-color="#84838b"/></linearGradient><linearGradient id="b" gradientTransform="matrix(.1139 0 0 .11627 -.088 -.345)" gradientUnits="userSpaceOnUse" x1="301.03" x2="703.07" y1="151.4" y2="553.44"><stop offset="0" stop-color="#276dc3"/><stop offset="1" stop-color="#165caa"/></linearGradient><g fill-rule="evenodd"><path d="M41.5 55.586C18.59 55.586.016 43.14.016 27.793.016 12.441 18.59 0 41.5 0s41.484 12.441 41.484 27.793c0 15.348-18.574 27.793-41.484 27.793zm6.352-44.719c-17.414 0-31.536 8.504-31.536 19 0 10.492 14.122 19 31.536 19s30.265-5.816 30.265-19c0-13.18-12.851-19-30.265-19zm0 0" fill="url(#a)"/><path d="M63.195 43.047s2.508.758 3.97 1.496c.503.254 1.382.766 2.01 1.437.622.657.923 1.325.923 1.325l9.894 16.687L64 64l-7.48-14.047s-1.532-2.633-2.473-3.398c-.785-.637-1.121-.864-1.899-.864h-3.8l.004 18.297-14.153.008V17.258h28.418s12.946.23 12.946 12.55-12.368 13.235-12.368 13.235zM57.04 27.395l-8.566-.004-.008 7.945 8.574-.004s3.969-.012 3.969-4.039c0-4.113-3.969-3.898-3.969-3.898zm0 0" fill="url(#b)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ra.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm10.8-6.6h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5H23s-.2 1.5-.4 2.5L22 15h2.1z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ram.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm9.8-6.6h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5H22s-.2 1.5-.4 2.5L21 15h2.1zm6.3-8.6H33l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H33l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1.2-14.3z" fill="#fff"/><path d="M22.9 73.9l-7.7-8.5v-.1l7.7-8.5v-5.7l-10.2 12v4.5l10.2 11.9zm25.8-22.8v5.7l7.9 8.5v.1l-7.9 8.5v5.6l10.2-11.7v-4.9zM41 55.5c-1.3-.6-3-1.6-3.6-3 0-.7-.6-1.3-1.3-1.3s-1.3.6-1.3 1.3v17.3c-1.3-.7-3.9-.5-5.9.6-3 1.7-4.3 4.9-3 7.2 1.3 2.2 5 2.7 8 1 2.1-1.2 3.5-3.2 3.6-5.1v-15c4.4 0 7 1.8 6 6-.2.8-.4 1.6-.8 2.3-.2.3-.2.5.1.8.2.2.6.2 1-.2 1.7-1.6 2.7-3.7 2.7-6 0-2.9-2.9-4.8-5.5-5.9z" fill="#039" stroke="#039" stroke-width=".5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="54"><path style="fill-rule:nonzero;fill:#039;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#039;stroke-opacity:1;stroke-miterlimit:10" d="m10.45 23.48-7.7-8.5v-.1l7.7-8.5V.68L.25 12.681v4.5l10.2 11.898zM36.25.679V6.38l7.9 8.5v.1l-7.9 8.5v5.6l10.2-11.7v-4.9zM28.549 5.08c-1.299-.6-3-1.6-3.598-3 0-.7-.602-1.3-1.301-1.3-.7 0-1.299.6-1.299 1.3v17.3c-1.3-.7-3.9-.5-5.9.6-3.002 1.7-4.3 4.899-3.002 7.2 1.301 2.2 5.002 2.7 8 1 2.1-1.2 3.502-3.2 3.601-5.1v-15c4.4 0 7 1.8 6 6-.199.8-.401 1.6-.8 2.299-.2.302-.2.5.1.802.2.198.6.198 1-.2 1.7-1.6 2.7-3.7 2.7-6.001 0-2.9-2.9-4.8-5.501-5.9zm0 0" transform="matrix(1.79872 0 0 1.81157 0 .047)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rar.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#90c}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm10.8-6.6h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5H23s-.2 1.5-.4 2.5L22 15h2.1zm6.8-8.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5H37l-2-4.8h-.8v4.8h-3.3V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6z" fill="#fff"/><path class="st0" d="M51.1 57.5h-5.7v-5.7l5.7 5.7zm-15.3-5.7v20.7h15.4V58.9H44v-7.1h-8.2zm2.4-5.4h-17v4h6.7l-4.2 3.3v3.5l6.2-4.8v-1.9h21.6v-1.6l-13.3-2.5zm-8.3 8.7l-6.2 4.8v3.5l6.2-4.8v-3.5zm-6.3 14.4l6.2-4.8v-3.5L23.6 66v3.5zm6.3 1.4v-3.5l-6.2 4.8V74h-2.5v4H25v2.8h-2.2c-.4-.7-1.1-1.2-2-1.2-1.3 0-2.3 1-2.3 2.3 0 1.3 1 2.3 2.3 2.3.9 0 1.6-.5 2-1.2H25v2.1h3.4V83h2.2c.4.7 1.1 1.2 2 1.2 1.3 0 2.3-1 2.3-2.3 0-1.3-1-2.3-2.3-2.3-.9 0-1.6.5-2 1.2h-2.2V78h9.7l13.3-2.4V74H25.7l4.2-3.1z"/></svg>
1
<svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/raw.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm9.8-6.6h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5H22s-.2 1.5-.4 2.5L21 15h2.1zm4.4-8.6h3.2l1.2 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.3-8.9h3.1l1.3 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.2-8.9h3.2L40 20.7h-3.7l-1.1-7.2c-.1-.9-.2-1.7-.2-1.7s0 .8-.1 1.7l-1.1 7.2H30L27.5 6.4z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rb.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm8.3-6.6H23c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zM23 12c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6s-.3-1.5-1.1-1.5h-1.2v3.1h1.1z" fill="#fff"/><path d="M54 47.5v36l-9-27 9-9zm-36 36h36l-27-9-9 9zm9-9l27 9-18-18-9 9zm9-9l18 18-9-27-9 9zm-18 9v9l9-9h-9zm18-9h-9v9l9-9zm9-9h-9v9l9-9zm9-9h-9v9l9-9zm-27 18l-9 9h9v-9zm9-9l-9 9h9v-9zm9-9l-9 9h9v-9z" fill="#992315"/><path d="M54 47.5v36l-9-27 9-9zm-36 36h36l-27-9-9 9zm9-9l27 9-18-18-9 9zm9-9l18 18-9-27-9 9zm-18 9v9l9-9h-9zm18-9h-9v9l9-9zm9-9h-9v9l9-9zm9-9h-9v9l9-9zm-27 18l-9 9h9v-9zm9-9l-9 9h9v-9zm9-9l-9 9h9v-9z" fill="#992315" fill-opacity="0" stroke="#fff"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M61.988 2.012v59.976L46.996 17.004zM2.012 61.988h59.976L17.004 46.996zm14.992-14.992 44.984 14.992L32 32zM32 32l29.988 29.988-14.992-44.984zM2.012 46.996v14.992l14.992-14.992zM32 32H17.004v14.996zm14.996-14.996H32V32zM61.988 2.012H46.996v14.992zM17.004 32 2.012 46.996h14.992zM32 17.004 17.004 32H32zM46.996 2.012 32 17.004h14.996zm0 0" fill="#992315" stroke="#fff" stroke-width="1.66605"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rdf.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm8.3-6.6H23c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.2-11.4h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path d="M23.7 75.5c-.5 0-1.1-.2-1.5-.6l-8.4-8.4c-.8-.8-.8-2.1 0-3l8.4-8.4c.8-.8 2.1-.8 3 0 .8.8.8 2.1 0 3L18.3 65l6.9 6.9c.8.8.8 2.1 0 3-.4.4-1 .6-1.5.6zm25.1 0c-.5 0-1.1-.2-1.5-.6-.8-.8-.8-2.1 0-3l6.9-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 3 0l8.4 8.4c.8.8.8 2.1 0 3l-8.4 8.4c-.4.4-1 .6-1.5.6zm-16.7 4.1c-.2 0-.4 0-.7-.1-1.1-.4-1.7-1.5-1.3-2.6l8.4-25.1c.4-1.1 1.5-1.7 2.6-1.3 1.1.4 1.7 1.5 1.3 2.6L34 78.2c-.2.9-1.1 1.4-1.9 1.4z" fill="#999" stroke="#999" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="54"><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M11.242 25.867c-.5 0-1.1-.2-1.498-.6l-8.4-8.401c-.802-.799-.802-2.099 0-3l8.4-8.398c.8-.8 2.098-.8 2.999 0 .8.8.8 2.098 0 2.999l-6.9 6.9 6.9 6.9c.8.801.8 2.1 0 3-.401.4-1 .6-1.5.6zm25.1 0c-.499 0-1.099-.2-1.5-.6-.8-.8-.8-2.099 0-3.002l6.9-6.898-6.9-6.9c-.8-.8-.8-2.101 0-3 .8-.8 2.1-.8 3.001 0l8.398 8.4c.802.8.802 2.1 0 3l-8.398 8.4c-.4.4-1.001.6-1.5.6zm-16.7 4.1c-.199 0-.398 0-.698-.1-1.102-.401-1.702-1.5-1.301-2.6l8.398-25.1c.4-1.1 1.5-1.699 2.6-1.301 1.102.4 1.702 1.5 1.301 2.601l-8.398 25.1c-.202.899-1.102 1.4-1.901 1.4zm0 0" transform="matrix(1.74425 0 0 1.75713 0 .013)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rdl.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm8.3-6.6H23c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.2-11.4h3.3v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><path d="M23.7 75.5c-.5 0-1.1-.2-1.5-.6l-8.4-8.4c-.8-.8-.8-2.1 0-3l8.4-8.4c.8-.8 2.1-.8 3 0 .8.8.8 2.1 0 3L18.3 65l6.9 6.9c.8.8.8 2.1 0 3-.4.4-1 .6-1.5.6zm25.1 0c-.5 0-1.1-.2-1.5-.6-.8-.8-.8-2.1 0-3l6.9-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 3 0l8.4 8.4c.8.8.8 2.1 0 3l-8.4 8.4c-.4.4-1 .6-1.5.6zm-16.7 4.1c-.2 0-.4 0-.7-.1-1.1-.4-1.7-1.5-1.3-2.6l8.4-25.1c.4-1.1 1.5-1.7 2.6-1.3 1.1.4 1.7 1.5 1.3 2.6L34 78.2c-.2.9-1.1 1.4-1.9 1.4z" fill="#999" stroke="#999" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="54"><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M11.242 25.867c-.5 0-1.1-.2-1.498-.6l-8.4-8.401c-.802-.799-.802-2.099 0-3l8.4-8.398c.8-.8 2.098-.8 2.999 0 .8.8.8 2.098 0 2.999l-6.9 6.9 6.9 6.9c.8.801.8 2.1 0 3-.401.4-1 .6-1.5.6zm25.1 0c-.499 0-1.099-.2-1.5-.6-.8-.8-.8-2.099 0-3.002l6.9-6.898-6.9-6.9c-.8-.8-.8-2.101 0-3 .8-.8 2.1-.8 3.001 0l8.398 8.4c.802.8.802 2.1 0 3l-8.398 8.4c-.4.4-1.001.6-1.5.6zm-16.7 4.1c-.199 0-.398 0-.698-.1-1.102-.401-1.702-1.5-1.301-2.6l8.398-25.1c.4-1.1 1.5-1.699 2.6-1.301 1.102.4 1.702 1.5 1.301 2.601l-8.398 25.1c-.202.899-1.102 1.4-1.901 1.4zm0 0" transform="matrix(1.74425 0 0 1.75713 0 .013)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/reg.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3a898d}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm8.3-6.6H26v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4zm16-.3c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.5-.6-1.3-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7H35v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.1-4.5 2.6-7.6 6.4-7.6z" fill="#fff"/><path class="st0" d="M19 78.9v-4.3h8.6v8.6H19v-4.3zm12.8 0v-4.3h8.6v8.6h-8.6v-4.3zm12.9 0v-4.3h8.6v8.6h-8.6v-4.3zm1.3-9.8l-3-3 3-3 3-3 3 3 3 3-3 3c-1.6 1.7-3 3-3 3l-3-3zm-27-3v-4.3h8.6v8.6H19v-4.3zm12.8 0v-4.3h8.6v8.6h-8.6v-4.3zm1.3-9.9l-3-3 3-3 3-3 3 3 3 3-3 3c-1.6 1.7-3 3-3 3l-3-3zm-14.1-3v-4.3h8.6v8.6H19v-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M0 56.355v-7.644h15.29V64H0zm22.754 0v-7.644h15.289V64h-15.29zm22.933 0v-7.644h15.29V64h-15.29zM48 38.934l-5.332-5.332L48 28.266l5.332-5.332 5.336 5.332L64 33.602l-5.332 5.332a125.106 125.106 0 0 1-5.336 5.332zM0 33.602v-7.645h15.29v15.29H0zm22.754 0v-7.645h15.289v15.29h-15.29zM25.066 16l-5.332-5.332 5.332-5.336L30.398 0l5.336 5.332 5.332 5.336L35.734 16c-2.843 3.023-5.336 5.332-5.336 5.332zM0 10.668V3.023h15.29v15.29H0zm0 0" fill="#3a898d"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/resx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d5006e}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.5-34.6h4.1c.5 0 1.2.1 1.7.4 1.3.6 2.2 2.1 2.2 4 0 1.7-.7 3.3-1.8 4 0 0 .2.2.4.9l2.1 5H12l-1.8-4.8h-.7v4.8h-3V6.4zM10 13c.8 0 1.4-.7 1.4-1.9 0-.7-.2-1.2-.5-1.5-.2-.2-.5-.3-.8-.3h-.6V13h.5zm6.6-6.6h6.5v2.9h-3.5V12h2.8v2.9h-2.8v2.9h3.7v2.9h-6.6V6.4zm9.2 10.3c.5.6 1.3 1.2 2.1 1.2s1.2-.6 1.2-1.2c0-2-4.3-2.1-4.3-6.2 0-2.4 1.5-4.3 4.1-4.3 1.1 0 2.2.3 3.1 1l-1.1 2.9c-.4-.4-1.3-.9-1.9-.9-.8 0-1.2.6-1.2 1.2 0 2.1 4.3 2 4.3 6.1 0 2.3-1.3 4.4-4 4.4-1.3 0-2.6-.5-3.6-1.4l1.3-2.8zM36 13.6l-3.1-7.2h3.3l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3.2l-3.1 7.2 3 7.1h-3.2l-1-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3H33l3-7.1z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#d5006e"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/retry.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M10.1 70.4h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.8v4.8h-3.2V70.4zM14 77c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V77h.6zm7.8-6.6H29v2.9h-3.9V76h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V70.4zM34 73.3h-3.1v-2.9h9.6v2.9h-3.2v11.4H34V73.3zm8.8-2.9h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8H46v4.8h-3.3l.1-14.3zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3H46V77h.7zm9.9 1.8L53 70.4h3.6l1.1 3.4c.3 1 .5 2.1.5 2.1h.1s.2-1.1.5-2.1l1.1-3.4h3.6l-3.6 8.4v5.9h-3.3c-.1 0-.1-5.9 0-5.9z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm4.7 20.8c0 8.7-7 15.7-15.7 15.7s-15.7-7-15.7-15.7c0-3 .9-5.8 2.4-8.2l5.1 2.9c-1 1.5-1.6 3.3-1.6 5.3 0 5.4 4.4 9.8 9.8 9.8s9.8-4.4 9.8-9.8c0-4.5-3.1-8.3-7.3-9.5v5l-14.6-8.4 14.6-8.4v5.8C47 32.5 52.7 39 52.7 46.8z"/></svg>
1
<svg height="64" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M54 36.781c0 14.856-12.04 26.813-27 26.813S0 51.637 0 36.78c0-5.12 1.547-9.906 4.129-14.004l8.77 4.953a16.11 16.11 0 0 0-2.75 9.051c0 9.223 7.566 16.735 16.851 16.735s16.852-7.512 16.852-16.735c0-7.683-5.329-14.172-12.551-16.222v8.539L6.19 14.754 31.301.406v9.906C44.199 12.364 54 23.462 54 36.782zm0 0" fill="#bababa"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rm.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm8.8-6.6H23l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H23l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1.1-14.3z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rmd.svg
1
<?xml version="1.0" encoding="UTF-8"?>
2
<svg version="1.1" viewBox="0 0 72 96" xmlns="http://www.w3.org/2000/svg">
3
<defs>
4
<linearGradient id="b" x1=".74144" x2="590.86" y1="3.6658" y2="593.79" gradientTransform="scale(1.2219 .81837)" gradientUnits="userSpaceOnUse">
5
<stop stop-color="#cbced0" offset="0"/>
6
<stop stop-color="#84838b" offset="1"/>
7
</linearGradient>
8
<linearGradient id="a" x1="301.03" x2="703.07" y1="151.4" y2="553.44" gradientTransform="scale(.98995 1.0102)" gradientUnits="userSpaceOnUse">
9
<stop stop-color="#276dc3" offset="0"/>
10
<stop stop-color="#165caa" offset="1"/>
11
</linearGradient>
12
</defs>
13
<style>.st0{fill:#999}</style>
14
<path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/>
15
<path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/>
16
<path d="m6 41h60v49h-60zm13.1-34.6h3.6l1.3 6c0.2 0.9 0.4 2.4 0.4 2.4h0.1s0.2-1.5 0.4-2.4l1.3-6h3.8l0.9 14.3h-3l-0.4-6.4c-0.1-1.1 0-2.4 0-2.4h-0.1s-0.2 1.5-0.4 2.4l-0.9 4.1h-3.1l-0.9-4.1c-0.2-0.9-0.4-2.4-0.4-2.4h-0.1s0.1 1.3 0 2.4l-0.4 6.4h-3zm14.6 0h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-0.8v8.5z" fill="#fff"/>
17
<path d="m6.5 6.4h4.5c0.6 0 1.3 0.1 1.9 0.4 1.4 0.6 2.4 2.1 2.4 4 0 1.7-0.8 3.3-2 4 0 0 0.2 0.2 0.5 0.9l2.3 5h-3.6l-2-4.8h-0.7v4.8h-3.3zm3.9 6.6c0.9 0 1.6-0.7 1.6-1.9 0-0.7-0.2-1.2-0.6-1.5-0.3-0.2-0.6-0.3-0.9-0.3h-0.7v3.7z" fill="#fff"/>
18
<g transform="matrix(1.0028 0 0 1.0028 -1.5386 -51.755)">
19
<path class="st0" d="m30.761 136.68v-13.901h4.0809l4.0809 5.1011 4.0809-5.1011h4.0809v13.901h-4.0809v-7.9705l-4.0809 5.1011-4.0809-5.1011v7.9705zm24.485 0-6.1214-6.759h4.0809v-7.1416h4.0809v7.1416h4.0809z" stroke-width=".63764"/>
20
<g transform="matrix(.042445 0 0 .042445 13.462 97.053)" fill-rule="evenodd">
21
<path d="m361.45 485.94c-199.12 0-360.55-108.11-360.55-241.47s161.42-241.47 360.55-241.47c199.12 0 360.55 108.11 360.55 241.47s-161.42 241.47-360.55 241.47zm55.188-388.53c-151.35 0-274.05 73.908-274.05 165.08s122.7 165.08 274.05 165.08 263.05-50.529 263.05-165.08c0-114.51-111.7-165.08-263.05-165.08z" fill="url(#b)"/>
22
<path d="m550 377s21.822 6.585 34.5 13c4.399 2.226 12.01 6.668 17.5 12.5 5.378 5.712 8 11.5 8 11.5l86 145-139 0.062-65-122.06s-13.31-22.869-21.5-29.5c-6.832-5.531-9.745-7.5-16.5-7.5h-33.026l0.026 158.97-123 0.052v-406.09h247s112.5 2.029 112.5 109.06-107.5 115-107.5 115zm-53.5-135.98-74.463-0.048-0.037 69.05 74.5-0.024s34.5-0.107 34.5-35.125c0-35.722-34.5-33.853-34.5-33.853z" fill="url(#a)"/>
23
</g>
24
</g>
25
</svg>
26
1
<svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><linearGradient id="a" gradientTransform="matrix(.08235 0 0 .05573 -.06 .108)" gradientUnits="userSpaceOnUse" x1=".741" x2="590.86" y1="3.666" y2="593.79"><stop offset="0" stop-color="#cbced0"/><stop offset="1" stop-color="#84838b"/></linearGradient><linearGradient id="b" gradientTransform="matrix(.06671 0 0 .0688 -.06 .108)" gradientUnits="userSpaceOnUse" x1="301.03" x2="703.07" y1="151.4" y2="553.44"><stop offset="0" stop-color="#276dc3"/><stop offset="1" stop-color="#165caa"/></linearGradient><path d="M27.406 63.688V41.383h6.48l6.477 8.187 6.48-8.187h6.481v22.304h-6.48V50.898l-6.48 8.184-6.477-8.184v12.79zm38.875 0-9.719-10.844h6.481V41.383h6.477v11.46H76zm0 0" fill="#999"/><g fill-rule="evenodd"><path d="M24.297 33.2C10.879 33.2 0 25.84 0 16.757S10.879.312 24.297.312c13.422 0 24.3 7.364 24.3 16.446s-10.878 16.441-24.3 16.441zm3.719-26.458c-10.2 0-18.47 5.031-18.47 11.242 0 6.207 8.27 11.243 18.47 11.243s17.73-3.442 17.73-11.243c0-7.797-7.531-11.242-17.73-11.242zm0 0" fill="url(#a)"/><path d="M37.004 25.781s1.473.45 2.324.887c.297.152.813.453 1.18.852.363.386.539.78.539.78l5.797 9.876-9.367.004-4.38-8.313s-.898-1.555-1.449-2.008c-.46-.375-.66-.511-1.113-.511H28.31l.003 10.828-8.289.004V10.523h16.645s7.582.137 7.582 7.426c0 7.29-7.246 7.832-7.246 7.832zm-3.606-9.258-5.015-.003-.004 4.703 5.02-.004s2.324-.008 2.324-2.39c0-2.434-2.325-2.306-2.325-2.306zm0 0" fill="url(#b)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rom.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#099}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm12.1-6.9c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c0-4.1 2.1-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm8-11.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.2-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4H33s.1 1.3 0 2.4l-.4 6.4h-3l1-14.3z" fill="#fff"/><path class="st0" d="M49 49.8H23.5v3.5h-5.2v1.1h-2.8v1h2.8v1.3h5.2v6.1h-5.2V64h-2.8v1h2.8v1.1h5.2v6.6h-5.2v1.2h-2.8v1h2.8V76h5.2v4.7H49V76h4.7v-1.2h2.8v-1h-2.8v-1.2H49V66h4.7v-1h2.8v-1h-2.8v-1.3H49v-6.1h4.7v-1.3h2.8v-1h-2.8v-1.1H49v-3.4zm-4.9 8.3c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2c0 1.2-.9 2-2 2z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M68.633.102H16.39v7.226H5.738v2.274H0v2.062h5.738v2.684h10.653V26.94H5.738v2.477H0v2.066h5.738v2.27h10.653v13.625H5.738v2.48H0v2.063h5.738v2.273h10.653v9.703h52.242v-9.703h9.629v-2.48H84v-2.063h-5.738v-2.476h-9.63v-13.63h9.63v-2.062H84v-2.066h-5.738v-2.684h-9.63V14.141h9.63v-2.684H84V9.395h-5.738V7.12h-9.63zm-10.04 17.136c-2.253 0-4.097-1.86-4.097-4.129S56.34 8.98 58.594 8.98s4.097 1.86 4.097 4.13c0 2.476-1.843 4.128-4.097 4.128zm0 0" fill="#099"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rpm.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#55486d}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm7.8-6.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm7.9-7h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1.2-14.3z" fill="#fff"/><path class="st0" d="M43.6 68.3l-7.3-3.4L51 58l7.3 3.4-7.3 3.5-7.4 3.4zM51 51.2l-7.3-3.4-7.3 3.4L51 58.1l7.3-3.4-7.3-3.5zM28.9 61.4L21.6 58l-7.3 3.4L29 68.3l7.3-3.4-7.4-3.5zm0-6.8l7.3-3.4-7.3-3.4-14.7 6.9 7.3 3.4 7.4-3.5zM51 66.9l-6.6 3-.8.4-.8-.4-6.6-3-6.6 3-.8.4-.8-.4-6.6-3v10.7l14.7 7.7L51 77.6V66.9z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#55486d"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rpt.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}.st1{fill:#fff}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st1" d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm7.8-6.6h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm9.6-4.1h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3z"/><path d="M32.7 46.8c-.4 0-.8.3-1 .7l-1 1.9h-6.8c-.7 0-1.3.6-1.3 1.2-.1 10.6.2 21.3 0 31.9 0 .7.6 1.3 1.3 1.3h24.2c.7 0 1.3-.6 1.3-1.3V50.6c0-.6-.6-1.3-1.3-1.3h-6.8l-1-1.9c-.2-.4-.7-.7-1.2-.7-2.2.1-4.5.1-6.4.1z" fill="#666" stroke="#666" stroke-miterlimit="10"/><path class="st1" d="M25.2 51.9h4.5c0 1.3.1 2.5 1.3 2.5h10.2c1.3 0 1.3-1.3 1.3-2.5H47v29.3H25.3c-.1-9.8-.1-19.6-.1-29.3z"/><path class="st0" d="M28.4 58.9h15.3v2.6H28.4zm0 5.1h15.3v2.6H28.4zm0 5.1h15.3v2.5H28.4zm0 5.1h10.2v2.6H28.4z"/></svg>
1
<svg height="63" width="47" xmlns="http://www.w3.org/2000/svg"><path d="M10.62.6c-.398 0-.8.3-.998.7l-1 1.901h-6.8c-.7 0-1.302.6-1.302 1.2-.098 10.6.2 21.299 0 31.899 0 .7.602 1.3 1.302 1.3H26.02c.7 0 1.302-.6 1.302-1.3V4.4c0-.6-.602-1.302-1.302-1.302h-6.799l-1-1.899c-.2-.4-.7-.7-1.2-.7-2.2.1-4.501.1-6.4.1zm0 0" fill="#666" stroke="#666" stroke-miterlimit="10" transform="matrix(1.67417 0 0 1.65354 .211 0)"/><path d="M5.438 9.426h7.53c0 2.148.169 4.133 2.18 4.133h17.075c2.175 0 2.175-2.149 2.175-4.133h7.536v48.449H5.605c-.168-16.207-.168-32.41-.168-48.45zm0 0" fill="#fff"/><path d="M10.793 21H36.41v4.3H10.793zm0 8.434H36.41v4.296H10.793zm0 8.433H36.41V42H10.793zm0 8.434h17.078v4.297H10.793zm0 0" fill="#666"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rsa.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#696}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm9 3.7c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L25 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zM31.8 6.4h3.6L39 20.7h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.9c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.9h2z" fill="#fff"/><path class="st0" d="M49.2 62.2h-2.6v-5C46.6 51.5 42 47 36.4 47s-10.2 4.6-10.2 10.2v5h-2.6c-1 0-1.8.8-1.8 1.8v17.4c0 1 .8 1.8 1.8 1.8h25.6c1 0 1.8-.8 1.8-1.8V63.9c0-.9-.8-1.7-1.8-1.7zM38.6 76.6c.2.6-.3 1.1-.9 1.1H35c-.6 0-1-.6-.9-1.1l.8-3.2c-1-.5-1.7-1.5-1.7-2.8 0-1.7 1.4-3.1 3.1-3.1 1.7 0 3.1 1.4 3.1 3.1 0 1.2-.7 2.3-1.7 2.8l.9 3.2zm2.9-14.4H31.3v-5c0-2.8 2.3-5.1 5.1-5.1s5.1 2.3 5.1 5.1v5z"/></svg>
1
<svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M48.793 26.879h-4.629V18.05C44.164 7.988 35.973.043 26 .043S7.836 8.164 7.836 18.051v8.828H3.207A3.181 3.181 0 0 0 0 30.059V60.78c0 1.762 1.426 3.176 3.207 3.176h45.586c1.781 0 3.207-1.414 3.207-3.176V29.883c0-1.59-1.426-3.004-3.207-3.004zM29.918 52.305c.355 1.058-.535 1.941-1.602 1.941h-4.808c-1.07 0-1.781-1.059-1.606-1.941l1.426-5.649c-1.781-.883-3.027-2.648-3.027-4.945 0-3 2.492-5.473 5.52-5.473 3.027 0 5.523 2.473 5.523 5.473 0 2.117-1.246 4.062-3.028 4.945zm5.164-25.426H16.918V18.05c0-4.942 4.098-9.004 9.082-9.004s9.082 4.062 9.082 9.004zm0 0" fill="#696"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rss.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#dd7d36}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm9 3.7c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L25 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10.7 0c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path id="RSS" class="st0" d="M27.4 75.2c.9.9 1.4 2.1 1.4 3.4 0 1.3-.5 2.5-1.4 3.4-.9.9-2.1 1.4-3.4 1.4-1.3 0-2.5-.5-3.4-1.4-.9-.9-1.4-2-1.4-3.4 0-1.3.5-2.5 1.4-3.4.9-.9 2.1-1.4 3.4-1.4 1.4 0 2.5.6 3.4 1.4zm0 0zM20.7 82zm-1.4-22.4v6.9c4.5 0 8.7 1.8 11.9 4.9 3.2 3.2 4.9 7.4 4.9 11.9H43c0-6.5-2.7-12.5-7-16.8-4.3-4.2-10.2-6.9-16.7-6.9zm0-12.2v6.9c16 0 29.1 13.1 29.1 29.1h6.9c0-9.9-4-18.9-10.6-25.4-6.5-6.6-15.5-10.6-25.4-10.6z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M14.54 49.375c1.593 1.594 2.48 3.723 2.48 6.027 0 2.305-.887 4.43-2.48 6.028a8.46 8.46 0 0 1-6.032 2.48 8.451 8.451 0 0 1-6.028-2.48C.887 59.832 0 57.883 0 55.402c0-2.304.887-4.433 2.48-6.027a8.439 8.439 0 0 1 6.028-2.484c2.484 0 4.433 1.066 6.031 2.484zM.175 21.719v12.23c7.98 0 15.426 3.192 21.097 8.688 5.676 5.672 8.688 13.12 8.688 21.097h12.234c0-11.523-4.789-22.16-12.41-29.785C22.16 26.504 11.7 21.72.175 21.72zm0-21.63V12.32c28.367 0 51.59 23.227 51.59 51.59H64c0-17.55-7.09-33.504-18.793-45.027C33.684 7.18 17.73.09.176.09zm0 0" fill="#dd7d36"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rst.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm9 3.7c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L25 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm12.3-7.4h-3.1V6.4h9.6v2.9H35v11.4h-3.3V9.3z" fill="#fff"/><path class="st0" d="M14.6 77.2h42.8v6.2H14.6zm0-14.8h42.8v6.2H14.6zm0-15h42.8v6.2H14.6z"/></svg>
1
<svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><path d="M.176 52.977h75.648V64H.176zm0-26.309h75.648v11.02H.176zM.176 0h75.648v11.023H.176zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rtf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm10.4-3.7h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3zm9.2-2.9h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M14.6 77.2h42.8v6.2H14.6zm0-14.8h42.8v6.2H14.6zm0-15h42.8v6.2H14.6z"/></svg>
1
<svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><path d="M.176 52.977h75.648V64H.176zm0-26.309h75.648v11.02H.176zM.176 0h75.648v11.023H.176zm0 0" fill="#666"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ru.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm8.2-6.6H22V16c0 1.4.6 1.9 1.5 1.9S25 17.4 25 16V6.4h3.3V16c0 3-1.9 4.9-4.7 4.9-2.9 0-4.8-1.9-4.8-4.9V6.4z" fill="#fff"/><path class="st0" d="M54 47.5v36l-9-27 9-9zm-36 36h36l-27-9-9 9zm9-9l27 9-18-18-9 9zm9-9l18 18-9-27-9 9zm-18 9v9l9-9h-9zm18-9h-9v9l9-9zm9-9h-9v9l9-9zm9-9h-9v9l9-9zm-27 18l-9 9h9v-9zm9-9l-9 9h9v-9zm9-9l-9 9h9v-9z"/><path d="M54 47.5v36l-9-27 9-9zm-36 36h36l-27-9-9 9zm9-9l27 9-18-18-9 9zm9-9l18 18-9-27-9 9zm-18 9v9l9-9h-9zm18-9h-9v9l9-9zm9-9h-9v9l9-9zm9-9h-9v9l9-9zm-27 18l-9 9h9v-9zm9-9l-9 9h9v-9zm9-9l-9 9h9v-9z" fill="#992315" fill-opacity="0" stroke="#fff"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M61.988 2.012v59.976L46.996 17.004zM2.012 61.988h59.976L17.004 46.996zm14.992-14.992 44.984 14.992L32 32zM32 32l29.988 29.988-14.992-44.984zM2.012 46.996v14.992l14.992-14.992zM32 32H17.004v14.996zm14.996-14.996H32V32zM61.988 2.012H46.996v14.992zM17.004 32 2.012 46.996h14.992zM32 17.004 17.004 32H32zM46.996 2.012 32 17.004h14.996zm0 0" fill="#666" stroke="#fff" stroke-width="1.66605"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rub.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm.6-34.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.7v4.8H6.6V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zm8.2-6.6H22V16c0 1.4.6 1.9 1.5 1.9S25 17.4 25 16V6.4h3.3V16c0 3-1.9 4.9-4.7 4.9-2.9 0-4.8-1.9-4.8-4.9l-.1-9.6zm13.2 0h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.1 5.8c.8 0 1.2-.7 1.2-1.6s-.3-1.5-1.1-1.5h-1.2v3.1h1.1z" fill="#fff"/><path d="M54 47.5v36l-9-27 9-9zm-36 36h36l-27-9-9 9zm9-9l27 9-18-18-9 9zm9-9l18 18-9-27-9 9zm-18 9v9l9-9h-9zm18-9h-9v9l9-9zm9-9h-9v9l9-9zm9-9h-9v9l9-9zm-27 18l-9 9h9v-9zm9-9l-9 9h9v-9zm9-9l-9 9h9v-9z" fill="#992315"/><path d="M54 47.5v36l-9-27 9-9zm-36 36h36l-27-9-9 9zm9-9l27 9-18-18-9 9zm9-9l18 18-9-27-9 9zm-18 9v9l9-9h-9zm18-9h-9v9l9-9zm9-9h-9v9l9-9zm9-9h-9v9l9-9zm-27 18l-9 9h9v-9zm9-9l-9 9h9v-9zm9-9l-9 9h9v-9z" fill="#992315" fill-opacity="0" stroke="#fff"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M61.988 2.012v59.976L46.996 17.004zM2.012 61.988h59.976L17.004 46.996zm14.992-14.992 44.984 14.992L32 32zM32 32l29.988 29.988-14.992-44.984zM2.012 46.996v14.992l14.992-14.992zM32 32H17.004v14.996zm14.996-14.996H32V32zM61.988 2.012H46.996v14.992zM17.004 32 2.012 46.996h14.992zM32 17.004 17.004 32H32zM46.996 2.012 32 17.004h14.996zm0 0" fill="#992315" stroke="#fff" stroke-width="1.66605"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/rxml.svg
1
<?xml version="1.0" encoding="UTF-8"?>
2
<svg version="1.1" viewBox="0 0 72 96" xmlns="http://www.w3.org/2000/svg">
3
<defs>
4
<linearGradient id="b" x1=".74144" x2="590.86" y1="3.6658" y2="593.79" gradientTransform="scale(1.2219 .81837)" gradientUnits="userSpaceOnUse">
5
<stop stop-color="#cbced0" offset="0"/>
6
<stop stop-color="#84838b" offset="1"/>
7
</linearGradient>
8
<linearGradient id="a" x1="301.03" x2="703.07" y1="151.4" y2="553.44" gradientTransform="scale(.98995 1.0102)" gradientUnits="userSpaceOnUse">
9
<stop stop-color="#276dc3" offset="0"/>
10
<stop stop-color="#165caa" offset="1"/>
11
</linearGradient>
12
</defs>
13
<style>.st0{fill:#999}</style>
14
<path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/>
15
<path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/>
16
<path d="m6 41h60v49h-60zm11.847-27.5-3-7h2.5l1.2 3.5c0.3 0.8 0.5 1.7 0.5 1.7s0.2-0.9 0.5-1.7l1.5-3.5h2.4l-3 7 3.1 7.2h-2.4l-1.4-3.8c-0.3-0.8-0.5-1.6-0.5-1.6s-0.2 0.8-0.5 1.6l-1.4 3.8h-2.6zm7.7531-7h2.4l1.7 6.9c0.2 0.9 0.4 2.2 0.4 2.2h0.1s0.2-1.3 0.4-2.2l1.7-6.9h2.4l0.8 14.2h-2.1l-0.4-7.9c-0.1-0.9 0-2.2 0-2.2h-0.1s-0.2 1.4-0.4 2.3l-1.4 5.4h-2.2l-1.4-5.4c-0.2-0.8-0.4-2.3-0.4-2.3h-0.1s0.1 1.3 0 2.2l-0.4 7.9h-2.1zm12 0h2.2v12h4.2v2.2h-6.4z" fill="#fff"/>
17
<path d="m6 6.5h3.6c0.5 0 1.1 0.1 1.6 0.4 1.1 0.6 1.9 2 1.9 3.8 0 1.9-0.9 3.3-1.8 3.9 0 0 0.2 0.3 0.4 0.8l2.1 5.3h-2.3l-1.9-5.3h-1.3v5.3h-2.1v-14.2zm3.3 6.7c0.9 0 1.7-0.9 1.7-2.3 0-0.8-0.2-1.5-0.7-1.9-0.3-0.2-0.7-0.3-1-0.3h-1.2v4.5z" fill="#fff"/>
18
<g transform="matrix(.99998 0 0 .99998 61.27 -36.905)">
19
<g transform="matrix(.042564 0 0 .042564 -49.009 80.988)" fill-rule="evenodd">
20
<path d="m361.45 485.94c-199.12 0-360.55-108.11-360.55-241.47s161.42-241.47 360.55-241.47c199.12 0 360.55 108.11 360.55 241.47s-161.42 241.47-360.55 241.47zm55.188-388.53c-151.35 0-274.05 73.908-274.05 165.08s122.7 165.08 274.05 165.08 263.05-50.529 263.05-165.08c0-114.51-111.7-165.08-263.05-165.08z" fill="url(#b)"/>
21
<path d="m550 377s21.822 6.585 34.5 13c4.399 2.226 12.01 6.668 17.5 12.5 5.378 5.712 8 11.5 8 11.5l86 145-139 0.062-65-122.06s-13.31-22.869-21.5-29.5c-6.832-5.531-9.745-7.5-16.5-7.5h-33.026l0.026 158.97-123 0.052v-406.09h247s112.5 2.029 112.5 109.06-107.5 115-107.5 115zm-53.5-135.98-74.463-0.048-0.037 69.05 74.5-0.024s34.5-0.107 34.5-35.125c0-35.722-34.5-33.853-34.5-33.853z" fill="url(#a)"/>
22
</g>
23
<path d="m-24.46 120.55c-0.32318 0-0.71099-0.12927-0.96953-0.38781l-5.3647-5.4293c-0.51708-0.51709-0.51708-1.3573 0-1.9391l5.4293-5.4294c0.51708-0.51708 1.3573-0.51708 1.9391 0 0.51708 0.51708 0.51708 1.3573 0 1.9391l-4.4598 4.4598 4.4598 4.4598c0.51708 0.51708 0.51708 1.3573 0 1.939-0.32318 0.25854-0.71099 0.38781-1.0342 0.38781zm16.223 0c-0.32318 0-0.71099-0.12927-0.96953-0.38781-0.51708-0.51708-0.51708-1.3573 0-1.939l4.4598-4.4598-4.4598-4.4598c-0.51708-0.51708-0.51708-1.3573 0-1.9391 0.51708-0.51708 1.3573-0.51708 1.9391 0l5.4293 5.4294c0.51708 0.51708 0.51708 1.3573 0 1.9391l-5.4293 5.4293c-0.25854 0.25854-0.64635 0.38781-0.96953 0.38781zm-10.794 2.65c-0.12927 0-0.25854 0-0.45244-0.0646-0.71099-0.25854-1.0988-0.96953-0.84026-1.6805l5.4293-16.223c0.25854-0.71099 0.96953-1.0988 1.6805-0.84026 0.71099 0.25854 1.0988 0.96953 0.84026 1.6805l-5.4293 16.223c-0.12927 0.58172-0.71099 0.90489-1.2281 0.90489z" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".96953"/>
24
</g>
25
</svg>
26
1
<svg height="64" width="71" xmlns="http://www.w3.org/2000/svg"><linearGradient id="a" gradientTransform="matrix(.07693 0 0 .05184 -.057 .13)" gradientUnits="userSpaceOnUse" x1=".741" x2="590.86" y1="3.666" y2="593.79"><stop offset="0" stop-color="#cbced0"/><stop offset="1" stop-color="#84838b"/></linearGradient><linearGradient id="b" gradientTransform="matrix(.06233 0 0 .064 -.057 .13)" gradientUnits="userSpaceOnUse" x1="301.03" x2="703.07" y1="151.4" y2="553.44"><stop offset="0" stop-color="#276dc3"/><stop offset="1" stop-color="#165caa"/></linearGradient><path d="M22.7 30.914C10.163 30.914 0 24.066 0 15.617 0 7.168 10.164.32 22.7.32c12.534 0 22.698 6.848 22.698 15.297 0 8.45-10.16 15.297-22.699 15.297zm3.476-24.613c-9.531 0-17.254 4.683-17.254 10.457 0 5.777 7.723 10.46 17.254 10.46 9.527 0 16.558-3.202 16.558-10.46 0-7.254-7.03-10.457-16.558-10.457zm0 0" fill="url(#a)" fill-rule="evenodd"/><path d="M34.57 24.016s1.375.414 2.172.82c.278.144.758.426 1.102.793.34.363.504.73.504.73l5.414 9.184-8.75.004-4.094-7.73s-.836-1.45-1.352-1.872c-.43-.347-.613-.472-1.039-.472H26.45v10.07l-7.742.004V9.82h15.55s7.083.13 7.083 6.907c0 6.78-6.77 7.285-6.77 7.285zm-3.367-8.618h-4.687l-.004 4.372h4.691s2.172-.008 2.172-2.227c0-2.262-2.172-2.145-2.172-2.145zm0 0" fill="url(#b)" fill-rule="evenodd"/><path d="M-24.46 120.549a1.43 1.43 0 0 1-.97-.386l-5.364-5.43c-.517-.517-.517-1.357 0-1.94l5.43-5.43c.515-.517 1.357-.517 1.938 0 .518.517.518 1.36 0 1.94l-4.46 4.461 4.46 4.46c.518.517.518 1.356 0 1.939-.322.257-.71.386-1.035.386zm16.222 0a1.43 1.43 0 0 1-.97-.386c-.517-.517-.517-1.357 0-1.94l4.461-4.459-4.46-4.461c-.518-.517-.518-1.357 0-1.94.517-.517 1.357-.517 1.94 0l5.428 5.43c.517.517.517 1.357 0 1.94l-5.427 5.43a1.432 1.432 0 0 1-.972.386zm-10.793 2.65c-.13 0-.26 0-.452-.062-.71-.26-1.098-.971-.84-1.683l5.427-16.222c.26-.711.972-1.1 1.683-.84.71.257 1.098.969.84 1.68l-5.43 16.222c-.13.583-.71.906-1.228.906zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".97" transform="matrix(1.47916 0 0 1.48836 72.435 -120.409)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sass.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#cd6799}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.1-24.3c.5.6 1.3 1.2 2.1 1.2s1.2-.6 1.2-1.2c0-2-4.3-2.1-4.3-6.2 0-2.4 1.5-4.3 4.1-4.3 1.1 0 2.2.3 3.1 1l-1.1 2.9c-.4-.4-1.3-.9-1.9-.9-.8 0-1.2.6-1.2 1.2 0 2.1 4.3 2 4.3 6.1 0 2.3-1.3 4.4-4 4.4-1.3 0-2.6-.5-3.6-1.4l1.3-2.8zM17.7 6.4h3.2l3.2 14.3h-3l-.5-3H18l-.5 3h-3l3.2-14.3zm2.5 8.6l-.5-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.4 2.8h1.8zm6.4 1.7c.5.6 1.3 1.2 2.1 1.2s1.2-.6 1.2-1.2c0-2-4.3-2.1-4.3-6.2 0-2.4 1.5-4.3 4.1-4.3 1.1 0 2.2.3 3.1 1l-1.1 2.9c-.4-.4-1.3-.9-1.9-.9-.8 0-1.2.6-1.2 1.2 0 2.1 4.3 2 4.3 6.1 0 2.3-1.3 4.4-4 4.4-1.3 0-2.6-.5-3.6-1.4l1.3-2.8zm9.2 0c.5.6 1.3 1.2 2.1 1.2s1.2-.6 1.2-1.2c0-2-4.3-2.1-4.3-6.2 0-2.4 1.5-4.3 4.1-4.3 1.1 0 2.2.3 3.1 1l-1.1 2.9c-.4-.4-1.3-.9-1.9-.9-.8 0-1.2.6-1.2 1.2 0 2.1 4.3 2 4.3 6.1 0 2.3-1.3 4.4-4 4.4-1.3 0-2.6-.5-3.6-1.4l1.3-2.8z" fill="#fff"/><path d="M53.6 69.6c-1.6 0-3.1.4-4.3 1-.4-.9-.9-1.6-1-2.2-.1-.7-.2-1-.1-1.8s.6-1.9.6-2-.1-.5-1-.5c-1 0-1.8.1-1.8.4-.1.2-.3.8-.4 1.4-.1.9-1.9 3.9-2.9 5.5-.3-.7-.6-1.2-.7-1.6-.1-.7-.2-1-.1-1.8s.6-1.9.6-2c0-.1-.1-.5-1-.5s-1.8.1-1.8.4c-.1.3-.2.8-.4 1.4-.2.6-2.5 5.6-3.1 7-.3.7-.6 1.2-.7 1.6v.1c-.1.3-.3.5-.3.5-.1.2-.3.4-.4.4s-.1-.6 0-1.5c.4-1.8 1.2-4.5 1.2-4.6 0-.1.1-.5-.5-.8-.7-.2-.9.1-1 .1-.1 0-.1.1-.1.1s.7-3.1-1.4-3.1c-1.3 0-3.2 1.5-4.2 2.8-.6.3-1.8 1-3.2 1.7-.5.3-1 .6-1.5.8l-.1-.1c-2.6-2.8-7.5-4.8-7.3-8.6.1-1.4.5-5 9.3-9.3 7.2-3.6 13-2.6 13.9-.4 1.4 3.2-3.1 9-10.6 9.8-2.9.3-4.3-.8-4.7-1.2-.4-.4-.4-.4-.6-.4-.2.1-.1.5 0 .7.2.6 1.2 1.6 2.7 2.1 1.4.4 4.7.7 8.7-.9 4.5-1.8 8.1-6.6 7-10.7-1-4.1-7.9-5.5-14.4-3.2-3.9 1.4-8.1 3.5-11.1 6.4-3.6 3.4-4.1 6.2-3.9 7.5.8 4.3 6.8 7.1 9.2 9.2-.1.1-.2.1-.3.1-1.2.6-5.7 2.9-6.9 5.5-1.3 2.9.2 4.9 1.2 5.1 3.1.9 6.2-.7 7.9-3.2 1.7-2.5 1.5-5.8.7-7.3v-.1c.3-.1.7-.4 1-.5.6-.4 1.2-.7 1.7-1-.3.8-.5 1.8-.6 3.2-.1 1.6.5 3.7 1.4 4.5.4.4.8.4 1.1.4 1 0 1.5-.8 2-1.8.6-1.2 1.2-2.6 1.2-2.6s-.7 3.8 1.2 3.8c.7 0 1.4-.9 1.7-1.3l.1-.1.1-.1c.3-.5.9-1.5 1.8-3.4 1.2-2.3 2.3-5.3 2.3-5.3s.1.7.4 1.9c.2.7.7 1.5 1 2.2-.3.4-.4.6-.4.6-.2.3-.4.6-.7 1-1 1.1-2.1 2.4-2.2 2.8-.1.4-.1.7.2 1 .2.2.7.2 1.2.2.8-.1 1.5-.3 1.7-.4.4-.1 1-.4 1.5-.8 1-.7 1.5-1.6 1.4-2.9 0-.7-.3-1.4-.5-2.1.1-.1.1-.2.2-.4 1.5-2.1 2.6-4.5 2.6-4.5s.1.7.4 1.9c.1.6.5 1.2.8 1.9-1.4 1.1-2.2 2.4-2.5 3.2-.5 1.5-.1 2.3.7 2.4.4.1.9-.1 1.2-.3.5-.1 1-.4 1.6-.8 1-.7 1.8-1.6 1.8-2.9 0-.6-.1-1.2-.4-1.7 1.2-.5 2.6-.7 4.5-.5 4.1.5 4.9 3 4.8 4.1-.1 1.1-1 1.7-1.3 1.8s-.4.2-.4.4.1.1.4.1c.4-.1 2.1-.9 2.2-2.9.2-2.2-2.2-4.9-6.4-4.9zM22.1 80.3c-1.3 1.5-3.2 2.1-4 1.5-.9-.5-.5-2.7 1.1-4.3 1-1 2.3-1.8 3.2-2.3.2-.1.5-.3.8-.5.1 0 .1-.1.1-.1.1-.1.1-.1.2-.1.6 2.2 0 4.1-1.4 5.8zm9.9-6.8c-.4 1.2-1.5 4.1-2.1 4-.5-.1-.8-2.3-.1-4.5.4-1.1 1.2-2.4 1.6-2.9.7-.8 1.5-1.1 1.8-.7.2.2-.9 3.4-1.2 4.1zm8.1 3.9c-.2.1-.4.1-.4.1l.1-.1s1-1.1 1.4-1.6c.2-.3.5-.7.8-1v.1c-.1 1.2-1.4 2.1-1.9 2.5zm6.2-1.4c-.1-.1-.1-.4.4-1.5.2-.4.7-1.1 1.4-1.8.1.3.1.5.1.8 0 1.6-1.1 2.2-1.9 2.5z" fill="#cd6799" stroke="#cd6799" stroke-width=".25" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="fill-rule:nonzero;fill:#cd6799;fill-opacity:1;stroke-width:.25;stroke-linecap:butt;stroke-linejoin:miter;stroke:#cd6799;stroke-opacity:1;stroke-miterlimit:10" d="M40.764 20.63c-1.602 0-3.101.4-4.3 1-.4-.9-.9-1.601-1.001-2.198-.1-.7-.2-1.001-.1-1.8.1-.804.599-1.904.599-2.003 0-.098-.1-.498-1-.498-.998 0-1.797.099-1.797.4-.101.197-.302.799-.4 1.398-.102.9-1.903 3.901-2.903 5.502-.3-.7-.6-1.201-.7-1.6-.1-.701-.2-1.002-.1-1.8.1-.802.6-1.902.6-2.001 0-.101-.1-.498-1-.498s-1.801.098-1.801.4c-.096.3-.197.798-.398 1.4-.2.597-2.5 5.598-3.1 6.999-.302.698-.6 1.2-.7 1.598v.101c-.099.301-.3.5-.3.5-.1.2-.3.4-.4.4-.101 0-.101-.599 0-1.5.4-1.8 1.199-4.5 1.199-4.6 0-.1.1-.5-.5-.8-.7-.2-.9.101-.997.101-.103 0-.103.099-.103.099s.7-3.1-1.399-3.1c-1.3 0-3.2 1.5-4.2 2.801-.6.299-1.8.997-3.2 1.697-.499.301-1 .602-1.5.802l-.1-.101c-2.598-2.8-7.5-4.8-7.3-8.6.099-1.398.5-4.999 9.3-9.3 7.202-3.598 13-2.6 13.9-.4 1.4 3.2-3.1 9.002-10.6 9.799-2.901.303-4.3-.797-4.7-1.199-.4-.4-.4-.4-.6-.4-.2.102-.098.501 0 .701.2.6 1.202 1.6 2.699 2.101 1.4.397 4.7.698 8.702-.9 4.498-1.8 8.099-6.602 6.998-10.7-1-4.102-7.9-5.5-14.4-3.202-3.898 1.401-8.098 3.5-11.1 6.4-3.6 3.4-4.099 6.2-3.9 7.502.801 4.299 6.8 7.1 9.202 9.199-.1.1-.201.1-.302.1-1.2.6-5.7 2.901-6.897 5.5-1.3 2.9.197 4.898 1.2 5.1 3.099.898 6.198-.7 7.897-3.2 1.7-2.501 1.501-5.8.702-7.3v-.101c.3-.1.7-.4.998-.499.6-.4 1.2-.7 1.7-1-.299.8-.5 1.8-.599 3.2-.098 1.6.5 3.7 1.399 4.5.4.4.8.4 1.103.4.998 0 1.497-.801 1.998-1.8.6-1.2 1.2-2.6 1.2-2.6s-.7 3.799 1.2 3.799c.7 0 1.4-.9 1.7-1.3l.1-.099.1-.1c.299-.501.9-1.5 1.8-3.401 1.2-2.3 2.3-5.298 2.3-5.298s.1.698.4 1.899c.2.7.7 1.5 1 2.2-.3.4-.401.6-.401.6-.2.3-.398.599-.698.998-1 1.1-2.101 2.402-2.2 2.802-.1.4-.1.7.197 1 .201.2.703.2 1.202.2.8-.1 1.499-.3 1.698-.4.4-.1 1-.4 1.502-.8 1-.7 1.499-1.601 1.4-2.9 0-.701-.3-1.4-.5-2.1.1-.1.1-.2.2-.4 1.5-2.1 2.6-4.5 2.6-4.5s.1.7.4 1.9c.1.6.5 1.2.8 1.9-1.4 1.1-2.202 2.4-2.5 3.2-.5 1.501-.1 2.3.699 2.399.4.1.9-.101 1.202-.299.499-.1 1-.4 1.6-.801 1-.698 1.799-1.6 1.799-2.898 0-.602-.1-1.203-.4-1.701 1.2-.501 2.602-.7 4.5-.501 4.099.5 4.9 3.001 4.8 4.101-.1 1.1-1 1.7-1.3 1.8-.3.1-.4.2-.4.4s.1.1.4.1c.4-.1 2.1-.9 2.199-2.9.201-2.2-2.2-4.9-6.4-4.9zm-31.5 10.701c-1.3 1.5-3.203 2.099-4.002 1.5-.9-.501-.499-2.7 1.101-4.301.998-1 2.3-1.8 3.2-2.299.2-.1.5-.3.799-.5.1 0 .1-.101.1-.101.101-.101.101-.101.202-.101.6 2.2 0 4.1-1.4 5.802zm9.9-6.801c-.401 1.2-1.5 4.1-2.1 4-.501-.101-.801-2.301-.1-4.5.4-1.1 1.199-2.4 1.6-2.901.7-.8 1.499-1.1 1.799-.7.2.202-.9 3.4-1.2 4.1zm8.1 3.899c-.202.1-.403.1-.403.1l.1-.1s1-1.1 1.402-1.599c.199-.298.5-.7.8-1v.1c-.1 1.199-1.4 2.1-1.9 2.5zm6.2-1.401c-.1-.099-.1-.4.399-1.5.2-.399.7-1.1 1.4-1.8.1.301.1.503.1.802 0 1.6-1.102 2.2-1.9 2.498zm0 0" transform="matrix(1.7456 0 0 1.77926 .217 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/scss.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#cd6799}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.1-24.3c.5.6 1.3 1.2 2.1 1.2s1.2-.6 1.2-1.2c0-2-4.3-2.1-4.3-6.2 0-2.4 1.5-4.3 4.1-4.3 1.1 0 2.2.3 3.1 1l-1.1 2.9c-.4-.4-1.3-.9-1.9-.9-.8 0-1.2.6-1.2 1.2 0 2.1 4.3 2 4.3 6.1 0 2.3-1.3 4.4-4 4.4-1.3 0-2.6-.5-3.6-1.4l1.3-2.8zM20.9 6.1c1.1 0 2.4.4 3.2 1.2L23 10.2c-.4-.5-1.2-.9-1.9-.9-1.9 0-2.9 1.9-2.9 4.2 0 2.3 1 4.4 2.9 4.4.9 0 1.5-.5 2.1-1l1.2 2.8c-.8.7-1.8 1.3-3.5 1.3-3.6 0-5.7-3.1-5.7-7.4-.1-4.3 2.1-7.5 5.7-7.5zM27 16.7c.5.6 1.3 1.2 2.1 1.2s1.2-.6 1.2-1.2c0-2-4.3-2.1-4.3-6.2 0-2.4 1.5-4.3 4.1-4.3 1.1 0 2.2.3 3.1 1l-1.1 2.9c-.4-.4-1.3-.9-1.9-.9-.8 0-1.2.6-1.2 1.2 0 2.1 4.3 2 4.3 6.1 0 2.3-1.3 4.4-4 4.4-1.3 0-2.6-.5-3.6-1.4l1.3-2.8zm9.2 0c.5.6 1.3 1.2 2.1 1.2s1.2-.6 1.2-1.2c0-2-4.3-2.1-4.3-6.2 0-2.4 1.5-4.3 4.1-4.3 1.1 0 2.2.3 3.1 1l-1.1 2.9c-.4-.4-1.3-.9-1.9-.9-.8 0-1.2.6-1.2 1.2 0 2.1 4.3 2 4.3 6.1 0 2.3-1.3 4.4-4 4.4-1.3 0-2.6-.5-3.6-1.4l1.3-2.8z" fill="#fff"/><path d="M53.6 69.6c-1.6 0-3.1.4-4.3 1-.4-.9-.9-1.6-1-2.2-.1-.7-.2-1-.1-1.8s.6-1.9.6-2-.1-.5-1-.5c-1 0-1.8.1-1.8.4-.1.2-.3.8-.4 1.4-.1.9-1.9 3.9-2.9 5.5-.3-.7-.6-1.2-.7-1.6-.1-.7-.2-1-.1-1.8s.6-1.9.6-2c0-.1-.1-.5-1-.5s-1.8.1-1.8.4c-.1.3-.2.8-.4 1.4-.2.6-2.5 5.6-3.1 7-.3.7-.6 1.2-.7 1.6v.1c-.1.3-.3.5-.3.5-.1.2-.3.4-.4.4s-.1-.6 0-1.5c.4-1.8 1.2-4.5 1.2-4.6 0-.1.1-.5-.5-.8-.7-.2-.9.1-1 .1-.1 0-.1.1-.1.1s.7-3.1-1.4-3.1c-1.3 0-3.2 1.5-4.2 2.8-.6.3-1.8 1-3.2 1.7-.5.3-1 .6-1.5.8l-.1-.1c-2.6-2.8-7.5-4.8-7.3-8.6.1-1.4.5-5 9.3-9.3 7.2-3.6 13-2.6 13.9-.4 1.4 3.2-3.1 9-10.6 9.8-2.9.3-4.3-.8-4.7-1.2-.4-.4-.4-.4-.6-.4-.2.1-.1.5 0 .7.2.6 1.2 1.6 2.7 2.1 1.4.4 4.7.7 8.7-.9 4.5-1.8 8.1-6.6 7-10.7-1-4.1-7.9-5.5-14.4-3.2-3.9 1.4-8.1 3.5-11.1 6.4-3.6 3.4-4.1 6.2-3.9 7.5.8 4.3 6.8 7.1 9.2 9.2-.1.1-.2.1-.3.1-1.2.6-5.7 2.9-6.9 5.5-1.3 2.9.2 4.9 1.2 5.1 3.1.9 6.2-.7 7.9-3.2 1.7-2.5 1.5-5.8.7-7.3v-.1c.3-.1.7-.4 1-.5.6-.4 1.2-.7 1.7-1-.3.8-.5 1.8-.6 3.2-.1 1.6.5 3.7 1.4 4.5.4.4.8.4 1.1.4 1 0 1.5-.8 2-1.8.6-1.2 1.2-2.6 1.2-2.6s-.7 3.8 1.2 3.8c.7 0 1.4-.9 1.7-1.3l.1-.1.1-.1c.3-.5.9-1.5 1.8-3.4 1.2-2.3 2.3-5.3 2.3-5.3s.1.7.4 1.9c.2.7.7 1.5 1 2.2-.3.4-.4.6-.4.6-.2.3-.4.6-.7 1-1 1.1-2.1 2.4-2.2 2.8-.1.4-.1.7.2 1 .2.2.7.2 1.2.2.8-.1 1.5-.3 1.7-.4.4-.1 1-.4 1.5-.8 1-.7 1.5-1.6 1.4-2.9 0-.7-.3-1.4-.5-2.1.1-.1.1-.2.2-.4 1.5-2.1 2.6-4.5 2.6-4.5s.1.7.4 1.9c.1.6.5 1.2.8 1.9-1.4 1.1-2.2 2.4-2.5 3.2-.5 1.5-.1 2.3.7 2.4.4.1.9-.1 1.2-.3.5-.1 1-.4 1.6-.8 1-.7 1.8-1.6 1.8-2.9 0-.6-.1-1.2-.4-1.7 1.2-.5 2.6-.7 4.5-.5 4.1.5 4.9 3 4.8 4.1-.1 1.1-1 1.7-1.3 1.8s-.4.2-.4.4.1.1.4.1c.4-.1 2.1-.9 2.2-2.9.2-2.2-2.2-4.9-6.4-4.9zM22.1 80.3c-1.3 1.5-3.2 2.1-4 1.5-.9-.5-.5-2.7 1.1-4.3 1-1 2.3-1.8 3.2-2.3.2-.1.5-.3.8-.5.1 0 .1-.1.1-.1.1-.1.1-.1.2-.1.6 2.2 0 4.1-1.4 5.8zm9.9-6.8c-.4 1.2-1.5 4.1-2.1 4-.5-.1-.8-2.3-.1-4.5.4-1.1 1.2-2.4 1.6-2.9.7-.8 1.5-1.1 1.8-.7.2.2-.9 3.4-1.2 4.1zm8.1 3.9c-.2.1-.4.1-.4.1l.1-.1s1-1.1 1.4-1.6c.2-.3.5-.7.8-1v.1c-.1 1.2-1.4 2.1-1.9 2.5zm6.2-1.4c-.1-.1-.1-.4.4-1.5.2-.4.7-1.1 1.4-1.8.1.3.1.5.1.8 0 1.6-1.1 2.2-1.9 2.5z" fill="#cd6799" stroke="#cd6799" stroke-width=".25" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="fill-rule:nonzero;fill:#cd6799;fill-opacity:1;stroke-width:.25;stroke-linecap:butt;stroke-linejoin:miter;stroke:#cd6799;stroke-opacity:1;stroke-miterlimit:10" d="M40.764 20.63c-1.602 0-3.101.4-4.3 1-.4-.9-.9-1.601-1.001-2.198-.1-.7-.2-1.001-.1-1.8.1-.804.599-1.904.599-2.003 0-.098-.1-.498-1-.498-.998 0-1.797.099-1.797.4-.101.197-.302.799-.4 1.398-.102.9-1.903 3.901-2.903 5.502-.3-.7-.6-1.201-.7-1.6-.1-.701-.2-1.002-.1-1.8.1-.802.6-1.902.6-2.001 0-.101-.1-.498-1-.498s-1.801.098-1.801.4c-.096.3-.197.798-.398 1.4-.2.597-2.5 5.598-3.1 6.999-.302.698-.6 1.2-.7 1.598v.101c-.099.301-.3.5-.3.5-.1.2-.3.4-.4.4-.101 0-.101-.599 0-1.5.4-1.8 1.199-4.5 1.199-4.6 0-.1.1-.5-.5-.8-.7-.2-.9.101-.997.101-.103 0-.103.099-.103.099s.7-3.1-1.399-3.1c-1.3 0-3.2 1.5-4.2 2.801-.6.299-1.8.997-3.2 1.697-.499.301-1 .602-1.5.802l-.1-.101c-2.598-2.8-7.5-4.8-7.3-8.6.099-1.398.5-4.999 9.3-9.3 7.202-3.598 13-2.6 13.9-.4 1.4 3.2-3.1 9.002-10.6 9.799-2.901.303-4.3-.797-4.7-1.199-.4-.4-.4-.4-.6-.4-.2.102-.098.501 0 .701.2.6 1.202 1.6 2.699 2.101 1.4.397 4.7.698 8.702-.9 4.498-1.8 8.099-6.602 6.998-10.7-1-4.102-7.9-5.5-14.4-3.202-3.898 1.401-8.098 3.5-11.1 6.4-3.6 3.4-4.099 6.2-3.9 7.502.801 4.299 6.8 7.1 9.202 9.199-.1.1-.201.1-.302.1-1.2.6-5.7 2.901-6.897 5.5-1.3 2.9.197 4.898 1.2 5.1 3.099.898 6.198-.7 7.897-3.2 1.7-2.501 1.501-5.8.702-7.3v-.101c.3-.1.7-.4.998-.499.6-.4 1.2-.7 1.7-1-.299.8-.5 1.8-.599 3.2-.098 1.6.5 3.7 1.399 4.5.4.4.8.4 1.103.4.998 0 1.497-.801 1.998-1.8.6-1.2 1.2-2.6 1.2-2.6s-.7 3.799 1.2 3.799c.7 0 1.4-.9 1.7-1.3l.1-.099.1-.1c.299-.501.9-1.5 1.8-3.401 1.2-2.3 2.3-5.298 2.3-5.298s.1.698.4 1.899c.2.7.7 1.5 1 2.2-.3.4-.401.6-.401.6-.2.3-.398.599-.698.998-1 1.1-2.101 2.402-2.2 2.802-.1.4-.1.7.197 1 .201.2.703.2 1.202.2.8-.1 1.499-.3 1.698-.4.4-.1 1-.4 1.502-.8 1-.7 1.499-1.601 1.4-2.9 0-.701-.3-1.4-.5-2.1.1-.1.1-.2.2-.4 1.5-2.1 2.6-4.5 2.6-4.5s.1.7.4 1.9c.1.6.5 1.2.8 1.9-1.4 1.1-2.202 2.4-2.5 3.2-.5 1.501-.1 2.3.699 2.399.4.1.9-.101 1.202-.299.499-.1 1-.4 1.6-.801 1-.698 1.799-1.6 1.799-2.898 0-.602-.1-1.203-.4-1.701 1.2-.501 2.602-.7 4.5-.501 4.099.5 4.9 3.001 4.8 4.101-.1 1.1-1 1.7-1.3 1.8-.3.1-.4.2-.4.4s.1.1.4.1c.4-.1 2.1-.9 2.199-2.9.201-2.2-2.2-4.9-6.4-4.9zm-31.5 10.701c-1.3 1.5-3.203 2.099-4.002 1.5-.9-.501-.499-2.7 1.101-4.301.998-1 2.3-1.8 3.2-2.299.2-.1.5-.3.799-.5.1 0 .1-.101.1-.101.101-.101.101-.101.202-.101.6 2.2 0 4.1-1.4 5.802zm9.9-6.801c-.401 1.2-1.5 4.1-2.1 4-.501-.101-.801-2.301-.1-4.5.4-1.1 1.199-2.4 1.6-2.901.7-.8 1.499-1.1 1.799-.7.2.202-.9 3.4-1.2 4.1zm8.1 3.899c-.202.1-.403.1-.403.1l.1-.1s1-1.1 1.402-1.599c.199-.298.5-.7.8-1v.1c-.1 1.199-1.4 2.1-1.9 2.5zm6.2-1.401c-.1-.099-.1-.4.399-1.5.2-.399.7-1.1 1.4-1.8.1.301.1.503.1.802 0 1.6-1.102 2.2-1.9 2.498zm0 0" transform="matrix(1.7456 0 0 1.77926 .217 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sdf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#a03537}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.3-24.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zm10-10.3h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.1-11.4h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M-4938.1 722.8c-4.8-.2-9.1-1.7-11.4-4-.7-.6-1.4-1.5-1.7-2.1l-.2-.4v-4.5c0-4.5 0-4.5.1-4.1.2 1 .8 2 1.7 2.8.6.5 1.8 1.4 2.8 1.9 1.7.9 3.9 1.5 6.2 1.8 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.5-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.2.4c-.7 1.4-1.9 2.6-3.5 3.6-3.1 1.8-7.8 2.8-12.4 2.6zm0-11.2c-4.2-.2-8.1-1.4-10.6-3.2-.6-.4-1.4-1.2-1.7-1.6-.3-.4-.6-.9-.8-1.4l-.2-.4v-4.4c0-4.4 0-4.4.1-4.1.2.7.5 1.5 1.1 2.1.3.4.8.9 1.1 1.1.1.1.4.2.6.4 2 1.4 4.8 2.4 8 2.9 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.4-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.3.6c-.5.9-.8 1.4-1.4 2-.6.6-1.2 1.1-2 1.5-3.2 1.8-7.9 2.8-12.5 2.5zm-.3-11.1c-2.8-.2-5-.7-7.1-1.5-2.5-1-4.3-2.3-5.2-3.9-.2-.3-.4-.7-.5-1.2-.1-.4-.2-1.4-.1-2 .6-3.2 4.9-5.8 10.7-6.7 1.4-.2 1.9-.2 3.9-.2s2.5 0 3.9.2c2.3.3 4.4 1 6.2 1.8 2.6 1.3 4.2 3 4.5 4.8.1.5.1 1.6-.1 2-.3 1-.7 1.6-1.5 2.4-2.1 2.2-5.8 3.6-10.4 4.1-.6.2-3.7.2-4.3.2z" transform="translate(4973.037 -638.07)"/></svg>
1
<svg height="64" width="51" xmlns="http://www.w3.org/2000/svg"><path d="M23.023 63.957c-8.199-.34-15.543-2.875-19.468-6.77-1.196-1.011-2.39-2.535-2.903-3.55L.31 52.96v-7.617c0-7.614 0-7.614.171-6.934.34 1.692 1.368 3.383 2.903 4.735 1.023.847 3.074 2.37 4.781 3.214 2.906 1.524 6.66 2.54 10.59 3.047 2.39.34 3.246.34 6.66.34 3.418 0 4.27 0 6.66-.34 3.93-.508 7.516-1.691 10.59-3.047 1.707-.843 3.758-2.199 4.781-3.214 1.368-1.352 2.563-3.043 2.903-4.735.172-.508.172-.508.172 6.934v7.445l-.34.68c-1.196 2.367-3.246 4.398-5.98 6.09-5.294 3.046-13.321 4.738-21.177 4.398zm0-18.95c-7.171-.339-13.832-2.37-18.101-5.413-1.027-.68-2.39-2.032-2.906-2.707-.512-.68-1.024-1.524-1.364-2.371L.31 33.84v-7.445c0-7.446 0-7.446.171-6.938.34 1.184.852 2.54 1.88 3.555.511.675 1.367 1.523 1.878 1.86.168.171.684.339 1.024.679 3.414 2.367 8.199 4.058 13.664 4.906 2.39.336 3.242.336 6.66.336 3.414 0 4.27 0 6.66-.336 3.93-.508 7.516-1.691 10.59-3.047 1.707-.847 3.758-2.2 4.781-3.215 1.367-1.351 2.39-3.047 2.903-4.738.171-.508.171-.508.171 6.938v7.445l-.511 1.015c-.856 1.524-1.368 2.368-2.39 3.383-1.028 1.016-2.052 1.864-3.419 2.54-5.465 3.046-13.492 4.738-21.348 4.23zm-.511-18.78c-4.782-.34-8.54-1.184-12.125-2.54-4.27-1.69-7.344-3.89-8.883-6.597a5.594 5.594 0 0 1-.852-2.031C.48 14.383.31 12.69.48 11.676 1.504 6.262 8.848 1.859 18.754.34 21.144 0 22 0 25.414 0c3.418 0 4.27 0 6.66.34 3.93.508 7.516 1.691 10.59 3.043 4.441 2.199 7.172 5.078 7.684 8.12.172.849.172 2.708-.168 3.388-.512 1.691-1.196 2.707-2.563 4.058-3.586 3.723-9.906 6.094-17.762 6.938-1.023.34-6.32.34-7.343.34zm0 0" fill="#a03537"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sed.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.3-24.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zm10-10.3h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4zm10.5 0H32c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z" fill="#fff"/><path class="st0" d="M38 68.1l2.8.8 1.7-6.2-2.8-.8c0-1-.1-2-.4-3l2.5-1.5-3.2-5.6-2.6 1.5c-.7-.7-1.5-1.3-2.4-1.8l.8-2.8-6.2-1.7-.8 2.8c-1 0-2 .1-3 .4l-1.5-2.5-5.6 3.2 1.5 2.5c-.7.7-1.3 1.5-1.8 2.4l-2.8-.8-1.7 6.2 2.8.8c0 1 .1 2 .4 3l-2.5 1.5 3.2 5.6 2.5-1.5c.7.7 1.5 1.3 2.4 1.8l-.8 2.8 6.2 1.7.8-2.8c1 0 2-.1 3-.4l1.5 2.5 5.6-3.2-1.5-2.5c.7-.7 1.4-1.5 1.9-2.4zm-15.5-3.3c-1.6-2.7-.6-6.2 2.1-7.8 2.7-1.6 6.2-.6 7.8 2.1 1.6 2.7.6 6.2-2.1 7.8-2.7 1.6-6.2.7-7.8-2.1zm30.2 19.8l3.6-2.1-1-1.7c.5-.5.9-1 1.2-1.6l1.9.5 1.1-4.1-1.9-.5c0-.7-.1-1.3-.3-2l1.7-1-2.1-3.6-1.7 1c-.5-.5-1-.9-1.6-1.2l.5-1.9-4.1-1.1-.5 1.9c-.7 0-1.3.1-2 .3l-1-1.7-3.4 2.2 1 1.7c-.5.5-.9 1-1.2 1.6l-1.9-.6-1.1 4.1 1.9.5c0 .7.1 1.3.3 2l-1.7 1 2.1 3.6 1.7-1c.5.5 1 .9 1.6 1.2l-.5 1.9 4.1 1.1.5-1.9c.7 0 1.3-.1 2-.3-.2 0 .8 1.7.8 1.7zm-6.2-7.5c-1-1.8-.4-4.1 1.4-5.1 1.8-1 4.1-.4 5.1 1.4 1 1.8.4 4.1-1.4 5.1-1.8 1-4.1.4-5.1-1.4z"/></svg>
1
<svg height="64" width="79" xmlns="http://www.w3.org/2000/svg"><path d="m42.852 35.445 4.695 1.344 2.851-10.418-4.695-1.344c0-1.68-.168-3.359-.672-5.039l4.192-2.52-5.364-9.405-4.359 2.519a18.036 18.036 0 0 0-4.023-3.023l1.34-4.704L26.421 0l-1.34 4.703c-1.676 0-3.352.168-5.027.672l-2.516-4.2-9.387 5.376 2.512 4.199a18.053 18.053 0 0 0-3.016 4.031l-4.695-1.343L.105 23.852l4.692 1.343c0 1.68.168 3.36.672 5.04l-4.192 2.523 5.364 9.406 4.191-2.52a18.126 18.126 0 0 0 4.023 3.024l-1.34 4.703 10.395 2.856 1.34-4.704c1.676 0 3.352-.168 5.031-.671l2.512 4.199 9.39-5.375-2.515-4.2c1.172-1.175 2.348-2.519 3.184-4.03zm-25.985-5.547c-2.68-4.535-1.004-10.414 3.52-13.101 4.527-2.688 10.394-1.008 13.078 3.527 2.683 4.535 1.004 10.414-3.52 13.106-4.527 2.687-10.394 1.175-13.078-3.532zm50.63 33.262 6.034-3.527-1.676-2.856c.84-.84 1.508-1.68 2.012-2.687l3.184.84 1.844-6.887-3.184-.84c0-1.176-.168-2.183-.504-3.36l2.852-1.679-3.52-6.047-2.852 1.68c-.84-.84-1.675-1.512-2.683-2.016l.84-3.191-6.875-1.852-.836 3.196c-1.176 0-2.18.168-3.356.504l-1.675-2.86-5.7 3.7 1.676 2.855c-.836.84-1.508 1.68-2.012 2.687l-3.183-1.007-1.844 6.886 3.184.84c0 1.176.168 2.184.504 3.36l-2.852 1.68 3.523 6.046 2.848-1.68c.84.84 1.676 1.512 2.684 2.016l-.84 3.191L61.965 64l.836-3.191c1.176 0 2.18-.168 3.355-.504-.336 0 1.34 2.855 1.34 2.855zM57.101 50.563c-1.676-3.024-.668-6.887 2.347-8.567 3.02-1.68 6.875-.672 8.551 2.352 1.676 3.023.672 6.886-2.348 8.566-3.015 1.68-6.875.672-8.55-2.352zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sh.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.3-24.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zm10-10.3h3.3v5.8h3.2V6.4H27v14.3h-3.3V15h-3.2v5.7h-3.3V6.4z" fill="#fff"/><path d="M30.8 61.4h10.9v2.7H30.8v-2.7zm0 5.4h10.9v2.7H30.8v-2.7zm0 5.5h10.9V75H30.8v-2.7zm19-24.4H28.1c-3 0-5.4 2.4-5.4 5.4v24.4h-5.4c0 3 2.4 5.4 5.4 5.4h21.7c3 0 5.4-2.4 5.4-5.4V56h5.4v-2.7c0-3-2.4-5.4-5.4-5.4zm-2.7 29.3c0 1.8-1.4 3.2-3.2 3.2H24c1.3-.9 1.3-2.7 1.3-2.7V53.3c0-1.5 1.2-2.7 2.7-2.7s2.7 1.2 2.7 2.7V56H47l.1 21.2zM33.5 53.3v-2.7h16.3c2.5 0 2.7 1.6 2.7 2.7h-19z" fill="#999" stroke="#999" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sit.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#90c}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.3-24.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zm10-10.3h3.3v14.3h-3.3V6.4zm9.2 2.9h-3.1V6.4H33v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path class="st0" d="M51.1 57.5h-5.7v-5.7l5.7 5.7zm-15.3-5.7v20.7h15.4V58.9H44v-7.1h-8.2zm2.4-5.4h-17v4h6.7l-4.2 3.3v3.5l6.2-4.8v-1.9h21.6v-1.6l-13.3-2.5zm-8.3 8.7l-6.2 4.8v3.5l6.2-4.8v-3.5zm-6.3 14.4l6.2-4.8v-3.5L23.6 66v3.5zm6.3 1.4v-3.5l-6.2 4.8V74h-2.5v4H25v2.8h-2.2c-.4-.7-1.1-1.2-2-1.2-1.3 0-2.3 1-2.3 2.3 0 1.3 1 2.3 2.3 2.3.9 0 1.6-.5 2-1.2H25v2.1h3.4V83h2.2c.4.7 1.1 1.2 2 1.2 1.3 0 2.3-1 2.3-2.3 0-1.3-1-2.3-2.3-2.3-.9 0-1.6.5-2 1.2h-2.2V78h9.7l13.3-2.4V74H25.7l4.2-3.1z"/></svg>
1
<svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sitemap.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M9.8 81.9c.4.4 1 .8 1.6.8s.9-.4.9-.9c0-1.4-3.3-1.5-3.3-4.4 0-1.7 1.2-3 3.2-3 .8 0 1.7.2 2.4.7l-.8 2c-.3-.3-1-.6-1.5-.6-.7 0-.9.4-.9.9 0 1.5 3.3 1.4 3.3 4.3 0 1.6-1 3.1-3.1 3.1-1 0-2-.3-2.8-1l1-1.9zm7-7.2h2.3v10h-2.3v-10zm6.4 2H21v-2h6.7v2h-2.2v8h-2.3v-8zm6.5-2h5v2H32v1.9h2.2v2H32v2h2.9v2h-5.2v-9.9zm7.6 0h2.5l.9 4.2c.1.7.3 1.7.3 1.7s.2-1 .3-1.7l.9-4.2h2.5l.6 10h-2.1l-.3-4.5c-.1-.8 0-1.7 0-1.7h-.1s-.2 1.1-.3 1.7l-.6 2.9H40l-.6-2.9c-.2-.6-.3-1.7-.3-1.7H39s.1.9 0 1.7l-.3 4.5h-2.1l.7-10zm12.3 0h2.5l2.5 10h-2.3l-.4-2.1h-2.1l-.4 2.1h-2.3l2.5-10zm1.9 6l-.4-2c-.1-.7-.3-1.7-.3-1.7h-.1s-.1 1.1-.3 1.7l-.4 2h1.5zm4.8-6h3.2c1.8 0 3.1 1.4 3.1 3.4s-1.2 3.5-3.1 3.5h-.9v3.1h-2.3v-10zm2.8 4.9c.7 0 1.1-.6 1.1-1.4s-.5-1.4-1.1-1.4h-.5v2.9l.5-.1z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm4.4 26.2c-.2-.3-.5-.4-.8-.4H42c-.3.7-.7 1.4-1 2.1-.8 1.6-1.7 3.4-2.5 4.9v.1c-.5.9-1.4 1.4-2.4 1.4s-1.9-.5-2.4-1.4c-.3-.5-1.3-2.4-2.6-4.9-.4-.7-.7-1.4-1-2.1h-5.2c-.3 0-.7.2-.8.5l-4.5 9.4c-.1.3-.1.6 0 .9.2.3.5.4.8.4h26.9c.3 0 .7-.2.8-.5l4.5-9.4c0-.4 0-.7-.2-1z"/><path class="st2" d="M36 26c-5.5 0-10 4.5-10 10 0 3.3 3.6 11.1 6.6 17.1 1.4 2.8 2.5 4.9 2.6 4.9.2.3.5.5.8.5.3 0 .6-.2.8-.5 0 0 1.1-2.1 2.6-4.9 3-6 6.6-13.8 6.6-17.1 0-5.5-4.5-10-10-10zm0 16c-2.5 0-4.6-1.9-4.8-4.4v-.5c0-2.7 2.2-4.9 4.9-4.9 2.5 0 4.6 1.9 4.8 4.4v.5c0 2.7-2.2 4.9-4.9 4.9z"/></svg>
1
<svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M56.645 44.492c-.348-.512-.864-.68-1.38-.68H38.728c-.516 1.188-1.204 2.376-1.723 3.567-1.375 2.715-2.926 5.773-4.305 8.32v.168c-.863 1.528-2.41 2.38-4.133 2.38s-3.273-.852-4.136-2.38c-.516-.847-2.239-4.074-4.477-8.32-.691-1.188-1.207-2.379-1.723-3.567H9.27c-.516 0-1.204.34-1.375.852L.14 60.793a2.327 2.327 0 0 0 0 1.527c.343.512.863.68 1.379.68h46.34c.515 0 1.203-.34 1.374-.848l7.754-15.965c0-.68 0-1.187-.343-1.695zm0 0" fill="#039"/><path d="M28.39 0c-9.472 0-17.222 7.64-17.222 16.98 0 5.606 6.2 18.852 11.367 29.04 2.41 4.753 4.309 8.32 4.48 8.32.344.508.86.847 1.376.847.52 0 1.035-.34 1.379-.847 0 0 1.894-3.567 4.48-8.32 5.168-10.188 11.367-23.434 11.367-29.04C45.617 7.64 37.867 0 28.391 0zm0 27.168c-4.304 0-7.921-3.223-8.265-7.469v-.851c0-4.582 3.79-8.32 8.441-8.32 4.305 0 7.922 3.226 8.266 7.472v.848c0 4.586-3.789 8.32-8.441 8.32zm0 0" fill="#efce4a"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/skin.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d5006e}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.2-24.3c.5.6 1.3 1.2 2.2 1.2.8 0 1.2-.6 1.2-1.2 0-2-4.5-2.1-4.5-6.2 0-2.4 1.6-4.3 4.3-4.3 1.1 0 2.3.3 3.2 1l-1.1 2.9c-.5-.4-1.4-.9-2.1-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.5 2 4.5 6.1 0 2.3-1.4 4.4-4.2 4.4-1.3 0-2.7-.5-3.8-1.4l1.6-2.8zm8.6-10.3h3.1v5.5h.6l2.1-5.5H25l-2.7 6.8 2.9 7.4h-3.5l-2.1-5.8H19v5.8h-3.1V6.4zm10.8 0h3.1v14.3h-3.1V6.4zm5.7 0h3.3l2.3 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h2.9v14.3h-3.3l-2.3-6.6c-.4-1-.6-2.4-.6-2.4h-.1s.2 1.5.2 2.4v6.6h-2.9V6.4z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#d5006e"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sldm.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2{fill:#c60}.st2{stroke:#c60;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm1-24.3c.4.6 1.1 1.2 1.9 1.2.7 0 1-.6 1-1.2 0-2-3.8-2.1-3.8-6.2C6 8 7.4 6.1 9.7 6.1c.9 0 2 .3 2.7 1l-.9 2.9c-.4-.4-1.2-.9-1.7-.9-.8 0-1.1.6-1.1 1.2 0 2.1 3.8 2 3.8 6.1 0 2.3-1.2 4.4-3.6 4.4-1.1 0-2.3-.5-3.2-1.4L7 16.7zm7.1-10.3h2.6v11.4h3.4v2.9H14V6.4h.1zm7.5 0h3.3c2.9 0 4.7 2.6 4.7 7.1s-1.8 7.2-4.7 7.2h-3.3V6.4zm3.3 11.4c1.3 0 2.1-1.5 2.1-4.3s-.8-4.2-2.1-4.2h-.7v8.5h.7zm6.9-11.4h2.9l1.1 6c.2.9.3 2.4.3 2.4s.2-1.5.3-2.4l1.1-6h2.9l.7 14.3h-2.4l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.7 4.1h-2.5l-.7-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.3 6.4H31l.8-14.3z" fill="#fff"/><path class="st2" d="M53 47.7H19c-1.7 0-3.1 1.4-3.1 3.1v21.8c0 1.7 1.4 3.1 3.1 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.5-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.5 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.1-1.4 3.1-3.1V50.8c0-1.7-1.4-3.1-3.1-3.1zm.3 25.1H18.7V50.6h34.5l.1 22.2z"/><path class="st2" d="M27.6 63.9h2.8v5.6h-2.8v-5.6zm4.7-1.8h2.8v7.4h-2.8v-7.4zm4.6-1.9h2.8v9.3h-2.8v-9.3zm4.6-1.8h2.8v11.1h-2.8V58.4zm-.2-4.1L36.4 57l-3.6-1.2-6.1 3.3.9 1 5.4-2.8 3.6 1.2 5.6-3.1.9 1 2.1-3.5-4.8.3.9 1.1z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#c60" stroke="#c60" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sldx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0,.st2{fill:#c60}.st2{stroke:#c60;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm1-24.3c.4.6 1.1 1.2 1.9 1.2.7 0 1-.6 1-1.2 0-2-3.8-2.1-3.8-6.2C6 8 7.4 6.1 9.7 6.1c.9 0 2 .3 2.7 1l-.9 2.9c-.4-.4-1.2-.9-1.7-.9-.8 0-1.1.6-1.1 1.2 0 2.1 3.8 2 3.8 6.1 0 2.3-1.2 4.4-3.6 4.4-1.1 0-2.3-.5-3.2-1.4L7 16.7zm7.1-10.3h2.6v11.4h3.4v2.9H14V6.4h.1zm7.5 0h3.3c2.9 0 4.7 2.6 4.7 7.1s-1.8 7.2-4.7 7.2h-3.3V6.4zm3.3 11.4c1.3 0 2.1-1.5 2.1-4.3s-.8-4.2-2.1-4.2h-.7v8.5h.7zm8.1-4.2l-2.8-7.2h2.9l.9 2.9c.3.9.4 1.8.4 1.8s.2-.9.5-1.8L36 6.4h2.9l-2.8 7.2 2.7 7.1H36l-.9-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.4 1.7l-.9 3h-2.8l2.5-7.1z" fill="#fff"/><path class="st2" d="M53 47.7H19c-1.7 0-3.1 1.4-3.1 3.1v21.8c0 1.7 1.4 3.1 3.1 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.5-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.5 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.1-1.4 3.1-3.1V50.8c0-1.7-1.4-3.1-3.1-3.1zm.3 25.1H18.7V50.6h34.5l.1 22.2z"/><path class="st2" d="M27.6 63.9h2.8v5.6h-2.8v-5.6zm4.7-1.8h2.8v7.4h-2.8v-7.4zm4.6-1.9h2.8v9.3h-2.8v-9.3zm4.6-1.8h2.8v11.1h-2.8V58.4zm-.2-4.1L36.4 57l-3.6-1.2-6.1 3.3.9 1 5.4-2.8 3.6 1.2 5.6-3.1.9 1 2.1-3.5-4.8.3.9 1.1z"/></svg>
1
<svg height="64" width="70" xmlns="http://www.w3.org/2000/svg"><g fill="#c60" stroke="#c60" stroke-miterlimit="10"><path d="M53 47.7H19a3.116 3.116 0 0 0-3.101 3.1v21.8c0 1.7 1.4 3.1 3.101 3.1h14.2L31.8 81h-1.6c-.7 0-1.2.501-1.2 1.2s.5 1.2 1.2 1.2h11.5c.7 0 1.2-.501 1.2-1.2s-.5-1.2-1.2-1.2H40l-1.4-5.4H53c1.7 0 3.101-1.4 3.101-3.1V50.8c0-1.7-1.4-3.1-3.101-3.1zm.3 25.1H18.7V50.6h34.5zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/><path d="M27.6 63.9h2.8v5.6h-2.8zm4.7-1.8h2.801v7.4h-2.8zM36.9 60.2h2.8v9.302h-2.8zm4.6-1.8h2.8v11.102h-2.8zm-.2-4.098L36.4 56.999l-3.6-1.198-6.1 3.3.9.998 5.4-2.798 3.6 1.198 5.6-3.1.9 1.001 2.101-3.5-4.8.3zm0 0" transform="matrix(1.69903 0 0 1.72133 -26.165 -80.833)"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sln.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d5006e}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.3-24.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zm10-10.3h3.3v11.4h4.3v2.9h-7.6V6.4zm10.3 0h3.5l2.4 6.6c.4 1 .7 2.4.7 2.4h.1s-.2-1.5-.2-2.4V6.4h3.1v14.3h-3.4l-2.5-6.6c-.4-1-.7-2.4-.7-2.4h-.1s.2 1.5.2 2.4v6.6h-3.1V6.4z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#d5006e"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sol.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fea500}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.3-24.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zM22.6 6.1c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c-.1-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm9-11.4h3.3v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><circle class="st0" cx="36" cy="65.5" r="10.4"/><path class="st0" d="M35.3 53.9h1.5c.5 0 .8-.4.8-.8v-5.2c0-.5-.4-.8-.8-.8h-1.5c-.5 0-.8.4-.8.8V53c-.1.5.3.9.8.9zm12.3 10.9v1.5c0 .5.4.8.8.8h5.2c.5 0 .8-.4.8-.8v-1.5c0-.5-.4-.8-.8-.8h-5.2c-.4-.1-.8.3-.8.8zM36.7 84c.5 0 .8-.4.8-.8V78c0-.5-.4-.8-.8-.8h-1.5c-.5 0-.8.4-.8.8v5.2c0 .5.4.8.8.8h1.5zM18.3 67.1h5.2c.5 0 .8-.4.8-.8v-1.5c0-.5-.4-.8-.8-.8h-5.2c-.5 0-.8.4-.8.8v1.5c0 .4.4.8.8.8zm26.4-9.3c.3.3.9.3 1.2 0l3.7-3.7c.3-.3.3-.9 0-1.2l-1-1c-.3-.3-.9-.3-1.2 0l-3.7 3.7c-.3.3-.3.9 0 1.2l1 1zm3.9 21.3l1-1c.3-.3.3-.9 0-1.2l-3.7-3.7c-.3-.3-.9-.3-1.2 0l-1 1c-.3.3-.3.9 0 1.2l3.7 3.7c.3.3.8.3 1.2 0zm-24 0l3.7-3.7c.3-.3.3-.9 0-1.2l-1-1c-.3-.3-.9-.3-1.2 0l-3.7 3.7c-.3.3-.3.9 0 1.2l1 1c.4.3.9.3 1.2 0zm1.5-21.3c.3.3.9.3 1.2 0l1-1c.3-.3.3-.9 0-1.2l-3.7-3.7c-.3-.3-.9-.3-1.2 0l-1 1c-.3.3-.3.9 0 1.2l3.7 3.7z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M30.871 11.793h2.602c.867 0 1.39-.691 1.39-1.387v-9.02C34.863.52 34.168 0 33.473 0H30.87c-.867 0-1.387.695-1.387 1.387v8.847c-.172.868.52 1.559 1.387 1.559zm21.336 18.906v2.602c0 .867.691 1.386 1.387 1.386h9.02c.866 0 1.386-.69 1.386-1.386v-2.602c0-.867-.695-1.387-1.387-1.387h-9.02c-.695-.175-1.386.52-1.386 1.387zM33.301 64c.867 0 1.386-.695 1.386-1.387v-9.02c0-.866-.69-1.386-1.386-1.386h-2.602c-.867 0-1.387.691-1.387 1.387v9.02c0 .866.692 1.386 1.387 1.386zM1.387 34.687h9.02c.866 0 1.386-.69 1.386-1.386v-2.602c0-.867-.691-1.387-1.387-1.387h-9.02C.52 29.313 0 30.005 0 30.7v2.602c0 .695.695 1.386 1.387 1.386zM47.176 18.56c.52.52 1.562.52 2.082 0l6.418-6.418c.52-.52.52-1.563 0-2.082L53.94 8.324c-.52-.52-1.562-.52-2.082 0l-6.418 6.418c-.52.52-.52 1.563 0 2.082zM53.94 55.5l1.735-1.734c.52-.52.52-1.559 0-2.078l-6.418-6.418c-.52-.524-1.563-.524-2.082 0l-1.735 1.734c-.52.52-.52 1.559 0 2.082L51.86 55.5c.52.523 1.387.523 2.082 0zm-41.629 0 6.418-6.414c.524-.523.524-1.563 0-2.082l-1.734-1.734c-.52-.524-1.558-.524-2.082 0L8.5 51.687c-.523.52-.523 1.56 0 2.079l1.734 1.734c.692.523 1.559.523 2.079 0zm2.602-36.941c.523.52 1.563.52 2.082 0l1.734-1.735c.524-.52.524-1.562 0-2.082l-6.418-6.418c-.519-.52-1.558-.52-2.078 0L8.5 10.06c-.523.52-.523 1.562 0 2.082zm0 0" fill="#fea500"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sphinx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M9.7 80.7c.5.6 1.3 1.2 2.1 1.2s1.2-.6 1.2-1.2c0-2-4.3-2.1-4.3-6.2 0-2.4 1.5-4.3 4.1-4.3 1.1 0 2.2.3 3.1 1l-1.1 2.9c-.4-.4-1.3-.9-1.9-.9-.8 0-1.2.6-1.2 1.2 0 2.1 4.3 2 4.3 6.1 0 2.3-1.3 4.4-4 4.4-1.3 0-2.6-.5-3.6-1.4l1.3-2.8zm8.1-10.3h4.1c2.4 0 3.9 2 3.9 4.9s-1.6 5-3.9 5h-1.1v4.4h-3V70.4zm3.5 7c.9 0 1.5-.9 1.5-2.1 0-1.2-.6-2-1.4-2h-.6v4.1h.5zm6.1-7h3v5.8h2.9v-5.8h2.9v14.3h-2.9V79h-2.9v5.7h-3V70.4zm11.2 0h3v14.3h-3V70.4zm5.4 0h3.1l2.2 6.6c.4 1 .6 2.4.6 2.4h.1s-.2-1.5-.2-2.4v-6.6h2.8v14.3h-3.1l-2.2-6.6c-.3-1-.6-2.4-.6-2.4h-.1s.2 1.5.2 2.4v6.6H44V70.4zm13.1 7.2L54 70.4h3.3l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3.2l-3.1 7.2 3 7.1h-3.2l-1-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3H54l3.1-7.1z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M35.8 21h2.4v1.6h-2.4zM56 37.7c.1-1.3 0-2.6-.3-3.8H50v-2.4h4.6c-.4-.6-.8-1.1-1.3-1.6l-5.7-5.7-.9 9c-.2 2.3-1.3 4.4-2.9 6v4H47c1.8 0 3.4.7 4.6 1.7 1.8-1.1 3.1-2.8 3.9-4.7H50v-2.4h6zm-17.8-15v2.9h-2.4v-2.9h-7l1 10.2c.2 1.8 1 3.5 2.4 4.7 1.3 1.2 3.1 1.9 4.9 1.9 1.8 0 3.5-.7 4.9-1.9 1.3-1.2 2.2-2.9 2.4-4.7l1-10.2h-7.2zm3.3 7.8h-3.2v3.9h-2.4v-3.9h-3.2v-2.4h8.8v2.4z"/><path class="st2" d="M46.9 45.5h-5.6v-4.7c-1.3.7-2.8 1-4.3 1s-3-.4-4.3-1v4.7h-5.6c-2.6 0-4.7 2.1-4.7 4.7v3c3.7.6 6.5 3.8 6.5 7.6V62H44v-1.2c0-4.2 3.4-7.6 7.6-7.7v-2.9c0-2.6-2.1-4.7-4.7-4.7z"/><path class="st2" d="M51.7 55.5c-2.9 0-5.3 2.4-5.3 5.3V62h4.1v-3.2h2.4V62H57v-1.2c0-3-2.4-5.3-5.3-5.3zM27.4 33.1l-.9-9-5.7 5.7c-.5.5-.9 1-1.3 1.6h4.6v2.4h-5.7c-.4 1.2-.5 2.5-.3 3.8h6.1V40h-5.5c.7 1.9 2.1 3.6 3.9 4.7 1.2-1.1 2.9-1.7 4.6-1.7h3.2v-4a8.91 8.91 0 0 1-3-5.9zm-6.1 22.4c-2.9 0-5.3 2.4-5.3 5.3V62h4.1v-3.2h2.4V62h4.1v-1.2c0-3-2.4-5.3-5.3-5.3zM48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M30.906 0h3.746v2.496h-3.746zm31.532 26.066c.156-2.027 0-4.058-.465-5.93h-8.899v-3.745h7.18a15.572 15.572 0 0 0-2.031-2.496l-8.895-8.899-1.406 14.047c-.313 3.59-2.027 6.871-4.527 9.367v6.242h4.996c2.808 0 5.308 1.094 7.18 2.657 2.808-1.72 4.84-4.371 6.09-7.336h-8.587v-3.75h9.364zM34.651 2.652V7.18h-3.746V2.652H19.98l1.563 15.922c.312 2.813 1.559 5.465 3.746 7.34 2.027 1.871 4.836 2.965 7.648 2.965 2.81 0 5.461-1.094 7.649-2.965 2.027-1.875 3.434-4.527 3.746-7.34l1.563-15.922zm5.153 12.176h-4.996v6.09h-3.746v-6.09h-4.997v-3.746h13.739zm0 0"/><path d="M48.234 38.242h-8.742v-7.336c-2.027 1.094-4.37 1.563-6.71 1.563-2.344 0-4.684-.625-6.716-1.563v7.336h-8.738a7.33 7.33 0 0 0-7.336 7.34v4.68c5.774.937 10.145 5.933 10.145 11.863V64h23.57v-1.875c0-6.555 5.309-11.863 11.863-12.02v-4.523a7.33 7.33 0 0 0-7.336-7.34zm0 0"/><path d="M55.727 53.855c-4.528 0-8.274 3.747-8.274 8.27V64h6.402v-4.996h3.747V64H64v-1.875c0-4.68-3.746-8.27-8.273-8.27zm-37.93-34.968L16.39 4.84l-8.899 8.898a15.342 15.342 0 0 0-2.027 2.496h7.18v3.746H3.746c-.625 1.875-.781 3.903-.469 5.934h9.524v3.746H4.215c1.094 2.965 3.277 5.617 6.086 7.336 1.875-1.719 4.527-2.656 7.183-2.656h4.993v-6.242a13.914 13.914 0 0 1-4.68-9.211zM8.273 53.855C3.746 53.855 0 57.602 0 62.125V64h6.398v-4.996h3.747V64h6.402v-1.875c0-4.68-3.746-8.27-8.274-8.27zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sql.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#a03537}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.3-24.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zM22.6 6.1c3.7 0 5.9 3.1 5.9 7.3 0 1.8-.6 3.3-1.1 4.2l1.4 1.3-1.8 2.2-1.3-1.3c-.6.5-1.6 1.1-3.1 1.1-3.8 0-5.9-3.2-5.9-7.5 0-4.1 2.1-7.3 5.9-7.3zm0 11.8c.3 0 .5 0 .9-.3l-1.6-1.5 1.8-2.1 1.2 1.3c.2-.7.2-1.2.2-1.9 0-2.5-.7-4.2-2.5-4.2s-2.5 1.7-2.5 4.2c0 2.7.8 4.5 2.5 4.5zm9-11.5h3.3v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><path class="st0" d="M-4938.1 722.8c-4.8-.2-9.1-1.7-11.4-4-.7-.6-1.4-1.5-1.7-2.1l-.2-.4v-4.5c0-4.5 0-4.5.1-4.1.2 1 .8 2 1.7 2.8.6.5 1.8 1.4 2.8 1.9 1.7.9 3.9 1.5 6.2 1.8 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.5-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.2.4c-.7 1.4-1.9 2.6-3.5 3.6-3.1 1.8-7.8 2.8-12.4 2.6zm0-11.2c-4.2-.2-8.1-1.4-10.6-3.2-.6-.4-1.4-1.2-1.7-1.6-.3-.4-.6-.9-.8-1.4l-.2-.4v-4.4c0-4.4 0-4.4.1-4.1.2.7.5 1.5 1.1 2.1.3.4.8.9 1.1 1.1.1.1.4.2.6.4 2 1.4 4.8 2.4 8 2.9 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.4-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.3.6c-.5.9-.8 1.4-1.4 2-.6.6-1.2 1.1-2 1.5-3.2 1.8-7.9 2.8-12.5 2.5zm-.3-11.1c-2.8-.2-5-.7-7.1-1.5-2.5-1-4.3-2.3-5.2-3.9-.2-.3-.4-.7-.5-1.2-.1-.4-.2-1.4-.1-2 .6-3.2 4.9-5.8 10.7-6.7 1.4-.2 1.9-.2 3.9-.2s2.5 0 3.9.2c2.3.3 4.4 1 6.2 1.8 2.6 1.3 4.2 3 4.5 4.8.1.5.1 1.6-.1 2-.3 1-.7 1.6-1.5 2.4-2.1 2.2-5.8 3.6-10.4 4.1-.6.2-3.7.2-4.3.2z" transform="translate(4973.037 -638.07)"/></svg>
1
<svg height="64" width="51" xmlns="http://www.w3.org/2000/svg"><path d="M23.023 63.957c-8.199-.34-15.543-2.875-19.468-6.77-1.196-1.011-2.39-2.535-2.903-3.55L.31 52.96v-7.617c0-7.614 0-7.614.171-6.934.34 1.692 1.368 3.383 2.903 4.735 1.023.847 3.074 2.37 4.781 3.214 2.906 1.524 6.66 2.54 10.59 3.047 2.39.34 3.246.34 6.66.34 3.418 0 4.27 0 6.66-.34 3.93-.508 7.516-1.691 10.59-3.047 1.707-.843 3.758-2.199 4.781-3.214 1.368-1.352 2.563-3.043 2.903-4.735.172-.508.172-.508.172 6.934v7.445l-.34.68c-1.196 2.367-3.246 4.398-5.98 6.09-5.294 3.046-13.321 4.738-21.177 4.398zm0-18.95c-7.171-.339-13.832-2.37-18.101-5.413-1.027-.68-2.39-2.032-2.906-2.707-.512-.68-1.024-1.524-1.364-2.371L.31 33.84v-7.445c0-7.446 0-7.446.171-6.938.34 1.184.852 2.54 1.88 3.555.511.675 1.367 1.523 1.878 1.86.168.171.684.339 1.024.679 3.414 2.367 8.199 4.058 13.664 4.906 2.39.336 3.242.336 6.66.336 3.414 0 4.27 0 6.66-.336 3.93-.508 7.516-1.691 10.59-3.047 1.707-.847 3.758-2.2 4.781-3.215 1.367-1.351 2.39-3.047 2.903-4.738.171-.508.171-.508.171 6.938v7.445l-.511 1.015c-.856 1.524-1.368 2.368-2.39 3.383-1.028 1.016-2.052 1.864-3.419 2.54-5.465 3.046-13.492 4.738-21.348 4.23zm-.511-18.78c-4.782-.34-8.54-1.184-12.125-2.54-4.27-1.69-7.344-3.89-8.883-6.597a5.594 5.594 0 0 1-.852-2.031C.48 14.383.31 12.69.48 11.676 1.504 6.262 8.848 1.859 18.754.34 21.144 0 22 0 25.414 0c3.418 0 4.27 0 6.66.34 3.93.508 7.516 1.691 10.59 3.043 4.441 2.199 7.172 5.078 7.684 8.12.172.849.172 2.708-.168 3.388-.512 1.691-1.196 2.707-2.563 4.058-3.586 3.723-9.906 6.094-17.762 6.938-1.023.34-6.32.34-7.343.34zm0 0" fill="#a03537"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sqlite.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#369}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M9.4 81.1c.5.6 1.3 1.1 2.1 1.1s1.2-.5 1.2-1.1c0-1.8-4.3-1.9-4.3-5.6 0-2.2 1.5-3.9 4.1-3.9 1.1 0 2.2.3 3.1.9l-1.1 2.6c-.4-.4-1.3-.8-1.9-.8-.8 0-1.2.5-1.2 1.1 0 1.9 4.3 1.8 4.3 5.5 0 2.1-1.3 3.9-4 3.9-1.3 0-2.6-.4-3.6-1.3l1.3-2.4zm13.7-9.5c3.4 0 5.3 2.8 5.3 6.6 0 1.7-.5 2.9-1 3.8l1.3 1.2-1.7 1.9-1.2-1.2c-.5.5-1.4 1-2.8 1-3.4 0-5.3-2.9-5.3-6.7.1-3.8 2.1-6.6 5.4-6.6zm0 10.6c.3 0 .5 0 .8-.2l-1.4-1.4 1.6-1.9 1.1 1.2c.1-.7.1-1.1.1-1.7 0-2.3-.7-3.8-2.2-3.8s-2.2 1.5-2.2 3.7c0 2.4.7 4.1 2.2 4.1zm8.1-10.4h3v10.3h3.9v2.6h-6.8V71.8h-.1zm9.3 0h3v12.9h-3V71.8zm8.3 2.6H46v-2.6h8.6v2.6h-2.8v10.3h-2.9l-.1-10.3zm8.3-2.6h6.5v2.6h-3.5v2.5h2.8v2.6h-2.8v2.6h3.7v2.6h-6.6V71.8h-.1z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zM33.9 65.7c-4.8-.2-9.1-1.7-11.4-4-.7-.6-1.4-1.5-1.7-2.1l-.2-.4v-4.5c0-4.5 0-4.5.1-4.1.2 1 .8 2 1.7 2.8.6.5 1.8 1.4 2.8 1.9 1.7.9 3.9 1.5 6.2 1.8 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.5-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.2.4c-.7 1.4-1.9 2.6-3.5 3.6-3.1 1.8-7.8 2.8-12.4 2.6zm0-11.2c-4.2-.2-8.1-1.4-10.6-3.2-.6-.4-1.4-1.2-1.7-1.6-.3-.4-.6-.9-.8-1.4l-.2-.4v-4.4c0-4.4 0-4.4.1-4.1.2.7.5 1.5 1.1 2.1.3.4.8.9 1.1 1.1.1.1.4.2.6.4 2 1.4 4.8 2.4 8 2.9 1.4.2 1.9.2 3.9.2s2.5 0 3.9-.2c2.3-.3 4.4-1 6.2-1.8 1-.5 2.2-1.3 2.8-1.9.8-.8 1.4-1.8 1.7-2.8.1-.3.1-.3.1 4.1v4.4l-.3.6c-.5.9-.8 1.4-1.4 2s-1.2 1.1-2 1.5c-3.2 1.8-7.9 2.8-12.5 2.5zm-.3-11.1c-2.8-.2-5-.7-7.1-1.5-2.5-1-4.3-2.3-5.2-3.9-.2-.3-.4-.7-.5-1.2-.1-.4-.2-1.4-.1-2 .6-3.2 4.9-5.8 10.7-6.7 1.4-.2 1.9-.2 3.9-.2s2.5 0 3.9.2c2.3.3 4.4 1 6.2 1.8 2.6 1.3 4.2 3 4.5 4.8.1.5.1 1.6-.1 2-.3 1-.7 1.6-1.5 2.4-2.1 2.2-5.8 3.6-10.4 4.1-.6.2-3.7.2-4.3.2z"/></svg>
1
<svg height="64" width="51" xmlns="http://www.w3.org/2000/svg"><path d="M23.023 63.957c-8.199-.34-15.543-2.875-19.468-6.77-1.196-1.011-2.39-2.535-2.903-3.55L.31 52.96v-7.617c0-7.614 0-7.614.171-6.934.34 1.692 1.368 3.383 2.903 4.735 1.023.847 3.074 2.37 4.781 3.214 2.906 1.524 6.66 2.54 10.59 3.047 2.39.34 3.246.34 6.66.34 3.418 0 4.27 0 6.66-.34 3.93-.508 7.516-1.691 10.59-3.047 1.707-.843 3.758-2.199 4.781-3.214 1.368-1.352 2.563-3.043 2.903-4.735.172-.508.172-.508.172 6.934v7.445l-.34.68c-1.196 2.367-3.246 4.398-5.98 6.09-5.294 3.046-13.321 4.738-21.177 4.398zm0-18.95c-7.171-.339-13.832-2.37-18.101-5.413-1.027-.68-2.39-2.032-2.906-2.707-.512-.68-1.024-1.524-1.364-2.371L.31 33.84v-7.445c0-7.446 0-7.446.171-6.938.34 1.184.852 2.54 1.88 3.555.511.675 1.367 1.523 1.878 1.86.168.171.684.339 1.024.679 3.414 2.367 8.199 4.058 13.664 4.906 2.39.336 3.242.336 6.66.336 3.414 0 4.27 0 6.66-.336 3.93-.508 7.516-1.691 10.59-3.047 1.707-.847 3.758-2.2 4.781-3.215 1.367-1.351 2.39-3.047 2.903-4.738.171-.508.171-.508.171 6.938v7.445l-.511 1.015c-.856 1.524-1.368 2.368-2.39 3.383-1.028 1.016-2.052 1.864-3.419 2.54-5.465 3.046-13.492 4.738-21.348 4.23zm-.511-18.78c-4.782-.34-8.54-1.184-12.125-2.54-4.27-1.69-7.344-3.89-8.883-6.597a5.594 5.594 0 0 1-.852-2.031C.48 14.383.31 12.69.48 11.676 1.504 6.262 8.848 1.859 18.754.34 21.144 0 22 0 25.414 0c3.418 0 4.27 0 6.66.34 3.93.508 7.516 1.691 10.59 3.043 4.441 2.199 7.172 5.078 7.684 8.12.172.849.172 2.708-.168 3.388-.512 1.691-1.196 2.707-2.563 4.058-3.586 3.723-9.906 6.094-17.762 6.938-1.023.34-6.32.34-7.343.34zm0 0" fill="#369"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/step.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#369}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.2-24.3c.5.6 1.3 1.2 2.2 1.2.8 0 1.2-.6 1.2-1.2 0-2-4.5-2.1-4.5-6.2 0-2.4 1.6-4.3 4.3-4.3 1.1 0 2.3.3 3.2 1l-1.1 2.9c-.5-.4-1.4-.9-2.1-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.5 2 4.5 6.1 0 2.3-1.4 4.4-4.2 4.4-1.3 0-2.7-.5-3.8-1.4l1.6-2.8zm10.7-7.4h-3V6.4H24v2.9h-3v11.4h-3.1V9.3zm7.8-2.9h6.8v2.9h-3.7V12h2.9v2.9h-2.9v2.9h3.9v2.9h-7V6.4zm9 0H39c2.5 0 4.1 2 4.1 4.9 0 2.9-1.7 5-4.1 5h-1.2v4.4h-3.1V6.4zm3.7 7c1 0 1.5-.9 1.5-2.1s-.6-2-1.5-2h-.6v4.1h.6z" fill="#fff"/><path d="M51.6 65.9c-.5-.2-1.1 0-1.3.5-1.1 2.5-2.9 4.7-5.1 6.4l-6.7-13.6c1-.8 1.6-2 1.6-3.4 0-2.1-1.5-3.9-3.5-4.3v-3.4c0-.5-.4-1-1-1-.5 0-1 .4-1 1v3.4c-2 .4-3.5 2.2-3.5 4.3 0 1.4.6 2.6 1.6 3.4L26 72.8c-2.2-1.7-4-3.8-5.1-6.4-.2-.5-.8-.7-1.3-.5-.5.2-.7.8-.5 1.3 1.3 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.1 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2s6-.8 8.7-2.2l3.8 7.8c.1.3.5.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.7-4.4 6-7.3.6-.5.4-1.1 0-1.3zm-16-12.6c1.4 0 2.5 1.1 2.5 2.5s-1.1 2.5-2.5 2.5-2.5-1.1-2.5-2.5 1.2-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.8-2l6.8-13.7c.3.1.7.1 1.1.1s.7 0 1.1-.1l6.8 13.7c-2.5 1.3-5.2 2-8 2z" fill="#369" stroke="#369" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M33.325 19.55c-.498-.2-1.1 0-1.299.5-1.1 2.5-2.901 4.7-5.1 6.4l-6.7-13.601c1-.8 1.6-1.999 1.6-3.4 0-2.099-1.501-3.899-3.501-4.3v-3.4a1 1 0 0 0-2 0v3.4c-2 .401-3.5 2.201-3.5 4.3 0 1.401.6 2.6 1.601 3.4l-6.7 13.602c-2.201-1.7-4-3.801-5.1-6.401-.201-.5-.8-.7-1.301-.5-.499.199-.7.8-.499 1.3 1.299 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.098 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2 3.1 0 6-.8 8.699-2.2l3.8 7.8c.1.3.501.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.701-4.4 6-7.3.6-.5.401-1.101 0-1.3zM17.326 6.95c1.4 0 2.5 1.1 2.5 2.499 0 1.401-1.1 2.502-2.5 2.502s-2.5-1.1-2.5-2.502c0-1.4 1.199-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.801-2l6.8-13.7c.3.1.701.1 1.1.1.402 0 .701 0 1.1-.1l6.8 13.7c-2.5 1.3-5.199 2-7.999 2zm0 0" fill="#369" stroke="#369" stroke-miterlimit="10" stroke-width="1.5" transform="matrix(1.6544 0 0 1.63607 0 .154)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/stl.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#369}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.3-24.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zm12.2-7.4h-3.1V6.4H26v2.9h-3.2v11.4h-3.3V9.3zm9.3-2.9H32v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><path d="M51.6 65.9c-.5-.2-1.1 0-1.3.5-1.1 2.5-2.9 4.7-5.1 6.4l-6.7-13.6c1-.8 1.6-2 1.6-3.4 0-2.1-1.5-3.9-3.5-4.3v-3.4c0-.5-.4-1-1-1-.5 0-1 .4-1 1v3.4c-2 .4-3.5 2.2-3.5 4.3 0 1.4.6 2.6 1.6 3.4L26 72.8c-2.2-1.7-4-3.8-5.1-6.4-.2-.5-.8-.7-1.3-.5-.5.2-.7.8-.5 1.3 1.3 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.1 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2s6-.8 8.7-2.2l3.8 7.8c.1.3.5.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.7-4.4 6-7.3.6-.5.4-1.1 0-1.3zm-16-12.6c1.4 0 2.5 1.1 2.5 2.5s-1.1 2.5-2.5 2.5-2.5-1.1-2.5-2.5 1.2-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.8-2l6.8-13.7c.3.1.7.1 1.1.1s.7 0 1.1-.1l6.8 13.7c-2.5 1.3-5.2 2-8 2z" fill="#369" stroke="#369" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg height="63" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M33.325 19.55c-.498-.2-1.1 0-1.299.5-1.1 2.5-2.901 4.7-5.1 6.4l-6.7-13.601c1-.8 1.6-1.999 1.6-3.4 0-2.099-1.501-3.899-3.501-4.3v-3.4a1 1 0 0 0-2 0v3.4c-2 .401-3.5 2.201-3.5 4.3 0 1.401.6 2.6 1.601 3.4l-6.7 13.602c-2.201-1.7-4-3.801-5.1-6.401-.201-.5-.8-.7-1.301-.5-.499.199-.7.8-.499 1.3 1.299 3 3.4 5.4 6 7.3l-4 8c-.2.5 0 1.1.4 1.3.098 0 .3.1.4.1.3 0 .7-.2.9-.5l3.8-7.8c2.7 1.5 5.6 2.2 8.7 2.2 3.1 0 6-.8 8.699-2.2l3.8 7.8c.1.3.501.5.9.5.1 0 .3 0 .4-.1.5-.2.7-.8.4-1.3l-3.9-8c2.6-1.8 4.701-4.4 6-7.3.6-.5.401-1.101 0-1.3zM17.326 6.95c1.4 0 2.5 1.1 2.5 2.499 0 1.401-1.1 2.502-2.5 2.502s-2.5-1.1-2.5-2.502c0-1.4 1.199-2.5 2.5-2.5zm0 22.6c-2.8 0-5.4-.7-7.801-2l6.8-13.7c.3.1.701.1 1.1.1.402 0 .701 0 1.1-.1l6.8 13.7c-2.5 1.3-5.199 2-7.999 2zm0 0" fill="#369" stroke="#369" stroke-miterlimit="10" stroke-width="1.5" transform="matrix(1.6544 0 0 1.63607 0 .154)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/svg.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fea500}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.3-24.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zM16 6.4h3.6l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3l1.7-8.1h3.5l-3.9 14.3h-3.3L16 6.4zm19.1-.3c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.6-7.6 6.5-7.6z" fill="#fff"/><path class="st0" d="M27.1 60.2L18 79.4l1.7 1.7L31 69.8c-.4-.9-.3-2 .5-2.8 1-1 2.5-1 3.5 0s1 2.5 0 3.5c-.7.7-1.9.9-2.8.5L20.9 82.3l1.7 1.7 19.2-9.1L46 63.4 38.6 56l-11.5 4.2zm26.3-2.3L44 48.5c-.8-.8-2-.8-2.8 0L39 50.7c-.8.8-.8 2 0 2.8l9.4 9.4c.8.8 2 .8 2.8 0l2.2-2.2c.8-.8.8-2 0-2.8z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M16.223 21.805.09 55.844l3.012 3.015 20.035-20.035c-.711-1.594-.532-3.543.886-4.96 1.774-1.774 4.43-1.774 6.204 0 1.773 1.769 1.773 4.429 0 6.202-1.243 1.243-3.368 1.594-4.965.887L5.23 60.984 8.242 64l34.04-16.133L49.73 27.48 36.61 14.36zm46.625-4.075L46.184 1.062c-1.418-1.417-3.547-1.417-4.965 0L37.32 4.966c-1.422 1.418-1.422 3.543 0 4.965l16.664 16.664c1.418 1.418 3.543 1.418 4.965 0l3.899-3.903c1.418-1.418 1.418-3.543 0-4.96zm0 0" fill="#fea500"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/swd.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm1.3-24.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zM15 6.4h3.2l1.2 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6L21 6.4h3.1l1.3 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.2-8.9H30l-2.5 14.3h-3.7l-1.1-7.2c-.1-.9-.2-1.7-.2-1.7h-.1s0 .8-.1 1.7l-1.1 7.2h-3.8L15 6.4zm16.4 0h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z" fill="#fff"/><path class="st0" d="M47.2 55.6c1-.4 2.1-.5 3.2-.5V48c-4.8-.1-9.4 2-12.4 5.8-1.2 1.6-2.3 3.3-3.1 5.2l-2.3 5.7c-.6 1.7-1.3 3.5-2.1 5.1-.6 1.4-1.3 2.6-2.2 3.8-.7 1-1.7 1.8-2.8 2.3-1.2.6-2.6.9-4 .9V84c4.8.1 9.4-2 12.4-5.8.9-1.3 1.8-2.7 2.5-4.1l1.9-4.5h8.3v-7.1h-5.5c.4-1.1 1-2.1 1.7-3.1.5-.9 1.2-1.6 1.9-2.2.9-.8 1.7-1.3 2.5-1.6z"/></svg>
1
<svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M46.168 13.516c1.793-.711 3.766-.891 5.738-.891V.008c-8.605-.18-16.851 3.554-22.23 10.308-2.153 2.844-4.125 5.864-5.559 9.243l-4.12 10.128c-1.079 3.024-2.333 6.223-3.767 9.067a31.916 31.916 0 0 1-3.945 6.754c-1.254 1.777-3.047 3.199-5.02 4.09-2.152 1.066-4.66 1.597-7.171 1.597v12.797c8.605.18 16.851-3.554 22.23-10.308 1.613-2.309 3.227-4.797 4.485-7.286l3.406-8h14.879v-12.62h-9.86c.715-1.954 1.793-3.731 3.047-5.508.895-1.602 2.153-2.844 3.407-3.91 1.613-1.422 3.046-2.313 4.48-2.844zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/swf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d10407}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.3-24.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zm9-10.3h3.2l1.2 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.3-8.9h3.1l1.3 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.2-8.9h3.2l-2.5 14.3h-3.7L24 13.5c-.1-.9-.2-1.7-.2-1.7h-.1s0 .8-.1 1.7l-1.1 7.2h-3.8L16.3 6.4zm17.7 0h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4H34V6.4z" fill="#fff"/><path class="st0" d="M47.2 55.6c1-.4 2.1-.5 3.2-.5V48c-4.8-.1-9.4 2-12.4 5.8-1.2 1.6-2.3 3.3-3.1 5.2l-2.3 5.7c-.6 1.7-1.3 3.5-2.1 5.1-.6 1.4-1.3 2.6-2.2 3.8-.7 1-1.7 1.8-2.8 2.3-1.2.6-2.6.9-4 .9V84c4.8.1 9.4-2 12.4-5.8.9-1.3 1.8-2.7 2.5-4.1l1.9-4.5h8.3v-7.1h-5.5c.4-1.1 1-2.1 1.7-3.1.5-.9 1.2-1.6 1.9-2.2.9-.8 1.7-1.3 2.5-1.6z"/></svg>
1
<svg height="64" width="52" xmlns="http://www.w3.org/2000/svg"><path d="M46.168 13.516c1.793-.711 3.766-.891 5.738-.891V.008c-8.605-.18-16.851 3.554-22.23 10.308-2.153 2.844-4.125 5.864-5.559 9.243l-4.12 10.128c-1.079 3.024-2.333 6.223-3.767 9.067a31.916 31.916 0 0 1-3.945 6.754c-1.254 1.777-3.047 3.199-5.02 4.09-2.152 1.066-4.66 1.597-7.171 1.597v12.797c8.605.18 16.851-3.554 22.23-10.308 1.613-2.309 3.227-4.797 4.485-7.286l3.406-8h14.879v-12.62h-9.86c.715-1.954 1.793-3.731 3.047-5.508.895-1.602 2.153-2.844 3.407-3.91 1.613-1.422 3.046-2.313 4.48-2.844zm0 0" fill="#d10407"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/swift.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f63}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path fill="#fff" d="M6 41h60v49H6z"/><path d="M6.8 17.5c.5.7 1.2 1.2 2 1.2.9 0 1.4-.7 1.4-1.8 0-2.6-4.1-2.5-4.1-6.6 0-2.3 1.3-4 3.5-4 .9 0 1.8.3 2.6.9l-.7 2.2c-.4-.4-1.2-.8-1.8-.8-1 0-1.5.8-1.5 1.7 0 2.6 4.1 2.4 4.1 6.5 0 2.2-1.1 4.1-3.4 4.1-1.1 0-2.2-.5-3-1.4l.9-2zm6.2-11h2l1.3 9.8c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6L18 6.5h1.9l1.3 9.8c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.3-9.8h2l-2.1 14.2h-2.3l-1.2-8.4c-.1-.9-.2-1.9-.2-1.9h-.1s0 .9-.2 1.9l-1.2 8.4h-2.3L13 6.5zm13 0h2v14.2h-2V6.5zm4.1 0h5.4v2.2h-3.4v4.1h2.8V15h-2.8v5.8h-2V6.5zm8.7 2.2H36V6.5h7.6v2.2h-2.8v12h-2v-12z" fill="#fff" stroke="#fff" stroke-width=".25" stroke-miterlimit="10"/><path d="M52.5 72.3S58.4 59 40.3 47c0 0 7.4 9.1 3.6 19.4 0 0-13.3-9.2-20-15.9 0 0 8.4 11.8 11.4 14.2 0 0-5-2.5-16.5-12.2 0 0 13.3 17 19.5 20.5 0 0-9.5 6.3-23.3-2.6 0 0 7.3 12.6 22.6 12.6 6.9 0 8.9-3.5 12.3-3.5 3.5 0 5.7 3.5 5.7 3.5 2-5-3.1-10.7-3.1-10.7z" fill="#fa2a22"/></svg>
1
<svg height="64" width="72" xmlns="http://www.w3.org/2000/svg"><path d="M65.75 44.957S76.094 21.352 44.36.051c0 0 12.972 16.152 6.312 34.433 0 0-23.32-16.328-35.067-28.222 0 0 14.727 20.945 19.989 25.207 0 0-8.77-4.438-28.93-21.657 0 0 23.316 30.176 34.188 36.387 0 0-16.657 11.184-40.852-4.613 0 0 12.8 22.363 39.625 22.363 12.098 0 15.605-6.21 21.566-6.21 6.137 0 9.993 6.21 9.993 6.21 3.507-8.875-5.434-18.992-5.434-18.992zm0 0" fill="#fa2a22"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/swp.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm1.3-24.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zm9-10.3h3.2l1.2 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.3-8.9h3.1l1.3 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.2-8.9h3.2l-2.5 14.3h-3.7L24 13.5c-.1-.9-.2-1.7-.2-1.7h-.1s0 .8-.1 1.7l-1.1 7.2h-3.8L16.3 6.4zm17.7 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4H34V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path class="st0" d="M56.5 76.6c0-1.6-1.3-2.9-2.9-2.9H17.7c-1.6 0-2.9 1.3-2.9 2.9v4.1c0 1.6 1.3 2.9 2.9 2.9h35.9c1.6 0 2.9-1.3 2.9-2.9v-4.1zM41 80.4c-.9 0-1.7-.7-1.7-1.7S40.1 77 41 77s1.7.7 1.7 1.7-.7 1.7-1.7 1.7zm5.1 0c-.9 0-1.7-.7-1.7-1.7s.7-1.7 1.7-1.7c.9 0 1.7.7 1.7 1.7s-.8 1.7-1.7 1.7zm5 0c-.9 0-1.7-.7-1.7-1.7s.7-1.7 1.7-1.7c.9 0 1.7.7 1.7 1.7s-.8 1.7-1.7 1.7zM17.7 72h35.9c.8 0 1.6.2 2.2.6l-3.5-7.3c-1-2.1-2.6-2.9-4.2-2.9h-3.9l-5.6 5.8c-.4.4-.9.7-1.4.9-.5.2-1.1.3-1.6.3-.6 0-1.1-.1-1.6-.3h-.2c-.4-.2-.8-.5-1.2-.8l-5.6-6h-3.9c-1.6 0-3.1.9-4.2 2.9l-3.5 7.3c.7-.3 1.4-.5 2.3-.5z"/><path class="st0" d="M44 59.6c.2-.2.3-.4.5-.7.1-.3.2-.5.2-.9 0-.3-.1-.6-.2-.8-.1-.3-.3-.5-.5-.7-.2-.2-.5-.4-.7-.5-.2-.1-.5-.2-.8-.2s-.6.1-.8.2c-.3.1-.5.3-.7.5l-3.2 3.2v-10c0-.3-.1-.6-.2-.8-.1-.3-.3-.5-.5-.7-.2-.2-.4-.4-.7-.5-.2-.1-.5-.1-.8-.1-.3 0-.6 0-.8.1-.3.1-.5.3-.7.5-.2.2-.4.4-.5.7-.1.3-.2.5-.2.8v10.1l-3.2-3.2c-.2-.2-.4-.4-.7-.5-.2-.1-.5-.2-.8-.2-.3 0-.6.1-.8.2-.2.1-.5.3-.7.5-.2.2-.4.4-.5.7-.1.3-.2.5-.2.8 0 .3.1.6.2.9.1.3.3.5.5.7l6.9 7c.2.2.4.4.7.5.2.1.5.2.8.2.3 0 .6-.1.8-.2.3-.1.5-.3.7-.5l6.9-7.1z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M73.734 51.555c0-2.844-2.289-5.157-5.109-5.157H5.375c-2.82 0-5.11 2.313-5.11 5.157v7.289c0 2.843 2.29 5.156 5.11 5.156h63.25c2.82 0 5.11-2.313 5.11-5.156zm-27.308 6.757a2.985 2.985 0 0 1-2.996-3.023 2.985 2.985 0 0 1 2.996-3.023 2.985 2.985 0 0 1 2.996 3.023c0 1.777-1.234 3.023-2.996 3.023zm8.984 0a2.984 2.984 0 0 1-2.992-3.023c0-1.777 1.23-3.023 2.992-3.023a2.985 2.985 0 0 1 2.996 3.023 2.985 2.985 0 0 1-2.996 3.023zm8.813 0a2.985 2.985 0 0 1-2.996-3.023c0-1.777 1.234-3.023 2.996-3.023a2.981 2.981 0 0 1 2.992 3.023 2.981 2.981 0 0 1-2.992 3.023zM5.375 43.38h63.25c1.41 0 2.82.355 3.879 1.066l-6.168-12.98c-1.762-3.73-4.582-5.153-7.398-5.153h-6.876L42.2 36.623c-.707.71-1.586 1.245-2.469 1.6-.878.356-1.937.532-2.82.532-1.055 0-1.937-.176-2.816-.531h-.352c-.707-.356-1.41-.891-2.117-1.422l-9.867-10.668h-6.871c-2.817 0-5.461 1.601-7.399 5.156L1.32 44.266c1.235-.532 2.47-.887 4.055-.887zm0 0"/><path d="M51.71 21.332c.352-.355.532-.71.884-1.242.176-.535.351-.89.351-1.602 0-.531-.175-1.066-.351-1.422-.176-.53-.532-.886-.883-1.246a5.273 5.273 0 0 0-1.23-.886c-.356-.18-.883-.356-1.41-.356-.532 0-1.06.176-1.41.356-.528.175-.884.53-1.235.886l-5.637 5.692V3.734c0-.535-.176-1.066-.352-1.421-.18-.536-.53-.891-.882-1.247-.352-.355-.703-.71-1.235-.886C37.97 0 37.441 0 36.91 0c-.527 0-1.055 0-1.406.18-.531.175-.883.53-1.234.886-.352.356-.708.711-.883 1.246-.176.532-.352.887-.352 1.422v17.953L27.398 16c-.351-.355-.707-.71-1.234-.89-.352-.176-.879-.356-1.41-.356-.527 0-1.055.18-1.41.355-.352.18-.88.536-1.23.891-.356.355-.708.71-.884 1.246-.175.531-.351.887-.351 1.422 0 .531.176 1.066.351 1.598.176.535.528.89.883 1.246L34.27 33.957c.351.355.703.711 1.234.887.351.18.879.355 1.406.355.531 0 1.059-.176 1.41-.355.532-.176.883-.532 1.235-.887zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/sys.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm1.3-24.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zm12.3-1.9L16 6.4h3.6l1.1 3.4c.3 1 .5 2.1.5 2.1h.1s.2-1.1.5-2.1l1.1-3.4h3.6l-3.6 8.4v5.9h-3.3v-5.9zm9.8 1.9c.6.6 1.4 1.2 2.3 1.2s1.3-.6 1.3-1.2c0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path class="st0" d="M51.9 77.8L40.3 66.2l-.3-.3 2.1-2.2.3-.3c2.7 1 5.9.5 8.1-1.7 1.6-1.6 2.4-3.8 2.2-6.1 0-.3-.2-.5-.4-.6-.2-.1-.5 0-.7.2l-3.7 3.7L44 58l-1-3.9 3.7-3.7c.2-.2.2-.5.2-.7-.1-.2-.3-.4-.6-.4-2.3-.2-4.5.6-6.1 2.2-2.2 2.2-2.8 5.4-1.7 8.1l-.3.3-3 2.9-5.6-5.6-.2-.2c.1-.1.1-.2.2-.4 1.2.2 3.3-2.1 5.1-3.9l-5.3-5.3c-2.4 2.4-4.1 4-3.9 5.1-.5.3-1 .6-1.4.9l-.7.7c-.5.5-.8 1.1-.9 1.7-.1.1-.1.2-.2.3l-.3.6v.1l-.3.4c-.2.2-.3.4-.4.7 0 .1-.1.2-.2.2l-.1.1c-.1.3-.3.5-.4.8-.1.3-.3.7-.4 1.1v.2c0 .1-.1.3-.1.4l-.1.5c-.1.3-.1.6-.1.9v1.8l.1.4v.2c0 .2.1.3.1.5l.3.9c.1.3.4.5.7.5.2 0 .3-.1.4-.2.1-.1.2-.2.2-.4l.1-1c0-.1 0-.2.1-.3 0-.1 0-.2.1-.2l.1-.4s0-.1.1-.1c0 0 0-.1.1-.1 0-.1.1-.2.1-.2.1-.2.1-.3.2-.4 0-.1.1-.1.1-.2.1-.2.2-.3.3-.5l.2-.3c0-.1.1-.1.2-.2l.1-.1c.1-.2.3-.3.5-.5l.1-.1c.1-.1.3-.2.4-.3.1 0 .1-.1.2-.1s.1-.1.2-.1c.1-.1.2-.2.4-.2l.3-.2.3-.1c.1-.1.2-.1.3-.1.1 0 .1 0 .2-.1 0 0 .1 0 .1-.1.1 0 .1 0 .2-.1h.1c.1.1.2.3.3.4l5.5 5.5-12.2 11.2c-1.5 1.5-1.7 3.6-.2 5.1 1.5 1.5 3.5 1.1 4.9-.4l10.3-10.9.2.2 11.6 11.6c1.3 1.3 3.4 1.3 4.7 0 1.3-1.3 1.3-3.4 0-4.7zm-28.4 2.6c-.5.5-1.4.5-1.9 0s-.5-1.4 0-1.9 1.4-.5 1.9 0c.6.5.6 1.4 0 1.9z"/></svg>
1
<svg height="63" width="60" xmlns="http://www.w3.org/2000/svg"><path d="M57.96 53.09 37.532 32.832l-.527-.523 3.7-3.844.526-.524c4.754 1.747 10.391.875 14.266-2.968 2.816-2.793 4.227-6.637 3.875-10.653 0-.523-.355-.875-.707-1.047-.352-.175-.879 0-1.23.348l-6.516 6.461-6.871-1.57-1.758-6.813 6.516-6.46c.351-.348.351-.872.351-1.223-.176-.348-.527-.7-1.058-.7-4.051-.347-7.922 1.051-10.743 3.844-3.87 3.844-4.93 9.43-2.992 14.145l-.527.523-5.285 5.067-9.86-9.782-.355-.347c.176-.176.176-.352.355-.7 2.114.348 5.809-3.668 8.98-6.812L18.337 0c-4.227 4.191-7.219 6.984-6.867 8.906-.88.524-1.762 1.047-2.465 1.57L7.77 11.7c-.88.875-1.407 1.922-1.582 2.969-.176.176-.176.352-.352.523l-.531 1.051v.172l-.528.7c-.351.35-.527.698-.703 1.222a.378.378 0 0 1-.351.352l-.18.171c-.176.524-.527.875-.703 1.399-.176.523-.527 1.222-.703 1.922v.347c0 .176-.176.524-.176.7l-.176.875c-.176.523-.176 1.046-.176 1.57v3.144l.176.696v.351c0 .348.176.524.176.871l.527 1.575c.176.523.703.87 1.235.87.351 0 .527-.171.703-.347s.351-.352.351-.7l.176-1.745c0-.176 0-.348.176-.524 0-.175 0-.351.176-.351l.175-.696s0-.175.176-.175c0 0 0-.176.18-.176 0-.172.176-.348.176-.348.175-.351.175-.523.351-.699 0-.176.176-.176.176-.348.176-.351.352-.527.527-.875l.352-.523c0-.176.176-.176.352-.352l.18-.172c.175-.351.527-.523.878-.875l.176-.171c.176-.176.527-.352.703-.528.176 0 .176-.172.355-.172.176 0 .176-.175.352-.175.176-.176.352-.348.703-.348l.528-.352.53-.175c.177-.172.352-.172.528-.172s.176 0 .352-.176c0 0 .175 0 .175-.176.176 0 .176 0 .352-.172h.176c.176.172.351.524.531.696l9.684 9.605L2.488 51.52c-2.64 2.617-2.992 6.285-.351 8.906 2.64 2.617 6.164 1.918 8.629-.7l18.136-19.035.356.348 20.426 20.258a5.883 5.883 0 0 0 8.277 0 5.763 5.763 0 0 0 0-8.207zM7.95 57.629c-.884.875-2.47.875-3.348 0-.88-.871-.88-2.445 0-3.316.878-.876 2.464-.876 3.347 0a2.134 2.134 0 0 1 0 3.316zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/tar.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#4d1b9b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.9 9.3H5.7V6.4h9.6v2.9h-3.2v11.4H8.9V9.3zm10.5-2.9H23l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2zm6.9-8.6h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8h-.8v4.8H29V6.4zM33 13c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6z" fill="#fff"/><path class="st0" d="M43.6 68.3l-7.3-3.4L51 58l7.3 3.4-7.3 3.5-7.4 3.4zM51 51.2l-7.3-3.4-7.3 3.4L51 58.1l7.3-3.4-7.3-3.5zM28.9 61.4L21.6 58l-7.3 3.4L29 68.3l7.3-3.4-7.4-3.5zm0-6.8l7.3-3.4-7.3-3.4-14.7 6.9 7.3 3.4 7.4-3.5zM51 66.9l-6.6 3-.8.4-.8-.4-6.6-3-6.6 3-.8.4-.8-.4-6.6-3v10.7l14.7 7.7L51 77.6V66.9z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#4d1b9b"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/tax.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#83ad51}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zM8.9 9.3H5.7V6.4h9.6v2.9h-3.2v11.4H8.9V9.3zm10-2.9h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2zm8.8-1.4L27 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.3-7.1z" fill="#fff"/><path d="M29.7 46.6c-2.8 0-5.2 2.3-5.2 5.2 0 2.8 2.3 5.2 5.2 5.2.9 0 1.7-.2 2.4-.6l2.1 2.1-6 6c-1 1-1 2.7 0 3.7l.2.2 12.1-12.1c.7.4 1.6.6 2.4.6 2.8 0 5.2-2.3 5.2-5.2 0-2.8-2.3-5.2-5.2-5.2-2.8 0-5.2 2.3-5.2 5.2 0 .9.2 1.7.6 2.4l-2.1 2.1-2.1-2.1c.4-.7.6-1.6.6-2.4.2-2.8-2.2-5.1-5-5.1zm0 3c1.2 0 2.2 1 2.2 2.2s-1 2.2-2.2 2.2-2.2-1-2.2-2.2c0-1.3 1-2.2 2.2-2.2zm13.3 0c1.2 0 2.2 1 2.2 2.2S44.2 54 43 54s-2.2-1-2.2-2.2c0-1.3 1-2.2 2.2-2.2zM20.1 59.9c-.2 0-.4 0-.6.1-.2 0-.4.1-.6.2-.2.1-.3.2-.5.3-.1.1-.3.2-.4.3s-.2.3-.3.4c-.1.1-.2.3-.3.5-.1.2-.1.3-.2.5v.1c0 .2-.1.4-.1.6v17.8c0 .2 0 .4.1.6 0 .2.1.4.2.6s.2.3.3.5c.1.1.2.3.3.4.1.1.3.2.4.3.1.1.3.2.5.3.2.1.3.1.5.2h.1c.2 0 .4.1.6.1h32.6c.2 0 .4 0 .6-.1.2 0 .4-.1.6-.2.2-.1.3-.2.5-.3.1-.1.3-.2.4-.3.1-.1.2-.3.3-.4s.2-.3.3-.5.1-.3.2-.5v-.1c0-.2.1-.4.1-.6V62.9c0-.2 0-.4-.1-.6 0-.2-.1-.4-.2-.6-.1-.2-.2-.3-.3-.5-.1-.1-.2-.3-.3-.4-.1-.1-.3-.2-.4-.3-.1-.1-.3-.2-.5-.3s-.3-.1-.5-.2h-.1c-.2 0-.4-.1-.6-.1H40.8l-3 3h11.8c0 1.6 1.3 3 3 3v11.8c-1.6 0-3 1.3-3 3H23c0-1.6-1.3-3-3-3V65.8c1.6 0 3-1.3 3-3h3.4l3-3-9.3.1zm16.3 5.9c-3.3 0-5.9 3-5.9 6.7 0 2.1.9 4 2.2 5.2H40c1.4-1.2 2.2-3.1 2.2-5.2.1-3.7-2.6-6.7-5.8-6.7zm-11.9 4.5c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5 1.5-.7 1.5-1.5-.7-1.5-1.5-1.5zm23.7 0c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5 1.5-.7 1.5-1.5-.7-1.5-1.5-1.5z" fill="#83ad51" stroke="#83ad51" stroke-width=".25" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M12.726.224c-2.801 0-5.202 2.302-5.202 5.2 0 2.8 2.302 5.2 5.202 5.2.9 0 1.698-.199 2.4-.599l2.099 2.101-6 6c-.999.999-.999 2.7 0 3.698l.2.202L23.524 9.925c.702.4 1.602.601 2.4.601 2.801 0 5.202-2.302 5.202-5.2 0-2.8-2.302-5.2-5.202-5.2-2.798 0-5.199 2.3-5.199 5.2 0 .898.2 1.698.601 2.4l-2.101 2.098-2.1-2.098c.399-.702.6-1.6.6-2.4.2-2.8-2.2-5.102-5-5.102zm0 3.001c1.199 0 2.2 1 2.2 2.2 0 1.2-1.001 2.2-2.2 2.2a2.22 2.22 0 0 1-2.2-2.2c0-1.3.998-2.2 2.2-2.2zm13.3 0c1.199 0 2.2 1 2.2 2.2 0 1.2-1.001 2.2-2.2 2.2a2.22 2.22 0 0 1-2.2-2.2c0-1.3.998-2.2 2.2-2.2zm-22.902 10.3c-.198 0-.398 0-.598.1-.2 0-.4.101-.601.2-.2.1-.3.2-.5.301-.1.098-.301.199-.4.3-.099.1-.2.299-.3.4-.1.1-.2.299-.3.5-.1.199-.1.3-.2.498v.1c0 .202-.1.4-.1.602v17.8c0 .198 0 .4.1.598 0 .201.1.4.2.601.1.2.2.3.3.501.1.098.201.3.3.4.099.098.3.199.4.3.1.1.3.198.5.299.2.1.299.1.5.201h.1c.2 0 .401.098.599.098h32.602c.198 0 .398 0 .598-.098.2 0 .4-.1.601-.201.2-.1.3-.199.5-.3.1-.1.301-.2.4-.299.099-.1.2-.302.3-.4.1-.1.2-.302.3-.5.1-.202.1-.3.2-.501v-.1c0-.2.1-.4.1-.6V16.526c0-.201 0-.4-.1-.601 0-.199-.1-.4-.2-.599-.1-.201-.2-.302-.3-.5-.1-.101-.201-.3-.3-.4-.099-.101-.3-.202-.4-.3-.1-.1-.3-.201-.5-.302-.2-.098-.299-.098-.5-.199h-.1c-.2 0-.401-.1-.599-.1h-11.9l-3.002 3.001h11.802c0 1.6 1.298 2.999 2.999 2.999v11.8c-1.6 0-2.999 1.3-2.999 3h-26.6c0-1.6-1.3-3-3.001-3v-11.9c1.6 0 3.001-1.299 3.001-3h3.4l2.998-3zm16.301 5.9c-3.3 0-5.9 3-5.9 6.699 0 2.1.899 4 2.2 5.2h7.3c1.401-1.2 2.2-3.1 2.2-5.2.1-3.698-2.601-6.7-5.8-6.7zm-11.9 4.5c-.8 0-1.499.7-1.499 1.5s.7 1.499 1.498 1.499c.801 0 1.5-.7 1.5-1.5s-.699-1.499-1.5-1.499zm23.7 0c-.8 0-1.501.7-1.501 1.5s.702 1.499 1.5 1.499c.801 0 1.501-.7 1.501-1.5s-.7-1.499-1.5-1.499zm0 0" fill="#83ad51" stroke="#83ad51" stroke-miterlimit="10" stroke-width=".25" transform="matrix(1.6973 0 0 1.70894 .53 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/tcsh.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.9 8.7H5.7V6.5h8.6v2.2h-3.2v12H8.9v-12zm11.5-2.5c1.1 0 2.4.4 3.2 1.2l-.9 2.1c-.4-.5-1.4-1-2.2-1-2.3 0-3.5 2.2-3.5 4.9 0 2.8 1.3 5.2 3.5 5.2 1 0 1.8-.5 2.5-1l.9 2.1c-.8.7-1.9 1.3-3.6 1.3-3.6 0-5.7-3.2-5.7-7.4 0-4.3 2.1-7.4 5.8-7.4zm5.1 11.3c.6.7 1.4 1.2 2.3 1.2 1 0 1.6-.7 1.6-1.8 0-2.6-4.6-2.5-4.6-6.6 0-2.3 1.5-4 3.9-4 1 0 2.1.3 2.9.9l-.8 2.2c-.5-.4-1.4-.8-2.1-.8-1.1 0-1.7.8-1.7 1.7 0 2.6 4.7 2.4 4.7 6.5 0 2.2-1.3 4.1-3.8 4.1-1.2 0-2.5-.5-3.4-1.4l1-2zm8-11h2.3v6h4.1v-6h2.3v14.2h-2.3v-6h-4.1v6h-2.3V6.5z" fill="#fff"/><path d="M30.8 61.4h10.9v2.7H30.8v-2.7zm0 5.4h10.9v2.7H30.8v-2.7zm0 5.5h10.9V75H30.8v-2.7zm19-24.4H28.1c-3 0-5.4 2.4-5.4 5.4v24.4h-5.4c0 3 2.4 5.4 5.4 5.4h21.7c3 0 5.4-2.4 5.4-5.4V56h5.4v-2.7c0-3-2.4-5.4-5.4-5.4zm-2.7 29.3c0 1.8-1.4 3.2-3.2 3.2H24c1.3-.9 1.3-2.7 1.3-2.7V53.3c0-1.5 1.2-2.7 2.7-2.7s2.7 1.2 2.7 2.7V56H47l.1 21.2zM33.5 53.3v-2.7h16.3c2.5 0 2.7 1.6 2.7 2.7h-19z" fill="#999" stroke="#999" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/tex.svg
1
<?xml version="1.0" encoding="UTF-8"?>
2
<svg version="1.1" viewBox="0 0 72 96" xmlns="http://www.w3.org/2000/svg">
3
<style>.st0{fill:#999}</style>
4
<path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/>
5
<path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/>
6
<path d="M6 41h60v49H6zM8.9 9.3H5.7V6.4h9.6v2.9h-3.2v11.4H8.9V9.3zm9.2-2.9h7.2v2.9h-3.9V12h3.1v2.9h-3.1v2.9h4.1v2.9h-7.4V6.4zm12.8 7.2l-3.4-7.2h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.2-7.1z" fill="#fff"/>
7
<g transform="matrix(.043311 0 0 .043311 34.814 62.785)" fill="#999">
8
<path d="m-121.08-209.68h-349.27l-10.21 133.77h10.87c7.82-100.19 16.41-117.73 110.21-117.73h33.39c11.55 1.81 11.55 9.16 11.55 23.08v329.26c0 21.86-1.83 28.53-52.78 28.53h-17.17v14.61c29.02-0.56 59.26-1.15 88.93-1.15 29.58 0 59.91 0.59 88.91 1.15v-14.61h-16.88c-50.19 0-52-6.67-52-28.53v-329.25c0-13.36 0-20.61 10.89-23.08h33.19c92.55 0 101.61 17.44 109.42 117.73h10.89"/>
9
<path d="m182.43 180.75h-10.87c-13.26 89.69-21.08 138.44-127.47 138.44h-83.95c-24.16 0-25.3-3.05-25.3-23.86v-169.07h57.06c57.06 0 62.5 20.91 62.5 71.96h9.72v-157.35h-9.72c0 50.19-5.45 70.71-62.5 70.71h-57.07v-149.9c0-20.42 1.15-23.47 25.3-23.47h82.7c93.6 0 104.49 37.2 112.97 117.17h10.9l-14.51-133.78h-306.26v16.61c42.84 0 49.7 0 49.7 27.19v326.42c0 27.19-6.77 27.19-49.7 27.19v14.61h314.76"/>
10
<path d="m345.49-27.058 89.49-129.38c8.96-12.7 27.19-38.84 76.82-39.5v-14.6c-13.85 1.15-36.83 1.15-51.34 1.15-19.93 0-44.75 0-59.82-1.15v14.61c19.37 1.81 24.13 13.92 24.13 23.67 0 7.23-2.96 12.11-7.25 18.12l-79.85 115.82-89.49-130.99c-4.2-6.59-4.79-8.5-4.79-10.31 0-5.45 6.59-15.75 26.62-16.32v-14.6c-19.37 1.15-48.95 1.15-68.88 1.15-15.66 0-45.89 0-60.5-1.15v14.61c33.22 0 44.09 1.25 57.45 20.03l116.68 171.37-105.22 153.71c-25.96 37.59-65.26 38.25-76.82 38.25v14.61c13.82-1.15 36.83-1.15 51.34-1.15 16.32 0 44.75 0 59.82 1.15v-14.61c-18.71-1.81-24.13-13.92-24.13-23.67 0-7.82 2.96-12.11 6.01-16.41l96.75-141.2 105.22 154.66c4.76 6.69 4.76 8.5 4.76 10.31 0 4.76-5.42 15.17-26.6 16.41v14.61c19.37-1.15 48.95-1.15 68.88-1.15 15.66 0 45.89 0 60.57 1.15v-14.61c-38.74 0-44.84-2.96-56.86-20.03"/>
11
</g>
12
</svg>
131
M src/main/resources/com/keenwrite/ui/fonts/icons/tfignore.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm2.5 10c-8-8-21-8-29 0s-8 21 0 29 21 8 29 0 8-21 0-29zM23.3 58.7c-3.8-5.9-3.1-13.8 2-18.9s13-5.8 18.9-2L23.3 58.7zm4.5 4.5l20.9-20.9c3.8 5.9 3.1 13.8-2 18.9s-13 5.8-18.9 2z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M54.633 9.367C42.145-3.12 21.855-3.12 9.367 9.367s-12.488 32.778 0 45.266 32.778 12.488 45.266 0 12.488-32.778 0-45.266zM12.176 44.801c-5.934-9.211-4.84-21.543 3.12-29.504s20.294-9.055 29.505-3.121zm7.023 7.023L51.824 19.2c5.934 9.211 4.84 21.543-3.12 29.504s-20.294 9.055-29.505 3.121zm0 0" fill="#bababa"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/tga.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.9 9.3H5.7V6.4h9.6v2.9h-3.2v11.4H8.9V9.3zm14.2-3.2c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.7-7.6 6.5-7.6zm10.3.3H37l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h2z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/tgz.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#90c}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.9 9.3H5.7V6.4h9.6v2.9h-3.2v11.4H8.9V9.3zm14.2-3.2c1.4 0 2.9.4 3.9 1.3l-1.4 2.8c-.6-.6-1.4-.9-2.3-.9-2.2 0-3.2 1.9-3.2 4.2 0 2.6 1.2 4.3 2.9 4.3.6 0 1.3-.2 1.7-.6v-1.7h-1.5v-2.9h4.3v8.1h-2.6v-.9c-.5.7-1.6 1.2-2.7 1.2-2.8 0-5.6-2.7-5.6-7.3.2-4.5 2.7-7.6 6.5-7.6zm7.3 12.4l4.2-7.9c.5-.9.8-1.3.8-1.3s-.3.1-.8.1h-4v-3h8.7v2.2l-4.2 8c-.5.9-.8 1.3-.8 1.3s.3-.1.8-.1h4.3v2.9h-8.9v-2.2z" fill="#fff"/><path class="st0" d="M51.1 57.5h-5.7v-5.7l5.7 5.7zm-15.3-5.7v20.7h15.4V58.9H44v-7.1h-8.2zm2.4-5.4h-17v4h6.7l-4.2 3.3v3.5l6.2-4.8v-1.9h21.6v-1.6l-13.3-2.5zm-8.3 8.7l-6.2 4.8v3.5l6.2-4.8v-3.5zm-6.3 14.4l6.2-4.8v-3.5L23.6 66v3.5zm6.3 1.4v-3.5l-6.2 4.8V74h-2.5v4H25v2.8h-2.2c-.4-.7-1.1-1.2-2-1.2-1.3 0-2.3 1-2.3 2.3 0 1.3 1 2.3 2.3 2.3.9 0 1.6-.5 2-1.2H25v2.1h3.4V83h2.2c.4.7 1.1 1.2 2 1.2 1.3 0 2.3-1 2.3-2.3 0-1.3-1-2.3-2.3-2.3-.9 0-1.6.5-2 1.2h-2.2V78h9.7l13.3-2.4V74H25.7l4.2-3.1z"/></svg>
1
<svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/tiff.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.9 9.3H5.7V6.4h9.6v2.9h-3.2v11.4H8.9V9.3zm9.2-2.9h3.3v14.3h-3.3V6.4zm6.9 0h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4H25V6.4zm10.1 0h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/tmp.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.9 9.3H5.7V6.4h9.6v2.9h-3.2v11.4H8.9V9.3zm9.6-2.9h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1.2-14.3zm15 0H38c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path class="st0" d="M45.8 65c.4.4 1.1.4 1.5-.1.4-.4.4-1 .1-1.5l-2.8-3.3c-.1-.1-.2-.3-.2-.5l-.4-6.2c0-.6-.5-1-1.1-1-.6 0-1 .4-1.1 1v.1l-.4 6.8v.1c0 .4.1.8.5 1.1l.2.2 3.7 3.3z"/><path class="st0" d="M43 47.3c-5.7 0-10.5 3.7-12.3 8.8 1.1.1 2.2.4 3.3.7 1.4-3.6 4.9-6.2 9-6.2 5.3 0 9.6 4.3 9.6 9.6 0 4.8-3.5 8.8-8.1 9.5.1.6.1 1.3.1 1.9 0 .5 0 1-.1 1.5C51 72.4 56 66.9 56 60.3c0-7.1-5.8-13-13-13z"/><path class="st0" d="M40.8 69.8h-1.7c-.3-1.4-.8-2.7-1.6-3.9l1.2-1.2c.4-.4.4-1.1 0-1.5L37.5 62c-.4-.4-1.1-.4-1.5 0l-1.2 1.2c-1.2-.8-2.5-1.4-3.9-1.6v-1.7c0-.6-.5-1.1-1.1-1.1h-1.7c-.6 0-1.1.5-1.1 1.1v1.7c-1.4.3-2.7.8-3.9 1.6L22 61.9c-.4-.4-1.1-.4-1.5 0l-1.2 1.2c-.4.4-.4 1.1 0 1.5l1.1 1.2c-.8 1.2-1.4 2.5-1.6 3.9h-1.6c-.6 0-1.1.5-1.1 1.1v1.7c0 .6.5 1.1 1.1 1.1h1.6c.3 1.4.8 2.7 1.6 3.9l-1.1 1.1c-.4.4-.4 1.1 0 1.5l1.2 1.2c.4.4 1.1.4 1.5 0l1.2-1.1c1.2.8 2.5 1.4 3.9 1.6v1.6c0 .6.5 1.1 1.1 1.1h1.7c.6 0 1.1-.5 1.1-1.1v-1.6c1.4-.3 2.7-.8 3.9-1.6l1.1 1.2c.4.4 1.1.4 1.5 0l1.2-1.2c.4-.4.4-1.1 0-1.5l-1.2-1.2c.8-1.2 1.4-2.5 1.6-3.9h1.7c.6 0 1.1-.5 1.1-1.1v-1.7c0-.5-.5-1-1.1-1zm-7.9 5.9c-2.2 2.2-5.8 2.2-8 0s-2.2-5.8 0-8 5.8-2.2 8 0c2.3 2.2 2.2 5.8 0 8z"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><g fill="#bababa"><path d="M51.227 30.453c.687.688 1.89.688 2.574-.172.687-.691.687-1.722.172-2.582l-4.805-5.676a1.33 1.33 0 0 1-.34-.863l-.687-10.664c0-1.035-.86-1.723-1.887-1.723-1.031 0-1.719.688-1.887 1.723v.172l-.687 11.7v.171c0 .688.172 1.375.855 1.89l.344.344zm0 0"/><path d="M46.426 0C36.645 0 28.41 6.367 25.32 15.14c1.887.172 3.774.688 5.664 1.204 2.403-6.192 8.407-10.668 15.442-10.668 9.094 0 16.469 7.398 16.469 16.52 0 8.257-6.004 15.136-13.899 16.343.172 1.031.172 2.234.172 3.266 0 .863 0 1.722-.172 2.582 11.152-1.203 19.734-10.668 19.734-22.02C68.73 10.152 58.777 0 46.426 0zm0 0"/><path d="M42.648 38.71h-2.914c-.515-2.41-1.375-4.644-2.746-6.71l2.059-2.066c.687-.688.687-1.891 0-2.579l-2.059-2.066c-.687-.687-1.886-.687-2.574 0l-2.059 2.066c-2.058-1.378-4.289-2.41-6.69-2.753v-2.926c0-1.031-.86-1.89-1.888-1.89H20.86c-1.027 0-1.886.859-1.886 1.89v2.926c-2.403.515-4.633 1.375-6.692 2.753l-1.886-2.238c-.688-.687-1.887-.687-2.575 0l-2.058 2.067c-.688.687-.688 1.89 0 2.578l1.886 2.066c-1.37 2.063-2.402 4.3-2.746 6.711H2.16c-1.031 0-1.89.86-1.89 1.89v2.926c0 1.032.859 1.891 1.89 1.891h2.742c.516 2.41 1.375 4.645 2.746 6.711l-1.886 1.89c-.688.692-.688 1.895 0 2.583l2.058 2.066c.688.688 1.887.688 2.575 0l2.058-1.894c2.059 1.375 4.29 2.41 6.692 2.753v2.754c0 1.032.859 1.891 1.886 1.891h2.918c1.028 0 1.887-.86 1.887-1.89v-2.755c2.402-.515 4.633-1.378 6.691-2.753l1.887 2.066c.688.687 1.887.687 2.574 0l2.059-2.066c.687-.688.687-1.891 0-2.579l-2.059-2.066c1.371-2.066 2.403-4.3 2.746-6.71h2.914c1.032 0 1.887-.86 1.887-1.892V40.43c0-.86-.855-1.72-1.887-1.72zM29.094 48.86c-3.774 3.785-9.95 3.785-13.723 0-3.777-3.786-3.777-9.977 0-13.762 3.774-3.785 9.95-3.785 13.723 0 3.949 3.785 3.777 9.976 0 13.761zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/tmx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.9 9.3H5.7V6.4h9.6v2.9h-3.2v11.4H8.9V9.3zM18 6.4h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.7 4.1h-3.2l-.8-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3L18 6.4zm16.9 7.2l-3.4-7.2h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.5-.9-.7-1.7-.7-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.3-7.1z" fill="#fff"/><path d="M34.9 68.2c-2.5-2.4-4.7-4.6-6-9.6h8.8V55H29v-4.9h-3.8v5h-8.8v3.7h9s-.1.7-.2 1.3c-1.3 4.9-2.7 8-8.8 11l1.3 3.7c5.7-3 8.7-6.9 10-11.1 1.3 3.2 3.4 5.8 5.8 8.2l1.4-3.7zm11.6-12h-5l-8.8 24.7h3.8l2.5-7.4h10l2.5 7.4h3.8l-8.8-24.7zm-6.2 13.6l3.8-9.8 3.8 9.9-7.6-.1z" fill="#999" stroke="#999" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><path d="M38.027 37.414c-5.011-4.812-9.425-9.223-12.03-19.25H43.64v-7.219H26.195V1.121h-7.617v10.024H.93v7.421h18.047s-.2 1.403-.399 2.606C15.968 30.996 13.164 37.215.93 43.23l2.61 7.418c11.429-6.015 17.444-13.835 20.05-22.257 2.605 6.418 6.816 11.629 11.629 16.441zM61.29 13.352H51.262L33.617 62.879h7.617l5.016-14.836H66.3l5.013 14.836h7.62zm-12.434 27.27 7.622-19.65 7.617 19.852zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width="1.5039150000000001"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/torrent.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M10.2 73.3H7.9v-2.9h7.2v2.9h-2.4v11.4h-2.4V73.3h-.1zm9.4-3.1c2.8 0 4.4 3.1 4.4 7.3 0 4.2-1.6 7.5-4.4 7.5s-4.4-3.2-4.4-7.5c0-4.2 1.6-7.3 4.4-7.3zm0 11.6c1.3 0 1.8-1.8 1.8-4.3s-.6-4.2-1.8-4.2-1.9 1.7-1.9 4.2c.1 2.5.6 4.3 1.9 4.3zm5.8-11.4h3.4c.4 0 1 .1 1.4.4 1.1.6 1.8 2.1 1.8 4 0 1.7-.6 3.3-1.5 4 0 0 .1.2.4.9l1.7 5h-2.7l-1.5-4.8h-.6v4.8h-2.5V70.4h.1zm2.9 6.6c.6 0 1.2-.7 1.2-1.9 0-.7-.2-1.2-.4-1.5-.2-.2-.5-.3-.6-.3h-.6V77h.4zm5.3-6.6H37c.4 0 1 .1 1.4.4 1.1.6 1.8 2.1 1.8 4 0 1.7-.6 3.3-1.5 4 0 0 .1.2.4.9l1.7 5h-2.7l-1.5-4.8H36v4.8h-2.5l.1-14.3zm2.9 6.6c.6 0 1.2-.7 1.2-1.9 0-.7-.2-1.2-.4-1.5-.2-.2-.5-.3-.6-.3H36V77h.5zm5.3-6.6h5.4v2.9h-2.9V76h2.3v2.9h-2.3v2.9h3.1v2.9h-5.5l-.1-14.3zm6.8 0h2.6L53 77c.3 1 .5 2.4.5 2.4h.1s-.1-1.5-.1-2.4v-6.6h2.3v14.3h-2.6l-1.8-6.6c-.3-1-.5-2.4-.5-2.4h-.1s.1 1.5.1 2.4v6.6h-2.3V70.4zm10.7 2.9h-2.4v-2.9h7.2v2.9h-2.4v11.4h-2.4V73.3z" fill="#666"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm6 30.8c-.2.9-.8 1.5-1.5 2.2-9.2 9.6-25.1 7.8-31.8-3.7-1.8-3.1-2.8-6.3-2.7-9.9.2-4.5 1.7-8.4 4.5-11.9 3.3-4.2 7.5-7 12.9-7.9 1.3-.2 2.6-.3 3.9-.5v3.7l-2.7.3c-7.6 1.1-14 7.5-14.5 14.9-.3 4.6.9 8.8 4 12.3 1.2 1.5 2.6 2.8 4.3 3.6.5.2 1.1.3 1.6.4-4.8-2.8-7.6-7-8.5-12.4-.6-3.6.1-7.1 2.1-10.2 5.1-7.9 14-9.2 20.1-6.6-.5 1.1-1 2.2-1.5 3.2-1.2-.2-2.4-.6-3.6-.6-3.5-.2-6.6.6-9.2 3.1-6.6 6.1-4.9 15.5 1.5 19.7 2 1.4 4.2 2.4 6.6 2.9.6.2 1.2 0 1.9-.1-.1-.1-.2-.1-.3-.1-3-.6-5.8-1.6-8.2-3.7-2.4-2.1-4.2-4.7-4.5-8-.3-4.7 1.5-8.5 5.5-10.9 3.5-2.2 7.2-2.2 10.9-.4 2.1 1 3.6 2.6 4.8 4.6-1.1.6-2.1 1.1-3.1 1.6-.9-.9-1.7-1.9-2.7-2.5-4.7-3.2-11.3-.2-11.8 5.7-.2 2.9 1 5.1 3 7.1 2.4 2.2 5.3 3 8.5 3.4 3.1.4 6.2.3 9.3-.1.6-.1.9.3 1.2.8 0-.1 0 0 0 0z"/></svg>
1
<svg height="64" width="58" xmlns="http://www.w3.org/2000/svg"><path d="M57.938 50.598c-.325 1.437-1.29 2.394-2.415 3.511-14.785 15.325-40.34 12.45-51.109-5.906-2.89-4.95-4.5-10.055-4.34-15.8.324-7.184 2.735-13.407 7.235-18.997C12.613 6.703 19.363 2.234 28.043.796 30.129.48 32.219.32 34.309 0v5.906l-4.34.477C17.754 8.14 7.469 18.355 6.664 30.168c-.48 7.34 1.45 14.047 6.43 19.633 1.93 2.394 4.18 4.469 6.91 5.746.805.32 1.77.476 2.574.637-7.715-4.47-12.215-11.172-13.664-19.793-.965-5.746.16-11.332 3.375-16.278C20.49 7.5 34.793 5.426 44.594 9.578c-.801 1.754-1.606 3.512-2.41 5.106-1.926-.317-3.856-.957-5.786-.957-5.625-.32-10.605.957-14.785 4.949-10.61 9.734-7.875 24.738 2.41 31.445 3.215 2.234 6.75 3.828 10.606 4.625.965.32 1.93 0 3.055-.156-.16-.16-.32-.16-.48-.16-4.825-.957-9.325-2.555-13.18-5.907-3.86-3.351-6.75-7.503-7.235-12.77-.48-7.503 2.414-13.566 8.84-17.398 5.625-3.511 11.574-3.511 17.52-.636 3.374 1.593 5.785 4.148 7.714 7.34-1.765.957-3.375 1.757-4.98 2.554-1.45-1.437-2.735-3.031-4.34-3.992-7.555-5.105-18.164-.316-18.965 9.102-.324 4.629 1.606 8.14 4.82 11.332 3.856 3.511 8.52 4.789 13.66 5.425 4.985.641 9.965.48 14.95-.16.965-.16 1.445.48 1.93 1.278 0-.16 0 0 0 0zm0 0" fill="#bababa"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/tpl.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.9 9.3H5.7V6.4h9.6v2.9h-3.2v11.4H8.9V9.3zm9.2-2.9h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm7.8-7h3.3v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><path class="st0" d="M51.8 48.5H24.5c-.4 0-.7.3-.7.7v2.1c0 .4.4.7.7.7H50v25.6c0 .3.4.7.7.7h2.1c.4 0 .7-.3.7-.7V50.2c0-1-.7-1.7-1.7-1.7z"/><path class="st0" d="M45.8 55.5H19.2c-.4 0-.7.3-.7.7v26.6c0 .3.4.7.7.7h26.6c.3 0 .7-.3.7-.7V56.2c0-.4-.3-.7-.7-.7zm-15 23.8c0 .3-.4.7-.7.7h-7.3c-.4 0-.7-.3-.7-.7v-2.1c0-.3.4-.7.7-.7H30c.4 0 .7.3.7.7v2.1zm0-7c0 .3-.4.7-.7.7h-7.3c-.4 0-.7-.3-.7-.7v-2.1c0-.4.4-.7.7-.7H30c.4 0 .7.3.7.7v2.1zm12.2 7c0 .3-.3.7-.7.7H35c-.4 0-.7-.3-.7-.7v-2.1c0-.3.3-.7.7-.7h7.3c.3 0 .7.3.7.7v2.1zm0-7c0 .3-.3.7-.7.7H35c-.4 0-.7-.3-.7-.7v-2.1c0-.4.3-.7.7-.7h7.3c.3 0 .7.3.7.7v2.1zm0-7c0 .3-.3.7-.7.7H22.7c-.4 0-.7-.3-.7-.7v-5.6c0-.4.4-.7.7-.7h19.6c.4 0 .7.3.7.7v5.6z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#999"><path d="M60.89 0H10.974C10.238 0 9.69.547 9.69 1.281v3.84c0 .73.73 1.277 1.282 1.277h46.629v46.813c0 .55.73 1.281 1.277 1.281h3.84A1.25 1.25 0 0 0 64 53.211V3.109C64 1.281 62.719 0 60.89 0zm0 0"/><path d="M49.922 12.8H1.282C.546 12.8 0 13.349 0 14.079v48.64C0 63.27.73 64 1.281 64h48.64c.548 0 1.278-.547 1.278-1.281v-48.64c0-.731-.547-1.278-1.277-1.278zm-27.43 43.52c0 .547-.73 1.282-1.281 1.282H7.863c-.73 0-1.281-.551-1.281-1.282v-3.84c0-.55.73-1.28 1.281-1.28h13.164c.735 0 1.282.55 1.282 1.28v3.84zm0-12.8c0 .55-.73 1.28-1.281 1.28H7.863c-.73 0-1.281-.55-1.281-1.28v-3.84c0-.73.73-1.282 1.281-1.282h13.164c.735 0 1.282.551 1.282 1.282v3.84zm22.309 12.8c0 .547-.551 1.282-1.281 1.282H30.172c-.73 0-1.281-.551-1.281-1.282v-3.84c0-.55.55-1.28 1.28-1.28H43.52c.55 0 1.28.55 1.28 1.28zm0-12.8c0 .55-.551 1.28-1.281 1.28H30.172c-.73 0-1.281-.55-1.281-1.28v-3.84c0-.73.55-1.282 1.28-1.282H43.52c.55 0 1.28.551 1.28 1.282zm0-12.801c0 .55-.551 1.281-1.281 1.281H7.68a1.25 1.25 0 0 1-1.282-1.281V20.48c0-.73.735-1.28 1.282-1.28h35.84c.73 0 1.28.55 1.28 1.28zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ts.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#4065aa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.9 9.3H5.7V6.4h9.6v2.9h-3.2v11.4H8.9V9.3zm9.9 7.4c.6.6 1.4 1.2 2.3 1.2s1.3-.6 1.3-1.2c0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path class="st0" d="M37.9 55.1v-7.6H33c-.1.3-.2.6-.2 1-.1.2-.1.3-.1.5-.5 2.8-2 4.8-4.5 5.9-.7.3-1.4.4-2.1.3v6.1h3.6c.1 8.6.1 13.1.1 13.3v.5c.5 3.8 2.4 6 5.9 6.9 1.4.4 2.9.6 4.5.6 2-.1 3.9-.4 5.8-1v-7.2c-1.1.3-2.1.6-3 .9-1.7.5-3.2.2-4.4-1-.1-.2-.3-.4-.3-.6-.2-.9-.3-1.9-.3-2.8v-9.6h7.8v-6.1h-7.9v-.1z"/></svg>
1
<svg height="64" width="37" xmlns="http://www.w3.org/2000/svg"><path d="M21.914 13.86V0h-9.039c-.187.547-.371 1.094-.371 1.824-.184.363-.184.547-.184.91-.922 5.106-3.691 8.754-8.3 10.758-1.293.547-2.582.73-3.875.547v11.125h6.64c.184 15.68.184 23.883.184 24.25v.91c.926 6.93 4.43 10.942 10.886 12.582 2.583.73 5.348 1.094 8.301 1.094 3.688-.184 7.196-.73 10.7-1.824v-13.13a101.367 101.367 0 0 0-5.536 1.645c-3.136.91-5.902.364-8.117-1.824-.183-.367-.55-.73-.55-1.094a23.898 23.898 0 0 1-.555-5.105V25.164h14.386V14.04h-14.57zm0 0" fill="#4065aa"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/tsv.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1f7244}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.9 9.3H5.7V6.4h9.6v2.9h-3.2v11.4H8.9V9.3zm9.9 7.4c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm8.7-10.3h3.6l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3l1.7-8.1h3.5l-3.9 14.3h-3.3L27.5 6.4z" fill="#fff"/><path d="M14 54h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H58m-44 5.9h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H58m-44 5.9h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H58m-44 5.9h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H58m-44 5.9h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H58" fill="none" stroke="#1f7244" stroke-width="3" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="52"><path style="fill:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke:#1f7244;stroke-opacity:1;stroke-miterlimit:10" d="M0 1.5h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 7.4h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 13.3h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 19.2h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44M0 25.1h8.5m3.3 0h8.5m3.4 0h8.5m3.3 0H44" transform="matrix(1.9091 0 0 1.92593 0 .385)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/ttf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#36454d}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.9 9.3H5.7V6.4h9.6v2.9h-3.2v11.4H8.9V9.3zm11.4 0h-3.1V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3zm9.2-2.9h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path d="M42.4 47v7.9h-.8c-.5-1.8-1-3.1-1.5-3.9s-1.3-1.4-2.3-1.9c-.5-.3-1.5-.4-2.9-.4h-2.2v22.5c0 1.5.1 2.4.2 2.8.2.4.5.7 1 1 .5.3 1.1.4 2 .4h1v.8H21.7v-.8h1c.8 0 1.5-.2 2-.5.4-.2.7-.5.9-1 .2-.3.2-1.2.2-2.7V48.7h-2.1c-2 0-3.4.4-4.3 1.2-1.2 1.2-2 2.8-2.4 5h-.8V47h26.2z" fill="#7291a1"/><path class="st0" d="M55.6 55.6v7.9h-.8c-.5-1.8-1-3.1-1.5-3.9S52 58.2 51 57.7c-.5-.3-1.5-.4-2.9-.4h-2.2v22.5c0 1.5.1 2.4.2 2.8.2.4.5.7 1 1s1.1.4 2 .4h1v.8H34.8V84h1c.8 0 1.5-.2 2-.5.4-.2.7-.5.9-1 .2-.3.2-1.2.2-2.7V57.3h-2.1c-2 0-3.4.4-4.3 1.2-1.2 1.2-2 2.8-2.4 5h-.8v-7.9h26.3z"/></svg>
1
<svg height="64" width="65" xmlns="http://www.w3.org/2000/svg"><path d="M43.223.492V13.66h-1.32c-.825-3-1.65-5.168-2.473-6.5-.825-1.332-2.145-2.336-3.797-3.168-.824-.5-2.473-.668-4.781-.668h-3.63v37.512c0 2.5.165 4 .329 4.668.328.668.824 1.168 1.648 1.668s1.817.664 3.301.664h1.648v1.336H9.074v-1.336h1.649c1.32 0 2.476-.332 3.3-.832.66-.332 1.153-.832 1.485-1.668.328-.5.328-2 .328-4.5V3.324h-3.461c-3.3 0-5.61.668-7.098 2.004-1.976 2-3.297 4.664-3.957 8.332H0V.492zm0 0" fill="#7291a1"/><path d="M65 14.828V28h-1.32c-.825-3-1.649-5.168-2.473-6.504-.828-1.332-2.145-2.332-3.797-3.168-.824-.5-2.472-.664-4.785-.664h-3.629v37.508c0 2.5.168 4.004.332 4.668.328.668.824 1.168 1.649 1.668.824.5 1.816.668 3.3.668h1.649v1.332H30.684v-1.332h1.652c1.32 0 2.473-.336 3.297-.836.66-.332 1.156-.832 1.488-1.664.328-.5.328-2.004.328-4.504V17.664h-3.465c-3.3 0-5.609.664-7.093 2-1.98 2-3.301 4.668-3.961 8.336h-1.317V14.828zm0 0" fill="#36454d"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/twig.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#7faf4a}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.8 8.7H5.7V6.5h8.4v2.2H11v12H8.8v-12zm5.8-2.2h2.2l1.4 9.8c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.6-9.8h2.1l1.5 9.8c.1.7.1 1.6.1 1.6h.2s0-.9.1-1.6l1.4-9.8h2.2l-2.3 14.2h-2.6l-1.3-8.4c-.1-.9-.2-1.9-.2-1.9h-.1s-.1.9-.2 1.9l-1.4 8.4H17L14.6 6.5zm14.4 0h2.2v14.2H29V6.5zm9.6-.3c1.2 0 2.5.4 3.4 1.2l-.9 2.1c-.6-.6-1.5-1-2.4-1-2.2 0-3.4 2.1-3.4 5 0 3.1 1.4 5 3.2 5 .8 0 1.6-.3 2.1-1v-2.2h-1.5v-2.2h3.4v7.5h-1.7v-1c-.5.8-1.6 1.3-2.7 1.3-2.6 0-5.1-2.7-5.1-7.3.1-4.4 2.3-7.4 5.6-7.4z" fill="#fff"/><path class="st0" d="M52.4 83.1c-2.4-20.9 2.8-15.3 2.8-15.3-5.7-6.8-8.6.3-10 6.9-.7-10.6-4-28.2-17.2-27.9 7.1 0 7.5 14.4 6.8 24.8-6.2-11-20.1-10.2-20.1-10.2S25.1 61 25.1 83h27.3z"/></svg>
1
<svg height="64" width="72" xmlns="http://www.w3.org/2000/svg"><path d="M66.387 64c-4.18-36.844 4.875-26.973 4.875-26.973-9.926-11.988-14.973.528-17.414 12.164C52.628 30.504 46.883-.523 23.898.008c12.364 0 13.059 25.383 11.84 43.719-10.797-19.391-35-17.98-35-17.98s18.11-.708 18.11 38.077h47.539zm0 0" fill="#7faf4a"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/txt.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM8.9 9.3H5.7V6.4h9.6v2.9h-3.2v11.4H8.9V9.3zm11.5 4.3L17 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1H24l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.3-7.1zm12.1-4.3h-3.1V6.4H39v2.9h-3.2v11.4h-3.3V9.3z" fill="#fff"/><path class="st0" d="M14.6 77.2h42.8v6.2H14.6zm0-14.8h42.8v6.2H14.6zm0-15h42.8v6.2H14.6z"/></svg>
1
<svg height="64" width="76" xmlns="http://www.w3.org/2000/svg"><path d="M.176 52.977h75.648V64H.176zm0-26.309h75.648v11.02H.176zM.176 0h75.648v11.023H.176zm0 0" fill="#666"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/udf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#eab41b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm.5-34.6h3.3V16c0 1.4.6 1.9 1.5 1.9s1.5-.5 1.5-1.9V6.4h3.3V16c0 3-1.9 4.9-4.7 4.9-2.9 0-4.8-1.9-4.8-4.9V6.4zm13.2 0h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2H23v8.5h.8zm9.1-11.4H40v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M33.7 65.5c0 .6.2 1.2.7 1.6.9.9 2.4.9 3.3 0 .4-.4.7-1 .7-1.6 0-.6-.2-1.2-.7-1.6-.4-.4-1-.7-1.6-.7s-1.2.2-1.6.7c-.6.4-.8 1-.8 1.6z"/><path class="st0" d="M22.9 52.4c-7.2 7.2-7.2 18.9 0 26.2 7.2 7.2 18.9 7.2 26.2 0 7.2-7.2 7.2-18.9 0-26.2-7.2-7.2-19-7.2-26.2 0zm27.4 20.9c-.7 1.2-1.6 2.4-2.6 3.4s-2.2 1.9-3.4 2.6L40 71.1s.4-.1 1.2-.9c.8-.8 1-1.2 1-1.2l8.1 4.3zm-11-11.1c.9.9 1.4 2.1 1.4 3.3 0 1.2-.5 2.4-1.4 3.3-1.8 1.8-4.7 1.8-6.5 0-.9-.9-1.4-2.1-1.4-3.3 0-1.2.4-2.4 1.4-3.3 1.7-1.8 4.7-1.8 6.5 0zM33 59s-.9.5-1.6 1.3c-.7.8-.7.9-1 1.3l-8.2-4.4c.7-1.2 1.6-2.4 2.6-3.4 1.1-1 2.2-1.9 3.4-2.6L33 59z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#eab41b"><path d="M28.023 32c0 1.04.344 2.074 1.211 2.766 1.555 1.558 4.149 1.558 5.707 0 .692-.692 1.211-1.727 1.211-2.766s-.347-2.074-1.21-2.766c-.692-.695-1.731-1.21-2.77-1.21-1.035 0-2.074.343-2.766 1.21-1.039.692-1.383 1.727-1.383 2.766zm0 0"/><path d="M9.34 9.34c-12.453 12.453-12.453 32.691 0 45.32 12.453 12.453 32.691 12.453 45.32 0 12.453-12.453 12.453-32.691 0-45.32-12.453-12.453-32.867-12.453-45.32 0zm47.394 36.152c-1.21 2.074-2.765 4.153-4.496 5.88-1.73 1.73-3.804 3.288-5.883 4.5l-7.437-14.184s.691-.176 2.078-1.56c1.383-1.382 1.727-2.073 1.727-2.073zM37.707 26.293c1.559 1.555 2.422 3.633 2.422 5.707s-.863 4.152-2.422 5.707a7.933 7.933 0 0 1-11.242 0c-1.559-1.555-2.422-3.633-2.422-5.707s.691-4.152 2.422-5.707c2.941-3.113 8.129-3.113 11.242 0zm-10.895-5.535s-1.558.863-2.769 2.246c-1.211 1.387-1.211 1.558-1.73 2.25l-14.184-7.61c1.21-2.078 2.77-4.152 4.5-5.882 1.902-1.73 3.805-3.285 5.879-4.496zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/vb.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d5006e}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zm13.5 0h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1z" fill="#fff"/><path class="st0" d="M30.1 67.5c-1.1.9-2.2 1.7-3.3 2.5l-6.6 5.1c-.3.2-.5.3-.8.1-.5-.3-.9-.5-1.4-.7-.3-.1-.4-.3-.4-.6V56.3c0-.2.2-.5.3-.6.5-.3 1-.5 1.6-.8.3-.1.5 0 .7.1 1.8 1.4 3.6 2.8 5.5 4.2 1.5 1.1 3 2.3 4.5 3.4l.3-.3C36 57 41.4 51.7 46.9 46.4c.3-.3.5-.3.9-.2 2.3.9 4.6 1.9 6.9 2.8.2.1.3.3.4.5.1.1 0 .3 0 .4v30.2c0 .7 0 .7-.7 1-2.2.9-4.4 1.7-6.6 2.6-.4.2-.6.1-.9-.2-5.5-5-10.9-10.3-16.4-15.5-.1-.2-.2-.3-.4-.5zm15.7 4.8V57.9l-9.6 7.2 9.6 7.2zm-20.1-7.2c-1.6-1.4-3.2-2.8-4.8-4.3v8.6c1.6-1.4 3.2-2.8 4.8-4.3z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M21.344 36.297c-1.871 1.527-3.739 2.887-5.61 4.246L4.52 49.211c-.512.34-.852.508-1.36.168A15.884 15.884 0 0 0 .781 48.19c-.511-.171-.68-.511-.68-1.02V17.267c0-.34.34-.852.508-1.02.852-.512 1.7-.851 2.72-1.36.51-.171.85 0 1.19.169 3.06 2.379 6.118 4.757 9.348 7.136 2.547 1.872 5.098 3.91 7.645 5.778l.511-.508C31.367 18.453 40.543 9.449 49.891.44c.507-.507.847-.507 1.527-.34 3.91 1.532 7.816 3.231 11.727 4.758.34.172.507.512.68.852.167.168 0 .508 0 .68v51.316c0 1.188 0 1.188-1.192 1.7-3.738 1.527-7.477 2.886-11.215 4.417-.68.34-1.02.168-1.527-.34-9.348-8.496-18.524-17.504-27.868-26.34-.171-.34-.34-.507-.68-.847zm26.676 8.156V19.984L31.707 32.22zM13.867 32.22c-2.719-2.38-5.437-4.758-8.16-7.309v14.613c2.723-2.378 5.441-4.757 8.16-7.304zm0 0" fill="#d5006e"/></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/vbproj.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M28.3 44.7c-1.3 1-2.5 1.9-3.7 2.8-2.5 1.9-4.9 3.7-7.4 5.6-.3.3-.6.3-.9.1-.5-.3-1-.5-1.6-.8-.3-.1-.4-.4-.4-.7V32.2c0-.2.2-.5.4-.6.6-.3 1.2-.6 1.7-.9.3-.2.6 0 .8.2 2 1.6 4.1 3.1 6.1 4.6 1.7 1.3 3.3 2.5 5 3.8l.3-.3c6.1-5.9 12.1-11.8 18.2-17.7.3-.3.6-.3 1-.2 2.6 1 5.1 2.1 7.7 3.1.2.1.3.3.4.5.1.1 0 .3 0 .5v33.6c0 .8 0 .8-.8 1.1-2.4 1-4.9 1.9-7.3 2.9-.4.2-.7.1-1-.2-6-5.9-12-11.7-18-17.5-.1-.1-.3-.2-.5-.4zM45.8 50V34c-3.6 2.7-7.1 5.3-10.7 8 3.6 2.7 7.1 5.3 10.7 8zm-22.4-8c-1.8-1.6-3.5-3.2-5.3-4.8v9.6c1.8-1.6 3.5-3.2 5.3-4.8z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M7.1 70.4h3l1.4 8.1c.2.9.3 2.3.3 2.3h.1s.1-1.4.3-2.3l1.4-8.1h3l-3.3 14.3h-2.8L7.1 70.4zm10.6 0h3.6c2.1 0 3.6 1.3 3.6 3.7 0 1.2-.4 2.4-1.4 3 1.4.5 1.8 1.9 1.8 3.2 0 3.1-1.7 4.3-3.8 4.3h-3.7V70.4h-.1zm3.6 5.6c.5 0 .7-.6.7-1.4 0-.7-.3-1.3-.8-1.3h-.7V76h.8zm.1 5.8c.7 0 1-.7 1-1.6s-.3-1.5-.9-1.5h-1v3.1h.9zM27 70.4h3.8c2.2 0 3.7 2 3.7 4.9s-1.5 5-3.7 5h-1v4.4H27V70.4zm3.3 7c.9 0 1.4-.9 1.4-2.1s-.6-2-1.3-2h-.6v4.1h.5zm5.9-7H40c.5 0 1.1.1 1.6.4 1.2.6 2 2.1 2 4 0 1.7-.7 3.3-1.7 4 0 0 .2.2.4.9l2 5h-3.1l-1.7-4.8H39v4.8h-2.8V70.4zm3.3 6.6c.7 0 1.3-.7 1.3-1.9 0-.7-.2-1.2-.5-1.5-.2-.2-.5-.3-.7-.3H39V77h.5zm10.7-6.8c3.2 0 5 3.1 5 7.3 0 4.2-1.8 7.5-5 7.5s-5-3.2-5-7.5c0-4.2 1.8-7.3 5-7.3zm0 11.6c1.4 0 2.1-1.8 2.1-4.3s-.6-4.2-2.1-4.2c-1.4 0-2.1 1.7-2.1 4.2s.6 4.3 2.1 4.3zm6-2.5H59v1.1c0 1.5.3 1.6.6 1.6.4 0 .6-.3.6-1.6v-7h-2.3v-2.9H63v9.9c0 3.3-1.7 4.6-3.4 4.6-1.8 0-3.4-1.4-3.4-4.6v-1.1z" fill="#666"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/vbs.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zm13.5 0h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1zm8.3-1.1c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path class="st0" d="M15.6 50.9v1.3l-1.6.6v-1.3l1.6-.6zm0 13v1.3l-1.6.7v-1.3l1.6-.7zm0 13.2v1.4l-1.6.6v-1.3l1.6-.7zm-.2-21.9v1.2l-1.3.6v-1.2l1.3-.6zm0 4.4v1.2l-1.3.6v-1.2l1.3-.6zm0 8.8v1.2l-1.3.6V69l1.3-.6zm0 4.4V74l-1.3.6v-1.2l1.3-.6zm4.1-21.2v1.6l-2.1.8v-1.5l2.1-.9zm0 13.2v1.5l-2.1.8v-1.5l2.1-.8zm0 13.3v1.5l-2.1.9V79l2.1-.9zm-.1-21.9v1.4l-1.7.7v-1.4l1.7-.7zm0 4.4V62l-1.7.7v-1.5l1.7-.6zm0 8.8v1.4l-1.7.7V70l1.7-.6zm0 4.4v1.4l-1.7.7v-1.4l1.7-.7zm4.1-21.2v1.9l-2.8 1.1v-1.8l2.8-1.2zm0 13.2v1.9l-2.8 1.1V67l2.8-1.2zm0 13.1v1.9l-2.8 1.1V80l2.8-1.1zm-.1-21.7v1.7l-2.3.9v-1.6l2.3-1zm0 4.4v1.6l-2.3.9v-1.6l2.3-.9zm0 8.8V72l-2.3.9v-1.6l2.3-.9zm0 4.2v1.7l-2.3.9v-1.6l2.3-1zm4.5-22.1V55l-3.4 1.4V54l3.4-1.5zm0 13.2v2.5l-3.4 1.3V67l3.4-1.3zm0 13.1v2.5l-3.4 1.4v-2.4l3.4-1.5zm-.2-21.7v2.3l-2.9 1.2v-2.3l2.9-1.2zm0 4.4v2.2l-2.9 1.2v-2.3l2.9-1.1zm0 8.8v2.3l-2.9 1.1v-2.3l2.9-1.1zm0 4.2v2.3l-2.9 1.1v-2.2l2.9-1.2zm4.7-22.4v3.2l-3.8 1.5v-3.2l3.8-1.5zm0 13.2v3.2L28.6 70v-3.2l3.8-1.5zm0 13.1v3.2l-3.8 1.5v-3.2l3.8-1.5zm-.2-21.5v2.7L29 60.9v-2.7l3.2-1.3zm0 4.2v2.7L29 65.1v-2.7l3.2-1.3zm0 9v2.7L28.9 74v-2.7l3.3-1.2zm0 4.2V77L29 78.3v-2.7l3.2-1.3zM37 50.5v4.4l-4.1 1.7v-4.1c1.4-.9 2.8-1.5 4.1-2zm0 4.8v3.8l-4.1 1.7V57l4.1-1.7zm0 4.3v3.8l-4.1 1.7v-3.8l4.1-1.7zm0 4.3v3.8l-4.1 1.7v-3.8l4.1-1.7zm0 4.3v3.9l-4.1 1.7v-3.9l4.1-1.7zm0 4.4v3.8l-4.1 1.8v-3.9l4.1-1.7zm0 4.3V81c-1.6.6-3 1.2-4.1 1.8v-4.1l4.1-1.8zm21-26.3v30.8c-2.6-1.7-5.9-2.6-9.7-2.6-3.2 0-6.8.7-10.8 2v-4.2c2.1-.8 4.4-1.4 7-1.8v-10c-2.1.3-4.5 1-7 2.2v-2.9c2.2-1 4.5-1.7 7-2.1v-9.8c-2.2.4-4.6 1.2-7 2.3v-4.3c3.5-1.5 7-2.3 10.4-2.3 3.6.1 7 1 10.1 2.7zm-4.1 2.7c-1.7-.9-3.7-1.3-6-1.3h-.8v10h.9c2 0 4 .3 5.9 1v-9.7zm0 12.5c-1.8-.8-3.8-1.2-5.9-1.2h-.9v10h.9c2.2 0 4.1.3 5.9.8v-9.6zm2.7 16.9V82h-.3v-.1h.7v.1h-.3v.7h-.1zm.5 0v-.8h.2l.3.6.3-.6h.1v.8h-.1V82l-.3.6h-.1l-.3-.6v.7h-.1z"/></svg>
1
<svg height="64" width="80" xmlns="http://www.w3.org/2000/svg"><path d="M3.121 5.453v2.363L.227 8.91V6.547zm0 23.637v2.363L.227 32.727v-2.364zm0 24v2.547l-2.894 1.09v-2.364zm-.363-39.817v2.18L.406 16.547v-2.184zm0 8v2.18L.406 24.547v-2.184zm0 16v2.18L.406 40.547v-2.184zm0 8v2.18L.406 48.547v-2.184zm7.414-38.546v2.91L6.375 11.09V8.363zm0 24v2.726L6.375 34.91v-2.726zm0 24.183v2.727l-3.797 1.636v-2.726zm-.184-39.82v2.547l-3.07 1.273v-2.547zm0 8v2.547l-3.07 1.273v-2.726zm0 16v2.547l-3.07 1.273v-2.726zm0 8v2.547l-3.07 1.273v-2.547zm7.414-38.543V12l-5.062 2v-3.273zm0 24V36l-5.062 2v-3.273zm0 23.816v3.453l-5.062 2v-3.453zm-.18-39.453V20l-4.16 1.637v-2.91zm0 8v2.906l-4.16 1.637v-2.906zm0 16v2.906l-4.16 1.637v-2.906zm0 7.637v3.09l-4.16 1.636v-2.91zm8.133-40.184v4.547l-6.144 2.543V11.09zm0 24v4.547l-6.144 2.363v-4.546zm0 23.82v4.544l-6.144 2.546V58.91zm-.359-39.456v4.183l-5.242 2.18v-4.18zm0 8v4l-5.242 2.183v-4.183zm0 16v4.183l-5.242 2v-4.183zm0 7.636v4.184l-5.242 2v-4zm8.496-40.726v5.816l-6.87 2.73v-5.82zm0 24v5.816l-6.87 2.73v-5.82zm0 23.816v5.82L26.622 64v-5.816zm-.363-39.09v4.91l-5.785 2.364v-4.91zm0 7.637v4.91l-5.785 2.363v-4.91zm0 16.363v4.91l-5.965 2.18v-4.906zm0 7.637v4.91l-5.785 2.363v-4.91zm8.68-43.273v8l-7.414 3.09V8.362c2.53-1.636 5.062-2.726 7.414-3.636zm0 8.726v6.91l-7.414 3.09v-6.906zm0 7.82v6.91l-7.414 3.09v-6.91zm0 7.817V36l-7.414 3.09v-6.906zm0 7.82V44l-7.414 3.09V40zm0 8v6.906l-7.414 3.274V48zm0 7.817v7.457c-2.895 1.09-5.426 2.18-7.414 3.27V56zM79.773 4.91v56c-4.699-3.094-10.668-4.726-17.535-4.726-5.785 0-12.297 1.27-19.527 3.632v-7.632c3.797-1.457 7.957-2.547 12.656-3.274V30.727c-3.797.546-8.137 1.82-12.656 4v-5.274a48.751 48.751 0 0 1 12.656-3.816V7.817C51.391 8.546 47.051 10 42.711 12V4.184C49.039 1.454 55.367 0 61.51 0c6.512.184 12.657 1.816 18.262 4.91zM72.36 9.816c-3.07-1.632-6.687-2.363-10.847-2.363h-1.446v18.184h1.63c3.613 0 7.23.547 10.663 1.816zm0 22.73c-3.254-1.456-6.867-2.183-10.664-2.183h-1.629v18.184h1.63c3.976 0 7.41.543 10.663 1.453zm4.883 30.727V62H76.7v-.184h1.266V62h-.543v1.273zm.903 0v-1.457h.363l.543 1.094.543-1.094h.18v1.457h-.18V62l-.543 1.09h-.184L78.328 62v1.273zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/vcd.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#eab41b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zm19.1-.3c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4zm6.6.3h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z" fill="#fff"/><path class="st0" d="M33.7 65.5c0 .6.2 1.2.7 1.6.9.9 2.4.9 3.3 0 .4-.4.7-1 .7-1.6 0-.6-.2-1.2-.7-1.6-.4-.4-1-.7-1.6-.7s-1.2.2-1.6.7c-.6.4-.8 1-.8 1.6z"/><path class="st0" d="M22.9 52.4c-7.2 7.2-7.2 18.9 0 26.2 7.2 7.2 18.9 7.2 26.2 0 7.2-7.2 7.2-18.9 0-26.2-7.2-7.2-19-7.2-26.2 0zm27.4 20.9c-.7 1.2-1.6 2.4-2.6 3.4s-2.2 1.9-3.4 2.6L40 71.1s.4-.1 1.2-.9c.8-.8 1-1.2 1-1.2l8.1 4.3zm-11-11.1c.9.9 1.4 2.1 1.4 3.3 0 1.2-.5 2.4-1.4 3.3-1.8 1.8-4.7 1.8-6.5 0-.9-.9-1.4-2.1-1.4-3.3 0-1.2.4-2.4 1.4-3.3 1.7-1.8 4.7-1.8 6.5 0zM33 59s-.9.5-1.6 1.3c-.7.8-.7.9-1 1.3l-8.2-4.4c.7-1.2 1.6-2.4 2.6-3.4 1.1-1 2.2-1.9 3.4-2.6L33 59z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><g fill="#eab41b"><path d="M28.023 32c0 1.04.344 2.074 1.211 2.766 1.555 1.558 4.149 1.558 5.707 0 .692-.692 1.211-1.727 1.211-2.766s-.347-2.074-1.21-2.766c-.692-.695-1.731-1.21-2.77-1.21-1.035 0-2.074.343-2.766 1.21-1.039.692-1.383 1.727-1.383 2.766zm0 0"/><path d="M9.34 9.34c-12.453 12.453-12.453 32.691 0 45.32 12.453 12.453 32.691 12.453 45.32 0 12.453-12.453 12.453-32.691 0-45.32-12.453-12.453-32.867-12.453-45.32 0zm47.394 36.152c-1.21 2.074-2.765 4.153-4.496 5.88-1.73 1.73-3.804 3.288-5.883 4.5l-7.437-14.184s.691-.176 2.078-1.56c1.383-1.382 1.727-2.073 1.727-2.073zM37.707 26.293c1.559 1.555 2.422 3.633 2.422 5.707s-.863 4.152-2.422 5.707a7.933 7.933 0 0 1-11.242 0c-1.559-1.555-2.422-3.633-2.422-5.707s.691-4.152 2.422-5.707c2.941-3.113 8.129-3.113 11.242 0zm-10.895-5.535s-1.558.863-2.769 2.246c-1.211 1.387-1.211 1.558-1.73 2.25l-14.184-7.61c1.21-2.078 2.77-4.152 4.5-5.882 1.902-1.73 3.805-3.285 5.879-4.496zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/vcf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#c11e07}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zm19.1-.3c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4zm6.6.3h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path d="M39.9 53.4v-2c0-2.1-1.8-3.9-3.9-3.9s-3.9 1.8-3.9 3.9v2H16.6v29.1h38.8V53.4H39.9zm11.6 25.2h-31V57.2h11.6v1.9h7.8v-1.9h11.6v21.4z"/><circle cx="28.2" cy="65" r="2"/><path d="M28.2 68.9c-2.1 0-3.9 1.8-3.9 3.9v2h7.8v-2c0-2.2-1.7-3.9-3.9-3.9zM38 63h9.7v3.9H38V63zm0 7.9h9.7v3.9H38v-3.9z"/></svg>
1
<svg height="64" width="71" xmlns="http://www.w3.org/2000/svg"><path d="M42.602 10.79V7.132C42.602 3.293 39.324 0 35.5 0s-7.102 3.293-7.102 7.133v3.656H.184V64h70.632V10.79zm21.117 46.077H7.28V17.738h21.117v3.473h14.204v-3.473h21.117zm0 0"/><path d="M24.941 32c0 2.02-1.628 3.656-3.64 3.656S17.66 34.02 17.66 32s1.628-3.656 3.64-3.656S24.94 29.98 24.94 32zM21.3 39.133c-3.823 0-7.1 3.289-7.1 7.129v3.66h14.198v-3.66c0-4.024-3.093-7.13-7.097-7.13zm17.84-10.79H56.8v7.13H39.14zm0 14.446H56.8v7.133H39.14zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/vcs.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#c11e07}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zm19.1-.3c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2 0 2.3 1.2 4.4 3.2 4.4 1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4zm7.3 10.6c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path d="M39.9 53.4v-2c0-2.1-1.8-3.9-3.9-3.9s-3.9 1.8-3.9 3.9v2H16.6v29.1h38.8V53.4H39.9zm11.6 25.2h-31V57.2h11.6v1.9h7.8v-1.9h11.6v21.4z"/><circle cx="28.2" cy="65" r="2"/><path d="M28.2 68.9c-2.1 0-3.9 1.8-3.9 3.9v2h7.8v-2c0-2.2-1.7-3.9-3.9-3.9zM38 63h9.7v3.9H38V63zm0 7.9h9.7v3.9H38v-3.9z"/></svg>
1
<svg height="64" width="71" xmlns="http://www.w3.org/2000/svg"><path d="M42.602 10.79V7.132C42.602 3.293 39.324 0 35.5 0s-7.102 3.293-7.102 7.133v3.656H.184V64h70.632V10.79zm21.117 46.077H7.28V17.738h21.117v3.473h14.204v-3.473h21.117zm0 0"/><path d="M24.941 32c0 2.02-1.628 3.656-3.64 3.656S17.66 34.02 17.66 32s1.628-3.656 3.64-3.656S24.94 29.98 24.94 32zM21.3 39.133c-3.823 0-7.1 3.289-7.1 7.129v3.66h14.198v-3.66c0-4.024-3.093-7.13-7.097-7.13zm17.84-10.79H56.8v7.13H39.14zm0 14.446H56.8v7.133H39.14zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/vdi.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#4d1b9b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zm13.5 0h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zM23 17.8c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm9.1-11.4h3.3v14.3h-3.3V6.4z" fill="#fff"/><path class="st0" d="M56.5 76.6c0-1.6-1.3-2.9-2.9-2.9H17.7c-1.6 0-2.9 1.3-2.9 2.9v4.1c0 1.6 1.3 2.9 2.9 2.9h35.9c1.6 0 2.9-1.3 2.9-2.9v-4.1zM41 80.4c-.9 0-1.7-.7-1.7-1.7S40.1 77 41 77s1.7.7 1.7 1.7-.7 1.7-1.7 1.7zm5.1 0c-.9 0-1.7-.7-1.7-1.7s.7-1.7 1.7-1.7c.9 0 1.7.7 1.7 1.7s-.8 1.7-1.7 1.7zm5 0c-.9 0-1.7-.7-1.7-1.7s.7-1.7 1.7-1.7c.9 0 1.7.7 1.7 1.7s-.8 1.7-1.7 1.7zM17.7 72h35.9c.8 0 1.6.2 2.2.6l-3.5-7.3c-1-2.1-2.6-2.9-4.2-2.9h-3.9l-5.6 5.8c-.4.4-.9.7-1.4.9-.5.2-1.1.3-1.6.3-.6 0-1.1-.1-1.6-.3h-.2c-.4-.2-.8-.5-1.2-.8l-5.6-6h-3.9c-1.6 0-3.1.9-4.2 2.9l-3.5 7.3c.7-.3 1.4-.5 2.3-.5z"/><path class="st0" d="M44 59.6c.2-.2.3-.4.5-.7.1-.3.2-.5.2-.9 0-.3-.1-.6-.2-.8-.1-.3-.3-.5-.5-.7-.2-.2-.5-.4-.7-.5-.2-.1-.5-.2-.8-.2s-.6.1-.8.2c-.3.1-.5.3-.7.5l-3.2 3.2v-10c0-.3-.1-.6-.2-.8-.1-.3-.3-.5-.5-.7-.2-.2-.4-.4-.7-.5-.2-.1-.5-.1-.8-.1-.3 0-.6 0-.8.1-.3.1-.5.3-.7.5-.2.2-.4.4-.5.7-.1.3-.2.5-.2.8v10.1l-3.2-3.2c-.2-.2-.4-.4-.7-.5-.2-.1-.5-.2-.8-.2-.3 0-.6.1-.8.2-.2.1-.5.3-.7.5-.2.2-.4.4-.5.7-.1.3-.2.5-.2.8 0 .3.1.6.2.9.1.3.3.5.5.7l6.9 7c.2.2.4.4.7.5.2.1.5.2.8.2.3 0 .6-.1.8-.2.3-.1.5-.3.7-.5l6.9-7.1z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#4d1b9b"><path d="M73.734 51.555c0-2.844-2.289-5.157-5.109-5.157H5.375c-2.82 0-5.11 2.313-5.11 5.157v7.289c0 2.843 2.29 5.156 5.11 5.156h63.25c2.82 0 5.11-2.313 5.11-5.156zm-27.308 6.757a2.985 2.985 0 0 1-2.996-3.023 2.985 2.985 0 0 1 2.996-3.023 2.985 2.985 0 0 1 2.996 3.023c0 1.777-1.234 3.023-2.996 3.023zm8.984 0a2.984 2.984 0 0 1-2.992-3.023c0-1.777 1.23-3.023 2.992-3.023a2.985 2.985 0 0 1 2.996 3.023 2.985 2.985 0 0 1-2.996 3.023zm8.813 0a2.985 2.985 0 0 1-2.996-3.023c0-1.777 1.234-3.023 2.996-3.023a2.981 2.981 0 0 1 2.992 3.023 2.981 2.981 0 0 1-2.992 3.023zM5.375 43.38h63.25c1.41 0 2.82.355 3.879 1.066l-6.168-12.98c-1.762-3.73-4.582-5.153-7.398-5.153h-6.876L42.2 36.623c-.707.71-1.586 1.245-2.469 1.6-.878.356-1.937.532-2.82.532-1.055 0-1.937-.176-2.816-.531h-.352c-.707-.356-1.41-.891-2.117-1.422l-9.867-10.668h-6.871c-2.817 0-5.461 1.601-7.399 5.156L1.32 44.266c1.235-.532 2.47-.887 4.055-.887zm0 0"/><path d="M51.71 21.332c.352-.355.532-.71.884-1.242.176-.535.351-.89.351-1.602 0-.531-.175-1.066-.351-1.422-.176-.53-.532-.886-.883-1.246a5.273 5.273 0 0 0-1.23-.886c-.356-.18-.883-.356-1.41-.356-.532 0-1.06.176-1.41.356-.528.175-.884.53-1.235.886l-5.637 5.692V3.734c0-.535-.176-1.066-.352-1.421-.18-.536-.53-.891-.882-1.247-.352-.355-.703-.71-1.235-.886C37.97 0 37.441 0 36.91 0c-.527 0-1.055 0-1.406.18-.531.175-.883.53-1.234.886-.352.356-.708.711-.883 1.246-.176.532-.352.887-.352 1.422v17.953L27.398 16c-.351-.355-.707-.71-1.234-.89-.352-.176-.879-.356-1.41-.356-.527 0-1.055.18-1.41.355-.352.18-.88.536-1.23.891-.356.355-.708.71-.884 1.246-.175.531-.351.887-.351 1.422 0 .531.176 1.066.351 1.598.176.535.528.89.883 1.246L34.27 33.957c.351.355.703.711 1.234.887.351.18.879.355 1.406.355.531 0 1.059-.176 1.41-.355.532-.176.883-.532 1.235-.887zm0 0"/></g></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/vdx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#37539d}.st2{fill:none;stroke:#37539d;stroke-width:2;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zm13.5 0h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zM23 17.8c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8zm11.2-4.2l-3.4-7.2h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H31l3.2-7.1z" fill="#fff"/><path class="st0" d="M17.1 51.3l21.3-4.1V83l-21.3-3.9z"/><path class="st0" d="M53.3 79.5H35.2c-.9 0-1.6-.7-1.6-1.6V52.4c0-.9.7-1.6 1.6-1.6h18.1c.9 0 1.6.7 1.6 1.6v25.5c0 .9-.7 1.6-1.6 1.6zM35.2 52.3c-.1 0-.2.1-.2.2V78c0 .1.1.2.2.2h18.1c.1 0 .2-.1.2-.2V52.4c0-.1-.1-.2-.2-.2l-18.1.1z"/><path class="st2" d="M36 68h6v6h-6z"/><path transform="rotate(-45.001 46.689 58.69)" class="st2" d="M44.1 56.1h5.1v5.1h-5.1z"/><path class="st2" d="M43 58.8h-5m9 3.2v9m-5 0h6"/><path d="M23 60.2h2.1l2.3 6.9c.2.6.4 1.6.4 1.6s.2-.9.4-1.6l2.4-6.9h2.1l-3.9 10.6h-1.9L23 60.2z" fill="#fff" stroke="#fff" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/vmdk.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#4d1b9b}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.7 6.5h1.8l1.2 9.8c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.3-9.8H12l1.2 9.8c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.2-9.8h1.8l-1.9 14.2h-2.1l-1.1-8.4c-.1-.9-.1-1.9-.1-1.9h-.1s0 .9-.2 1.9l-1.1 8.4H7.7l-2-14.2zm12.3 0h2l1.4 6.9c.2.9.3 2.2.3 2.2s.2-1.3.3-2.2l1.4-6.9h2l.7 14.2h-1.7l-.4-7.9v-2.2s-.2 1.4-.4 2.3l-1.1 5.4h-1.8l-1.1-5.4c-.2-.8-.3-2.3-.3-2.3h-.1s.1 1.3 0 2.2l-.2 7.9h-1.7L18 6.5zm9.9 0h3c2.6 0 4.3 2.6 4.3 7.1s-1.7 7.1-4.3 7.1h-3V6.5zm2.8 12c1.6 0 2.5-1.7 2.5-4.9s-.9-4.9-2.5-4.9h-1v9.8h1zm5.9-12h1.8v5.8h.8l1.9-5.8h2l-2.3 6.8 2.4 7.4h-2.1l-2-6.2h-.8v6.2h-1.8V6.5z" fill="#fff"/><path class="st0" d="M56.5 76.6c0-1.6-1.3-2.9-2.9-2.9H17.7c-1.6 0-2.9 1.3-2.9 2.9v4.1c0 1.6 1.3 2.9 2.9 2.9h35.9c1.6 0 2.9-1.3 2.9-2.9v-4.1zM41 80.4c-.9 0-1.7-.7-1.7-1.7S40.1 77 41 77s1.7.7 1.7 1.7-.7 1.7-1.7 1.7zm5.1 0c-.9 0-1.7-.7-1.7-1.7s.7-1.7 1.7-1.7c.9 0 1.7.7 1.7 1.7s-.8 1.7-1.7 1.7zm5 0c-.9 0-1.7-.7-1.7-1.7s.7-1.7 1.7-1.7c.9 0 1.7.7 1.7 1.7s-.8 1.7-1.7 1.7zM17.7 72h35.9c.8 0 1.6.2 2.2.6l-3.5-7.3c-1-2.1-2.6-2.9-4.2-2.9h-3.9l-5.6 5.8c-.4.4-.9.7-1.4.9-.5.2-1.1.3-1.6.3-.6 0-1.1-.1-1.6-.3h-.2c-.4-.2-.8-.5-1.2-.8l-5.6-6h-3.9c-1.6 0-3.1.9-4.2 2.9l-3.5 7.3c.7-.3 1.4-.5 2.3-.5z"/><path class="st0" d="M44 59.6c.2-.2.3-.4.5-.7.1-.3.2-.5.2-.9 0-.3-.1-.6-.2-.8-.1-.3-.3-.5-.5-.7-.2-.2-.5-.4-.7-.5-.2-.1-.5-.2-.8-.2s-.6.1-.8.2c-.3.1-.5.3-.7.5l-3.2 3.2v-10c0-.3-.1-.6-.2-.8-.1-.3-.3-.5-.5-.7-.2-.2-.4-.4-.7-.5-.2-.1-.5-.1-.8-.1-.3 0-.6 0-.8.1-.3.1-.5.3-.7.5-.2.2-.4.4-.5.7-.1.3-.2.5-.2.8v10.1l-3.2-3.2c-.2-.2-.4-.4-.7-.5-.2-.1-.5-.2-.8-.2-.3 0-.6.1-.8.2-.2.1-.5.3-.7.5-.2.2-.4.4-.5.7-.1.3-.2.5-.2.8 0 .3.1.6.2.9.1.3.3.5.5.7l6.9 7c.2.2.4.4.7.5.2.1.5.2.8.2.3 0 .6-.1.8-.2.3-.1.5-.3.7-.5l6.9-7.1z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#4d1b9b"><path d="M73.734 51.555c0-2.844-2.289-5.157-5.109-5.157H5.375c-2.82 0-5.11 2.313-5.11 5.157v7.289c0 2.843 2.29 5.156 5.11 5.156h63.25c2.82 0 5.11-2.313 5.11-5.156zm-27.308 6.757a2.985 2.985 0 0 1-2.996-3.023 2.985 2.985 0 0 1 2.996-3.023 2.985 2.985 0 0 1 2.996 3.023c0 1.777-1.234 3.023-2.996 3.023zm8.984 0a2.984 2.984 0 0 1-2.992-3.023c0-1.777 1.23-3.023 2.992-3.023a2.985 2.985 0 0 1 2.996 3.023 2.985 2.985 0 0 1-2.996 3.023zm8.813 0a2.985 2.985 0 0 1-2.996-3.023c0-1.777 1.234-3.023 2.996-3.023a2.981 2.981 0 0 1 2.992 3.023 2.981 2.981 0 0 1-2.992 3.023zM5.375 43.38h63.25c1.41 0 2.82.355 3.879 1.066l-6.168-12.98c-1.762-3.73-4.582-5.153-7.398-5.153h-6.876L42.2 36.623c-.707.71-1.586 1.245-2.469 1.6-.878.356-1.937.532-2.82.532-1.055 0-1.937-.176-2.816-.531h-.352c-.707-.356-1.41-.891-2.117-1.422l-9.867-10.668h-6.871c-2.817 0-5.461 1.601-7.399 5.156L1.32 44.266c1.235-.532 2.47-.887 4.055-.887zm0 0"/><path d="M51.71 21.332c.352-.355.532-.71.884-1.242.176-.535.351-.89.351-1.602 0-.531-.175-1.066-.351-1.422-.176-.53-.532-.886-.883-1.246a5.273 5.273 0 0 0-1.23-.886c-.356-.18-.883-.356-1.41-.356-.532 0-1.06.176-1.41.356-.528.175-.884.53-1.235.886l-5.637 5.692V3.734c0-.535-.176-1.066-.352-1.421-.18-.536-.53-.891-.882-1.247-.352-.355-.703-.71-1.235-.886C37.97 0 37.441 0 36.91 0c-.527 0-1.055 0-1.406.18-.531.175-.883.53-1.234.886-.352.356-.708.711-.883 1.246-.176.532-.352.887-.352 1.422v17.953L27.398 16c-.351-.355-.707-.71-1.234-.89-.352-.176-.879-.356-1.41-.356-.527 0-1.055.18-1.41.355-.352.18-.88.536-1.23.891-.356.355-.708.71-.884 1.246-.175.531-.351.887-.351 1.422 0 .531.176 1.066.351 1.598.176.535.528.89.883 1.246L34.27 33.957c.351.355.703.711 1.234.887.351.18.879.355 1.406.355.531 0 1.059-.176 1.41-.355.532-.176.883-.532 1.235-.887zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/vob.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zM24 6.1c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c-.1-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm8.9-11.4h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/vox.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zM24 6.1c3.8 0 5.9 3.1 5.9 7.3 0 4.2-2.1 7.5-5.9 7.5s-5.8-3.2-5.8-7.5c-.1-4.1 2-7.3 5.8-7.3zm0 11.7c1.7 0 2.5-1.8 2.5-4.3s-.8-4.2-2.5-4.2-2.5 1.7-2.5 4.2.8 4.3 2.5 4.3zm11-4.2l-3.4-7.2h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.2-7.1z" fill="#fff"/><path class="st0" d="M33.1 59.6l6.6 4.4V48.5l-6.6 4.4v-2.2c0-1.2-1-2.2-2.2-2.2H17.6c-1.2 0-2.2 1-2.2 2.2v11.1c0 1.2 1 2.2 2.2 2.2h13.3c1.2 0 2.2-1 2.2-2.2v-2.2zm10.2 4v6.6c0 2.4 2 4.4 4.4 4.4 2.4 0 4.4-2 4.4-4.4v-6.6c0-2.4-2-4.4-4.4-4.4-2.4 0-4.4 2-4.4 4.4z"/><path class="st0" d="M54.4 70.2c0 3.7-3 6.6-6.6 6.6-3.7 0-6.6-3-6.6-6.6H39c0 4.1 2.8 7.5 6.6 8.5v4.7H50v-4.7c3.8-1 6.6-4.4 6.6-8.5h-2.2z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><g fill="#039"><path d="m31.793 20.445 11.852 8.008V.246L31.793 8.254V4.25c0-2.184-1.797-4.004-3.953-4.004H3.953C1.797.246 0 2.066 0 4.25v20.2c0 2.183 1.797 4.003 3.953 4.003H27.84c2.156 0 3.953-1.82 3.953-4.004zm18.32 7.278v12.011c0 4.368 3.59 8.008 7.903 8.008 4.308 0 7.902-3.64 7.902-8.008V27.723c0-4.368-3.594-8.004-7.902-8.004-4.313 0-7.903 3.636-7.903 8.004zm0 0"/><path d="M70.047 39.734c0 6.73-5.387 12.008-11.852 12.008-6.648 0-11.855-5.457-11.855-12.008h-3.953A15.96 15.96 0 0 0 54.242 55.2v8.555h7.903v-8.555A15.955 15.955 0 0 0 74 39.734zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/vscodeignore.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st1{fill:#bababa}</style><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st1" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st1" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2zm2.5 10c-8-8-21-8-29 0s-8 21 0 29 21 8 29 0 8-21 0-29zM23.3 58.7c-3.8-5.9-3.1-13.8 2-18.9s13-5.8 18.9-2L23.3 58.7zm4.5 4.5l20.9-20.9c3.8 5.9 3.1 13.8-2 18.9s-13 5.8-18.9 2z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M54.633 9.367C42.145-3.12 21.855-3.12 9.367 9.367s-12.488 32.778 0 45.266 32.778 12.488 45.266 0 12.488-32.778 0-45.266zM12.176 44.801c-5.934-9.211-4.84-21.543 3.12-29.504s20.294-9.055 29.505-3.121zm7.023 7.023L51.824 19.2c5.934 9.211 4.84 21.543-3.12 29.504s-20.294 9.055-29.505 3.121zm0 0" fill="#bababa"/></svg>
D src/main/resources/com/keenwrite/ui/fonts/icons/vsd.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#37539d}.st2{fill:none;stroke:#37539d;stroke-width:2;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zm14.1 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L25 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10-10.3h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z" fill="#fff"/><path class="st0" d="M17.1 51.3l21.3-4.1V83l-21.3-3.9z"/><path class="st0" d="M53.3 79.5H35.2c-.9 0-1.6-.7-1.6-1.6V52.4c0-.9.7-1.6 1.6-1.6h18.1c.9 0 1.6.7 1.6 1.6v25.5c0 .9-.7 1.6-1.6 1.6zM35.2 52.3c-.1 0-.2.1-.2.2V78c0 .1.1.2.2.2h18.1c.1 0 .2-.1.2-.2V52.4c0-.1-.1-.2-.2-.2l-18.1.1z"/><path class="st2" d="M36 68h6v6h-6z"/><path transform="rotate(-45.001 46.689 58.69)" class="st2" d="M44.1 56.1h5.1v5.1h-5.1z"/><path class="st2" d="M43 58.8h-5m9 3.2v9m-5 0h6"/><path d="M23 60.2h2.1l2.3 6.9c.2.6.4 1.6.4 1.6s.2-.9.4-1.6l2.4-6.9h2.1l-3.9 10.6h-1.9L23 60.2z" fill="#fff" stroke="#fff" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
D src/main/resources/com/keenwrite/ui/fonts/icons/vss.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#37539d}.st2{fill:none;stroke:#37539d;stroke-width:2;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zm14.1 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L25 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10.7 0c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path class="st0" d="M17.1 51.3l21.3-4.1V83l-21.3-3.9z"/><path class="st0" d="M53.3 79.5H35.2c-.9 0-1.6-.7-1.6-1.6V52.4c0-.9.7-1.6 1.6-1.6h18.1c.9 0 1.6.7 1.6 1.6v25.5c0 .9-.7 1.6-1.6 1.6zM35.2 52.3c-.1 0-.2.1-.2.2V78c0 .1.1.2.2.2h18.1c.1 0 .2-.1.2-.2V52.4c0-.1-.1-.2-.2-.2l-18.1.1z"/><path class="st2" d="M36 68h6v6h-6z"/><path transform="rotate(-45.001 46.689 58.69)" class="st2" d="M44.1 56.1h5.1v5.1h-5.1z"/><path class="st2" d="M43 58.8h-5m9 3.2v9m-5 0h6"/><path d="M23 60.2h2.1l2.3 6.9c.2.6.4 1.6.4 1.6s.2-.9.4-1.6l2.4-6.9h2.1l-3.9 10.6h-1.9L23 60.2z" fill="#fff" stroke="#fff" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
D src/main/resources/com/keenwrite/ui/fonts/icons/vst.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#37539d}.st2{fill:none;stroke:#37539d;stroke-width:2;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zm14.1 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L25 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm12.2-7.4h-3.1V6.4h9.6v2.9H35v11.4h-3.3V9.3z" fill="#fff"/><path class="st0" d="M17.1 51.3l21.3-4.1V83l-21.3-3.9z"/><path class="st0" d="M53.3 79.5H35.2c-.9 0-1.6-.7-1.6-1.6V52.4c0-.9.7-1.6 1.6-1.6h18.1c.9 0 1.6.7 1.6 1.6v25.5c0 .9-.7 1.6-1.6 1.6zM35.2 52.3c-.1 0-.2.1-.2.2V78c0 .1.1.2.2.2h18.1c.1 0 .2-.1.2-.2V52.4c0-.1-.1-.2-.2-.2l-18.1.1z"/><path class="st2" d="M36 68h6v6h-6z"/><path transform="rotate(-45.001 46.689 58.69)" class="st2" d="M44.1 56.1h5.1v5.1h-5.1z"/><path class="st2" d="M43 58.8h-5m9 3.2v9m-5 0h6"/><path d="M23 60.2h2.1l2.3 6.9c.2.6.4 1.6.4 1.6s.2-.9.4-1.6l2.4-6.9h2.1l-3.9 10.6h-1.9L23 60.2z" fill="#fff" stroke="#fff" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
D src/main/resources/com/keenwrite/ui/fonts/icons/vsx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#37539d}.st2{fill:none;stroke:#37539d;stroke-width:2;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zm14.1 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L25 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm12.3-3.1l-3.4-7.2H32l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.7-1.7-.7-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.3-7.1z" fill="#fff"/><path class="st0" d="M17.1 51.3l21.3-4.1V83l-21.3-3.9z"/><path class="st0" d="M53.3 79.5H35.2c-.9 0-1.6-.7-1.6-1.6V52.4c0-.9.7-1.6 1.6-1.6h18.1c.9 0 1.6.7 1.6 1.6v25.5c0 .9-.7 1.6-1.6 1.6zM35.2 52.3c-.1 0-.2.1-.2.2V78c0 .1.1.2.2.2h18.1c.1 0 .2-.1.2-.2V52.4c0-.1-.1-.2-.2-.2l-18.1.1z"/><path class="st2" d="M36 68h6v6h-6z"/><path transform="rotate(-45.001 46.689 58.69)" class="st2" d="M44.1 56.1h5.1v5.1h-5.1z"/><path class="st2" d="M43 58.8h-5m9 3.2v9m-5 0h6"/><path d="M23 60.2h2.1l2.3 6.9c.2.6.4 1.6.4 1.6s.2-.9.4-1.6l2.4-6.9h2.1l-3.9 10.6h-1.9L23 60.2z" fill="#fff" stroke="#fff" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
D src/main/resources/com/keenwrite/ui/fonts/icons/vtx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#37539d}.st2{fill:none;stroke:#37539d;stroke-width:2;stroke-miterlimit:10}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.4 6.4H9l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3L13 6.4h3.5l-3.9 14.3H9.3L5.4 6.4zm15.8 2.9H18V6.4h9.6v2.9h-3.2v11.4h-3.3V9.3zm11.5 4.3l-3.4-7.2h3.6L34 9.3l.6 1.8s.2-.9.6-1.8l1.2-2.9H40l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3h-3.5l3.2-7.1z" fill="#fff"/><path class="st0" d="M17.1 51.3l21.3-4.1V83l-21.3-3.9z"/><path class="st0" d="M53.3 79.5H35.2c-.9 0-1.6-.7-1.6-1.6V52.4c0-.9.7-1.6 1.6-1.6h18.1c.9 0 1.6.7 1.6 1.6v25.5c0 .9-.7 1.6-1.6 1.6zM35.2 52.3c-.1 0-.2.1-.2.2V78c0 .1.1.2.2.2h18.1c.1 0 .2-.1.2-.2V52.4c0-.1-.1-.2-.2-.2l-18.1.1z"/><path class="st2" d="M36 68h6v6h-6z"/><path transform="rotate(-45.001 46.689 58.69)" class="st2" d="M44.1 56.1h5.1v5.1h-5.1z"/><path class="st2" d="M43 58.8h-5m9 3.2v9m-5 0h6"/><path d="M23 60.2h2.1l2.3 6.9c.2.6.4 1.6.4 1.6s.2-.9.4-1.6l2.4-6.9h2.1l-3.9 10.6h-1.9L23 60.2z" fill="#fff" stroke="#fff" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
M src/main/resources/com/keenwrite/ui/fonts/icons/war.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}.st2,.st3{fill:#265db4;stroke:#265db4;stroke-width:.5;stroke-miterlimit:10}.st3{fill:#c00;stroke:#c00}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.6 6.4h3.2l1.2 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.3-8.9h3.1l1.3 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.2-8.9h3.2l-2.5 14.3h-3.7l-1.1-7.2c-.1-.9-.2-1.7-.2-1.7h-.1s0 .8-.1 1.7l-1.1 7.2H8.1L5.6 6.4zm18.7 0h3.6l3.6 14.3h-3.3l-.6-3h-3l-.6 3h-3.3l3.6-14.3zm2.8 8.6l-.6-2.8c-.2-.9-.4-2.5-.4-2.5H26s-.2 1.5-.4 2.5l-.5 2.8h2zM33 6.4h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5H39l-2-4.8h-.8v4.8H33V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6z" fill="#fff"/><path class="st2" d="M44.2 75.3c7.2-3.7 3.9-7.3 1.5-6.8-.6.1-.8.2-.8.2s.2-.3.6-.5c4.6-1.6 8.1 4.8-1.5 7.3l.2-.2"/><path class="st3" d="M37.8 64.8c1.8 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.1 0 .1-13.1 3.4-6.8 10.6"/><path class="st3" d="M39.8 46.5s4 4-3.8 10.1c-6.2 4.9-1.4 7.7 0 10.9-3.6-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.2"/><path class="st2" d="M31 76.8s-1.5.9 1 1.1c3 .3 4.6.3 7.9-.3 0 0 .9.6 2.1 1-7.4 3.3-16.9-.1-11-1.8m-.9-4.2s-1.6 1.2.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.6 1-9.1 2.6-19.2.2-12.7-2"/><path class="st2" d="M47.7 79.9s1.1.9-1.2 1.6c-4.3 1.3-18 1.7-21.8.1-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.2 23.9-3m-16-11.6s-7 1.7-2.5 2.3c1.9.3 5.7.2 9.2-.1 2.9-.2 5.8-.8 5.8-.8s-1 .4-1.8.9c-7.1 1.9-20.7 1-16.8-.9 3.4-1.6 6.1-1.4 6.1-1.4"/><path class="st2" d="M32.4 85.4c6.9.4 17.5-.2 17.7-3.5 0 0-.5 1.2-5.7 2.2-5.9 1.1-13.1 1-17.5.3.1 0 1 .7 5.5 1"/></svg>
1
<svg height="64" width="48" xmlns="http://www.w3.org/2000/svg"><g stroke-miterlimit="10" stroke-width=".5"><path d="M44.2 75.3c7.2-3.701 3.9-7.3 1.5-6.799-.6.099-.801.2-.801.2s.2-.3.601-.5C50.1 66.6 53.6 73 44 75.5zm0 0" fill="#265db4" stroke="#265db4" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M37.8 64.8c1.801 2.1-.5 4-.5 4s4.7-2.4 2.5-5.5c-2-2.8-3.6-4.2 4.8-9.101 0 .101-13.1 3.401-6.8 10.6" fill="#c00" stroke="#c00" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M39.8 46.499s3.999 4-3.8 10.102c-6.2 4.898-1.4 7.7 0 10.899-3.601-3.3-6.3-6.2-4.5-8.8 2.7-4 9.9-5.9 8.3-12.201" fill="#c00" stroke="#c00" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><g fill="#265db4" stroke="#265db4"><path d="M31 76.8s-1.5.9 1 1.1c3 .299 4.6.299 7.9-.3 0 0 .9.599 2.1 1-7.4 3.3-16.901-.1-11-1.8m-.9-4.2s-1.6 1.199.9 1.5c3.2.3 5.8.4 10.2-.5 0 0 .6.6 1.599 1-9.1 2.6-19.199.2-12.698-2" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M47.7 79.9s1.1.9-1.2 1.599c-4.3 1.302-18 1.702-21.8.101-1.4-.6 1.2-1.4 2-1.6.8-.2 1.3-.1 1.3-.1-1.5-1.1-9.8 2.1-4.2 3 15.3 2.4 27.9-1.199 23.9-3M31.7 68.3s-7 1.702-2.499 2.301c1.9.301 5.699.2 9.2-.101 2.9-.2 5.799-.8 5.799-.8s-1 .4-1.8.901c-7.1 1.9-20.7.999-16.8-.9 3.4-1.6 6.1-1.401 6.1-1.401" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/><path d="M32.399 85.4c6.901.4 17.502-.2 17.7-3.5 0 0-.499 1.2-5.699 2.2-5.899 1.1-13.101 1-17.5.3.1 0 1 .7 5.499 1" transform="matrix(1.63687 0 0 1.62288 -34.986 -75.177)"/></g></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/wav.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.6 6.4h3.1l1.1 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.2-8.9h2.9l1.2 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.1-8.9h3.1l-2.4 14.3H14l-1.1-7.2c-.1-.9-.2-1.7-.2-1.7h-.1s0 .8-.1 1.7l-1 7.2H8L5.6 6.4zm18.3 0h3.4l3.4 14.3h-3.1l-.6-3h-2.9l-.6 3h-3.1l3.5-14.3zm2.6 8.6l-.5-2.9c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.9h1.9zm4.3-8.6h3.4l1.6 8.1c.2.9.3 2.3.3 2.3h.1s.2-1.4.3-2.3l1.6-8.1h3.3l-3.7 14.3h-3.2L30.8 6.4z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/wbk.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.6 6.4h3.2l1.2 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.3-8.9h3.1l1.3 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.2-8.9h3.2l-2.5 14.3h-3.7l-1.1-7.2c-.1-.9-.2-1.7-.2-1.7h-.1s0 .8-.1 1.7l-1.1 7.2H8.1L5.6 6.4zm16.7 0h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3h-4.4V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1zm6.6-11.4h3.3v5.5h.6l2.3-5.5H43l-2.9 6.8 3 7.4h-3.7l-2.3-5.8h-.6v5.8h-3.3V6.4z" fill="#fff"/><path class="st0" d="M19.5 67.1l-4.8-14.8c-.2-.6-.3-.8-.4-.8-.1-.1-.2-.1-.3-.2l-1.7-.5-.1-2.1h9l.2 2.1-1.7.5v.2c0 .2.1.6.3 1l1.8 5.7 3.2-9.5 2.4-.1 2.9 9.5 2-5.7c.1-.4.3-.8.3-1v-.1l-1.5-.4-.1-2.2h7l.2 2.1-1.9.6c-.1 0-.2.1-.3.1 0 .1-.2.2-.3.7l-5.3 14.7-2.5.2-2.7-9.1-3.2 8.9-2.5.2z"/><path d="M42.4 48.6H60v2.8H42.4zm0 7.4H60v2.8H42.4zm0 7.7H60v2.8H42.4zM13 71.5h47v2.8H13zm0 7.6h47v2.8H13z" fill="#999" stroke="#999" stroke-width=".5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/webinfo.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fff}.st2{fill:#bababa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6.3 70.4h2.6l.9 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1-8.9h2.4l1 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l.9-8.9h2.6l-2 14.3h-3l-.9-7.2c-.1-.9-.1-1.7-.1-1.7s0 .8-.1 1.7l-.9 7.2h-3l-2-14.3zm13 0H25v2.9h-3.1V76h2.5v2.9h-2.5v2.9h3.3v2.9h-5.9V70.4zm7.2 0h3.3c2 0 3.4 1.3 3.4 3.7 0 1.2-.4 2.4-1.3 3 1.3.5 1.7 1.9 1.7 3.2 0 3.1-1.6 4.3-3.6 4.3h-3.5V70.4zm3.3 5.6c.5 0 .7-.6.7-1.4 0-.7-.2-1.3-.8-1.3h-.6V76h.7zm.2 5.8c.7 0 .9-.7.9-1.6s-.3-1.5-.8-1.5h-.9v3.1h.8zm4.8-11.4h2.6v14.3h-2.6V70.4zm4.4 0H42l2 6.6c.3 1 .6 2.4.6 2.4h.1s-.1-1.5-.1-2.4v-6.6h2.5v14.3h-2.8l-2-6.6c-.3-1-.5-2.4-.5-2.4h-.1s.1 1.5.1 2.4v6.6h-2.5l-.1-14.3zm9.4 0h5.7v2.9h-3.1v3.1h2.5v2.9h-2.5v5.4h-2.6V70.4zm11.1-.2c3 0 4.7 3.1 4.7 7.3 0 4.2-1.7 7.5-4.7 7.5S55 81.7 55 77.5s1.7-7.3 4.7-7.3zm0 11.6c1.4 0 2-1.8 2-4.3s-.6-4.2-2-4.2-2 1.7-2 4.2.6 4.3 2 4.3z" fill="#666"/><path class="st2" d="M26.8 50.3c2.2-.9 4.5-1.5 6.9-1.6v-6.4h-8.4c.1 2.7.6 5.5 1.5 8zm-4.6-24.6c1 1 2.2 1.8 3.3 2.5 1-2.3 2.3-4.5 3.9-6.5-2.7.8-5.1 2.1-7.2 4zm21 6c-2.2.9-4.5 1.5-6.9 1.6v6.4h8.4c-.1-2.7-.6-5.5-1.5-8zm-9.4 1.5c-2.4-.2-4.8-.7-6.9-1.6-.9 2.6-1.4 5.3-1.5 8.1h8.4v-6.5zm-6-3.9c1.9.8 3.9 1.2 6 1.4v-9.8h-.2l-1.1 1.2c-2.1 2.1-3.6 4.6-4.7 7.2zm16.9 12.9h-8.4v6.4c2.4.2 4.8.7 6.9 1.6.9-2.4 1.4-5.2 1.5-8zm-8.5-11.4c2.1-.2 4.1-.6 6-1.4-1.2-2.7-2.8-5.1-4.7-7.3l-.8-1.1h-.4l-.1 9.8zm11.7-5.2c-2.1-1.8-4.6-3.2-7.3-3.9 1.6 2 2.9 4.2 3.9 6.5 1.2-.7 2.3-1.5 3.4-2.6zM33.8 51.2c-2.1.2-4.1.6-6 1.4 1.2 2.6 2.7 5.1 4.6 7.2l1 1.1h.3l.1-9.7zm-11-11.4c.1-3.2.8-6.2 1.7-9.2-1.5-.8-2.8-1.8-4.2-3.1l-.1-.1c-3 3.3-5 7.6-5.2 12.4h7.8zm24.4 2.4c-.1 3.2-.8 6.2-1.7 9.2 1.5.8 2.8 1.8 4.2 3.1l.2.2c3-3.3 5-7.6 5.3-12.4-.2-.1-8-.1-8-.1zm2.4-14.7c-1.2 1.2-2.7 2.2-4.2 3.1 1.1 2.9 1.7 6 1.7 9.2H55c-.3-4.8-2.2-9.1-5.3-12.4l-.1.1zm-1.8 28.8c-1-1-2.2-1.8-3.3-2.5-1 2.3-2.3 4.5-3.9 6.5 2.7-.8 5.2-2.1 7.2-4zm-27.4-1.8c1.2-1.2 2.7-2.2 4.1-3.1-1.1-2.9-1.7-6-1.8-9.2H15c.3 4.8 2.2 9.1 5.2 12.4l.2-.1zm5.1-.7c-1.2.7-2.3 1.6-3.3 2.5 2.1 1.8 4.6 3.2 7.3 3.9-1.7-1.9-3-4-4-6.4zm16.7-1.1c-1.9-.8-3.9-1.2-6-1.4v9.8h.3l1.1-1.2c2-2.1 3.5-4.7 4.6-7.2z"/><path class="st2" d="M0 94V2C0 .9.9 0 2 0h48c.6 0 1.1.2 1.5.7l20 22.3c.3.4.5.8.5 1.3V94c0 1.1-.9 2-2 2H2c-1.1 0-2-.9-2-2zm68-68.9L49.1 4H4v88h64V25.1z"/><path class="st2" d="M48 26V4c0-1.1.9-2 2-2s2 .9 2 2v20h16c1.1 0 2 .9 2 2s-.9 2-2 2H50c-1.1 0-2-.9-2-2z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M18.785 46.805c3.504-1.43 7.164-2.387 10.985-2.547V34.07H16.398c.16 4.297.954 8.754 2.387 12.735zM11.461 7.64c1.594 1.593 3.504 2.867 5.254 3.98 1.594-3.66 3.664-7.164 6.21-10.348-4.3 1.274-8.12 3.344-11.464 6.368zm33.434 9.554c-3.5 1.43-7.165 2.387-10.985 2.547V29.93h13.375c-.16-4.297-.957-8.754-2.39-12.735zM29.93 19.582c-3.82-.316-7.64-1.113-10.985-2.547A43.883 43.883 0 0 0 16.56 29.93h13.37zm-9.551-6.207c3.023 1.273 6.207 1.91 9.55 2.227V0h-.316L27.86 1.91c-3.343 3.344-5.73 7.324-7.48 11.465zM47.285 33.91H33.91v10.188c3.82.32 7.64 1.117 10.985 2.55 1.433-3.824 2.23-8.28 2.39-12.738zM33.75 15.762c3.344-.32 6.527-.957 9.555-2.23-1.91-4.298-4.457-8.118-7.485-11.622L34.547.16h-.637zm18.629-8.278c-3.344-2.867-7.324-5.097-11.621-6.21a45.734 45.734 0 0 1 6.207 10.347c1.91-1.113 3.66-2.387 5.414-4.137zm-22.45 40.754c-3.343.32-6.527.957-9.55 2.23 1.91 4.137 4.297 8.118 7.324 11.462l1.59 1.75h.477zM12.419 30.09c.16-5.094 1.273-9.871 2.707-14.649-2.39-1.273-4.457-2.863-6.687-4.933l-.16-.16C3.503 15.602.32 22.449 0 30.09zm38.848 3.82c-.16 5.094-1.278 9.871-2.707 14.649 2.386 1.273 4.457 2.863 6.683 4.933l.32.32C60.34 48.56 63.523 41.712 64 34.07c-.32-.16-12.734-.16-12.734-.16zm3.82-23.402c-1.91 1.91-4.3 3.504-6.688 4.933 1.75 4.618 2.707 9.555 2.707 14.649H63.68c-.477-7.64-3.5-14.488-8.438-19.742zm-2.867 45.851c-1.594-1.593-3.504-2.867-5.254-3.98a45.734 45.734 0 0 1-6.207 10.348c4.297-1.274 8.277-3.344 11.46-6.368zM8.598 53.492c1.91-1.91 4.297-3.504 6.527-4.933-1.75-4.618-2.707-9.555-2.867-14.649H0c.477 7.64 3.504 14.488 8.277 19.742zm8.117-1.113c-1.91 1.113-3.66 2.547-5.254 3.98 3.344 2.864 7.324 5.094 11.625 6.207-2.707-3.023-4.777-6.367-6.371-10.187zm26.59-1.754c-3.028-1.273-6.211-1.91-9.555-2.227V64h.48l1.75-1.91c3.184-3.344 5.57-7.485 7.325-11.465zm0 0" fill="#bababa"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/webm.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.6 6.4H8l.9 8.9c.1.7.1 1.6.1 1.6s0-.9.1-1.6l1-8.9h2.3l1 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l.9-8.9H17l-2 14.3h-2.8l-.8-7.2c-.1-.9-.1-1.7-.1-1.7s0 .8-.1 1.7l-.8 7.2H7.5L5.6 6.4zm12.5 0h5.4v2.9h-2.9V12h2.3v2.9h-2.3v2.9h3.1v2.9h-5.5V6.4zm7.1 0h3.1c1.9 0 3.2 1.3 3.2 3.7 0 1.2-.4 2.4-1.2 3 1.2.5 1.6 1.9 1.6 3.2 0 3.1-1.5 4.3-3.3 4.3h-3.3V6.4zm3.2 5.6c.5 0 .7-.6.7-1.4s-.2-1.3-.7-1.3h-.6V12h.6zm.1 5.8c.6 0 .9-.7.9-1.6 0-.9-.2-1.5-.8-1.5h-.9v3.1h.8zm5.3-11.4h2.7l1 6c.1.9.3 2.4.3 2.4s.2-1.5.3-2.4l1-6H42l.7 14.3h-2.3l-.3-6.4c-.1-1.1 0-2.4 0-2.4H40s-.2 1.5-.3 2.4l-.6 4.1h-2.4l-.6-4.1c-.2-.9-.3-2.4-.3-2.4h-.1s.1 1.3 0 2.4l-.3 6.4h-2.3l.7-14.3z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/webp.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.8 6.5H8l1.4 9.8c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.5-9.8h2.1l1.5 9.8c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.4-9.8h2.1l-2.3 14.2h-2.5l-1.3-8.4c-.1-.9-.2-1.9-.2-1.9h-.1s-.1.9-.2 1.9l-1.4 8.4H8.1L5.8 6.5zm14.2 0h6.1v2.2h-3.9v3.8h3.1v2.2h-3.1v3.9h4.1v2.2H20V6.5zm8 0h3.5c2 0 3.5 1.3 3.5 3.7 0 1.3-.6 2.5-1.5 3 1.3.5 1.9 1.8 1.9 3.4 0 2.8-1.6 4.1-3.9 4.1H28V6.5zm3.5 5.8c.7 0 1.2-.8 1.2-1.9s-.5-1.8-1.4-1.8h-1.2v3.7h1.4zm0 6.2c1.2 0 1.6-.9 1.6-2.1 0-1.3-.5-2.1-1.4-2.1h-1.5v4.2h1.3zm5.6-12h3.6c2.2 0 3.8 1.9 3.8 4.6s-1.5 4.7-3.8 4.7h-1.4v4.9h-2.2V6.5zm3.2 7.1c1.2 0 1.9-1 1.9-2.5s-.8-2.5-1.9-2.5h-1.1v5h1.1z" fill="#fff"/><path class="st0" d="M14 48.5v33.9h44V48.5H14zM55.5 51v14.8l-10.5-8-11.5 11.5-8.1-4.5-8.8 7V51h38.9z"/><circle class="st0" cx="23" cy="57.6" r="3.1"/></svg>
1
<svg height="64" width="82" xmlns="http://www.w3.org/2000/svg"><g fill="#3c3"><path d="M0 .094v63.812h82V.094zM77.34 4.8v27.86L57.773 17.6 36.34 39.247l-15.094-8.469L4.844 43.953V4.801zm0 0"/><path d="M22.55 17.223c0 3.222-2.585 5.836-5.777 5.836-3.191 0-5.777-2.614-5.777-5.836s2.586-5.836 5.777-5.836c3.192 0 5.778 2.613 5.778 5.836zm0 0"/></g></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/wma.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.6 6.4h2.9l1.1 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6L11 6.4h2.8l1.2 8.9v1.6h.1s0-.9.1-1.6l1-8.9h2.9l-2.3 14.3h-3.3l-1-7.2c-.1-.9-.1-1.7-.1-1.7h-.1s0 .8-.1 1.7l-1 7.2H7.8L5.6 6.4zm16 0h3.3l1.2 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.2-6h3.3l.8 14.3h-2.7l-.3-6.4c-.1-1.1 0-2.4 0-2.4H29s-.2 1.5-.4 2.4l-.8 4.1H25l-.8-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-2.7l1-14.3zm15.2 0H40l3.2 14.3h-3l-.5-3H37l-.5 3h-3l3.3-14.3zm2.6 8.6l-.5-2.8c-.2-.9-.4-2.5-.4-2.5h-.1s-.2 1.5-.4 2.5l-.5 2.8h1.9z" fill="#fff"/><path class="st0" d="M47 66c-3.1-1.2-6.7.3-8 3.4-1.2 3.1.3 6.7 3.4 8 .6.3 1.3.4 2 .4 3.5.1 6.4-2.6 6.4-6V47.9c-.2 0-.3.1-.5.1-6.8 1.9-13.5 3.9-20.3 5.8-.6.2-.6.5-.6 1v16.8c-.5-.2-.7-.3-1.1-.4-2.5-.9-4.7-.4-6.5 1.4-1.8 1.7-2.3 4.3-1.3 6.6 1.3 3.1 4.9 4.6 8 3.4 2.3-1 3.8-3.2 3.8-5.7V61.3c0-.7.2-.9.9-1.1 3.3-.9 6.6-1.9 10-2.8L48 56v10.4c-.5-.2-.7-.3-1-.4z"/></svg>
1
<svg height="64" width="57" xmlns="http://www.w3.org/2000/svg"><path d="M49.766 32.992c-5.68-2.187-12.278.547-14.66 6.196-2.2 5.652.55 12.21 6.23 14.582 1.102.546 2.383.73 3.668.73 6.414.18 11.726-4.742 11.726-10.938V0c-.363 0-.546.184-.914.184-12.464 3.46-24.742 7.105-37.207 10.57-1.097.363-1.097.91-1.097 1.824V43.2c-.918-.367-1.285-.547-2.016-.73-4.582-1.64-8.617-.73-11.914 2.55-3.3 3.098-4.215 7.84-2.383 12.032 2.383 5.648 8.98 8.383 14.66 6.195 4.22-1.82 6.965-5.832 6.965-10.387V24.426c0-1.278.367-1.64 1.653-2.008 6.046-1.64 12.093-3.461 18.328-5.102l8.797-2.55v18.953c-.918-.364-1.286-.547-1.836-.727zm0 0" fill="#039"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/wmf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#fea500}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.6 6.4h3l1.1 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.2-8.9H14l1.2 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.1-8.9h3l-2.3 14.3h-3.4l-1-7.2c-.1-.9-.1-1.7-.1-1.7h-.1s0 .8-.1 1.7l-1 7.2H7.9L5.6 6.4zm16.3 0h3.3l1.2 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.2-6h3.3l.8 14.3H30l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.8 4.1h-2.9l-.8-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4H21l.9-14.3zm13.4 0h6.6v2.9h-3.5v3.1h2.9v2.9h-2.9v5.4h-3V6.4z" fill="#fff"/><path class="st0" d="M27.1 60.2L18 79.4l1.7 1.7L31 69.8c-.4-.9-.3-2 .5-2.8 1-1 2.5-1 3.5 0s1 2.5 0 3.5c-.7.7-1.9.9-2.8.5L20.9 82.3l1.7 1.7 19.2-9.1L46 63.4 38.6 56l-11.5 4.2zm26.3-2.3L44 48.5c-.8-.8-2-.8-2.8 0L39 50.7c-.8.8-.8 2 0 2.8l9.4 9.4c.8.8 2 .8 2.8 0l2.2-2.2c.8-.8.8-2 0-2.8z"/></svg>
1
<svg height="64" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M16.223 21.805.09 55.844l3.012 3.015 20.035-20.035c-.711-1.594-.532-3.543.886-4.96 1.774-1.774 4.43-1.774 6.204 0 1.773 1.769 1.773 4.429 0 6.202-1.243 1.243-3.368 1.594-4.965.887L5.23 60.984 8.242 64l34.04-16.133L49.73 27.48 36.61 14.36zm46.625-4.075L46.184 1.062c-1.418-1.417-3.547-1.417-4.965 0L37.32 4.966c-1.422 1.418-1.422 3.543 0 4.965l16.664 16.664c1.418 1.418 3.543 1.418 4.965 0l3.899-3.903c1.418-1.418 1.418-3.543 0-4.96zm0 0" fill="#fea500"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/wmv.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#f60}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.6 6.4h2.9l1.1 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6L11 6.4h2.8l1.2 8.9v1.6h.1s0-.9.1-1.6l1-8.9h2.9l-2.3 14.3h-3.3l-1-7.2c-.1-.9-.1-1.7-.1-1.7h-.1s0 .8-.1 1.7l-1 7.2H7.8L5.6 6.4zm16 0h3.3l1.2 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.2-6h3.3l.8 14.3h-2.7l-.3-6.4c-.1-1.1 0-2.4 0-2.4H29s-.2 1.5-.4 2.4l-.8 4.1H25l-.8-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-2.7l1-14.3zm11.8 0h3.2l1.5 8.1c.2.9.3 2.3.3 2.3h.1s.1-1.4.3-2.3l1.5-8.1h3.1l-3.5 14.3h-3L33.4 6.4z" fill="#fff"/><path class="st0" d="M13 83.1h46V47.9H13v35.2zm8.9-2.7h-5.5v-3.9h5.5v3.9zm16.9 0h-5.5v-3.9h5.5v3.9zm11.3-30.1h5.5v4h-5.5v-4zm0 26.1h5.5v3.9h-5.5v-3.9zm-8.5-26.1H47v3.9h-5.5v-3.9zm0 26.1H47v3.9h-5.5l.1-3.9zm-8.4-26.1h5.5v3.9h-5.5v-3.9zm-.8 9.7l7.2 4.1c1.3.8 1.3 2 0 2.8L32.4 71c-1.3.8-2.4.1-2.4-1.4v-8.3c0-1.4 1.1-2.1 2.4-1.3zm-7.7-9.7h5.4v3.9h-5.4v-3.9zm0 26.1h5.4v3.9h-5.4v-3.9zm-8.3-26.1h5.5v4h-5.5v-4z"/></svg>
1
<svg height="64" width="84" xmlns="http://www.w3.org/2000/svg"><path d="M.238 64h83.524V0H.238zm16.16-4.91H6.41V52h9.988zm30.688 0h-9.988V52h9.988zM67.602 4.363h9.988v7.274h-9.988zm0 47.453h9.988v7.094h-9.988zM52.168 4.363h9.805v7.09h-9.985v-7.09zm0 47.453h9.805v7.094h-9.985zM36.914 4.363h9.988v7.09h-9.988zM35.464 22l13.071 7.453c2.363 1.457 2.363 3.637 0 5.094L35.465 42c-2.363 1.453-4.36.184-4.36-2.547v-15.09c0-2.547 1.997-3.816 4.36-2.363zM21.485 4.363h9.805v7.09h-9.805zm0 47.453h9.805v7.094h-9.805zM6.41 4.363h9.988v7.274H6.41zm0 0" fill="#f60"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/woff.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#36454d}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.7 6.5h2L9 16.3c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.5-9.8h2l1.4 9.8c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.3-9.8h2l-2.2 14.2h-2.4L12 12.3c-.1-.9-.2-1.9-.2-1.9h-.1s-.1.9-.2 1.9l-1.3 8.4H7.9L5.7 6.5zm17.8-.3c3 0 4.9 3 4.9 7.3s-1.9 7.4-4.9 7.4c-3 0-4.9-3.1-4.9-7.4 0-4.2 1.9-7.3 4.9-7.3zm0 12.4c1.7 0 2.7-2 2.7-5.1 0-3-1-4.9-2.7-4.9-1.7 0-2.7 1.9-2.7 4.9-.1 3.1.9 5.1 2.7 5.1zM30 6.5h5.6v2.2h-3.5v4.1H35V15h-2.9v5.8H30V6.5zm7 0h5.6v2.2h-3.5v4.1H42V15h-2.9v5.8H37V6.5z" fill="#fff"/><path d="M28.1 68.3h-8.9l-1.1 2.4c-.3.8-.5 1.4-.5 2 0 .7.3 1.2.9 1.5.3.2 1.2.3 2.5.4v.7h-8.4v-.7c.9-.1 1.6-.5 2.2-1.1.6-.6 1.3-1.8 2.1-3.7l9-19.4h.4l9.1 19.9c.9 1.9 1.6 3.1 2.1 3.6.4.4 1 .6 1.8.6v.7H27.2v-.7h.5c1 0 1.7-.1 2.1-.4.3-.2.4-.5.4-.8 0-.2 0-.4-.1-.7 0-.1-.2-.6-.6-1.3l-1.4-3zm-.6-1.3l-3.7-8.4-3.9 8.4h7.6z" fill="#7291a1"/><path class="st0" d="M58.2 59.2l-3.6 11.9-.4 1.5c0 .2-.1.3-.1.4 0 .1.1.3.2.4.1.1.2.2.3.2.3 0 .6-.2 1.1-.6.2-.2.6-.7 1.3-1.6l.6.3c-.9 1.6-1.8 2.7-2.8 3.4-1 .7-2.1 1.1-3.2 1.1-.7 0-1.2-.2-1.6-.5-.4-.4-.6-.8-.6-1.3s.2-1.3.6-2.6l.4-1.5c-1.4 2.4-2.8 4.1-4.1 5.1-.8.6-1.6.9-2.4.9-1.1 0-2-.5-2.5-1.4s-.8-1.9-.8-3.1c0-1.7.5-3.6 1.6-5.8 1.1-2.2 2.5-3.9 4.2-5.3 1.4-1.1 2.8-1.6 4-1.6.7 0 1.2.2 1.7.6.4.4.7 1.1.9 2.1l.7-2.2 4.5-.4zm-5.9 3.5c0-1-.2-1.7-.5-2.1-.2-.3-.5-.4-.9-.4s-.8.2-1.2.5c-.8.7-1.7 2.2-2.7 4.5-1 2.3-1.4 4.2-1.4 5.9 0 .6.1 1.1.3 1.4.2.3.5.4.7.4.6 0 1.1-.3 1.7-.9.8-.9 1.6-2 2.2-3.2 1.2-2.4 1.8-4.4 1.8-6.1z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="48"><path style="stroke:none;fill-rule:nonzero;fill:#7291a1;fill-opacity:1" d="M28.621 33.172h-16.32l-2.012 4.45c-.55 1.483-.918 2.593-.918 3.706 0 1.297.547 2.223 1.649 2.781.55.371 2.203.555 4.582.743v1.293H.203v-1.293c1.652-.188 2.934-.93 4.035-2.04 1.098-1.113 2.383-3.34 3.848-6.859L24.586 0h.73L42 36.879c1.648 3.52 2.934 5.746 3.852 6.672.73.742 1.832 1.113 3.296 1.113v1.297h-22.18v-1.297h.919c1.832 0 3.113-.184 3.847-.742.551-.371.735-.926.735-1.48 0-.372 0-.743-.184-1.301 0-.184-.367-1.11-1.101-2.407zm-1.101-2.406-6.786-15.57-7.148 15.57zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#36454d;fill-opacity:1" d="m83.797 16.309-6.602 22.054-.734 2.778c0 .375-.184.558-.184.742 0 .187.184.558.371.742.184.188.368.371.547.371.551 0 1.102-.371 2.016-1.113.371-.367 1.102-1.297 2.387-2.965l1.097.559c-1.648 2.964-3.3 5.003-5.132 6.3-1.833 1.297-3.852 2.04-5.864 2.04-1.285 0-2.203-.372-2.933-.93-.735-.742-1.102-1.485-1.102-2.407 0-.93.367-2.41 1.102-4.82l.73-2.781c-2.562 4.45-5.133 7.601-7.516 9.453C60.516 47.442 59.05 48 57.582 48c-2.016 0-3.668-.926-4.582-2.594-.918-1.668-1.465-3.523-1.465-5.746 0-3.152.914-6.672 2.934-10.75 2.011-4.074 4.582-7.226 7.695-9.82 2.566-2.04 5.133-2.965 7.332-2.965 1.285 0 2.203.367 3.121 1.11.73.742 1.281 2.038 1.649 3.89l1.28-4.074zM72.98 22.797c0-1.856-.367-3.152-.918-3.895-.367-.554-.914-.742-1.648-.742-.734 0-1.469.375-2.2.93-1.464 1.297-3.116 4.074-4.948 8.336-1.832 4.265-2.57 7.785-2.57 10.937 0 1.11.183 2.035.554 2.594.363.559.914.742 1.281.742 1.098 0 2.016-.558 3.117-1.668 1.465-1.668 2.934-3.707 4.032-5.93 2.199-4.449 3.3-8.156 3.3-11.304zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/woff2.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#36454d}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.7 6.5h1.7l1.1 9.8c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6L10 6.5h1.6l1.1 9.8c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1-9.8h1.7l-1.8 14.2h-2l-1-8.4c-.1-.9-.1-1.9-.1-1.9h-.1s0 .9-.2 1.9l-1.1 8.4h-2L5.7 6.5zm14.6-.3c2.5 0 4 3 4 7.3s-1.6 7.4-4 7.4c-2.5 0-4-3.1-4-7.4 0-4.2 1.5-7.3 4-7.3zm0 12.4c1.4 0 2.2-2 2.2-5.1 0-3-.8-4.9-2.2-4.9-1.4 0-2.3 1.9-2.3 4.9 0 3.1.9 5.1 2.3 5.1zm5.4-12.1h4.6v2.2h-2.9v4.1h2.4V15h-2.4v5.8h-1.7V6.5zm5.8 0h4.6v2.2h-2.9v4.1h2.4V15h-2.4v5.8h-1.7V6.5zM37 19.4c0-4.8 3.4-5.5 3.4-8.9 0-1.2-.5-1.9-1.2-1.9-.5 0-1 .4-1.3 1l-1.2-1.4c.5-1.1 1.5-2 2.7-2 1.5 0 2.7 1.4 2.7 4 0 4.3-3.3 5.5-3.4 8.3h3.5v2.2H37v-1.3z" fill="#fff"/><path d="M28.1 68.3h-8.9l-1.1 2.4c-.3.8-.5 1.4-.5 2 0 .7.3 1.2.9 1.5.3.2 1.2.3 2.5.4v.7h-8.4v-.7c.9-.1 1.6-.5 2.2-1.1.6-.6 1.3-1.8 2.1-3.7l9-19.4h.4l9.1 19.9c.9 1.9 1.6 3.1 2.1 3.6.4.4 1 .6 1.8.6v.7H27.2v-.7h.5c1 0 1.7-.1 2.1-.4.3-.2.4-.5.4-.8 0-.2 0-.4-.1-.7 0-.1-.2-.6-.6-1.3l-1.4-3zm-.6-1.3l-3.7-8.4-3.9 8.4h7.6z" fill="#7291a1"/><path class="st0" d="M58.2 59.2l-3.6 11.9-.4 1.5c0 .2-.1.3-.1.4 0 .1.1.3.2.4.1.1.2.2.3.2.3 0 .6-.2 1.1-.6.2-.2.6-.7 1.3-1.6l.6.3c-.9 1.6-1.8 2.7-2.8 3.4-1 .7-2.1 1.1-3.2 1.1-.7 0-1.2-.2-1.6-.5-.4-.4-.6-.8-.6-1.3s.2-1.3.6-2.6l.4-1.5c-1.4 2.4-2.8 4.1-4.1 5.1-.8.6-1.6.9-2.4.9-1.1 0-2-.5-2.5-1.4s-.8-1.9-.8-3.1c0-1.7.5-3.6 1.6-5.8 1.1-2.2 2.5-3.9 4.2-5.3 1.4-1.1 2.8-1.6 4-1.6.7 0 1.2.2 1.7.6.4.4.7 1.1.9 2.1l.7-2.2 4.5-.4zm-5.9 3.5c0-1-.2-1.7-.5-2.1-.2-.3-.5-.4-.9-.4s-.8.2-1.2.5c-.8.7-1.7 2.2-2.7 4.5-1 2.3-1.4 4.2-1.4 5.9 0 .6.1 1.1.3 1.4.2.3.5.4.7.4.6 0 1.1-.3 1.7-.9.8-.9 1.6-2 2.2-3.2 1.2-2.4 1.8-4.4 1.8-6.1z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="48"><path style="stroke:none;fill-rule:nonzero;fill:#7291a1;fill-opacity:1" d="M28.621 33.172h-16.32l-2.012 4.45c-.55 1.483-.918 2.593-.918 3.706 0 1.297.547 2.223 1.649 2.781.55.371 2.203.555 4.582.743v1.293H.203v-1.293c1.652-.188 2.934-.93 4.035-2.04 1.098-1.113 2.383-3.34 3.848-6.859L24.586 0h.73L42 36.879c1.648 3.52 2.934 5.746 3.852 6.672.73.742 1.832 1.113 3.296 1.113v1.297h-22.18v-1.297h.919c1.832 0 3.113-.184 3.847-.742.551-.371.735-.926.735-1.48 0-.372 0-.743-.184-1.301 0-.184-.367-1.11-1.101-2.407zm-1.101-2.406-6.786-15.57-7.148 15.57zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#36454d;fill-opacity:1" d="m83.797 16.309-6.602 22.054-.734 2.778c0 .375-.184.558-.184.742 0 .187.184.558.371.742.184.188.368.371.547.371.551 0 1.102-.371 2.016-1.113.371-.367 1.102-1.297 2.387-2.965l1.097.559c-1.648 2.964-3.3 5.003-5.132 6.3-1.833 1.297-3.852 2.04-5.864 2.04-1.285 0-2.203-.372-2.933-.93-.735-.742-1.102-1.485-1.102-2.407 0-.93.367-2.41 1.102-4.82l.73-2.781c-2.562 4.45-5.133 7.601-7.516 9.453C60.516 47.442 59.05 48 57.582 48c-2.016 0-3.668-.926-4.582-2.594-.918-1.668-1.465-3.523-1.465-5.746 0-3.152.914-6.672 2.934-10.75 2.011-4.074 4.582-7.226 7.695-9.82 2.566-2.04 5.133-2.965 7.332-2.965 1.285 0 2.203.367 3.121 1.11.73.742 1.281 2.038 1.649 3.89l1.28-4.074zM72.98 22.797c0-1.856-.367-3.152-.918-3.895-.367-.554-.914-.742-1.648-.742-.734 0-1.469.375-2.2.93-1.464 1.297-3.116 4.074-4.948 8.336-1.832 4.265-2.57 7.785-2.57 10.937 0 1.11.183 2.035.554 2.594.363.559.914.742 1.281.742 1.098 0 2.016-.558 3.117-1.668 1.465-1.668 2.934-3.707 4.032-5.93 2.199-4.449 3.3-8.156 3.3-11.304zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/wps.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#6190aa}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zM5.6 6.4h3.2l1.2 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.3-8.9h3.1l1.3 8.9c.1.7.1 1.6.1 1.6h.1s0-.9.1-1.6l1.2-8.9h3.2l-2.5 14.3h-3.7l-1.1-7.2c-.1-.9-.2-1.7-.2-1.7h-.1s0 .8-.1 1.7l-1.1 7.2H8.1L5.6 6.4zm16.7 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm7.6 3.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path class="st0" d="M19.5 67.1l-4.8-14.8c-.2-.6-.3-.8-.4-.8-.1-.1-.2-.1-.3-.2l-1.7-.5-.1-2.1h9l.2 2.1-1.7.5v.2c0 .2.1.6.3 1l1.8 5.7 3.2-9.5 2.4-.1 2.9 9.5 2-5.7c.1-.4.3-.8.3-1v-.1l-1.5-.4-.1-2.2h7l.2 2.1-1.9.6c-.1 0-.2.1-.3.1 0 .1-.2.2-.3.7l-5.3 14.7-2.5.2-2.7-9.1-3.2 8.9-2.5.2z"/><path d="M42.4 48.6H60v2.8H42.4zm0 7.4H60v2.8H42.4zm0 7.7H60v2.8H42.4zM13 71.5h47v2.8H13zm0 7.6h47v2.8H13z" fill="#6190aa" stroke="#6190aa" stroke-width=".5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="60"><path style="stroke:none;fill-rule:nonzero;fill:#6190aa;fill-opacity:1" d="m12.762 33.262-8.39-26.09c-.349-1.059-.524-1.41-.7-1.41-.176-.176-.352-.176-.527-.352l-2.97-.883L0 .824h15.734l.348 3.703-2.973.883v.352c0 .351.176 1.058.528 1.761L16.78 17.57 22.38.824 26.57.648l5.07 16.747 3.497-10.051c.175-.703.527-1.41.527-1.762V5.41l-2.621-.707-.176-3.879h12.235l.351 3.703-3.32 1.059c-.176 0-.352.176-.528.176 0 .176-.347.351-.523 1.234l-9.266 25.91-4.37.356-4.716-16.043-5.597 15.687zm0 0"/><path style="fill-rule:nonzero;fill:#6190aa;fill-opacity:1;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#6190aa;stroke-opacity:1;stroke-miterlimit:10" d="M42.4 48.6H60v2.8H42.4zm0 7.401H60V58.8H42.4zm0 7.7H60V66.5H42.4zm-29.4 7.8h47v2.798H13zm0 7.598h47v2.8H13zm0 0" transform="matrix(1.74818 0 0 1.76287 -21.328 -85.027)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/wsf.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm0-22.5l4.2-7.9c.5-.9.8-1.3.8-1.3s-.3.1-.8.1h-4v-3h8.7v2.2l-4.2 8c-.5.9-.8 1.3-.8 1.3s.3-.1.8-.1H15v2.9H6v-2.2zm12.8-1.8c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.3-.5-1.3-.9-2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zm10-10.3h3.3v5.8h3.2V6.4h3.3v14.3h-3.3V15h-3.2v5.7h-3.3V6.4z" fill="#fff"/><path d="M30.8 61.4h10.9v2.7H30.8v-2.7zm0 5.4h10.9v2.7H30.8v-2.7zm0 5.5h10.9V75H30.8v-2.7zm19-24.4H28.1c-3 0-5.4 2.4-5.4 5.4v24.4h-5.4c0 3 2.4 5.4 5.4 5.4h21.7c3 0 5.4-2.4 5.4-5.4V56h5.4v-2.7c0-3-2.4-5.4-5.4-5.4zm-2.7 29.3c0 1.8-1.4 3.2-3.2 3.2H24c1.3-.9 1.3-2.7 1.3-2.7V53.3c0-1.5 1.2-2.7 2.7-2.7s2.7 1.2 2.7 2.7V56H47l.1 21.2zM33.5 53.3v-2.7h16.3c2.5 0 2.7 1.6 2.7 2.7h-19z" fill="#999" stroke="#999" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xaml.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm2.8-27.5l-3-7h2.5L9.5 10c.3.8.5 1.7.5 1.7s.2-.9.5-1.7L12 6.5h2.4l-3 7 3.1 7.2h-2.4l-1.4-3.8c-.3-.8-.5-1.6-.5-1.6s-.2.8-.5 1.6l-1.4 3.8H5.7l3.1-7.2zm9.3-7h2.4l3.4 14.2h-2.2l-.8-3.7h-3.2l-.8 3.7h-2.2l3.4-14.2zm2.5 8.5l-.8-3.8c-.2-.8-.4-2.2-.4-2.2h-.1s-.2 1.4-.4 2.2l-.8 3.8h2.5zm5-8.5H28l1.7 6.9c.2.9.4 2.2.4 2.2h.1s.2-1.3.4-2.2l1.7-6.9h2.4l.8 14.2h-2.1l-.4-7.9c-.1-.9 0-2.2 0-2.2h-.1s-.2 1.4-.4 2.3l-1.4 5.4h-2.2l-1.4-5.4c-.2-.8-.4-2.3-.4-2.3H27s.1 1.3 0 2.2l-.4 7.9h-2.1l1.1-14.2zm12 0h2.2v12H44v2.2h-6.4V6.5z" fill="#fff"/><path d="M23.7 76c-.5 0-1.1-.2-1.5-.6L13.9 67c-.8-.8-.8-2.1 0-3l8.4-8.4c.8-.8 2.1-.8 3 0 .8.8.8 2.1 0 3l-6.9 6.9 6.9 6.9c.8.8.8 2.1 0 3-.5.4-1.1.6-1.6.6zm25.1 0c-.5 0-1.1-.2-1.5-.6-.8-.8-.8-2.1 0-3l6.9-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 3 0l8.4 8.4c.8.8.8 2.1 0 3l-8.4 8.4c-.4.4-1 .6-1.5.6zm-16.7 4.1c-.2 0-.4 0-.7-.1-1.1-.4-1.7-1.5-1.3-2.6l8.4-25.1c.4-1.1 1.5-1.7 2.6-1.3 1.1.4 1.7 1.5 1.3 2.6L34 78.7c-.2.9-1.1 1.4-1.9 1.4z" fill="#999" stroke="#999" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="55"><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M11.143 25.867c-.5 0-1.1-.2-1.502-.6l-8.298-8.4c-.8-.799-.8-2.1 0-3.001l8.398-8.4c.8-.798 2.101-.798 3.002 0 .8.801.8 2.1 0 3.001l-6.901 6.9 6.9 6.9c.8.8.8 2.098 0 3-.5.4-1.1.6-1.6.6zm25.101 0c-.503 0-1.102-.2-1.502-.6-.8-.8-.8-2.1 0-3l6.901-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 2.998 0l8.4 8.399c.801.8.801 2.102 0 3l-8.4 8.4c-.4.4-.999.6-1.5.6zm-16.7 4.1c-.202 0-.403 0-.7-.1-1.102-.399-1.7-1.5-1.3-2.599l8.398-25.1c.402-1.101 1.5-1.702 2.6-1.302 1.1.4 1.7 1.502 1.3 2.6l-8.4 25.101c-.198.901-1.1 1.4-1.899 1.4zm0 0" transform="matrix(1.74792 0 0 1.75607 0 .53)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xcf.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#3c3}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm3-27.4L5.5 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H5.7L9 13.6zm15.4-7.5c1.3 0 2.6.4 3.6 1.2l-1.4 2.8c-.4-.5-1.3-.9-2.1-.9-2.1 0-3.2 1.9-3.2 4.2s1.2 4.4 3.2 4.4c1 0 1.7-.5 2.3-1l1.4 2.8c-.9.7-2 1.3-3.9 1.3-4 0-6.3-3.1-6.3-7.4 0-4.2 2.4-7.4 6.4-7.4zm6.5.3H38v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M47.6 71.7c.4.2.9.4 1.3.7 1.3.8 2.5 1.6 3.7 2.4.2.1.4.2.6.1 1.4-.3 2.9.5 3.3 1.9.3.9.4 1.8.5 2.8.1 1.1.1 2.3.2 3.5-2-.5-3.9-1.1-5.3-2.6-.4-.4-.5-1-.8-1.5-.1-.1-.2-.3-.3-.3-2.6-.6-5.1-1.5-7.5-2.7-.1-.1-.4-.1-.5 0-2.4 1.2-5 1.7-7.7 1.5-3.6-.2-6.9-1.4-10.1-2.9-.5-.3-1.1-.6-1.6-.9 2.5-1.2 3.6-3.2 3.6-5.9-.6-.1-1.2-.1-1.7-.2-.1.5-.1 1.1-.2 1.7-.6 2.2-2.7 3.4-5 2.8-3-.8-5.7-4.3-5.4-7.7.2-2.5 2.4-4.1 4.8-3.5.4.1.8.2 1.2.4.4.2.7.4 1.1.6.3-.5.5-1.1.8-1.6.1-.1 0-.3 0-.4v-8h.1c.1.1.2.2.3.4.9 1.3 1.7 2.6 2.8 3.7 1.3 1.2 2.6 2.2 4.3 2.6.5.1.9.1 1.4-.2 1.9-1.2 3.8-1.3 5.8-.3.1.1.3.1.5.1 2.8-.7 5.4-1.9 7.5-4 .9-.9 1.6-2 2.1-3.3.2-.6.5-1.1.8-1.7.3-.5.7-.8 1.2-.7.6.1.9.5 1 1 .2 1 .4 2 .5 3 .1 1.8.1 3.6.1 5.4-.1 3.7-.5 7.4-1.8 10.9-.6.7-1.1 1.8-1.6 2.9zm-5-.2c.4-.6.4-1.2.1-1.8-.5-.9-1.3-1.6-2.3-2h-.1l.3.6c.1.2.2.4.2.7.2.8.1 1.2-.7 1.5-.5.2-1 .3-1.4.4-2.4.4-4.9.4-7.3.3h-.7c0 .1.1.1.1.1 2.4.8 4.8 1.4 7.3 1.6.9.1 1.9.1 2.8-.2.3-.1.5 0 .7.1 2.7 1.8 5.6 3.1 8.8 3.9.6.2.6.2.9-.4.1-.1.1-.2.2-.3-2.7-2-5.7-3.4-8.9-4.5zm-8.5-9.4c-.1 1.2.1 1.7.8 1.9.6.2 1.3 0 1.5-.5.2-.3.2-.7.2-1.1-.1-.3-.4-.6-.6-.9 1.2.1 1.9.8 2.3 1.9.3-1-.2-3-1.7-4-1.6-1-3.8-.8-5.1.6-1.3 1.4-1.4 3.5-.4 5.1 1 1.5 3 2 3.9 1.6-1.1-.4-1.8-1.2-1.9-2.4 0-.9.3-1.6 1-2.2zm-7.3 3.8c-1.8-1-2.2-2.9-.9-3.8-.2.8 0 1.3.6 1.6.4.2 1.1.1 1.3-.4.2-.3.3-.7.2-1-.1-.3-.4-.5-.6-.9.5.2.9.3 1.3.5.3-.9.3-.9 0-1.3-.9-.8-1.9-1.1-3-.8-1.2.3-1.9 1.1-2.2 2.3-.1.5-.2 1 .1 1.5l.9 1.5c.1.1.1.3.3.3.5.4 1.2.5 2 .5zm-10.5-1.2c0 .5.2 1.1.6 1.6.6.7 1.6.7 2.3 0 1-1 .9-2.7-.2-3.6-.3-.3-.7-.4-1.1-.3-1 .1-1.7 1-1.6 2.3z"/></svg>
1
<svg height="64" width="78" xmlns="http://www.w3.org/2000/svg"><path d="M60.387 42.926c.734.367 1.648.738 2.383 1.293 2.382 1.48 4.585 2.957 6.785 4.437.367.184.734.371 1.101.184 2.567-.555 5.317.926 6.051 3.512.55 1.664.734 3.328.918 5.18.184 2.03.184 4.25.367 6.468-3.668-.926-7.152-2.035-9.719-4.805-.734-.742-.918-1.851-1.468-2.773-.184-.188-.368-.555-.551-.555A61.383 61.383 0 0 1 52.5 50.875c-.184-.188-.734-.188-.918 0-4.398 2.219-9.168 3.14-14.121 2.773-6.602-.37-12.652-2.59-18.52-5.363-.918-.555-2.02-1.11-2.937-1.664 4.586-2.219 6.605-5.914 6.605-10.906-1.101-.184-2.203-.184-3.12-.371-.184.926-.184 2.035-.368 3.144-1.098 4.067-4.95 6.285-9.168 5.176C4.453 42.184-.5 35.714.051 29.43c.367-4.621 4.402-7.578 8.8-6.47.735.185 1.47.368 2.204.74.734.366 1.28.738 2.015 1.109.551-.926.918-2.036 1.47-2.957.183-.188 0-.555 0-.743V6.32h.183c.183.184.367.371.55.739 1.649 2.406 3.118 4.808 5.133 6.843 2.383 2.215 4.77 4.067 7.887 4.805.918.184 1.648.184 2.566-.371 3.485-2.219 6.97-2.402 10.637-.555.184.188.55.188.918.188 5.133-1.297 9.902-3.512 13.754-7.395 1.652-1.664 2.934-3.699 3.852-6.101.367-1.11.917-2.035 1.468-3.145.547-.922 1.282-1.476 2.2-1.293 1.101.184 1.648.926 1.832 1.848.367 1.851.734 3.699.917 5.547.184 3.328.184 6.656.184 9.984-.184 6.84-.918 13.68-3.3 20.149-1.102 1.296-2.016 3.328-2.934 5.363zm-9.172-.371c.734-1.11.734-2.22.183-3.328-.914-1.664-2.382-2.957-4.214-3.696H47l.547 1.11c.183.367.367.738.367 1.293.367 1.48.184 2.218-1.281 2.773-.918.371-1.836.555-2.57.738-4.399.739-8.985.739-13.387.555h-1.281c0 .184.183.184.183.184 4.399 1.48 8.8 2.59 13.387 2.96 1.648.184 3.484.184 5.133-.37.55-.184.918 0 1.285.183 4.953 3.328 10.27 5.73 16.137 7.211 1.101.371 1.101.371 1.652-.738.183-.188.183-.371.367-.555-4.953-3.7-10.453-6.285-16.324-8.32zm-15.586-17.38c-.184 2.22.184 3.145 1.465 3.516 1.101.368 2.386 0 2.754-.925.367-.555.367-1.293.367-2.036-.184-.554-.735-1.109-1.102-1.664 2.2.188 3.485 1.48 4.219 3.516.547-1.852-.367-5.547-3.117-7.395-2.938-1.851-6.973-1.48-9.356 1.11-2.382 2.586-2.566 6.469-.734 9.426 1.836 2.773 5.504 3.699 7.152 2.957-2.015-.739-3.3-2.215-3.484-4.434 0-1.664.55-2.96 1.836-4.07zm-13.387 7.028c-3.3-1.848-4.035-5.363-1.652-7.027-.367 1.48 0 2.406 1.101 2.96.735.368 2.016.184 2.383-.741.367-.555.551-1.293.367-1.848s-.734-.926-1.101-1.664c.918.37 1.652.555 2.387.926.546-1.664.546-1.664 0-2.403-1.653-1.48-3.485-2.035-5.504-1.48-2.2.554-3.485 2.035-4.035 4.25-.184.926-.368 1.851.183 2.773l1.652 2.774c.184.187.184.554.551.554.914.743 2.2.926 3.668.926zM2.984 29.984c0 .926.368 2.036 1.102 2.957 1.098 1.293 2.934 1.293 4.219 0 1.832-1.847 1.648-4.992-.367-6.656-.551-.555-1.286-.738-2.02-.555-1.832.188-3.117 1.852-2.934 4.254zm0 0" fill="#3c3"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xfl.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#d10407}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm3-27.4L5.5 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H5.7L9 13.6zm9.8-7.2h7.1v2.9h-3.8v3.1h3.1v2.9h-3.1v5.4h-3.3V6.4zm10.1 0h3.3v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><path d="M28.2 54v10.1h8.5v2.6h-8.5v13.7h-3.9v-29h13.3V54h-9.4zm14.4 26.3V51.6h3.7v28.7h-3.7z" fill="#d10407" stroke="#d10407" stroke-width="1.25" stroke-miterlimit="10"/></svg>
1
<svg height="63" width="49" xmlns="http://www.w3.org/2000/svg"><path d="M4.524 3.224v10.102h8.5v2.598h-8.5v13.7h-3.9V.626h13.301v2.598zm14.402 26.3V.826h3.7v28.7zm0 0" fill="#d10407" stroke="#d10407" stroke-miterlimit="10" stroke-width="1.25" transform="matrix(2.10753 0 0 2.07742 0 .079)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xlm.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1f7244}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm3-27.4L5.5 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H5.7L9 13.6zm9.8-7.2h3.3v11.4h4.3v2.9h-7.6V6.4zm10.8 0h3.6l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.2-6.4c-.1-1.1 0-2.4 0-2.4s-.2 1.5-.4 2.4l-.9 4.1h-3.2l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l.9-14.3z" fill="#fff"/><path class="st0" d="M46.8 49.2H59v8.1H46.8zm0 12.5H59v8.1H46.8zm0 12.4H59v8.1H46.8zm-16.5 0h12.2v8.1H30.3zm-16.5 0H26v8.1H13.8zm27.1-4.8l-8-10.1 7.3-9.2H33l-3.8 5-3.5-5h-7.5l7.4 9.4-7.8 9.9h7.3l4.1-5.5 4.1 5.5z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xls.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1f7244}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm3-27.4L5.5 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H5.7L9 13.6zm9.8-7.2h3.3v11.4h4.3v2.9h-7.6V6.4zm11 10.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.3-.5-1.3-.9-2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8z" fill="#fff"/><path class="st0" d="M46.8 49.2H59v8.1H46.8zm0 12.5H59v8.1H46.8zm0 12.4H59v8.1H46.8zm-16.5 0h12.2v8.1H30.3zm-16.5 0H26v8.1H13.8zm27.1-4.8l-8-10.1 7.3-9.2H33l-3.8 5-3.5-5h-7.5l7.4 9.4-7.8 9.9h7.3l4.1-5.5 4.1 5.5z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xlsm.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1f7244}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm2.4-27.4L5.5 6.4h3.1l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3.1l-2.9 7.2 2.8 7.1h-3l-.9-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3h-3l2.7-7.1zM16 6.4h2.8v11.4h3.7v2.9H16V6.4zm8.5 10.3c.5.6 1.2 1.2 2 1.2.7 0 1.1-.6 1.1-1.2 0-2-4-2.1-4-6.2 0-2.4 1.4-4.3 3.9-4.3 1 0 2.1.3 2.9 1l-1 2.9c-.4-.4-1.2-.9-1.8-.9-.8 0-1.1.6-1.1 1.2 0 2.1 4.1 2 4.1 6.1 0 2.3-1.3 4.4-3.8 4.4-1.2 0-2.4-.5-3.4-1.4l1.1-2.8zm8-10.3h3.1l1.1 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.1-6h3.1l.8 14.3H40l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.7 4.1h-2.7l-.7-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.3 6.4h-2.6l.8-14.3z" fill="#fff"/><path class="st0" d="M46.8 49.2H59v8.1H46.8zm0 12.5H59v8.1H46.8zm0 12.4H59v8.1H46.8zm-16.5 0h12.2v8.1H30.3zm-16.5 0H26v8.1H13.8zm27.1-4.8l-8-10.1 7.3-9.2H33l-3.8 5-3.5-5h-7.5l7.4 9.4-7.8 9.9h7.3l4.1-5.5 4.1 5.5z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xlsx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1f7244}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm2.6-27.4L5.5 6.4h3.3l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9H15l-3.1 7.2 3 7.1h-3.2l-1-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3H5.6l3-7.1zm8-7.2h3v11.4h3.9v2.9h-6.8V6.4zm9 10.3c.5.6 1.3 1.2 2.1 1.2s1.2-.6 1.2-1.2c0-2-4.3-2.1-4.3-6.2 0-2.4 1.5-4.3 4.1-4.3 1.1 0 2.2.3 3.1 1l-1.1 2.9c-.4-.4-1.3-.9-1.9-.9-.8 0-1.2.6-1.2 1.2 0 2.1 4.3 2 4.3 6.1 0 2.3-1.3 4.4-4 4.4-1.3 0-2.6-.5-3.6-1.4l1.3-2.8zm10.2-3.1l-3.1-7.2H36l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3.2l-3.1 7.2 3 7.1h-3.2l-1-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3h-3.2l3.1-7.1z" fill="#fff"/><path class="st0" d="M46.8 49.2H59v8.1H46.8zm0 12.5H59v8.1H46.8zm0 12.4H59v8.1H46.8zm-16.5 0h12.2v8.1H30.3zm-16.5 0H26v8.1H13.8zm27.1-4.8l-8-10.1 7.3-9.2H33l-3.8 5-3.5-5h-7.5l7.4 9.4-7.8 9.9h7.3l4.1-5.5 4.1 5.5z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xlt.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1f7244}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm3-27.4L5.5 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H5.7L9 13.6zm9.8-7.2h3.3v11.4h4.3v2.9h-7.6V6.4zm10.9 2.9h-3.1V6.4h9.6v2.9H33v11.4h-3.3V9.3z" fill="#fff"/><path class="st0" d="M46.8 49.2H59v8.1H46.8zm0 12.5H59v8.1H46.8zm0 12.4H59v8.1H46.8zm-16.5 0h12.2v8.1H30.3zm-16.5 0H26v8.1H13.8zm27.1-4.8l-8-10.1 7.3-9.2H33l-3.8 5-3.5-5h-7.5l7.4 9.4-7.8 9.9h7.3l4.1-5.5 4.1 5.5z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xltm.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1f7244}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm2.4-27.4L5.5 6.4h3.1l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3.1l-2.9 7.2 2.8 7.1h-3l-.9-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3h-3l2.7-7.1zM16 6.4h2.8v11.4h3.7v2.9H16V6.4zm8.4 2.9h-2.7V6.4h8.1v2.9h-2.7v11.4h-2.8V9.3zm7.3-2.9h3.1l1.1 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.1-6H41l.8 14.3h-2.6l-.3-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.7 4.1H35l-.7-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.3 6.4h-2.6l.8-14.3z" fill="#fff"/><path class="st0" d="M46.8 49.2H59v8.1H46.8zm0 12.5H59v8.1H46.8zm0 12.4H59v8.1H46.8zm-16.5 0h12.2v8.1H30.3zm-16.5 0H26v8.1H13.8zm27.1-4.8l-8-10.1 7.3-9.2H33l-3.8 5-3.5-5h-7.5l7.4 9.4-7.8 9.9h7.3l4.1-5.5 4.1 5.5z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xltx.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#1f7244}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm2.6-27.4L5.5 6.4h3.3l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9H15l-3.1 7.2 3 7.1h-3.2l-1-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3H5.6l3-7.1zm8.2-7.2h3v11.4h3.9v2.9h-6.8V6.4zm9 2.9H23V6.4h8.6v2.9h-2.8v11.4h-2.9V9.3zm9.7 4.3l-3.1-7.2h3.3l1 2.9c.3.9.5 1.8.5 1.8s.2-.9.5-1.8l1-2.9h3.2L39 13.6l3 7.1h-3.2l-1-3c-.3-.9-.5-1.7-.5-1.7s-.2.8-.5 1.7l-1 3h-3.2l2.9-7.1z" fill="#fff"/><path class="st0" d="M46.8 49.2H59v8.1H46.8zm0 12.5H59v8.1H46.8zm0 12.4H59v8.1H46.8zm-16.5 0h12.2v8.1H30.3zm-16.5 0H26v8.1H13.8zm27.1-4.8l-8-10.1 7.3-9.2H33l-3.8 5-3.5-5h-7.5l7.4 9.4-7.8 9.9h7.3l4.1-5.5 4.1 5.5z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="62"><path style="stroke:none;fill-rule:nonzero;fill:#1f7244;fill-opacity:1" d="M61.328.137H84v15.152H61.328zm0 23.383H84v15.152H61.328zm0 23.19H84v15.153H61.328zm-30.664 0h22.672v15.153H30.664zM0 46.71h22.672v15.153H0zm50.363-8.98L35.496 18.84 49.06 1.633H35.684l-7.067 9.351-6.5-9.347H8.18l13.746 17.578L7.434 37.73H21l7.617-10.285 7.621 10.285zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xml.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#666}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm3-27.4L5.5 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H5.7L9 13.6zm10.3-7.2H23l1.3 6c.2.9.4 2.4.4 2.4h.1s.2-1.5.4-2.4l1.3-6h3.6l.9 14.3h-3l-.4-6.4c-.1-1.1 0-2.4 0-2.4h-.1s-.2 1.5-.4 2.4l-.9 4.1H23l-.9-4.1c-.2-.9-.4-2.4-.4-2.4h-.1s.1 1.3 0 2.4l-.4 6.4h-3l1.1-14.3zm15.1 0h3.3v11.4H42v2.9h-7.6V6.4z" fill="#fff"/><path d="M23.5 76c-.5 0-1.1-.2-1.5-.6L13.6 67c-.8-.8-.8-2.1 0-3l8.4-8.4c.8-.8 2.1-.8 3 0 .8.8.8 2.1 0 3l-6.9 6.9 6.9 6.9c.8.8.8 2.1 0 3-.5.4-1 .6-1.5.6zm25 0c-.5 0-1.1-.2-1.5-.6-.8-.8-.8-2.1 0-3l6.9-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 3 0l8.4 8.4c.8.8.8 2.1 0 3L50 75.4c-.4.4-.9.6-1.5.6zm-16.7 4.1c-.2 0-.4 0-.7-.1-1.1-.4-1.7-1.5-1.3-2.6l8.4-25.1c.4-1.1 1.5-1.7 2.6-1.3s1.7 1.5 1.3 2.6l-8.4 25.1c-.2.9-1 1.4-1.9 1.4z" fill="#666" stroke="#666" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="55"><path style="fill-rule:nonzero;fill:#666;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#666;stroke-opacity:1;stroke-miterlimit:10" d="M11.241 25.867c-.498 0-1.1-.2-1.5-.6l-8.398-8.4c-.8-.799-.8-2.1 0-3.001l8.398-8.4c.8-.798 2.101-.798 3.002 0 .8.801.8 2.1 0 3.001l-6.901 6.9 6.9 6.9c.8.8.8 2.098 0 3-.5.4-.998.6-1.499.6zm25 0c-.5 0-1.099-.2-1.499-.6-.8-.8-.8-2.1 0-3l6.901-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 2.998 0l8.4 8.399c.801.8.801 2.102 0 3l-8.4 8.4c-.4.4-.898.6-1.5.6zm-16.698 4.1c-.2 0-.402 0-.7-.1-1.1-.399-1.7-1.5-1.3-2.599l8.399-25.1c.402-1.101 1.5-1.702 2.6-1.302 1.1.4 1.7 1.502 1.3 2.6l-8.4 25.101c-.198.901-1 1.4-1.899 1.4zm0 0" transform="matrix(1.74792 0 0 1.75607 0 .53)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xpi.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm3-27.4L5.5 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H5.7L9 13.6zm9.8-7.2h4.5c2.6 0 4.4 2 4.4 4.9s-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2H22v4.1h.7zm7.9-7h3.3v14.3h-3.3V6.4z" fill="#fff"/><path class="st0" d="M44.1 47.3c3.6 2.5 5.7 9 5.7 13.9 0 1.3-.2 2.5-.5 3.6-.3-2.9-1.7-5.4-3.9-7 1.2 1.6 1.9 3.6 1.9 5.8 0 5.4-4.4 9.8-9.8 9.8-2.2 0-3.3-.4-4.9-1.6 3.3 0 5.4-3.3 8.2-3.3 0 0-.4-1.6-2.5-1.6s-1.1 1.6-4.9 1.6-5.7-2.3-5.7-4.1c0-1.8 2.7-3.1 3.3-2.5.6-.6 0-1.6 0-1.6l4.9-3.3h-1.6c-7.3 0-3.1-5.1-1.6-6.5-2.6 0-4.2 2.4-4.9 3.3-.4-.2-3.3-.2-4.1 0-.4.1-.9-.6-1.3-1.4-.6-1.1-1.1-2.6-1.1-3.5-2.1 2.1-1.7 5.2-.9 6.4l-.1.1c-1.5 2.7-2.3 5.7-2.3 9 0 10.4 8.4 18.8 18.8 18.8s18.8-7.6 18.8-18v-1.6c-.1-9.7-6.3-14.7-11.5-16.3z"/></svg>
1
<svg height="64" width="67" xmlns="http://www.w3.org/2000/svg"><path d="M46.406 0c6.367 4.457 10.078 16.043 10.078 24.781 0 2.317-.351 4.457-.882 6.418-.532-5.172-3.008-9.629-6.895-12.48 2.121 2.851 3.36 6.418 3.36 10.34 0 9.625-7.782 17.468-17.329 17.468-3.89 0-5.836-.71-8.664-2.851 5.836 0 9.547-5.883 14.5-5.883 0 0-.71-2.852-4.422-2.852-3.715 0-1.945 2.852-8.664 2.852S17.41 33.695 17.41 30.484c0-3.207 4.774-5.527 5.836-4.457 1.059-1.07 0-2.851 0-2.851l8.664-5.883h-2.832c-12.906 0-5.48-9.094-2.828-11.59-4.598 0-7.426 4.281-8.664 5.883-.707-.356-5.832-.356-7.246 0-.707.18-1.594-1.066-2.3-2.492-1.06-1.961-1.946-4.637-1.946-6.242-3.711 3.746-3.004 9.27-1.59 11.41l-.176.18C1.676 19.253.262 24.601.262 30.483.262 49.024 15.113 64 33.5 64s33.238-13.547 33.238-32.09V29.06C66.563 11.766 55.602 2.852 46.406 0zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xps.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm3-27.4L5.5 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H5.7L9 13.6zm9.8-7.2h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2H22v4.1h.7zm8.6 3.3c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8z" fill="#fff"/><path d="M23.7 76c-.5 0-1.1-.2-1.5-.6L13.9 67c-.8-.8-.8-2.1 0-3l8.4-8.4c.8-.8 2.1-.8 3 0 .8.8.8 2.1 0 3l-6.9 6.9 6.9 6.9c.8.8.8 2.1 0 3-.5.4-1.1.6-1.6.6zm25.1 0c-.5 0-1.1-.2-1.5-.6-.8-.8-.8-2.1 0-3l6.9-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 3 0l8.4 8.4c.8.8.8 2.1 0 3l-8.4 8.4c-.4.4-1 .6-1.5.6zm-16.7 4.1c-.2 0-.4 0-.7-.1-1.1-.4-1.7-1.5-1.3-2.6l8.4-25.1c.4-1.1 1.5-1.7 2.6-1.3 1.1.4 1.7 1.5 1.3 2.6L34 78.7c-.2.9-1.1 1.4-1.9 1.4z" fill="#999" stroke="#999" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="55"><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M11.143 25.867c-.5 0-1.1-.2-1.502-.6l-8.298-8.4c-.8-.799-.8-2.1 0-3.001l8.398-8.4c.8-.798 2.101-.798 3.002 0 .8.801.8 2.1 0 3.001l-6.901 6.9 6.9 6.9c.8.8.8 2.098 0 3-.5.4-1.1.6-1.6.6zm25.101 0c-.503 0-1.102-.2-1.502-.6-.8-.8-.8-2.1 0-3l6.901-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 2.998 0l8.4 8.399c.801.8.801 2.102 0 3l-8.4 8.4c-.4.4-.999.6-1.5.6zm-16.7 4.1c-.202 0-.403 0-.7-.1-1.102-.399-1.7-1.5-1.3-2.599l8.398-25.1c.402-1.101 1.5-1.702 2.6-1.302 1.1.4 1.7 1.502 1.3 2.6l-8.4 25.101c-.198.901-1.1 1.4-1.899 1.4zm0 0" transform="matrix(1.74792 0 0 1.75607 0 .53)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xrb.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#55486d}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm3-27.4L5.5 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H5.7L9 13.6zm9.8-7.2h4.5c.6 0 1.3.1 1.9.4 1.4.6 2.4 2.1 2.4 4 0 1.7-.8 3.3-2 4 0 0 .2.2.5.9l2.3 5h-3.6l-2-4.8H22v4.8h-3.3V6.4zm3.9 6.6c.9 0 1.6-.7 1.6-1.9 0-.7-.2-1.2-.6-1.5-.3-.2-.6-.3-.9-.3h-.7V13h.6zM31 6.4h4.2c2.5 0 4.2 1.3 4.2 3.7 0 1.2-.5 2.4-1.7 3 1.6.5 2.1 1.9 2.1 3.2 0 3.1-2 4.3-4.4 4.3H31V6.4zm4.2 5.6c.6 0 .9-.6.9-1.4s-.3-1.3-1-1.3h-.8V12h.9zm.2 5.8c.8 0 1.2-.7 1.2-1.6 0-.9-.3-1.5-1.1-1.5h-1.2v3.1h1.1z" fill="#fff"/><path class="st0" d="M43.6 68.3l-7.3-3.4L51 58l7.3 3.4-7.3 3.5-7.4 3.4zM51 51.2l-7.3-3.4-7.3 3.4L51 58.1l7.3-3.4-7.3-3.5zM28.9 61.4L21.6 58l-7.3 3.4L29 68.3l7.3-3.4-7.4-3.5zm0-6.8l7.3-3.4-7.3-3.4-14.7 6.9 7.3 3.4 7.4-3.5zM51 66.9l-6.6 3-.8.4-.8-.4-6.6-3-6.6 3-.8.4-.8-.4-6.6-3v10.7l14.7 7.7L51 77.6V66.9z"/></svg>
1
<svg height="64" width="74" xmlns="http://www.w3.org/2000/svg"><path d="m49.332 34.941-12.25-5.714L61.75 17.633 74 23.348l-12.25 5.879zM61.75 6.207 49.5.492 37.25 6.207l24.5 11.594L74 12.086zm-37.082 17.14-12.25-5.714-12.25 5.715L24.836 34.94l12.246-5.714zm0-11.429 12.25-5.711L24.668.492 0 12.086 12.25 17.8zM61.75 32.59l-11.074 5.039-1.344.672-1.34-.672-11.074-5.04-11.078 5.04-1.34.672-1.344-.672-11.074-5.04v17.977L36.75 63.508l25-12.942zm0 0" fill="#55486d"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xsd.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6V41zm3-27.4L5.5 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H5.7L9 13.6zm10.5 3.1c.6.6 1.4 1.2 2.3 1.2s1.3-.6 1.3-1.2c0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L25 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10-10.3h4.2c3.7 0 5.9 2.6 5.9 7.1s-2.2 7.2-5.9 7.2h-4.2V6.4zm4.1 11.4c1.7 0 2.6-1.5 2.6-4.3s-1-4.2-2.6-4.2h-.8v8.5h.8z" fill="#fff"/><path class="st0" d="M481.7 307.9h8.8v8.8h-8.8zm0 26.4h8.8v8.8h-8.8zm-14.7 0h8.8v8.8H467zm29.4 0h8.8v8.8h-8.8zm-8.8-10.3v-5.8h-3v5.8h-14.7v8.8h3V327h11.7v5.8h3V327h11.7v5.8h3V324z" transform="translate(-450 -260)"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M26.555 0h15.89v16h-15.89zm0 48h15.89v16h-15.89zM.015 48h15.887v16H.016zm53.083 0h15.886v16H53.098zM37.207 29.273V18.727h-5.414v10.546H5.25v16h5.418V34.727h21.125v10.546h5.414V34.727h21.125v10.546h5.418v-16zm0 0" fill="#999"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xsl.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm3-27.4L5.5 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H5.7L9 13.6zm10.5 3.1c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1L25 10.1c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm10-10.3h3.3v11.4h4.3v2.9h-7.6V6.4z" fill="#fff"/><path d="M23.7 76c-.5 0-1.1-.2-1.5-.6L13.9 67c-.8-.8-.8-2.1 0-3l8.4-8.4c.8-.8 2.1-.8 3 0 .8.8.8 2.1 0 3l-6.9 6.9 6.9 6.9c.8.8.8 2.1 0 3-.5.4-1.1.6-1.6.6zm25.1 0c-.5 0-1.1-.2-1.5-.6-.8-.8-.8-2.1 0-3l6.9-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 3 0l8.4 8.4c.8.8.8 2.1 0 3l-8.4 8.4c-.4.4-1 .6-1.5.6zm-16.7 4.1c-.2 0-.4 0-.7-.1-1.1-.4-1.7-1.5-1.3-2.6l8.4-25.1c.4-1.1 1.5-1.7 2.6-1.3 1.1.4 1.7 1.5 1.3 2.6L34 78.7c-.2.9-1.1 1.4-1.9 1.4z" fill="#999" stroke="#999" stroke-width="1.5" stroke-miterlimit="10"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="55"><path style="fill-rule:nonzero;fill:#999;fill-opacity:1;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke:#999;stroke-opacity:1;stroke-miterlimit:10" d="M11.143 25.867c-.5 0-1.1-.2-1.502-.6l-8.298-8.4c-.8-.799-.8-2.1 0-3.001l8.398-8.4c.8-.798 2.101-.798 3.002 0 .8.801.8 2.1 0 3.001l-6.901 6.9 6.9 6.9c.8.8.8 2.098 0 3-.5.4-1.1.6-1.6.6zm25.101 0c-.503 0-1.102-.2-1.502-.6-.8-.8-.8-2.1 0-3l6.901-6.9-6.9-6.9c-.8-.8-.8-2.1 0-3 .8-.8 2.1-.8 2.998 0l8.4 8.399c.801.8.801 2.102 0 3l-8.4 8.4c-.4.4-.999.6-1.5.6zm-16.7 4.1c-.202 0-.403 0-.7-.1-1.102-.399-1.7-1.5-1.3-2.599l8.398-25.1c.402-1.101 1.5-1.702 2.6-1.302 1.1.4 1.7 1.502 1.3 2.6l-8.4 25.101c-.198.901-1.1 1.4-1.899 1.4zm0 0" transform="matrix(1.74792 0 0 1.75607 0 .53)"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xspf.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#039}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm3-27.4L5.5 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H5.7L9 13.6zm9 3.1c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.5-.4-1.4-.9-2.2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.6-2.8zm8.5-10.3H31c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7zm6.3-7h7.1v2.9H40v3.1h3.1v2.9H40v5.4h-3.3V6.4z" fill="#fff"/><path class="st0" d="M14.6 54.3h22.9c1.2 0 2.1-.9 2.1-2.1s-.9-2.1-2.1-2.1H14.6c-1.2 0-2.1.9-2.1 2.1s.9 2.1 2.1 2.1zm0 11.1h22.9c1.2 0 2.1-.9 2.1-2.1s-.9-2.1-2.1-2.1H14.6c-1.2 0-2.1.9-2.1 2.1s.9 2.1 2.1 2.1zm11 5.9h-11c-1.2 0-2.1.9-2.1 2.1s.9 2.1 2.1 2.1h11c1.2 0 2.1-.9 2.1-2.1s-.9-2.1-2.1-2.1z"/><path class="st0" d="M52.5 53.8c-1.6-.8-3.7-2-4.5-3.7 0-.9-.7-1.6-1.6-1.6-.9 0-1.6.7-1.6 1.6v21.5c-1.7-.9-4.9-.6-7.3.8-3.8 2.1-5.4 6.1-3.8 8.8s6.1 3.3 9.9 1.2c2.6-1.5 4.4-3.9 4.5-6.3V57.6c5.4 0 8.7 2.2 7.5 7.5-.2 1-.6 1.9-1 2.9-.2.3-.2.7.1 1 .3.3.8.2 1.2-.2 2-2 3.3-4.6 3.4-7.5-.1-3.8-3.7-6-6.8-7.5z"/></svg>
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#039;fill-opacity:1" d="M4.059 10.39h40.254c2.109 0 3.69-1.613 3.69-3.761 0-2.149-1.581-3.758-3.69-3.758H4.059c-2.11 0-3.692 1.61-3.692 3.758 0 2.152 1.582 3.762 3.692 3.762zm0 19.891h40.254c2.109 0 3.69-1.613 3.69-3.765 0-2.149-1.581-3.762-3.69-3.762H4.059c-2.11 0-3.692 1.613-3.692 3.762 0 2.148 1.582 3.765 3.692 3.765zm19.336 10.57H4.059c-2.11 0-3.692 1.614-3.692 3.762 0 2.149 1.582 3.766 3.692 3.766h19.336c2.109 0 3.69-1.617 3.69-3.766 0-2.148-1.581-3.761-3.69-3.761zm0 0"/><path style="stroke:none;fill-rule:nonzero;fill:#039;fill-opacity:1" d="M70.68 9.496c-2.813-1.434-6.504-3.582-7.91-6.629C62.77 1.254 61.54 0 59.957 0c-1.582 0-2.812 1.254-2.812 2.867v38.52c-2.989-1.614-8.614-1.075-12.833 1.433-6.68 3.766-9.492 10.93-6.68 15.766 2.813 4.84 10.723 5.914 17.4 2.152 4.573-2.687 7.738-6.988 7.913-11.289V16.305c9.492 0 15.29 3.941 13.18 13.437-.352 1.793-1.05 3.403-1.754 5.195-.355.54-.355 1.254.176 1.793.527.536 1.402.356 2.11-.359 3.515-3.582 5.796-8.242 5.976-13.437-.18-6.805-6.508-10.75-11.953-13.438zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/xz.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#90c}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm3-27.4L5.5 6.4h3.6l1.1 2.9.6 1.8s.2-.9.6-1.8l1.2-2.9h3.6l-3.4 7.2 3.3 7.1h-3.5l-1.1-3c-.4-.9-.6-1.7-.6-1.7s-.2.8-.6 1.7l-1.1 3H5.7L9 13.6zm9.2 4.9l4.2-7.9c.5-.9.8-1.3.8-1.3s-.3.1-.8.1h-4v-3h8.7v2.2l-4.2 8c-.5.9-.8 1.3-.8 1.3s.3-.1.8-.1h4.3v2.9h-8.9v-2.2z" fill="#fff"/><path class="st0" d="M51.1 57.5h-5.7v-5.7l5.7 5.7zm-15.3-5.7v20.7h15.4V58.9H44v-7.1h-8.2zm2.4-5.4h-17v4h6.7l-4.2 3.3v3.5l6.2-4.8v-1.9h21.6v-1.6l-13.3-2.5zm-8.3 8.7l-6.2 4.8v3.5l6.2-4.8v-3.5zm-6.3 14.4l6.2-4.8v-3.5L23.6 66v3.5zm6.3 1.4v-3.5l-6.2 4.8V74h-2.5v4H25v2.8h-2.2c-.4-.7-1.1-1.2-2-1.2-1.3 0-2.3 1-2.3 2.3 0 1.3 1 2.3 2.3 2.3.9 0 1.6-.5 2-1.2H25v2.1h3.4V83h2.2c.4.7 1.1 1.2 2 1.2 1.3 0 2.3-1 2.3-2.3 0-1.3-1-2.3-2.3-2.3-.9 0-1.6.5-2 1.2h-2.2V78h9.7l13.3-2.4V74H25.7l4.2-3.1z"/></svg>
1
<svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/yaml.svg
1
<?xml version="1.0" encoding="UTF-8"?>
2
<svg version="1.1" viewBox="0 0 72 96" xmlns="http://www.w3.org/2000/svg">
3
<style>.st0{fill:#999}</style>
4
<path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/>
5
<path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/>
6
<path d="M6 41h60v49H6zm2.9-26.2L5.5 6.5H8l1.5 4.2c.3.9.5 1.9.5 1.9s.2-1 .5-1.9L12 6.5h2.5l-3.4 8.3v5.9H8.9v-5.9zm8.4-8.3h2.5l3.5 14.2H21l-.9-3.7h-3.2l-.8 3.7h-2.3l3.5-14.2zm2.4 8.5l-.8-3.8c-.2-.8-.4-2.2-.4-2.2h-.1s-.2 1.4-.4 2.2l-.8 3.8h2.5zm5.2-8.5h2.5l1.8 6.9c.2.9.4 2.2.4 2.2h.1s.2-1.3.4-2.2l1.8-6.9h2.5l.8 14.2h-2.1l-.4-7.9c-.1-.9 0-2.2 0-2.2h-.1s-.2 1.4-.4 2.3l-1.4 5.4h-2.2l-1.4-5.4c-.2-.8-.4-2.3-.4-2.3h-.1s.1 1.3 0 2.2l-.4 7.9h-2.1l.7-14.2zm12.3 0h2.3v12h4.3v2.2h-6.5V6.5z" fill="#fff"/>
7
<path class="st0" d="M14 48.9h37v4.3H14zm7 9.6h37v4.3H21zm-7 9.6h37v4.3H14zm7 9.6h37V82H21z" fill="#efce4a"/>
8
</svg>
9
1
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="63"><path style="stroke:none;fill-rule:nonzero;fill:#999;fill-opacity:1" d="M.125 0h69.586v8.184H.125zm13.164 18.273h69.586v8.18H13.289zM.125 36.543h69.586v8.184H.125zm13.164 18.273h69.586V63H13.289zm0 0"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/z.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#90c}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm0-22.5l4.2-7.9c.5-.9.8-1.3.8-1.3s-.3.1-.8.1h-4v-3h8.7v2.2l-4.2 8c-.5.9-.8 1.3-.8 1.3s.3-.1.8-.1H15v2.9H6v-2.2z" fill="#fff"/><path class="st0" d="M51.1 57.5h-5.7v-5.7l5.7 5.7zm-15.3-5.7v20.7h15.4V58.9H44v-7.1h-8.2zm2.4-5.4h-17v4h6.7l-4.2 3.3v3.5l6.2-4.8v-1.9h21.6v-1.6l-13.3-2.5zm-8.3 8.7l-6.2 4.8v3.5l6.2-4.8v-3.5zm-6.3 14.4l6.2-4.8v-3.5L23.6 66v3.5zm6.3 1.4v-3.5l-6.2 4.8V74h-2.5v4H25v2.8h-2.2c-.4-.7-1.1-1.2-2-1.2-1.3 0-2.3 1-2.3 2.3 0 1.3 1 2.3 2.3 2.3.9 0 1.6-.5 2-1.2H25v2.1h3.4V83h2.2c.4.7 1.1 1.2 2 1.2 1.3 0 2.3-1 2.3-2.3 0-1.3-1-2.3-2.3-2.3-.9 0-1.6.5-2 1.2h-2.2V78h9.7l13.3-2.4V74H25.7l4.2-3.1z"/></svg>
1
<svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg>
2
M src/main/resources/com/keenwrite/ui/fonts/icons/zip.svg
1
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#90c}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm0-22.5l4.2-7.9c.5-.9.8-1.3.8-1.3s-.3.1-.8.1h-4v-3h8.7v2.2l-4.2 8c-.5.9-.8 1.3-.8 1.3s.3-.1.8-.1H15v2.9H6v-2.2zM18.1 6.4h3.3v14.3h-3.3V6.4zm7 0h4.5c2.6 0 4.4 2 4.4 4.9 0 2.9-1.7 5-4.4 5h-1.2v4.4h-3.3V6.4zm3.9 7c1 0 1.6-.9 1.6-2.1s-.7-2-1.6-2h-.7v4.1h.7z" fill="#fff"/><path class="st0" d="M51.1 57.5h-5.7v-5.7l5.7 5.7zm-15.3-5.7v20.7h15.4V58.9H44v-7.1h-8.2zm2.4-5.4h-17v4h6.7l-4.2 3.3v3.5l6.2-4.8v-1.9h21.6v-1.6l-13.3-2.5zm-8.3 8.7l-6.2 4.8v3.5l6.2-4.8v-3.5zm-6.3 14.4l6.2-4.8v-3.5L23.6 66v3.5zm6.3 1.4v-3.5l-6.2 4.8V74h-2.5v4H25v2.8h-2.2c-.4-.7-1.1-1.2-2-1.2-1.3 0-2.3 1-2.3 2.3 0 1.3 1 2.3 2.3 2.3.9 0 1.6-.5 2-1.2H25v2.1h3.4V83h2.2c.4.7 1.1 1.2 2 1.2 1.3 0 2.3-1 2.3-2.3 0-1.3-1-2.3-2.3-2.3-.9 0-1.6.5-2 1.2h-2.2V78h9.7l13.3-2.4V74H25.7l4.2-3.1z"/></svg>
1
<svg height="63" width="54" xmlns="http://www.w3.org/2000/svg"><path d="M53.344 18.172H44.02V8.965zM28.309 8.965v33.437h25.199V20.434H41.727V8.964zm3.93-8.723H4.417v6.461h10.965l-6.875 5.332v5.652l10.148-7.753V6.867H54V4.281zM18.655 14.297 8.508 22.05v5.652l10.148-7.754zM8.344 37.559l10.148-7.754v-5.657L8.344 31.902zm10.312 2.261v-5.656L8.508 41.918v2.91h-4.09v6.461h6.219v4.523H7.035c-.652-1.132-1.797-1.937-3.273-1.937C1.637 53.875 0 55.488 0 57.59c0 2.097 1.637 3.715 3.762 3.715 1.476 0 2.62-.809 3.273-1.938h3.602v3.39h5.562v-3.39h3.602c.652 1.13 1.8 1.938 3.273 1.938 2.125 0 3.762-1.618 3.762-3.715 0-2.102-1.637-3.715-3.762-3.715-1.472 0-2.62.805-3.273 1.938h-3.602v-4.524h15.875l21.762-3.879v-2.582H11.78zm0 0" fill="#90c"/></svg>
M src/main/resources/com/keenwrite/ui/fonts/icons/zsh.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 96"><style>.st0{fill:#999}</style><path class="st0" d="M0 2v92c0 1.1.9 2 2 2h68c1.1 0 2-.9 2-2V28H50c-1.1 0-2-.9-2-2V0H2C.9 0 0 .9 0 2z"/><path class="st0" d="M71.9 24c-.1-.4-.2-.7-.4-1L52 1.2V24h19.9z"/><path d="M6 41h60v49H6zm0-22.5l4.2-7.9c.5-.9.8-1.3.8-1.3s-.3.1-.8.1h-4v-3h8.7v2.2l-4.2 8c-.5.9-.8 1.3-.8 1.3s.3-.1.8-.1H15v2.9H6v-2.2zm12.8-1.8c.6.6 1.4 1.2 2.3 1.2.9 0 1.3-.6 1.3-1.2 0-2-4.8-2.1-4.8-6.2 0-2.4 1.7-4.3 4.5-4.3 1.2 0 2.4.3 3.4 1l-1.2 2.9c-.3-.5-1.3-.9-2-.9-.9 0-1.3.6-1.3 1.2 0 2.1 4.8 2 4.8 6.1 0 2.3-1.5 4.4-4.4 4.4-1.4 0-2.9-.5-4-1.4l1.4-2.8zm10-10.3h3.3v5.8h3.2V6.4h3.3v14.3h-3.3V15h-3.2v5.7h-3.3V6.4z" fill="#fff"/><path d="M30.8 61.4h10.9v2.7H30.8v-2.7zm0 5.4h10.9v2.7H30.8v-2.7zm0 5.5h10.9V75H30.8v-2.7zm19-24.4H28.1c-3 0-5.4 2.4-5.4 5.4v24.4h-5.4c0 3 2.4 5.4 5.4 5.4h21.7c3 0 5.4-2.4 5.4-5.4V56h5.4v-2.7c0-3-2.4-5.4-5.4-5.4zm-2.7 29.3c0 1.8-1.4 3.2-3.2 3.2H24c1.3-.9 1.3-2.7 1.3-2.7V53.3c0-1.5 1.2-2.7 2.7-2.7s2.7 1.2 2.7 2.7V56H47l.1 21.2zM33.5 53.3v-2.7h16.3c2.5 0 2.7 1.6 2.7 2.7h-19z" fill="#999" stroke="#999" stroke-width=".75" stroke-miterlimit="10"/></svg>
1
<svg height="64" width="69" xmlns="http://www.w3.org/2000/svg"><path d="M13.875 13.874h10.9v2.701h-10.9zm0 5.4h10.9v2.701h-10.9zm0 5.5h10.9v2.702h-10.9zm19-24.399H11.177c-3 0-5.402 2.4-5.402 5.4v24.4h-5.4c0 3 2.402 5.4 5.4 5.4h21.7c3 0 5.402-2.4 5.402-5.4v-21.7h5.4v-2.7c0-3-2.402-5.4-5.4-5.4zm-2.7 29.3c0 1.801-1.4 3.2-3.2 3.2h-19.9c1.3-.9 1.3-2.7 1.3-2.7v-24.4c0-1.5 1.2-2.7 2.7-2.7 1.501 0 2.7 1.2 2.7 2.7v2.7h16.3zm-13.6-23.9v-2.7h16.3c2.501 0 2.7 1.6 2.7 2.7zm0 0" fill="#999" stroke="#999" stroke-miterlimit="10" stroke-width=".75" transform="matrix(1.7717 0 0 1.78025 .262 0)"/></svg>
A src/test/java/com/keenwrite/io/MediaTypeSnifferTest.java
1
package com.keenwrite.io;
2
3
import org.junit.jupiter.api.Test;
4
5
import java.io.File;
6
7
import static com.keenwrite.io.MediaTypeExtension.valueFrom;
8
import static org.apache.commons.io.FilenameUtils.getExtension;
9
import static org.junit.jupiter.api.Assertions.*;
10
11
/**
12
 * Responsible for testing that {@link MediaTypeSniffer} can return the
13
 * correct IANA-defined {@link MediaType} for known file types.
14
 */
15
class MediaTypeSnifferTest {
16
17
  @Test
18
  void test_Read_KnownFileTypes_MediaTypeReturned()
19
    throws Exception {
20
    final var clazz = getClass();
21
    final var pkgName = clazz.getPackageName();
22
    final var dir = pkgName.replace( '.', '/' );
23
24
    final var urls = clazz.getClassLoader().getResources( dir + "/images" );
25
    assertTrue( urls.hasMoreElements() );
26
27
    while( urls.hasMoreElements() ) {
28
      final var url = urls.nextElement();
29
      final var path = new File( url.toURI().getPath() );
30
      final var files = path.listFiles();
31
      assertNotNull( files );
32
33
      for( final var image : files ) {
34
        final var media = MediaTypeSniffer.getMediaType( image );
35
        final var actualExtension = valueFrom( media ).getExtension();
36
        final var expectedExtension = getExtension( image.toString() );
37
        assertEquals( expectedExtension, actualExtension );
38
      }
39
    }
40
  }
41
}
142
M src/test/java/com/keenwrite/io/MediaTypeTest.java
77
import java.util.Map;
88
9
import static com.keenwrite.io.HttpFacade.httpGet;
910
import static com.keenwrite.io.MediaType.*;
1011
import static org.junit.jupiter.api.Assertions.*;
...
2627
2728
  /**
28
   * Test that {@link MediaType#valueFrom(String)} can lookup by file name.
29
   * Test that {@link MediaType#fromFilename(String)} can lookup by file name.
2930
   */
3031
  @Test
...
4142
    );
4243
43
    map.forEach( ( k, v ) -> assertEquals( v, valueFrom( "f." + k ) ) );
44
    map.forEach( ( k, v ) -> assertEquals( v, fromFilename( "f." + k ) ) );
4445
  }
4546
4647
  /**
47
   * Test that {@link HttpMediaType#valueFrom(URI)} will pull and identify the
48
   * type of resource based on the HTTP Content-Type header.
48
   * Test that remote fetches will pull and identify the type of resource
49
   * based on the HTTP Content-Type header (or shallow decoding).
4950
   */
5051
  @Test
5152
  public void test_HttpRequest_Supported_Success() {
5253
    //@formatter:off
5354
    final var map = Map.of(
5455
       "https://stackoverflow.com/robots.txt", TEXT_PLAIN,
5556
       "https://place-hold.it/300x500", IMAGE_GIF,
57
       "https://placekitten.com/g/200/300", IMAGE_JPEG,
5658
       "https://upload.wikimedia.org/wikipedia/commons/9/9f/Vimlogo.svg", IMAGE_SVG_XML,
57
       "https://kroki.io//graphviz/svg/eNpLyUwvSizIUHBXqPZIzcnJ17ULzy_KSanlAgB1EAjQ", TEXT_PLAIN
59
       "https://kroki.io//graphviz/svg/eNpLyUwvSizIUHBXqPZIzcnJ17ULzy_KSanlAgB1EAjQ", IMAGE_SVG_XML
5860
    );
5961
    //@formatter:on
6062
6163
    map.forEach( ( k, v ) -> {
62
      try {
63
        assertEquals( v, HttpMediaType.valueFrom( new URI( k ) ) );
64
      try( var response = httpGet( new URI( k ) ) ) {
65
        assertEquals( v, response.getMediaType() );
6466
      } catch( Exception e ) {
6567
        fail();
M src/test/java/com/keenwrite/processors/markdown/ImageLinkExtensionTest.java
2626
import java.util.Map;
2727
28
import static com.keenwrite.Constants.DOCUMENT_DEFAULT;
28
import static com.keenwrite.constants.Constants.DOCUMENT_DEFAULT;
2929
import static com.keenwrite.ExportFormat.NONE;
3030
import static java.lang.String.format;
...
151151
      new HashMap<>(),
152152
      documentPath,
153
      Caret.builder().build(),
153
      null,
154154
      NONE,
155
      sWorkspace
155
      sWorkspace,
156
      Caret.builder().build()
156157
    );
157158
  }
A src/test/java/com/keenwrite/quotes/SmartQuotesTest.java
1
/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
2
package com.keenwrite.quotes;
3
4
import org.junit.jupiter.api.Disabled;
5
import org.junit.jupiter.api.Test;
6
7
import java.io.BufferedReader;
8
import java.io.IOException;
9
import java.io.InputStreamReader;
10
11
import static org.junit.jupiter.api.Assertions.assertEquals;
12
import static org.junit.jupiter.api.Assertions.assertNotNull;
13
14
/**
15
 * Test that English straight quotes are converted to curly quotes and
16
 * apostrophes.
17
 */
18
public class SmartQuotesTest {
19
  @Disabled
20
  @SuppressWarnings( "unused" )
21
  public void test_Parse_StraightQuotes_CurlyQuotes() throws IOException {
22
    final var fixer = new SmartQuotes();
23
24
    try( final var reader = openResource( "smartypants.txt" ) ) {
25
      String line;
26
      String testLine = "";
27
      String expected = "";
28
29
      while( ((line = reader.readLine()) != null) ) {
30
        if( line.startsWith( "#" ) || line.isBlank() ) { continue; }
31
32
        // Read the first line of the couplet.
33
        if( testLine.isBlank() ) {
34
          testLine = line;
35
          continue;
36
        }
37
38
        // Read the second line of the couplet.
39
        if( expected.isBlank() ) {
40
          expected = line;
41
        }
42
43
        final var actual = fixer.replace( testLine );
44
        assertEquals(expected, actual);
45
46
        testLine = "";
47
        expected = "";
48
      }
49
    }
50
  }
51
52
  @SuppressWarnings( "SameParameterValue" )
53
  private BufferedReader openResource( final String filename ) {
54
    final var is = getClass().getResourceAsStream( filename );
55
    assertNotNull( is );
56
57
    return new BufferedReader( new InputStreamReader( is ) );
58
  }
59
}
160
M src/test/java/com/keenwrite/tex/TeXRasterization.java
3535
import com.whitemagicsoftware.tex.graphics.SvgDomGraphics2D;
3636
import com.whitemagicsoftware.tex.graphics.SvgGraphics2D;
37
import org.apache.batik.transcoder.TranscoderException;
3738
import org.junit.jupiter.api.Test;
3839
import org.xml.sax.SAXException;
...
4647
import java.io.IOException;
4748
import java.nio.file.Path;
49
import java.text.ParseException;
4850
4951
import static com.keenwrite.preview.SvgRasterizer.*;
...
7577
  @Test
7678
  public void test_Rasterize_SimpleFormula_CorrectImageSize()
77
      throws IOException {
79
    throws IOException, ParseException, TranscoderException {
7880
    final var g = new SvgGraphics2D();
7981
    drawGraphics( g );
...
8789
  @Test
8890
  public void getTest_SvgDomGraphics2D_InputElement_OutputRasterizedImage()
89
      throws ParserConfigurationException, IOException, SAXException {
91
    throws ParserConfigurationException, IOException, SAXException,
92
    ParseException, TranscoderException {
9093
    final var g = new SvgGraphics2D();
9194
    drawGraphics( g );
...
112115
  @Test
113116
  public void test_SvgDomGraphics2D_InputDom_OutputRasterizedImage()
114
      throws IOException {
117
    throws IOException, ParseException, TranscoderException {
115118
    final var g = new SvgDomGraphics2D();
116119
    drawGraphics( g );
A src/test/resources/com/keenwrite/io/images/example.bmp
Binary file
A src/test/resources/com/keenwrite/io/images/example.eps
Binary file
A src/test/resources/com/keenwrite/io/images/example.gif
Binary file
A src/test/resources/com/keenwrite/io/images/example.jpg
Binary file
A src/test/resources/com/keenwrite/io/images/example.png
Binary file
A src/test/resources/com/keenwrite/io/images/example.svg
1
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 34" width="68px" height="34px" fill="#005a9c">
2
<desc>W3C</desc>
3
<path d="m16.117 1.006 5.759 19.58 5.759-19.58h4.17 11.444v1.946l-5.879 10.128c2.065.663 3.627 1.868 4.686 3.615 1.059 1.748 1.589 3.799 1.589 6.155 0 2.914-.775 5.363-2.324 7.348s-3.555 2.978-6.017 2.978c-1.854 0-3.469-.589-4.845-1.767-1.377-1.178-2.396-2.773-3.058-4.786l3.256-1.35c.477 1.218 1.106 2.178 1.887 2.879.781.702 1.701 1.052 2.76 1.052 1.112 0 2.052-.622 2.82-1.866.768-1.245 1.152-2.74 1.152-4.489 0-1.933-.411-3.429-1.231-4.488-.954-1.244-2.45-1.867-4.489-1.867h-1.588v-1.906l5.56-9.612h-6.712l-.382.65-8.163 27.548h-.397l-5.958-19.937-5.957 19.937h-.397l-9.53-32.168h4.17l5.759 19.58 3.892-13.185-1.906-6.395z"/>
4
<path d="m64.92 1.006c-.819 0-1.554.295-2.111.861-.591.6-.92 1.376-.92 2.178s.313 1.545.887 2.128c.583.591 1.334.912 2.145.912.793 0 1.562-.321 2.161-.903.574-.557.887-1.3.887-2.136 0-.811-.321-1.57-.878-2.136-.584-.592-1.344-.904-2.171-.904zm2.643 3.065c0 .701-.271 1.351-.768 1.832-.524.507-1.174.777-1.892.777-.675 0-1.342-.278-1.84-.785s-.777-1.157-.777-1.849.287-1.368.802-1.891c.481-.49 1.131-.751 1.84-.751.726 0 1.376.271 1.883.785.49.489.752 1.147.752 1.882zm-2.559-1.807h-1.3v3.445h.65v-1.469h.642l.701 1.469h.726l-.769-1.57c.498-.102.785-.439.785-.929 0-.625-.472-.946-1.435-.946zm-.118.422c.608 0 .886.169.886.591 0 .405-.278.549-.87.549h-.549v-1.14z"/>
5
<path d="m59.807.825.676 4.107-2.391 4.575s-.918-1.941-2.443-3.015c-1.285-.905-2.122-1.102-3.431-.832-1.681.347-3.587 2.357-4.419 4.835-.995 2.965-1.005 4.4-1.04 5.718-.056 2.113.277 3.362.277 3.362s-1.452-2.686-1.438-6.62c.009-2.808.451-5.354 1.75-7.867 1.143-2.209 2.842-3.535 4.35-3.691 1.559-.161 2.791.59 3.743 1.403 1 .854 2.01 2.721 2.01 2.721z"/>
6
<path d="m60.102 24.063s-1.057 1.889-1.715 2.617c-.659.728-1.837 2.01-3.292 2.651s-2.218.762-3.656.624c-1.437-.138-2.772-.97-3.24-1.317s-1.664-1.369-2.34-2.322-1.733-2.859-1.733-2.859.589 1.91.958 2.721c.212.467.864 1.894 1.789 3.136.863 1.159 2.539 3.154 5.086 3.604 2.547.451 4.297-.693 4.73-.97s1.346-1.042 1.924-1.66c.603-.645 1.174-1.468 1.49-1.962.231-.36.607-1.092.607-1.092z"/>
7
</svg>
18
A src/test/resources/com/keenwrite/io/images/example.xbm
1
#define 1617524430813_width 72
2
#define 1617524430813_height 48
3
static char 1617524430813_bits[] = {
4
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 
5
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
6
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
7
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 
8
  0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
9
  0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 
10
  0x10, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0xAA, 0x78, 0x80, 0x07, 
11
  0xC0, 0xFF, 0x3F, 0xE0, 0x41, 0x44, 0x78, 0x80, 0x0F, 0xC0, 0xFF, 0x3F, 
12
  0xF8, 0x67, 0x18, 0xF0, 0x80, 0x07, 0xE0, 0xFF, 0x3F, 0xF8, 0xE7, 0x00, 
13
  0xE0, 0x00, 0x0F, 0xE0, 0xFF, 0x1F, 0xFC, 0xFF, 0x00, 0xF0, 0x01, 0x0F, 
14
  0xE0, 0x01, 0x1D, 0xFC, 0x7F, 0x00, 0xF0, 0x01, 0x1F, 0xE0, 0x81, 0x0F, 
15
  0x3E, 0x7C, 0x00, 0xE0, 0x01, 0x1E, 0xE0, 0x81, 0x07, 0x0E, 0x38, 0x00, 
16
  0xE0, 0x01, 0x17, 0xF0, 0xC0, 0x07, 0x0F, 0x30, 0x00, 0xE0, 0x03, 0x3F, 
17
  0xF0, 0xC0, 0x03, 0x07, 0x00, 0x00, 0xC0, 0x03, 0x3F, 0xF8, 0xE0, 0x03, 
18
  0x07, 0x00, 0x00, 0xC0, 0x83, 0x3F, 0x78, 0xF0, 0x01, 0x07, 0x00, 0x00, 
19
  0xC0, 0x83, 0x3F, 0x78, 0xB0, 0x00, 0x03, 0x00, 0x00, 0x80, 0x87, 0x7F, 
20
  0x78, 0xF8, 0x03, 0x03, 0x00, 0x00, 0x80, 0x87, 0x7B, 0x78, 0xFC, 0x07, 
21
  0x03, 0x00, 0x00, 0x80, 0xCF, 0x7B, 0x3C, 0xF8, 0x0F, 0x03, 0x00, 0x00, 
22
  0x80, 0xC7, 0xE3, 0x3E, 0xC8, 0x1F, 0x02, 0x00, 0x00, 0x00, 0xEF, 0xF2, 
23
  0x3C, 0x00, 0x1F, 0x02, 0x00, 0x00, 0x00, 0xEF, 0xF1, 0x1C, 0x00, 0x3E, 
24
  0x02, 0x00, 0x00, 0x00, 0xEF, 0xB1, 0x1F, 0x00, 0x3C, 0x00, 0x00, 0x00, 
25
  0x00, 0xFE, 0xE1, 0x1F, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xE0, 
26
  0x17, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xE0, 0x0F, 0x00, 0x3C, 
27
  0x00, 0x00, 0x00, 0x00, 0x7E, 0xC0, 0x0F, 0x00, 0x7C, 0x00, 0x00, 0x00, 
28
  0x00, 0xFC, 0xC0, 0x0F, 0x00, 0xFC, 0x00, 0x40, 0x00, 0x00, 0x7C, 0x80, 
29
  0x07, 0x03, 0xBC, 0x00, 0x60, 0x00, 0x00, 0x7C, 0xC0, 0xC7, 0x01, 0x3E, 
30
  0x03, 0xE0, 0x00, 0x00, 0x18, 0x80, 0xC7, 0x07, 0x1E, 0x03, 0x70, 0x00, 
31
  0x00, 0x38, 0x80, 0x82, 0x87, 0x1F, 0x0E, 0x7C, 0x00, 0x00, 0x38, 0x00, 
32
  0x03, 0xFF, 0x1D, 0xBC, 0x3F, 0x00, 0x00, 0x30, 0x00, 0x03, 0xFF, 0x0F, 
33
  0xFC, 0x1F, 0x00, 0x00, 0x10, 0x00, 0x03, 0xFC, 0x07, 0xF0, 0x1F, 0x00, 
34
  0x00, 0x10, 0x00, 0x01, 0xF8, 0x01, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 
35
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
36
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
37
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
38
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
39
  0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
40
  };
141
A src/test/resources/com/keenwrite/io/images/example_2.bmp
Binary file
A src/test/resources/com/keenwrite/io/images/example_2.gif
Binary file
A src/test/resources/com/keenwrite/io/images/example_2.jpg
Binary file
A src/test/resources/com/keenwrite/io/images/example_2.png
Binary file
A src/test/resources/com/keenwrite/io/images/example_256.bmp
Binary file
A src/test/resources/com/keenwrite/io/images/example_256.gif
Binary file
A src/test/resources/com/keenwrite/io/images/example_256.jpg
Binary file
A src/test/resources/com/keenwrite/io/images/example_256.png
Binary file
A src/test/resources/com/keenwrite/io/images/example_animation.gif
Binary file
A src/test/resources/com/keenwrite/io/images/example_animation.mng
Binary file
A src/test/resources/com/keenwrite/io/images/example_gray.bmp
Binary file
A src/test/resources/com/keenwrite/io/images/example_gray.gif
Binary file
A src/test/resources/com/keenwrite/io/images/example_gray.jpg
Binary file
A src/test/resources/com/keenwrite/io/images/example_gray.png
Binary file
A src/test/resources/com/keenwrite/quotes/smartypants.txt
1
# ########################################################################
2
# Decades
3
# ########################################################################
4
The Roaring '20s had the best music, no?
5
The Roaring &apos;20s had the best music, no?
6
7
Took place in '04, yes'm!
8
Took place in &apos;04, yes&apos;m!
9
10
# ########################################################################
11
# Inside contractions (no leading/trailing apostrophes)
12
# ########################################################################
13
I don't like it: I love's it!
14
I don&apos;t like it: I love&apos;s it!
15
16
We'd've thought that pancakes'll be sweeter there.
17
We&apos;d&apos;ve thought that pancakes&apos;ll be sweeter there.
18
19
She'd be coming o'er when the horse'd gone to pasture...
20
She&apos;d be coming o&apos;er when the horse&apos;d gone to pasture...
21
22
# ########################################################################
23
# Beginning contractions (leading apostrophes)
24
# ########################################################################
25
'Twas and 'tis whate'er lay 'twixt dawn and dusk 'n River Styx.
26
&apos;Twas and &apos;tis whate&apos;er lay &apos;twixt dawn and dusk &apos;n River Styx.
27
28
# ########################################################################
29
# Ending contractions (trailing apostrophes)
30
# ########################################################################
31
Didn' get th' message.
32
Didn&apos; get th&apos; message.
33
34
Namsayin', y'know what I'ma sayin'?
35
Namsayin&apos;, y&apos;know what I&apos;ma sayin&apos;?
36
37
# ########################################################################
38
# Outside contractions (leading and trailing, no middle)
39
# ########################################################################
40
Salt 'n' vinegar, fish-'n'-chips, sugar 'n' spice!
41
Salt &apos;n&apos; vinegar, fish-&apos;n&apos;-chips, sugar &apos;n&apos; spice!
42
43
# ########################################################################
44
# Primes (single, double)
45
# ########################################################################
46
She stood 5\'7\".
47
She stood 5&prime;7&Prime;.
48
49
# No space after the feet sign.
50
It's 4'11" away.
51
It&apos;s 4&prime;11&Prime; away.
52
53
Alice's friend is 6'3" tall.
54
Alice&apos;s friend is 6&prime;3&Prime; tall.
55
56
Bob's table is 5'' × 4''.
57
Bob&apos;s table is 5&Prime; × 4&Prime;.
58
59
What's this -5.5'' all about?
60
What&apos;s this -5.5&Prime; all about?
61
62
+7.9'' is weird.
63
+7.9&Prime; is weird.
64
65
Foolscap? Naw, I use 11.5"x14.25" paper!
66
Foolscap? Naw, I use 11.5&Prime;x14.25&Prime; paper!
67
68
An angular measurement, 3° 5' 30" means 3 degs, 5 arcmins, and 30 arcsecs.
69
An angular measurement, 3° 5&prime; 30&Prime; means 3 degs, 5 arcmins, and 30 arcsecs.
70
71
# ########################################################################
72
# Backticks (left and right double quotes)
73
# ########################################################################
74
``I am Sam''
75
&ldquo;I am Sam&rdquo;
76
77
``Sam's away today''
78
&ldquo;Sam&apos;s away today&rdquo;
79
80
``Sam's gone!
81
&ldquo;Sam&apos;s gone!
82
83
``5'10" tall 'e was!''
84
&ldquo;5&prime;10&Prime; tall &apos;e was!&rdquo;
85
86
# ########################################################################
87
# Consecutive quotes
88
# ########################################################################
89
"'I'm trouble.'"
90
&ldquo;&lsquo;I&apos;m trouble.&rsquo;&rdquo;
91
92
'"Trouble's my name."'
93
&lsquo;&ldquo;Trouble&apos;s my name.&ldquo;&lsquo;
94
95
# ########################################################################
96
# Escaped quotes
97
# ########################################################################
98
\"What?\"
99
&ldquo;What?&rdquo;
100
101
# ########################################################################
102
# Double quotes
103
# ########################################################################
104
"I am Sam"
105
&ldquo;I am Sam&rdquo;
106
107
"...even better!"
108
&ldquo;...even better!&rdquo;
109
110
"It was so," said he.
111
&ldquo;It was so,&rdquo; said he.
112
113
"She said, 'Llamas'll languish, they'll--
114
&ldquo;She said, &lsquo;Llamas&apos;ll languish, they&apos;ll--
115
116
With "air quotes" in the middle.
117
With &ldquo;air quotes&rdquo; in the middle.
118
119
With--"air quotes"--and dashes.
120
With--&ldquo;air quotes&rdquo;--and dashes.
121
122
"Not "quite" what you expected?"
123
&ldquo;Not &ldquo;quite&rdquo; what you expected?&rdquo;
124
125
# ########################################################################
126
# Nested quotations
127
# ########################################################################
128
"'Here I am,' said Sam"
129
&ldquo;&lsquo;Here I am,&rsquo; said Sam&rdquo;
130
131
'"Here I am," said Sam'
132
&lsquo;&ldquo;Here I am,&rdquo;, said Sam&rsquo;
133
134
'Hello, "Dr. Brown," what's your real name?'
135
&lsquo;Hello, &ldquo;Dr. Brown,&rdquo; what's your real name?&rsquo;
136
137
"'Twas, t'wasn't thy name, 'twas it?" said Jim "the Barber" Brown.
138
&ldquo;&apos;Twas, t&apos;wasn&apos;t thy name, &apos;twas it?&rdquo; said Jim &ldquo;the Barber&rdquo; Brown.
139
140
# ########################################################################
141
# Single quotes
142
# ########################################################################
143
'I am Sam'
144
&lsquo;I am Sam&rsquo;
145
146
'It was so,' said he.
147
&lsquo;It was so,&rsquo; said he.
148
149
'...even better!'
150
&lsquo;...even better!&rsquo;
151
152
With 'quotes' in the middle.
153
With &lsquo;quotes&rsquo; in the middle.
154
155
With--'imaginary'--dashes.
156
With--&lsquo;imaginary&rsquo;--dashes.
157
158
'Not 'quite' what you expected?'
159
&lsquo;Not &lsquo;quite&rsquo; what you expected?&rsquo;
160
161
''Cause I don't like it, 's why,' said Pat.
162
&lsquo;&apos;Cause I don't like it, &apos;s why,&rsquo; said Pat.
163
164
'It's a beautiful day!'
165
&lsquo;It&apos;s a beautiful day!&rsquo;
166
167
'He said, 'Thinkin'.'
168
&lsquo;He said, &lsquo;Thinkin&rsquo;.&rsquo;
169
170
# ########################################################################
171
# Possessives
172
# ########################################################################
173
Sam's Sams' and the Ross's roses' thorns were prickly.
174
Sam&apos;s Sams&apos; and the Ross&apos;s roses&apos; thorns were prickly.
175
176
# ########################################################################
177
# Mixed
178
# ########################################################################
179
"I heard she said, 'That's Sam's'," said the Sams' cat.
180
&ldquo;I heard she said, &lsquo;That&apos;s Sam&apos;s&rsquo;,&rdquo; said the Sams&apos; cat.
181
182
"'Janes' said, ''E'll be spooky, Sam's son with the jack-o'-lantern!'" said the O'Mally twins'---y'know---ghosts in unison.
183
&ldquo;&lsquo;Janes&apos; said, &lsquo;&apos;E&apos;ll be spooky, Sam&apos;s son with the jack-o&apos;-lantern!&rsquo;&rdquo; said the O&apos;Mally twins&apos;---y&apos;know---ghosts in unison.
184
185
'He's at Sams'
186
&lsquo;He&apos; at Sams&rsquo;
187
188
\"Hello!\"
189
&ldquo;Hello!&rdquo;
190
191
ma'am
192
ma&apos;am
193
194
'Twas midnight
195
&apos;Twas midnight
196
197
\"Hello,\" said the spider. \"'Shelob' is my name.\"
198
&ldquo;Hello,&rdquo; said the spider. &ldquo;&lsquo;Shelob&rsquo; is my name.&rdquo;
199
200
'A', 'B', and 'C' are letters.
201
&lsquo;A&rsquo; &lsquo;B&rsquo; and &lsquo;C&rsquo; are letters.
202
203
'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'
204
&lsquo;Oak,&rsquo; &lsquo;elm,&rsquo; and &lsquo;beech&rsquo; are names of trees. So is &lsquo;pine.&rsquo;
205
206
'He said, \"I want to go.\"' Were you alive in the 70's?
207
&lsquo;He said, &ldquo;I want to go.&rdquo;&rsquo; Were you alive in the 70&apos;s?
208
209
\"That's a 'magic' sock.\"
210
&ldquo;That&apos;s a &lsquo;magic&rsquo; sock.&rdquo;
211
212
Website! Company Name, Inc. (\"Company Name\" or \"Company\") recommends reading the following terms and conditions, carefully:
213
Website! Company Name, Inc. (&ldquo;Company Name&rdquo; or &ldquo;Company&rdquo;) recommends reading the following terms and conditions, carefully:
214
215
Website! Company Name, Inc. ('Company Name' or 'Company') recommends reading the following terms and conditions, carefully:
216
Website! Company Name, Inc. (&lsquo;Company Name&rsquo; or &lsquo;Company&rsquo;) recommends reading the following terms and conditions, carefully:
217
218
Workin' hard
219
Workin&apos; hard
220
221
'70s are my favorite numbers,' she said.
222
&lsquo;70s are my favorite numbers,&rsquo; she said.
223
224
'70s fashion was weird.
225
&apos;70s fashion was weird.
226
227
12\" record, 5'10\" height
228
12&Prime; record, 5&prime;10&Prime; height
229
230
Model \"T2000\"
231
Model &ldquo;T2000&rdquo;
232
233
iPad 3's battery life is not great.
234
iPad 3&apos;s battery life is not great.
235
236
Book 'em, Danno. Rock 'n' roll. 'Cause 'twas the season.
237
Book &apos;em, Danno. Rock &apos;n&apos; roll. &apos;Cause &apos;twas the season.
238
239
'85 was a good year. (The entire '80s were.)
240
&apos;85 was a good year. (The entire &apos;80s were.)
241
1242
A src/test/sikuli/.gitignore
1
*.class
12
A src/test/sikuli/README.md
1
Sikuli is used for the following purposes:
2
3
* Create application videos.
4
* Create integration tests.
5
16
A src/test/sikuli/demo.sikuli/1594187265140.png
Binary file
A src/test/sikuli/demo.sikuli/1594592396134.png
Binary file
A src/test/sikuli/demo.sikuli/1594593710440.png
Binary file
A src/test/sikuli/demo.sikuli/1594593794335.png
Binary file
A src/test/sikuli/demo.sikuli/1594594984108.png
Binary file
A src/test/sikuli/demo.sikuli/1594689573764.png
Binary file
A src/test/sikuli/demo.sikuli/demo.py
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
# Runs all scripts
26
# -----------------------------------------------------------------------------
27
28
import s01
29
import s02
30
import s03
31
import s04
132
A src/test/sikuli/demo.sikuli/s01.py
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
from sikuli import *
28
import sys
29
30
if not "../editor.sikuli" in sys.path:
31
    sys.path.append( "../editor.sikuli" )
32
33
from editor import *
34
35
# ---------------------------------------------------------------
36
# Fresh start
37
# ---------------------------------------------------------------
38
rm( app_home + "/variables.yaml" )
39
rm( app_home + "/untitled.md" )
40
rm( dir_home + "/.scrivenvar" )
41
42
# ---------------------------------------------------------------
43
# Wait for application to launch
44
# ---------------------------------------------------------------
45
openApp( "java -jar " + app_bin )
46
47
wait("1594187265140.png", 30)
48
49
# Breathing room for video recording.
50
wait( 4 )
51
52
# ---------------------------------------------------------------
53
# Introduction
54
# ---------------------------------------------------------------
55
set_typing_speed( 240 )
56
57
heading( "What is this application?" )
58
typer( "Well, this application is a text editor that supports interpolated definitions, ")
59
typer( "a few different text formats, real-time preview, spell check ") 
60
typer( "as you tipe" ) 
61
wait( 0.5 )
62
recur( 3, backspace )
63
typer( "ype, and R statements." )
64
paragraph()
65
wait( 1 )
66
67
# ---------------------------------------------------------------
68
# Definition demo
69
# ---------------------------------------------------------------
70
heading( "What are definitions?" )
71
typer( "Watch. " )
72
wait( .5 )
73
74
# Focus the definition editor.
75
click_create()
76
recur( 4, tab )
77
78
wait( .5 )
79
rename_definition( "application" )
80
81
insert()
82
rename_definition( "title" )
83
84
insert()
85
rename_definition( "Scrivenvar" )
86
87
# Set focus to the text editor.
88
tab()
89
90
typer( "The left-hand pane contains a nested, folder-like structure of names " )
91
typer( "and values that are called *definitions*. " )
92
wait( .5 )
93
typer( "Such definitions can simplify updating documents. " )
94
wait( 1 )
95
96
edit_find( "this application" )
97
typer( "$application.title$" )
98
99
edit_find_next()
100
typer( "$application.title$" )
101
102
type( Key.END, Key.CTRL )
103
104
typer( "The right-hand pane shows the result after having substituted definition " )
105
typer( "values into the document." ) 
106
107
paragraph()
108
typer( "Now nobody wants to type definition names all the time. Instead, type any " )
109
typer( "partial definition value followed by `Ctrl+Space`, such as: scr" )
110
wait( 0.5 )
111
autoinsert()
112
wait( 1 )
113
typer( ". *Much* better!" )
114
paragraph()
115
116
heading( "What is interpolation?" )
117
typer( "Definition values can reference definition names. " )
118
wait( .5 )
119
typer( "The definition names act as placeholders. Substituting placeholders with " )
120
typer( "their definition value is called *interpolation*. Let's see how it works." )
121
wait( 2 )
1122
A src/test/sikuli/demo.sikuli/s02.py
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
from sikuli import *
28
import sys
29
30
if not "../editor.sikuli" in sys.path:
31
    sys.path.append( "../editor.sikuli" )
32
33
from editor import *
34
35
# -----------------------------------------------------------------------------
36
# Open sample chapter.
37
# -----------------------------------------------------------------------------
38
file_open()
39
type( Key.UP, Key.ALT )
40
wait( 1 )
41
typer( Key.END )
42
wait( 1 )
43
enter()
44
wait( 0.5 )
45
enter()
46
wait( 1 )
47
48
# -----------------------------------------------------------------------------
49
# Open the corresponding definition file.
50
# -----------------------------------------------------------------------------
51
file_open()
52
recur( 2, down )
53
wait( 1 )
54
enter()
55
wait( 1 )
56
57
# -----------------------------------------------------------------------------
58
# Edit the sample document.
59
# -----------------------------------------------------------------------------
60
set_typing_speed( 80 )
61
62
type( Key.HOME, Key.CTRL )
63
recur( 2, down )
64
65
# Grey
66
recur( 3, skip_right )
67
autoinsert()
68
69
# 34
70
recur( 4, skip_right )
71
autoinsert()
72
73
# Central
74
recur( 10, skip_right )
75
autoinsert()
76
77
# London
78
skip_right()
79
autoinsert()
80
81
# Hatchery
82
skip_right()
83
autoinsert()
84
85
# and Conditioning
86
recur( 2, select_word_right )
87
delete()
88
89
# Centre
90
skip_right()
91
autoinsert()
92
93
set_typing_speed( 220 )
94
95
typer( " Let's interpolate those four definitions instead!" )
96
wait( 4 )
97
recur( 13, type, Key.BACKSPACE, Key.CTRL )
98
recur( 9, backspace )
99
100
set_typing_speed( 60 )
101
102
typer( "name$" )
103
wait( 2 )
104
105
# Collapse all definitions
106
tab()
107
recur( 8, typer, Key.LEFT )
108
109
# Expand to city
110
recur( 4, typer, Key.RIGHT )
111
112
# Jump to name
113
recur( 2, down )
114
recur( 2, typer, Key.RIGHT )
115
116
# Open the text field to show the full value
117
typer( Key.F2 )
118
119
# Traverse the text field
120
home()
121
recur( 16, type, Key.RIGHT, Key.CTRL )
122
esc()
123
124
restore_typing_speed()
125
126
tab()
127
type( Key.HOME, Key.CTRL )
128
edit_find( "Director" )
129
autoinsert()
130
131
edit_find_next()
132
autoinsert()
133
134
edit_find_next()
135
typer( Key.RIGHT )
136
recur( 2, delete )
137
autoinsert()
138
typer( "'s" )
139
140
edit_find( "Hatcheries" )
141
autoinsert()
142
143
# and Conditioning
144
recur( 2, select_word_right )
145
delete()
146
147
edit_find( "Central" )
148
autoinsert()
149
150
skip_right()
151
autoinsert()
152
153
typer( " How about a different city?" )
154
wait( 2 )
155
recur( 5, type, Key.BACKSPACE, Key.CTRL )
156
wait( 1 )
157
tab()
158
typer( Key.F2 )
159
typer( "Seattle" )
160
enter()
161
tab()
162
wait( 2 )
163
164
type( Key.END, Key.CTRL )
165
paragraph()
166
typer( "No?" )
167
paragraph()
168
169
tab()
170
typer( Key.F2 )
171
typer( "London" )
172
enter()
173
174
tab()
175
typer( "Organizing definitions is left to your ")
176
typer( "doub" )
177
autoinsert()
178
typer( " Good imagination." )
179
tab()
180
181
# Jump to "char" definition
182
home()
183
184
# Jump to "char.a.primary.name" definition
185
recur( 6, typer, Key.RIGHT )
186
187
# Jump to "char.a.primary.caste" definition
188
down()
189
typer( Key.RIGHT )
190
191
# Jump to root-level "caste" definition
192
recur( 7, down )
193
194
# Reselect "super"
195
recur( 5, typer, Key.RIGHT )
196
wait( 2 )
197
198
# Close the window, no save
199
type( "w", Key.CTRL )
200
wait( 0.5 )
201
tab()
202
wait( 0.5 )
203
typer( Key.SPACE )
204
wait( 1 )
1205
A src/test/sikuli/demo.sikuli/s03.py
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
from sikuli import *
28
import sys
29
30
if not "../editor.sikuli" in sys.path:
31
    sys.path.append( "../editor.sikuli" )
32
33
from editor import *
34
35
set_typing_speed( 80 )
36
37
file_open()
38
type( Key.UP, Key.ALT )
39
wait( 0.5 )
40
home()
41
wait( 0.25 )
42
enter()
43
wait( 1 )
44
end()
45
wait( 0.25 )
46
enter()
47
wait( 1 )
48
49
set_typing_speed( 200 )
50
51
paragraph()
52
heading( "What text formats are supported?" )
53
54
typer( "Scr" )
55
autoinsert()
56
typer( " supports Markdown, R Markdown, XML, and R XML; however, the software " )
57
typer( "architecture enables it to easily add new formats. The following figure " )
58
typer( "depicts the overall architecture: " )
59
paragraph()
60
typer( "![](../writing/images/architecture)" )
61
paragraph()
62
typer( "Many text editors can only open one type of plain text markup format that is " )
63
typer( "only output as HTML. With a little more effort, text editors could support " )
64
typer( "multiple input and output formats. Scr" )
65
autoinsert()
66
typer( " does so and goes one step further by introducing interpolated definitions." )
67
paragraph()
68
typer( "Kitten interlude:" )
69
paragraph()
70
typer( "![](https://i.imgur.com/jboueQH.jpg)" )
71
paragraph()
72
73
heading( "What is R?" )
74
typer( "R is a programming language. You might have noticed a few potential grammar " )
75
typer( "problems with direct substitution. Rules for possessive forms, numbers, and " )
76
typer( "other quirks can be tackled using R." )
77
78
# -----------------------------------------------------------------------------
79
# Demo bootstrapping
80
# -----------------------------------------------------------------------------
81
82
# Jump to the end
83
type( Key.END, Key.CTRL )
84
paragraph()
85
86
set_typing_speed( 300 )
87
heading( "How is R used?" )
88
typer( "R must be instructed where to find script files and what ones to load. The " )
89
typer( "*working directory* is the full path to those R files; the *startup script* " )
90
typer( "defines what R files to load. Both preferences must be changed before prose " )
91
typer( "may be processed. Preferences can be opened using either the " )
92
typeln( "**Edit > Preferences** menu or by pressing `Ctrl+Alt+s`. Here goes!" ) 
93
wait( 2 )
94
95
# -----------------------------------------------------------------------------
96
# Select the R script directory
97
# -----------------------------------------------------------------------------
98
99
# Change the working directory by clicking "Browse"
100
type( "s", Key.CTRL + Key.ALT )
101
wait("1594592396134.png", 1)
102
click("1594592396134.png")
103
wait( 0.5 )
104
105
# Navigate to and select the "r" directory
106
type( Key.UP, Key.ALT )
107
wait( 0.5 )
108
end()
109
wait( 0.5 )
110
enter()
111
wait( 0.5 )
112
end()
113
wait( 0.5 )
114
type( Key.UP )
115
wait( 0.5 )
116
recur( 2, tab )
117
wait( 0.5 )
118
enter()
119
wait( 1 )
120
121
# -----------------------------------------------------------------------------
122
# Set the R startup script instructions
123
# -----------------------------------------------------------------------------
124
125
wait("1594593710440.png", 5)
126
click("1594593710440.png")
127
128
set_typing_speed( 440 )
129
130
typeln( "setwd( '$application.r.working.directory$' )" )
131
typeln( "assign( 'anchor', '$date.anchor$', envir = .GlobalEnv )" )
132
typeln( "source( 'pluralize.R' )" )
133
typeln( "source( 'possessive.R' )" )
134
typeln( "source( 'conversion.R' )" )
135
typeln( "source( 'csv.R' )" )
136
137
wait("1594593794335.png", 3)
138
click("1594593794335.png")
139
140
paragraph()
141
set_typing_speed( 220 )
142
143
typer( "R is now configured. The startup script and other R " )
144
typer( "files can be found in the " )
145
typer( "[repository](https://github.com/DaveJarvis/scrivenvar/tree/master/R). " )
146
wait( 1.5 )
147
148
# Wait for the browser to appear.
149
wait("1594594984108.png", 5)
150
click("1594594984108.png")
151
152
wait( 5 )
153
click("1594689573764.png")
154
155
paragraph()
156
typer( "Next, we'll see how definitions and R can work together." )
157
wait( 2 )
1158
A src/test/sikuli/demo.sikuli/s04.py
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
from sikuli import *
28
import sys
29
30
if not "../editor.sikuli" in sys.path:
31
    sys.path.append( "../editor.sikuli" )
32
33
from editor import *
34
35
set_typing_speed( 220 )
36
37
# -----------------------------------------------------------------------------
38
# Open the demo text.
39
# -----------------------------------------------------------------------------
40
file_open()
41
type( Key.UP, Key.ALT )
42
wait( 0.5 )
43
end()
44
wait( 0.5 )
45
enter()
46
wait( 0.5 )
47
down()
48
wait( 0.5 )
49
enter()
50
wait( 2 )
51
52
# -----------------------------------------------------------------------------
53
# Re-open the corresponding definition file.
54
# -----------------------------------------------------------------------------
55
file_open()
56
recur( 2, down )
57
wait( 1 )
58
enter()
59
wait( 2 )
60
61
# -----------------------------------------------------------------------------
62
# Brief introduction to R
63
# -----------------------------------------------------------------------------
64
type( Key.HOME, Key.CTRL )
65
end()
66
paragraph()
67
68
typer( "## Using R" )
69
paragraph()
70
typer( "Insert R code into documents as follows: `r# 1+1`. " )
71
wait( 1.5 )
72
typer( "Notice how the right-hand pane shows the computed result. I'll wait. " )
73
wait( 3 )
74
typer( "The syntax is: open backtick, r#, *computable expression*, close " )
75
typer( "backtick. That expression can be any valid R statement. The status bar " ) 
76
typer( "will provide clues when an R expression cannot be computed by the " )
77
typer( "editor. `r# glitch`" )
78
wait( 4 )
79
recur( 11, backspace )
80
typer( "Let's swap 34 storeys for a definition value and replace the number " )
81
typer( "according to the Chicago Manual of Style (cms) rules." )
82
83
# -----------------------------------------------------------------------------
84
# Demo pluralization
85
# -----------------------------------------------------------------------------
86
set_typing_speed( 80 )
87
88
edit_find( "34" )
89
autoinsert()
90
91
edit_find( "x(" )
92
typer( "cms(" )
93
94
edit_find( "storeys." )
95
typer( "34." )
96
autoinsert()
97
edit_find( "x(" )
98
typer( "pl( 'storey'," )
99
wait( 4 )
100
101
tab()
102
rename_definition( "1" )
103
wait( 4 )
104
rename_definition( "142" )
105
wait( 4 )
106
rename_definition( "34" )
107
wait( 4 )
108
tab()
109
110
# -----------------------------------------------------------------------------
111
# Demo possessives (it, her, his, Director)
112
# -----------------------------------------------------------------------------
113
type( Key.HOME, Key.CTRL )
114
edit_find( "Director" )
115
autoinsert()
116
edit_find_next()
117
autoinsert()
118
edit_find_next()
119
autoinsert()
120
type( Key.RIGHT )
121
recur( 2, delete )
122
autoinsert()
123
home()
124
edit_find( "x(" )
125
typer( "pos(" )
126
wait( 2 )
127
128
tab()
129
rename_definition( "Headmistress" )
130
wait( 4 )
131
rename_definition( "Director" )
132
wait( 2 )
133
tab()
134
135
type( Key.END, Key.CTRL )
136
paragraph()
137
typer( "Other possessives: `r# pos( 'it' )`, `r# pos( 'her' )`, `r# pos( 'his' )`, " )
138
typer( "and `r# pos( 'my' )`." )
139
140
# -----------------------------------------------------------------------------
141
# Demo conversion, including ordinal numbers
142
# -----------------------------------------------------------------------------
143
set_typing_speed( 160 )
144
145
paragraph()
146
heading( "Date Conversions" )
147
typer( "Mixing R code with definitions invites endless possibilities. " )
148
typer( "Imagine someone racing to the " ) 
149
typer( "`r#cms( v$location$breeder$storeys, ordinal=TRUE )` floor, whereby that " )
150
typer( "ordinal stems from the Hatchery's storeys' definition. Or how about " )
151
typer( "a complex timeline where dates are expressed in days relative to one " )
152
typer( "point in time. Let's call this the *anchor date* and define it." )
153
154
tab()
155
home()
156
typer( Key.SPACE )
157
insert()
158
rename_definition( "date" )
159
insert()
160
rename_definition( "anchor" )
161
insert()
162
rename_definition( "1969-10-29" )
163
tab()
164
165
paragraph()
166
typer( "Next, set an R variable named `now` to the current date" )
167
typer( "`r# now = format( Sys.time(), '%Y-%m-%d' ); ''`--- the empty single quotes " )
168
typer( "prevent the date from appearing in the output document. " )
169
170
paragraph()
171
typer( "We set the anchor date to `r# annal()`, which was " )
172
typer( "`r# elapsed( 0, days( v$date$anchor, format( Sys.time(), '%Y-%m-%d' ) ) )` " )
173
typer( "ago from `r# format( as.Date( now ), '%B %d, %Y' )`. " )
174
175
# -----------------------------------------------------------------------------
176
# Demo CSV file import
177
# -----------------------------------------------------------------------------
178
paragraph()
179
heading( "Tabular Data" )
180
typer( "The following table shows average Canadian lifespans by birth " )
181
typer( "year and sex:" )
182
paragraph()
183
typer( "`r# csv2md( '../data.csv', total=FALSE )`" )
184
paragraph()
185
typer( "Calling `csv2md` converts the comma-separated values in the spreadsheet " )
186
typer( "to a table formatted using Markdown. The HTML preview pane changes the " )
187
typer( "appearance of the resulting table. Using `../data.csv` instructs R to " )
188
typer( "open `data.csv` from one directory above the *working directory*." )
189
190
# -----------------------------------------------------------------------------
191
# Demo HTML export
192
# -----------------------------------------------------------------------------
193
paragraph()
194
heading( "Export" )
195
typer( "Retrieve the output HTML by using the **Edit > Copy HTML** menu. Let's " )
196
typer( "peek at the output." )
197
wait( 2 )
198
199
type( "e", Key.ALT )
200
wait( 0.5 )
201
down()
202
wait( 0.25 )
203
enter()
204
wait( 0.25 )
205
206
type( "a", Key.CTRL )
207
wait( 0.25 )
208
type( "v", Key.CTRL )
209
wait( 5 )
210
211
set_typing_speed( 40 )
212
213
# Jump to page bottom (should already be there, but just in case)
214
type( Key.END, Key.CTRL )
215
recur( 3, typer, Key.PAGE_UP )
216
type( Key.HOME, Key.CTRL )
217
wait( 3 )
218
219
set_typing_speed( 220 )
220
type( "z", Key.CTRL )
221
type( Key.END, Key.CTRL )
222
223
paragraph()
224
typer( "That's all for now, thank you!" )
225
wait( 5 )
226
227
# Delete the anchor date.
228
tab()
229
end()
230
recur( 2, type, Key.UP )
231
delete()
232
tab()
1233
A src/test/sikuli/demo.sikuli/test.py
1
from sikuli import *
2
3
import sys
4
import os
5
6
def set_class_path():
7
    path_script = getBundlePath()
8
    dir_script = os.path.dirname( path_script )
9
    path_lib = dir_script + "/keycast/build/libs/keycast.jar"
10
    
11
    sys.path.append( path_lib )
12
13
def launch():
14
    from com.whitemagicsoftware.keycast import KeyCast
15
    kc = KeyCast()
16
    kc.show()
17
18
def main():
19
    set_class_path()
20
    launch()
21
   
22
23
if __name__ == "__main__":
24
    main()
125
A src/test/sikuli/editor.sikuli/1594187923258.png
Binary file
A src/test/sikuli/editor.sikuli/editor.py
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
dir_home = expanduser( "~" )
36
app_home = dir_home + "/bin"
37
app_bin = app_home + "/scrivenvar.jar"
38
39
wpm_typing_speed = 80
40
41
# -----------------------------------------------------------------------------
42
# Try to delete the file pointed to by the path variable. If there is no such
43
# file, this will silently ignore the exception.
44
# -----------------------------------------------------------------------------
45
def rm( path ):
46
    try:
47
        os.remove( path )
48
    except:
49
        print "Ignored"
50
51
# -----------------------------------------------------------------------------
52
# Changes the current typing speed, where speed is given in words per minute.
53
# -----------------------------------------------------------------------------
54
def set_typing_speed( wpm ):
55
    global wpm_typing_speed
56
    wpm_typing_speed = wpm
57
58
# -----------------------------------------------------------------------------
59
# Creates a delay between keystrokes to emulate typing at a particular speed.
60
# -----------------------------------------------------------------------------
61
def random_wait():
62
    from time import sleep
63
    from random import uniform
64
    cpm = wpm_typing_speed * 5.1
65
    cps = cpm / 60.0
66
    ms_per_char = 1000.0 / cps
67
    ms_per_stroke = ms_per_char / 2.0
68
69
    noise = uniform( 0, ms_per_stroke / 2 )
70
    duration = (ms_per_stroke + noise ) / 1000
71
    
72
    sleep( duration )
73
74
# -----------------------------------------------------------------------------
75
# Repeats a function call, f, n times.
76
# -----------------------------------------------------------------------------
77
def recur( n, f, *args ):
78
    for i in range( n ):
79
        f( *args )
80
        random_wait()
81
82
# -----------------------------------------------------------------------------
83
# Emulate a typist who is typing in the given text.
84
# -----------------------------------------------------------------------------
85
def typer( text ):
86
    for c in text:
87
        type( c )
88
        random_wait()
89
90
# -----------------------------------------------------------------------------
91
# Type a line of text followed by typing the ENTER key.
92
# -----------------------------------------------------------------------------
93
def typeln( text ):
94
    typer( text )
95
    enter()
96
97
# -----------------------------------------------------------------------------
98
# Injects a definition.
99
# -----------------------------------------------------------------------------
100
def autoinsert():
101
    type( Key.SPACE, Key.CTRL )
102
    random_wait()
103
104
# -----------------------------------------------------------------------------
105
# Types the TAB key.
106
# -----------------------------------------------------------------------------
107
def tab():
108
    typer( Key.TAB )
109
110
# -----------------------------------------------------------------------------
111
# Types the ENTER key.
112
# -----------------------------------------------------------------------------
113
def enter():
114
    typer( Key.ENTER )
115
116
# -----------------------------------------------------------------------------
117
# Types the ESC key.
118
# -----------------------------------------------------------------------------
119
def esc():
120
    typer( Key.ESC )
121
122
# -----------------------------------------------------------------------------
123
# Types the DOWN arrow key.
124
# -----------------------------------------------------------------------------
125
def down():
126
    typer( Key.DOWN )
127
128
# -----------------------------------------------------------------------------
129
# Types the HOME key.
130
# -----------------------------------------------------------------------------
131
def home():
132
    typer( Key.HOME )
133
134
# -----------------------------------------------------------------------------
135
# Types the END key.
136
# -----------------------------------------------------------------------------
137
def end():
138
    typer( Key.END )
139
140
# -----------------------------------------------------------------------------
141
# Types the BACKSPACE key.
142
# -----------------------------------------------------------------------------
143
def backspace():
144
    typer( Key.BACKSPACE )
145
146
# -----------------------------------------------------------------------------
147
# Types the INSERT key, often to insert a new definition.
148
# -----------------------------------------------------------------------------
149
def insert():
150
    typer( Key.INSERT )
151
152
# -----------------------------------------------------------------------------
153
# Types the DELETE key, often to remove selected text.
154
# -----------------------------------------------------------------------------
155
def delete():
156
    typer( Key.DELETE )
157
158
# -----------------------------------------------------------------------------
159
# Moves the cursor one word to the right.
160
# -----------------------------------------------------------------------------
161
def skip_right():
162
    type( Key.RIGHT, Key.CTRL )
163
    random_wait()
164
165
def select_word_right():
166
    type( Key.RIGHT, Key.CTRL + Key.SHIFT )
167
    random_wait()
168
169
# -----------------------------------------------------------------------------
170
# Types ENTER twice to begin a new paragraph.
171
# -----------------------------------------------------------------------------
172
def paragraph():
173
    recur( 2, enter )
174
    wait( 1.5 )
175
176
# -----------------------------------------------------------------------------
177
# Writes a heading to the document using the given text value as the content.
178
# -----------------------------------------------------------------------------
179
def heading( text ):
180
    typer( "# " + text )
181
    paragraph()
182
183
# -----------------------------------------------------------------------------
184
# Clicks the "Create" button to add a new definition.
185
# -----------------------------------------------------------------------------
186
def click_create():
187
    click("1594187923258.png")
188
    wait( .5 )
189
190
# -----------------------------------------------------------------------------
191
# Changes the text for the actively selected definition.
192
# -----------------------------------------------------------------------------
193
def rename_definition( text ):
194
    typer( Key.F2 )
195
    typer( text )
196
    enter()
197
    wait( .5 )
198
199
# -----------------------------------------------------------------------------
200
# Searches for the given text within the document.
201
# -----------------------------------------------------------------------------
202
def edit_find( text ):
203
    type( "f", Key.CTRL )
204
    typer( text )
205
    enter()
206
    wait( .25 )
207
    esc()
208
    wait( .5 )
209
210
# -----------------------------------------------------------------------------
211
# Searches for the next occurrence of the previous search term.
212
# -----------------------------------------------------------------------------
213
def edit_find_next():
214
    typer( Key.F3 )
215
    wait( .5 )
216
217
# -----------------------------------------------------------------------------
218
# Opens a dialog for selecting a file.
219
# -----------------------------------------------------------------------------
220
def file_open():
221
    type( "o", Key.CTRL )
222
    wait( 1 )
1223
D testing/.gitignore
1
*.class
21
D testing/demo.sikuli/1594187265140.png
Binary file
D testing/demo.sikuli/1594592396134.png
Binary file
D testing/demo.sikuli/1594593710440.png
Binary file
D testing/demo.sikuli/1594593794335.png
Binary file
D testing/demo.sikuli/1594594984108.png
Binary file
D testing/demo.sikuli/1594689573764.png
Binary file
D testing/demo.sikuli/demo.py
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
# Runs all scripts
26
# -----------------------------------------------------------------------------
27
28
import s01
29
import s02
30
import s03
31
import s04
321
D testing/demo.sikuli/s01.py
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
from sikuli import *
28
import sys
29
30
if not "../editor.sikuli" in sys.path:
31
    sys.path.append( "../editor.sikuli" )
32
33
from editor import *
34
35
# ---------------------------------------------------------------
36
# Fresh start
37
# ---------------------------------------------------------------
38
rm( app_home + "/variables.yaml" )
39
rm( app_home + "/untitled.md" )
40
rm( dir_home + "/.scrivenvar" )
41
42
# ---------------------------------------------------------------
43
# Wait for application to launch
44
# ---------------------------------------------------------------
45
openApp( "java -jar " + app_bin )
46
47
wait("1594187265140.png", 30)
48
49
# Breathing room for video recording.
50
wait( 4 )
51
52
# ---------------------------------------------------------------
53
# Introduction
54
# ---------------------------------------------------------------
55
set_typing_speed( 240 )
56
57
heading( "What is this application?" )
58
typer( "Well, this application is a text editor that supports interpolated definitions, ")
59
typer( "a few different text formats, real-time preview, spell check ") 
60
typer( "as you tipe" ) 
61
wait( 0.5 )
62
recur( 3, backspace )
63
typer( "ype, and R statements." )
64
paragraph()
65
wait( 1 )
66
67
# ---------------------------------------------------------------
68
# Definition demo
69
# ---------------------------------------------------------------
70
heading( "What are definitions?" )
71
typer( "Watch. " )
72
wait( .5 )
73
74
# Focus the definition editor.
75
click_create()
76
recur( 4, tab )
77
78
wait( .5 )
79
rename_definition( "application" )
80
81
insert()
82
rename_definition( "title" )
83
84
insert()
85
rename_definition( "Scrivenvar" )
86
87
# Set focus to the text editor.
88
tab()
89
90
typer( "The left-hand pane contains a nested, folder-like structure of names " )
91
typer( "and values that are called *definitions*. " )
92
wait( .5 )
93
typer( "Such definitions can simplify updating documents. " )
94
wait( 1 )
95
96
edit_find( "this application" )
97
typer( "$application.title$" )
98
99
edit_find_next()
100
typer( "$application.title$" )
101
102
type( Key.END, Key.CTRL )
103
104
typer( "The right-hand pane shows the result after having substituted definition " )
105
typer( "values into the document." ) 
106
107
paragraph()
108
typer( "Now nobody wants to type definition names all the time. Instead, type any " )
109
typer( "partial definition value followed by `Ctrl+Space`, such as: scr" )
110
wait( 0.5 )
111
autoinsert()
112
wait( 1 )
113
typer( ". *Much* better!" )
114
paragraph()
115
116
heading( "What is interpolation?" )
117
typer( "Definition values can reference definition names. " )
118
wait( .5 )
119
typer( "The definition names act as placeholders. Substituting placeholders with " )
120
typer( "their definition value is called *interpolation*. Let's see how it works." )
121
wait( 2 )
1221
D testing/demo.sikuli/s02.py
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
from sikuli import *
28
import sys
29
30
if not "../editor.sikuli" in sys.path:
31
    sys.path.append( "../editor.sikuli" )
32
33
from editor import *
34
35
# -----------------------------------------------------------------------------
36
# Open sample chapter.
37
# -----------------------------------------------------------------------------
38
file_open()
39
type( Key.UP, Key.ALT )
40
wait( 1 )
41
typer( Key.END )
42
wait( 1 )
43
enter()
44
wait( 0.5 )
45
enter()
46
wait( 1 )
47
48
# -----------------------------------------------------------------------------
49
# Open the corresponding definition file.
50
# -----------------------------------------------------------------------------
51
file_open()
52
recur( 2, down )
53
wait( 1 )
54
enter()
55
wait( 1 )
56
57
# -----------------------------------------------------------------------------
58
# Edit the sample document.
59
# -----------------------------------------------------------------------------
60
set_typing_speed( 80 )
61
62
type( Key.HOME, Key.CTRL )
63
recur( 2, down )
64
65
# Grey
66
recur( 3, skip_right )
67
autoinsert()
68
69
# 34
70
recur( 4, skip_right )
71
autoinsert()
72
73
# Central
74
recur( 10, skip_right )
75
autoinsert()
76
77
# London
78
skip_right()
79
autoinsert()
80
81
# Hatchery
82
skip_right()
83
autoinsert()
84
85
# and Conditioning
86
recur( 2, select_word_right )
87
delete()
88
89
# Centre
90
skip_right()
91
autoinsert()
92
93
set_typing_speed( 220 )
94
95
typer( " Let's interpolate those four definitions instead!" )
96
wait( 4 )
97
recur( 13, type, Key.BACKSPACE, Key.CTRL )
98
recur( 9, backspace )
99
100
set_typing_speed( 60 )
101
102
typer( "name$" )
103
wait( 2 )
104
105
# Collapse all definitions
106
tab()
107
recur( 8, typer, Key.LEFT )
108
109
# Expand to city
110
recur( 4, typer, Key.RIGHT )
111
112
# Jump to name
113
recur( 2, down )
114
recur( 2, typer, Key.RIGHT )
115
116
# Open the text field to show the full value
117
typer( Key.F2 )
118
119
# Traverse the text field
120
home()
121
recur( 16, type, Key.RIGHT, Key.CTRL )
122
esc()
123
124
restore_typing_speed()
125
126
tab()
127
type( Key.HOME, Key.CTRL )
128
edit_find( "Director" )
129
autoinsert()
130
131
edit_find_next()
132
autoinsert()
133
134
edit_find_next()
135
typer( Key.RIGHT )
136
recur( 2, delete )
137
autoinsert()
138
typer( "'s" )
139
140
edit_find( "Hatcheries" )
141
autoinsert()
142
143
# and Conditioning
144
recur( 2, select_word_right )
145
delete()
146
147
edit_find( "Central" )
148
autoinsert()
149
150
skip_right()
151
autoinsert()
152
153
typer( " How about a different city?" )
154
wait( 2 )
155
recur( 5, type, Key.BACKSPACE, Key.CTRL )
156
wait( 1 )
157
tab()
158
typer( Key.F2 )
159
typer( "Seattle" )
160
enter()
161
tab()
162
wait( 2 )
163
164
type( Key.END, Key.CTRL )
165
paragraph()
166
typer( "No?" )
167
paragraph()
168
169
tab()
170
typer( Key.F2 )
171
typer( "London" )
172
enter()
173
174
tab()
175
typer( "Organizing definitions is left to your ")
176
typer( "doub" )
177
autoinsert()
178
typer( " Good imagination." )
179
tab()
180
181
# Jump to "char" definition
182
home()
183
184
# Jump to "char.a.primary.name" definition
185
recur( 6, typer, Key.RIGHT )
186
187
# Jump to "char.a.primary.caste" definition
188
down()
189
typer( Key.RIGHT )
190
191
# Jump to root-level "caste" definition
192
recur( 7, down )
193
194
# Reselect "super"
195
recur( 5, typer, Key.RIGHT )
196
wait( 2 )
197
198
# Close the window, no save
199
type( "w", Key.CTRL )
200
wait( 0.5 )
201
tab()
202
wait( 0.5 )
203
typer( Key.SPACE )
204
wait( 1 )
2051
D testing/demo.sikuli/s03.py
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
from sikuli import *
28
import sys
29
30
if not "../editor.sikuli" in sys.path:
31
    sys.path.append( "../editor.sikuli" )
32
33
from editor import *
34
35
set_typing_speed( 80 )
36
37
file_open()
38
type( Key.UP, Key.ALT )
39
wait( 0.5 )
40
home()
41
wait( 0.25 )
42
enter()
43
wait( 1 )
44
end()
45
wait( 0.25 )
46
enter()
47
wait( 1 )
48
49
set_typing_speed( 200 )
50
51
paragraph()
52
heading( "What text formats are supported?" )
53
54
typer( "Scr" )
55
autoinsert()
56
typer( " supports Markdown, R Markdown, XML, and R XML; however, the software " )
57
typer( "architecture enables it to easily add new formats. The following figure " )
58
typer( "depicts the overall architecture: " )
59
paragraph()
60
typer( "![](../writing/images/architecture)" )
61
paragraph()
62
typer( "Many text editors can only open one type of plain text markup format that is " )
63
typer( "only output as HTML. With a little more effort, text editors could support " )
64
typer( "multiple input and output formats. Scr" )
65
autoinsert()
66
typer( " does so and goes one step further by introducing interpolated definitions." )
67
paragraph()
68
typer( "Kitten interlude:" )
69
paragraph()
70
typer( "![](https://i.imgur.com/jboueQH.jpg)" )
71
paragraph()
72
73
heading( "What is R?" )
74
typer( "R is a programming language. You might have noticed a few potential grammar " )
75
typer( "problems with direct substitution. Rules for possessive forms, numbers, and " )
76
typer( "other quirks can be tackled using R." )
77
78
# -----------------------------------------------------------------------------
79
# Demo bootstrapping
80
# -----------------------------------------------------------------------------
81
82
# Jump to the end
83
type( Key.END, Key.CTRL )
84
paragraph()
85
86
set_typing_speed( 300 )
87
heading( "How is R used?" )
88
typer( "R must be instructed where to find script files and what ones to load. The " )
89
typer( "*working directory* is the full path to those R files; the *startup script* " )
90
typer( "defines what R files to load. Both preferences must be changed before prose " )
91
typer( "may be processed. Preferences can be opened using either the " )
92
typeln( "**Edit > Preferences** menu or by pressing `Ctrl+Alt+s`. Here goes!" ) 
93
wait( 2 )
94
95
# -----------------------------------------------------------------------------
96
# Select the R script directory
97
# -----------------------------------------------------------------------------
98
99
# Change the working directory by clicking "Browse"
100
type( "s", Key.CTRL + Key.ALT )
101
wait("1594592396134.png", 1)
102
click("1594592396134.png")
103
wait( 0.5 )
104
105
# Navigate to and select the "r" directory
106
type( Key.UP, Key.ALT )
107
wait( 0.5 )
108
end()
109
wait( 0.5 )
110
enter()
111
wait( 0.5 )
112
end()
113
wait( 0.5 )
114
type( Key.UP )
115
wait( 0.5 )
116
recur( 2, tab )
117
wait( 0.5 )
118
enter()
119
wait( 1 )
120
121
# -----------------------------------------------------------------------------
122
# Set the R startup script instructions
123
# -----------------------------------------------------------------------------
124
125
wait("1594593710440.png", 5)
126
click("1594593710440.png")
127
128
set_typing_speed( 440 )
129
130
typeln( "setwd( '$application.r.working.directory$' )" )
131
typeln( "assign( 'anchor', '$date.anchor$', envir = .GlobalEnv )" )
132
typeln( "source( 'pluralize.R' )" )
133
typeln( "source( 'possessive.R' )" )
134
typeln( "source( 'conversion.R' )" )
135
typeln( "source( 'csv.R' )" )
136
137
wait("1594593794335.png", 3)
138
click("1594593794335.png")
139
140
paragraph()
141
set_typing_speed( 220 )
142
143
typer( "R is now configured. The startup script and other R " )
144
typer( "files can be found in the " )
145
typer( "[repository](https://github.com/DaveJarvis/scrivenvar/tree/master/R). " )
146
wait( 1.5 )
147
148
# Wait for the browser to appear.
149
wait("1594594984108.png", 5)
150
click("1594594984108.png")
151
152
wait( 5 )
153
click("1594689573764.png")
154
155
paragraph()
156
typer( "Next, we'll see how definitions and R can work together." )
157
wait( 2 )
1581
D testing/demo.sikuli/s04.py
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
from sikuli import *
28
import sys
29
30
if not "../editor.sikuli" in sys.path:
31
    sys.path.append( "../editor.sikuli" )
32
33
from editor import *
34
35
set_typing_speed( 220 )
36
37
# -----------------------------------------------------------------------------
38
# Open the demo text.
39
# -----------------------------------------------------------------------------
40
file_open()
41
type( Key.UP, Key.ALT )
42
wait( 0.5 )
43
end()
44
wait( 0.5 )
45
enter()
46
wait( 0.5 )
47
down()
48
wait( 0.5 )
49
enter()
50
wait( 2 )
51
52
# -----------------------------------------------------------------------------
53
# Re-open the corresponding definition file.
54
# -----------------------------------------------------------------------------
55
file_open()
56
recur( 2, down )
57
wait( 1 )
58
enter()
59
wait( 2 )
60
61
# -----------------------------------------------------------------------------
62
# Brief introduction to R
63
# -----------------------------------------------------------------------------
64
type( Key.HOME, Key.CTRL )
65
end()
66
paragraph()
67
68
typer( "## Using R" )
69
paragraph()
70
typer( "Insert R code into documents as follows: `r# 1+1`. " )
71
wait( 1.5 )
72
typer( "Notice how the right-hand pane shows the computed result. I'll wait. " )
73
wait( 3 )
74
typer( "The syntax is: open backtick, r#, *computable expression*, close " )
75
typer( "backtick. That expression can be any valid R statement. The status bar " ) 
76
typer( "will provide clues when an R expression cannot be computed by the " )
77
typer( "editor. `r# glitch`" )
78
wait( 4 )
79
recur( 11, backspace )
80
typer( "Let's swap 34 storeys for a definition value and replace the number " )
81
typer( "according to the Chicago Manual of Style (cms) rules." )
82
83
# -----------------------------------------------------------------------------
84
# Demo pluralization
85
# -----------------------------------------------------------------------------
86
set_typing_speed( 80 )
87
88
edit_find( "34" )
89
autoinsert()
90
91
edit_find( "x(" )
92
typer( "cms(" )
93
94
edit_find( "storeys." )
95
typer( "34." )
96
autoinsert()
97
edit_find( "x(" )
98
typer( "pl( 'storey'," )
99
wait( 4 )
100
101
tab()
102
rename_definition( "1" )
103
wait( 4 )
104
rename_definition( "142" )
105
wait( 4 )
106
rename_definition( "34" )
107
wait( 4 )
108
tab()
109
110
# -----------------------------------------------------------------------------
111
# Demo possessives (it, her, his, Director)
112
# -----------------------------------------------------------------------------
113
type( Key.HOME, Key.CTRL )
114
edit_find( "Director" )
115
autoinsert()
116
edit_find_next()
117
autoinsert()
118
edit_find_next()
119
autoinsert()
120
type( Key.RIGHT )
121
recur( 2, delete )
122
autoinsert()
123
home()
124
edit_find( "x(" )
125
typer( "pos(" )
126
wait( 2 )
127
128
tab()
129
rename_definition( "Headmistress" )
130
wait( 4 )
131
rename_definition( "Director" )
132
wait( 2 )
133
tab()
134
135
type( Key.END, Key.CTRL )
136
paragraph()
137
typer( "Other possessives: `r# pos( 'it' )`, `r# pos( 'her' )`, `r# pos( 'his' )`, " )
138
typer( "and `r# pos( 'my' )`." )
139
140
# -----------------------------------------------------------------------------
141
# Demo conversion, including ordinal numbers
142
# -----------------------------------------------------------------------------
143
set_typing_speed( 160 )
144
145
paragraph()
146
heading( "Date Conversions" )
147
typer( "Mixing R code with definitions invites endless possibilities. " )
148
typer( "Imagine someone racing to the " ) 
149
typer( "`r#cms( v$location$breeder$storeys, ordinal=TRUE )` floor, whereby that " )
150
typer( "ordinal stems from the Hatchery's storeys' definition. Or how about " )
151
typer( "a complex timeline where dates are expressed in days relative to one " )
152
typer( "point in time. Let's call this the *anchor date* and define it." )
153
154
tab()
155
home()
156
typer( Key.SPACE )
157
insert()
158
rename_definition( "date" )
159
insert()
160
rename_definition( "anchor" )
161
insert()
162
rename_definition( "1969-10-29" )
163
tab()
164
165
paragraph()
166
typer( "Next, set an R variable named `now` to the current date" )
167
typer( "`r# now = format( Sys.time(), '%Y-%m-%d' ); ''`--- the empty single quotes " )
168
typer( "prevent the date from appearing in the output document. " )
169
170
paragraph()
171
typer( "We set the anchor date to `r# annal()`, which was " )
172
typer( "`r# elapsed( 0, days( v$date$anchor, format( Sys.time(), '%Y-%m-%d' ) ) )` " )
173
typer( "ago from `r# format( as.Date( now ), '%B %d, %Y' )`. " )
174
175
# -----------------------------------------------------------------------------
176
# Demo CSV file import
177
# -----------------------------------------------------------------------------
178
paragraph()
179
heading( "Tabular Data" )
180
typer( "The following table shows average Canadian lifespans by birth " )
181
typer( "year and sex:" )
182
paragraph()
183
typer( "`r# csv2md( '../data.csv', total=FALSE )`" )
184
paragraph()
185
typer( "Calling `csv2md` converts the comma-separated values in the spreadsheet " )
186
typer( "to a table formatted using Markdown. The HTML preview pane changes the " )
187
typer( "appearance of the resulting table. Using `../data.csv` instructs R to " )
188
typer( "open `data.csv` from one directory above the *working directory*." )
189
190
# -----------------------------------------------------------------------------
191
# Demo HTML export
192
# -----------------------------------------------------------------------------
193
paragraph()
194
heading( "Export" )
195
typer( "Retrieve the output HTML by using the **Edit > Copy HTML** menu. Let's " )
196
typer( "peek at the output." )
197
wait( 2 )
198
199
type( "e", Key.ALT )
200
wait( 0.5 )
201
down()
202
wait( 0.25 )
203
enter()
204
wait( 0.25 )
205
206
type( "a", Key.CTRL )
207
wait( 0.25 )
208
type( "v", Key.CTRL )
209
wait( 5 )
210
211
set_typing_speed( 40 )
212
213
# Jump to page bottom (should already be there, but just in case)
214
type( Key.END, Key.CTRL )
215
recur( 3, typer, Key.PAGE_UP )
216
type( Key.HOME, Key.CTRL )
217
wait( 3 )
218
219
set_typing_speed( 220 )
220
type( "z", Key.CTRL )
221
type( Key.END, Key.CTRL )
222
223
paragraph()
224
typer( "That's all for now, thank you!" )
225
wait( 5 )
226
227
# Delete the anchor date.
228
tab()
229
end()
230
recur( 2, type, Key.UP )
231
delete()
232
tab()
2331
D testing/demo.sikuli/test.py
1
from sikuli import *
2
3
import sys
4
import os
5
6
def set_class_path():
7
    path_script = getBundlePath()
8
    dir_script = os.path.dirname( path_script )
9
    path_lib = dir_script + "/keycast/build/libs/keycast.jar"
10
    
11
    sys.path.append( path_lib )
12
13
def launch():
14
    from com.whitemagicsoftware.keycast import KeyCast
15
    kc = KeyCast()
16
    kc.show()
17
18
def main():
19
    set_class_path()
20
    launch()
21
   
22
23
if __name__ == "__main__":
24
    main()
251
D testing/editor.sikuli/1594187923258.png
Binary file
D testing/editor.sikuli/editor.py
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
dir_home = expanduser( "~" )
36
app_home = dir_home + "/bin"
37
app_bin = app_home + "/scrivenvar.jar"
38
39
wpm_typing_speed = 80
40
41
# -----------------------------------------------------------------------------
42
# Try to delete the file pointed to by the path variable. If there is no such
43
# file, this will silently ignore the exception.
44
# -----------------------------------------------------------------------------
45
def rm( path ):
46
    try:
47
        os.remove( path )
48
    except:
49
        print "Ignored"
50
51
# -----------------------------------------------------------------------------
52
# Changes the current typing speed, where speed is given in words per minute.
53
# -----------------------------------------------------------------------------
54
def set_typing_speed( wpm ):
55
    global wpm_typing_speed
56
    wpm_typing_speed = wpm
57
58
# -----------------------------------------------------------------------------
59
# Creates a delay between keystrokes to emulate typing at a particular speed.
60
# -----------------------------------------------------------------------------
61
def random_wait():
62
    from time import sleep
63
    from random import uniform
64
    cpm = wpm_typing_speed * 5.1
65
    cps = cpm / 60.0
66
    ms_per_char = 1000.0 / cps
67
    ms_per_stroke = ms_per_char / 2.0
68
69
    noise = uniform( 0, ms_per_stroke / 2 )
70
    duration = (ms_per_stroke + noise ) / 1000
71
    
72
    sleep( duration )
73
74
# -----------------------------------------------------------------------------
75
# Repeats a function call, f, n times.
76
# -----------------------------------------------------------------------------
77
def recur( n, f, *args ):
78
    for i in range( n ):
79
        f( *args )
80
        random_wait()
81
82
# -----------------------------------------------------------------------------
83
# Emulate a typist who is typing in the given text.
84
# -----------------------------------------------------------------------------
85
def typer( text ):
86
    for c in text:
87
        type( c )
88
        random_wait()
89
90
# -----------------------------------------------------------------------------
91
# Type a line of text followed by typing the ENTER key.
92
# -----------------------------------------------------------------------------
93
def typeln( text ):
94
    typer( text )
95
    enter()
96
97
# -----------------------------------------------------------------------------
98
# Injects a definition.
99
# -----------------------------------------------------------------------------
100
def autoinsert():
101
    type( Key.SPACE, Key.CTRL )
102
    random_wait()
103
104
# -----------------------------------------------------------------------------
105
# Types the TAB key.
106
# -----------------------------------------------------------------------------
107
def tab():
108
    typer( Key.TAB )
109
110
# -----------------------------------------------------------------------------
111
# Types the ENTER key.
112
# -----------------------------------------------------------------------------
113
def enter():
114
    typer( Key.ENTER )
115
116
# -----------------------------------------------------------------------------
117
# Types the ESC key.
118
# -----------------------------------------------------------------------------
119
def esc():
120
    typer( Key.ESC )
121
122
# -----------------------------------------------------------------------------
123
# Types the DOWN arrow key.
124
# -----------------------------------------------------------------------------
125
def down():
126
    typer( Key.DOWN )
127
128
# -----------------------------------------------------------------------------
129
# Types the HOME key.
130
# -----------------------------------------------------------------------------
131
def home():
132
    typer( Key.HOME )
133
134
# -----------------------------------------------------------------------------
135
# Types the END key.
136
# -----------------------------------------------------------------------------
137
def end():
138
    typer( Key.END )
139
140
# -----------------------------------------------------------------------------
141
# Types the BACKSPACE key.
142
# -----------------------------------------------------------------------------
143
def backspace():
144
    typer( Key.BACKSPACE )
145
146
# -----------------------------------------------------------------------------
147
# Types the INSERT key, often to insert a new definition.
148
# -----------------------------------------------------------------------------
149
def insert():
150
    typer( Key.INSERT )
151
152
# -----------------------------------------------------------------------------
153
# Types the DELETE key, often to remove selected text.
154
# -----------------------------------------------------------------------------
155
def delete():
156
    typer( Key.DELETE )
157
158
# -----------------------------------------------------------------------------
159
# Moves the cursor one word to the right.
160
# -----------------------------------------------------------------------------
161
def skip_right():
162
    type( Key.RIGHT, Key.CTRL )
163
    random_wait()
164
165
def select_word_right():
166
    type( Key.RIGHT, Key.CTRL + Key.SHIFT )
167
    random_wait()
168
169
# -----------------------------------------------------------------------------
170
# Types ENTER twice to begin a new paragraph.
171
# -----------------------------------------------------------------------------
172
def paragraph():
173
    recur( 2, enter )
174
    wait( 1.5 )
175
176
# -----------------------------------------------------------------------------
177
# Writes a heading to the document using the given text value as the content.
178
# -----------------------------------------------------------------------------
179
def heading( text ):
180
    typer( "# " + text )
181
    paragraph()
182
183
# -----------------------------------------------------------------------------
184
# Clicks the "Create" button to add a new definition.
185
# -----------------------------------------------------------------------------
186
def click_create():
187
    click("1594187923258.png")
188
    wait( .5 )
189
190
# -----------------------------------------------------------------------------
191
# Changes the text for the actively selected definition.
192
# -----------------------------------------------------------------------------
193
def rename_definition( text ):
194
    typer( Key.F2 )
195
    typer( text )
196
    enter()
197
    wait( .5 )
198
199
# -----------------------------------------------------------------------------
200
# Searches for the given text within the document.
201
# -----------------------------------------------------------------------------
202
def edit_find( text ):
203
    type( "f", Key.CTRL )
204
    typer( text )
205
    enter()
206
    wait( .25 )
207
    esc()
208
    wait( .5 )
209
210
# -----------------------------------------------------------------------------
211
# Searches for the next occurrence of the previous search term.
212
# -----------------------------------------------------------------------------
213
def edit_find_next():
214
    typer( Key.F3 )
215
    wait( .5 )
216
217
# -----------------------------------------------------------------------------
218
# Opens a dialog for selecting a file.
219
# -----------------------------------------------------------------------------
220
def file_open():
221
    type( "o", Key.CTRL )
222
    wait( 1 )
2231
A themes
11
D video/.gitignore
1
*.avi
2
*.wav
3
*.png
4
*.mp4
5
*.mp3
6
71
D video/title.blend
Binary file
D video/traced-text.svg
1
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
<svg
3
   xmlns:dc="http://purl.org/dc/elements/1.1/"
4
   xmlns:cc="http://creativecommons.org/ns#"
5
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
6
   xmlns:svg="http://www.w3.org/2000/svg"
7
   xmlns="http://www.w3.org/2000/svg"
8
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
9
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
10
   width="211.87125mm"
11
   height="56.576mm"
12
   viewBox="0 0 211.87125 56.576"
13
   version="1.1"
14
   id="svg8"
15
   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
16
   sodipodi:docname="traced-text.svg">
17
  <defs
18
     id="defs2" />
19
  <sodipodi:namedview
20
     id="base"
21
     pagecolor="#ffffff"
22
     bordercolor="#666666"
23
     borderopacity="1.0"
24
     inkscape:pageopacity="0.0"
25
     inkscape:pageshadow="2"
26
     inkscape:zoom="1.4142136"
27
     inkscape:cx="367.6429"
28
     inkscape:cy="129.23348"
29
     inkscape:document-units="mm"
30
     inkscape:current-layer="layer1"
31
     inkscape:document-rotation="0"
32
     showgrid="false"
33
     fit-margin-top="10"
34
     fit-margin-left="10"
35
     fit-margin-right="10"
36
     fit-margin-bottom="10" />
37
  <metadata
38
     id="metadata5">
39
    <rdf:RDF>
40
      <cc:Work
41
         rdf:about="">
42
        <dc:format>image/svg+xml</dc:format>
43
        <dc:type
44
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
45
        <dc:title></dc:title>
46
      </cc:Work>
47
    </rdf:RDF>
48
  </metadata>
49
  <g
50
     inkscape:label="Layer 1"
51
     inkscape:groupmode="layer"
52
     id="layer1"
53
     transform="translate(-1.4263456,-106.05539)">
54
    <text
55
       xml:space="preserve"
56
       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.8px;line-height:1.25;font-family:'Alex Brush';-inkscape-font-specification:'Alex Brush, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
57
       x="12.289946"
58
       y="147.80539"
59
       id="text835"><tspan
60
         sodipodi:role="line"
61
         id="tspan833"
62
         x="12.289946"
63
         y="147.80539"
64
         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.8px;font-family:'Alex Brush';-inkscape-font-specification:'Alex Brush, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.264583">Scrivenvar</tspan></text>
65
    <path
66
       sodipodi:nodetypes="cssssc"
67
       id="path859"
68
       d="m 47.37594,126.25759 c 5.878995,0.58684 8.108819,-2.8906 6.991897,-5.39049 -4.163299,-9.31827 -26.104298,-1.57165 -26.47428,4.67958 -0.290066,4.90098 4.329286,5.69691 9.138161,6.81221 4.75698,1.10326 9.980125,1.72503 10.138085,4.5281 0.511551,9.07772 -11.28247,13.50974 -21.577969,13.14767"
69
       style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#4eb059;stroke-width:0.132292;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
70
    <path
71
       sodipodi:nodetypes="cssc"
72
       id="path861"
73
       d="m 61.538159,137.91416 c 8.229745,-12.05206 -9.227635,-1.22793 -10.272792,5.40306 -0.929347,5.89623 4.566953,5.63307 9.024721,2.11036 5.095939,-4.02702 8.706628,-8.11599 12.031905,-13.9409"
74
       style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#4eb059;stroke-width:0.132292;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
75
    <path
76
       sodipodi:nodetypes="ccssc"
77
       id="path863"
78
       d="m 72.321991,131.48668 c 3.834665,-5.91801 -1.131419,0.83402 0.75311,2.48796 2.189872,1.94816 6.580549,-2.11016 5.400159,-0.72958 -0.854851,0.99983 -9.857527,10.41157 -5.126492,13.80621 2.461609,1.76627 8.936925,-2.58857 11.751532,-5.5313"
79
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
80
    <path
81
       sodipodi:nodetypes="csssc"
82
       id="path963"
83
       d="m 85.1003,141.51997 c 0,0 6.754775,-9.24626 6.743495,-8.01563 -0.01328,1.44899 -5.040946,6.68411 -6.63123,10.08427 -0.90584,1.93677 -0.626402,4.68995 2.447111,4.25184 1.468017,-0.20926 5.212094,-2.44913 10.029682,-7.66684"
84
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
85
    <path
86
       sodipodi:nodetypes="csccc"
87
       id="path965"
88
       d="m 97.689357,140.17361 c 0,0 3.797813,-8.42805 4.594353,-7.95573 0.58723,0.34822 -6.526154,13.32545 -5.477472,14.50806 2.435753,1.7862 19.064212,-11.51107 15.563042,-16.73913 -0.73409,-1.34256 -3.18033,-1.99148 -3.18033,-1.99148"
89
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
90
    <path
91
       sodipodi:nodetypes="csssc"
92
       d="m 113.37707,141.34636 c 4.23091,0.29831 11.94363,-4.90618 10.94354,-7.7799 -1.29105,-3.70978 -8.05529,1.78774 -9.69006,3.68511 -4.97668,5.77609 -4.11733,10.31478 -0.92228,10.61275 3.436,0.32045 8.83724,-3.13085 13.69698,-9.62574"
93
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
94
       id="path967" />
95
    <path
96
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
97
       d="m 146.49943,140.17361 c 0,0 3.79781,-8.42805 4.59435,-7.95573 0.58723,0.34822 -6.52616,13.32545 -5.47747,14.50806 2.43575,1.7862 19.06421,-11.51107 15.56304,-16.73913 -0.73409,-1.34256 -3.10123,-1.96263 -3.10123,-1.96263"
98
       id="path970"
99
       sodipodi:nodetypes="csccc" />
100
    <path
101
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
102
       d="m 188.80833,131.36316 c 3.83466,-5.91801 -1.13142,0.83402 0.75311,2.48796 2.18987,1.94816 6.58055,-2.11016 5.40016,-0.72958 -0.85485,0.99983 -9.98962,10.60367 -5.12649,13.80621 2.8329,1.86556 9.63808,-2.25455 13.61435,-8.05051"
103
       id="path987"
104
       sodipodi:nodetypes="ccssc" />
105
    <path
106
       sodipodi:nodetypes="ccsssccc"
107
       d="m 127.40525,138.23858 c 1.53961,-1.23511 5.06979,-6.4876 5.94375,-5.82833 -1.7832,2.5949 -8.95273,13.68991 -7.1105,13.94503 1.19011,0.16482 7.25976,-8.00422 10.87675,-10.901 1.83151,-1.46682 4.35069,-3.49971 5.94917,-3.73267 1.66376,-0.24247 -1.93803,2.90472 -3.80099,5.77097 -1.36327,2.14988 -4.92421,8.02816 -2.69839,9.35481 3.0826,1.21137 7.35116,-4.27566 9.93439,-6.67382"
108
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
109
       id="path989" />
110
    <path
111
       sodipodi:nodetypes="csscsc"
112
       id="path992"
113
       d="m 176.85645,132.78853 c -3.26879,-6.24001 -16.43513,7.99373 -16.14879,12.14556 0.1378,1.99804 2.16776,3.14653 3.8818,2.44798 4.44909,-1.8132 11.93103,-13.58278 13.4413,-14.18515 -6.97685,9.84354 -7.04537,13.29844 -4.02229,13.83262 2.49715,0.44125 8.94275,-6.11484 14.79986,-15.66638"
114
       style="fill:none;fill-opacity:0.8;stroke:#4eb059;stroke-width:0.132292;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
115
  </g>
116
</svg>
1171